diff options
| author | Andrew Thompson <thompsa@FreeBSD.org> | 2012-04-20 09:55:50 +0000 |
|---|---|---|
| committer | Andrew Thompson <thompsa@FreeBSD.org> | 2012-04-20 09:55:50 +0000 |
| commit | 7702d4013b15419f0391d006a9c20ef652ab2111 (patch) | |
| tree | 5e720f1f10937bda6108ab3cf3fe0a0b81caa055 /sys/net | |
| parent | b50d8083ab595257e0dd4f156bb30b405e38bac9 (diff) | |
Notes
Diffstat (limited to 'sys/net')
| -rw-r--r-- | sys/net/bridgestp.c | 28 | ||||
| -rw-r--r-- | sys/net/bridgestp.h | 4 | ||||
| -rw-r--r-- | sys/net/if.c | 4 | ||||
| -rw-r--r-- | sys/net/if_bridge.c | 59 |
4 files changed, 60 insertions, 35 deletions
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c index 06d7f1518d47..dd2aa095367a 100644 --- a/sys/net/bridgestp.c +++ b/sys/net/bridgestp.c @@ -1767,28 +1767,16 @@ bstp_notify_rtage(void *arg, int pending) } void -bstp_linkstate(struct ifnet *ifp, int state) +bstp_linkstate(struct bstp_port *bp) { - struct bstp_state *bs; - struct bstp_port *bp; + struct bstp_state *bs = bp->bp_bs; - /* search for the stp port */ - mtx_lock(&bstp_list_mtx); - LIST_FOREACH(bs, &bstp_list, bs_list) { - BSTP_LOCK(bs); - LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { - if (bp->bp_ifp == ifp) { - bstp_ifupdstatus(bs, bp); - bstp_update_state(bs, bp); - /* it only exists once so return */ - BSTP_UNLOCK(bs); - mtx_unlock(&bstp_list_mtx); - return; - } - } - BSTP_UNLOCK(bs); + BSTP_LOCK(bs); + if (bp->bp_active) { + bstp_ifupdstatus(bs, bp); + bstp_update_state(bs, bp); } - mtx_unlock(&bstp_list_mtx); + BSTP_UNLOCK(bs); } static void @@ -2103,10 +2091,8 @@ bstp_modevent(module_t mod, int type, void *data) case MOD_LOAD: mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF); LIST_INIT(&bstp_list); - bstp_linkstate_p = bstp_linkstate; break; case MOD_UNLOAD: - bstp_linkstate_p = NULL; mtx_destroy(&bstp_list_mtx); break; default: diff --git a/sys/net/bridgestp.h b/sys/net/bridgestp.h index 8cec09c83828..e76cfe9c0510 100644 --- a/sys/net/bridgestp.h +++ b/sys/net/bridgestp.h @@ -369,8 +369,6 @@ struct bstp_state { extern const uint8_t bstp_etheraddr[]; -extern void (*bstp_linkstate_p)(struct ifnet *ifp, int state); - void bstp_attach(struct bstp_state *, struct bstp_cb_ops *); void bstp_detach(struct bstp_state *); void bstp_init(struct bstp_state *); @@ -379,7 +377,7 @@ int bstp_create(struct bstp_state *, struct bstp_port *, struct ifnet *); int bstp_enable(struct bstp_port *); void bstp_disable(struct bstp_port *); void bstp_destroy(struct bstp_port *); -void bstp_linkstate(struct ifnet *, int); +void bstp_linkstate(struct bstp_port *); int bstp_set_htime(struct bstp_state *, int); int bstp_set_fdelay(struct bstp_state *, int); int bstp_set_maxage(struct bstp_state *, int); diff --git a/sys/net/if.c b/sys/net/if.c index 8d2c5f230cb0..bf332db115fd 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -124,7 +124,7 @@ static MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions"); static struct sx ifdescr_sx; SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr"); -void (*bstp_linkstate_p)(struct ifnet *ifp, int state); +void (*bridge_linkstate_p)(struct ifnet *ifp); void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); void (*lagg_linkstate_p)(struct ifnet *ifp, int state); /* These are external hooks for CARP. */ @@ -1910,7 +1910,7 @@ do_link_state_change(void *arg, int pending) if (ifp->if_carp) (*carp_linkstate_p)(ifp); if (ifp->if_bridge) - (*bstp_linkstate_p)(ifp, link_state); + (*bridge_linkstate_p)(ifp); if (ifp->if_lagg) (*lagg_linkstate_p)(ifp, link_state); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index a25f648dc791..271ef307228a 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -333,6 +333,9 @@ static int bridge_ip6_checkbasic(struct mbuf **mp); #endif /* INET6 */ static int bridge_fragment(struct ifnet *, struct mbuf *, struct ether_header *, int, struct llc *); +static void bridge_linkstate(struct ifnet *ifp); + +extern void (*bridge_linkstate_p)(struct ifnet *ifp); /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */ #define VLANTAGOF(_m) \ @@ -496,6 +499,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_input_p = bridge_input; bridge_output_p = bridge_output; bridge_dn_p = bridge_dummynet; + bridge_linkstate_p = bridge_linkstate; bridge_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, bridge_ifdetach, NULL, EVENTHANDLER_PRI_ANY); @@ -508,6 +512,7 @@ bridge_modevent(module_t mod, int type, void *data) bridge_input_p = NULL; bridge_output_p = NULL; bridge_dn_p = NULL; + bridge_linkstate_p = NULL; mtx_destroy(&bridge_list_mtx); break; default: @@ -988,6 +993,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, bridge_set_ifcap(sc, bif, bif->bif_savedcaps); } bstp_destroy(&bif->bif_stp); /* prepare to free */ + bridge_linkstate(ifs); BRIDGE_LOCK(sc); free(bif, M_DEVBUF); } @@ -1087,17 +1093,17 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) /* Set interface capabilities to the intersection set of all members */ bridge_mutecaps(sc); + BRIDGE_UNLOCK(sc); + /* Update the linkstate for the bridge */ + bridge_linkstate(ifs); + /* Place the interface into promiscuous mode */ switch (ifs->if_type) { - case IFT_ETHER: - case IFT_L2VLAN: - /* - * Place the interface into promiscuous mode. - */ - BRIDGE_UNLOCK(sc); - error = ifpromisc(ifs, 1); - BRIDGE_LOCK(sc); - break; + case IFT_ETHER: + case IFT_L2VLAN: + error = ifpromisc(ifs, 1); + break; } + BRIDGE_LOCK(sc); if (error) bridge_delete_member(sc, bif, 0); out: @@ -3475,3 +3481,38 @@ out: m_freem(m); return (error); } + +static void +bridge_linkstate(struct ifnet *ifp) +{ + struct bridge_softc *sc = ifp->if_bridge; + struct bridge_iflist *bif, *bif2; + int new_link, hasls; + + BRIDGE_LOCK(sc); + bif = bridge_lookup_member_if(sc, ifp); + if (bif == NULL) { + BRIDGE_UNLOCK(sc); + return; + } + new_link = LINK_STATE_DOWN; + hasls = 0; + /* Our link is considered up if at least one of our ports is active */ + LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { + if (bif2->bif_ifp->if_capabilities & IFCAP_LINKSTATE) + hasls++; + if (bif2->bif_ifp->if_link_state == LINK_STATE_UP) { + new_link = LINK_STATE_UP; + break; + } + } + if (!LIST_EMPTY(&sc->sc_iflist) && !hasls) { + /* If no interfaces support link-state then we default to up */ + new_link = LINK_STATE_UP; + } + if_link_state_change(sc->sc_ifp, new_link); + BRIDGE_UNLOCK(sc); + + bstp_linkstate(&bif->bif_stp); +} + |
