summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorphilip <philip@FreeBSD.org>2008-07-01 08:14:58 +0000
committerphilip <philip@FreeBSD.org>2008-07-01 08:14:58 +0000
commit72aa24167add15119f7202e64e850e5724701206 (patch)
tree8d2e9238a91aaaebdcfe55cac6f95e1b5c14d771 /sys/net
parent9ff980a478fc3df349087578fac081683d75aaf9 (diff)
downloadFreeBSD-src-72aa24167add15119f7202e64e850e5724701206.zip
FreeBSD-src-72aa24167add15119f7202e64e850e5724701206.tar.gz
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
Diffstat (limited to 'sys/net')
-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 168a5fa..4c4ebe6 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);
/*
OpenPOWER on IntegriCloud