aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorPhilip Paeps <philip@FreeBSD.org>2008-07-01 08:14:58 +0000
committerPhilip Paeps <philip@FreeBSD.org>2008-07-01 08:14:58 +0000
commitfe878019faaa17cf9b387ba48de5e5a2a36c59de (patch)
tree8d2e9238a91aaaebdcfe55cac6f95e1b5c14d771 /sys/net/if_bridge.c
parente54fdca237f1f2913a6725f3e9912afecd155a08 (diff)
downloadsrc-fe878019faaa17cf9b387ba48de5e5a2a36c59de.tar.gz
src-fe878019faaa17cf9b387ba48de5e5a2a36c59de.zip
Set bridge MAC addresses to the MAC address of their first interface unless
locally configured. This is more in line with the behaviour of other popular bridging implementations and makes bridges more predictable after reboots for example. Reviewed by: thompsa MFC after: 1 week
Notes
Notes: svn path=/head/; revision=180140
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 168a5fa75050..4c4ebe6b1e16 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -216,6 +216,7 @@ struct bridge_softc {
LIST_HEAD(, bridge_iflist) sc_spanlist; /* span ports list */
struct bstp_state sc_stp; /* STP state */
uint32_t sc_brtexceeded; /* # of cache drops */
+ u_char sc_defaddr[6]; /* Default MAC address */
};
static struct mtx bridge_list_mtx;
@@ -546,7 +547,6 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct bridge_softc *sc, *sc2;
struct ifnet *bifp, *ifp;
- u_char eaddr[6];
int retry;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
@@ -588,21 +588,22 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
* this hardware address isn't already in use on another bridge.
*/
for (retry = 1; retry != 0;) {
- arc4rand(eaddr, ETHER_ADDR_LEN, 1);
- eaddr[0] &= ~1; /* clear multicast bit */
- eaddr[0] |= 2; /* set the LAA bit */
+ arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
+ sc->sc_defaddr[0] &= ~1; /* clear multicast bit */
+ sc->sc_defaddr[0] |= 2; /* set the LAA bit */
retry = 0;
mtx_lock(&bridge_list_mtx);
LIST_FOREACH(sc2, &bridge_list, sc_list) {
bifp = sc2->sc_ifp;
- if (memcmp(eaddr, IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0)
+ if (memcmp(sc->sc_defaddr,
+ IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0)
retry = 1;
}
mtx_unlock(&bridge_list_mtx);
}
bstp_attach(&sc->sc_stp, &bridge_ops);
- ether_ifattach(ifp, eaddr);
+ ether_ifattach(ifp, sc->sc_defaddr);
/* Now undo some of the damage... */
ifp->if_baudrate = 0;
ifp->if_type = IFT_BRIDGE;
@@ -857,6 +858,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
int gone)
{
struct ifnet *ifs = bif->bif_ifp;
+ struct ifnet *fif = NULL;
BRIDGE_LOCK_ASSERT(sc);
@@ -890,6 +892,22 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
LIST_REMOVE(bif, bif_next);
BRIDGE_XDROP(sc);
+ /*
+ * If removing the interface that gave the bridge its mac address, set
+ * the mac address of the bridge to the address of the next member, or
+ * to its default address if no members are left.
+ */
+ if (!memcmp(IF_LLADDR(sc->sc_ifp), IF_LLADDR(ifs), ETHER_ADDR_LEN)) {
+ if (LIST_EMPTY(&sc->sc_iflist))
+ bcopy(sc->sc_defaddr,
+ IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
+ else {
+ fif = LIST_FIRST(&sc->sc_iflist)->bif_ifp;
+ bcopy(IF_LLADDR(fif),
+ IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
+ }
+ }
+
bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
KASSERT(bif->bif_addrcnt == 0,
("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt));
@@ -979,6 +997,15 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
goto out;
}
+ /*
+ * Assign the interface's MAC address to the bridge if it's the first
+ * member and the MAC address of the bridge has not been changed from
+ * the default randomly generated one.
+ */
+ if (LIST_EMPTY(&sc->sc_iflist) &&
+ !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN))
+ bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
+
ifs->if_bridge = sc;
bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp);
/*