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
This commit is contained in:
Philip Paeps 2008-07-01 08:14:58 +00:00
parent e54fdca237
commit fe878019fa

View File

@ -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);
/*