diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 86ca7c3..a7397b6 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -197,21 +197,25 @@ __CTASSERT(offsetof(struct ifbifconf, ifbic_buf) == offsetof(struct ifbaconf, if #ifdef NET_MPSAFE -#define ACQUIRE_GLOBAL_LOCKS(s) do { s = 0; } while (0) -#define RELEASE_GLOBAL_LOCKS(s) do { (void)s; } while (0) +#define DECLARE_LOCK_VARIABLE +#define ACQUIRE_GLOBAL_LOCKS() do { } while (0) +#define RELEASE_GLOBAL_LOCKS() do { } while (0) #else -#define ACQUIRE_GLOBAL_LOCKS(s) do { \ +#define DECLARE_LOCK_VARIABLE int __s +#define ACQUIRE_GLOBAL_LOCKS() do { \ KERNEL_LOCK(1, NULL); \ mutex_enter(softnet_lock); \ - s = splnet(); \ + __s = splnet(); \ } while (0) -#define RELEASE_GLOBAL_LOCKS(s) do { \ - splx(s); \ +#define RELEASE_GLOBAL_LOCKS() do { \ + splx(__s); \ mutex_exit(softnet_lock); \ KERNEL_UNLOCK_ONE(NULL); \ } while (0) #endif +struct psref_class *bridge_psref_class __read_mostly; + int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; static struct pool bridge_rtnode_pool; @@ -263,9 +267,9 @@ static void bridge_release_member(struct bridge_softc *, struct bridge_iflist *, struct psref *); static void bridge_delete_member(struct bridge_softc *, struct bridge_iflist *); -static struct bridge_iflist *bridge_try_hold_bif(struct bridge_softc *sc, - struct bridge_iflist *, - struct psref *); +static void bridge_acquire_member(struct bridge_softc *sc, + struct bridge_iflist *, + struct psref *); static int bridge_ioctl_add(struct bridge_softc *, void *); static int bridge_ioctl_del(struct bridge_softc *, void *); @@ -374,6 +378,8 @@ bridgeattach(int n) pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode), 0, 0, 0, "brtpl", NULL, IPL_NET); + bridge_psref_class = psref_class_create("bridge", IPL_SOFTNET); + if_clone_attach(&bridge_cloner); } @@ -400,7 +406,6 @@ bridge_clone_create(struct if_clone *ifc, int unit) sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME; sc->sc_filter_flags = 0; - sc->sc_dying = false; /* Initialize our routing table. */ bridge_rtable_init(sc); @@ -416,11 +421,6 @@ bridge_clone_create(struct if_clone *ifc, int unit) mutex_init(&sc->sc_iflist_psref.bip_lock, MUTEX_DEFAULT, IPL_NONE); PSLIST_INIT(&sc->sc_iflist_psref.bip_iflist); sc->sc_iflist_psref.bip_psz = pserialize_create(); - if (sc->sc_iflist_psref.bip_psz == NULL) - panic("%s: pserialize_create %d\n", __func__, error); - - sc->sc_iflist_psref.bip_class = - psref_class_create("if_bridge_cv", IPL_SOFTNET); if_initname(ifp, ifc->ifc_name, unit); ifp->if_softc = sc; @@ -457,7 +457,6 @@ bridge_clone_destroy(struct ifnet *ifp) s = splnet(); - sc->sc_dying = true; bridge_stop(ifp, 1); BRIDGE_LOCK(sc); @@ -640,7 +639,8 @@ bridge_lookup_member(struct bridge_softc *sc, const char *name, struct psref *ps if (strcmp(ifp->if_xname, name) == 0) break; } - bif = bridge_try_hold_bif(sc, bif, psref); + if (bif != NULL) + bridge_acquire_member(sc, bif, psref); BRIDGE_PSZ_REXIT(s); @@ -664,7 +664,7 @@ bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp, bif = member_ifp->if_bridgeif; if (bif != NULL) { psref_acquire(psref, &bif->bif_psref, - sc->sc_iflist_psref.bip_class); + bridge_psref_class); } BRIDGE_PSZ_REXIT(s); @@ -672,16 +672,12 @@ bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp, return bif; } -static struct bridge_iflist * -bridge_try_hold_bif(struct bridge_softc *sc, struct bridge_iflist *bif, +static void +bridge_acquire_member(struct bridge_softc *sc, struct bridge_iflist *bif, struct psref *psref) { - if (bif != NULL) { - psref_acquire(psref, &bif->bif_psref, - sc->sc_iflist_psref.bip_class); - } - return bif; + psref_acquire(psref, &bif->bif_psref, bridge_psref_class); } /* @@ -694,7 +690,7 @@ bridge_release_member(struct bridge_softc *sc, struct bridge_iflist *bif, struct psref *psref) { - psref_release(psref, &bif->bif_psref, sc->sc_iflist_psref.bip_class); + psref_release(psref, &bif->bif_psref, bridge_psref_class); } /* @@ -717,8 +713,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif) BRIDGE_PSZ_PERFORM(sc); BRIDGE_UNLOCK(sc); - psref_target_destroy(&bif->bif_psref, - sc->sc_iflist_psref.bip_class); + psref_target_destroy(&bif->bif_psref, bridge_psref_class); PSLIST_ENTRY_DESTROY(bif, bif_next); kmem_free(bif, sizeof(*bif)); @@ -734,9 +729,6 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) struct ifnet *ifs; int error = 0; - if (sc->sc_dying) - return ENOENT; - ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) return (ENOENT); @@ -780,7 +772,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; bif->bif_path_cost = BSTP_DEFAULT_PATH_COST; PSLIST_ENTRY_INIT(bif, bif_next); - psref_target_init(&bif->bif_psref, sc->sc_iflist_psref.bip_class); + psref_target_init(&bif->bif_psref, bridge_psref_class); BRIDGE_LOCK(sc); @@ -1467,9 +1459,8 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa, BRIDGE_PSZ_RENTER(s); BRIDGE_IFLIST_READER_FOREACH(bif, sc) { struct psref psref; - bif = bridge_try_hold_bif(sc, bif, &psref); - if (bif == NULL) - continue; + + bridge_acquire_member(sc, bif, &psref); BRIDGE_PSZ_REXIT(s); dst_if = bif->bif_ifp; @@ -1568,8 +1559,8 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m) struct bridge_iflist *bif; struct ifnet *src_if, *dst_if; struct ether_header *eh; - int s; struct psref psref; + DECLARE_LOCK_VARIABLE; if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return; @@ -1691,9 +1682,9 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m) bridge_release_member(sc, bif, &psref); - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); bridge_enqueue(sc, dst_if, m, 1); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); out: /* XXX gcc */ return; @@ -1743,22 +1734,23 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) struct ether_header *eh; int s; struct psref psref; + DECLARE_LOCK_VARIABLE; KASSERT(!cpu_intr_p()); if (__predict_false(sc == NULL) || (sc->sc_if.if_flags & IFF_RUNNING) == 0) { - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); return; } bif = bridge_lookup_member_if(sc, ifp, &psref); if (bif == NULL) { - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); return; } @@ -1786,7 +1778,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) BRIDGE_IFLIST_READER_FOREACH(_bif, sc) { /* It is destined for us. */ if (bridge_ourether(_bif, eh, 0)) { - _bif = bridge_try_hold_bif(sc, _bif, &_psref); + bridge_acquire_member(sc, _bif, &_psref); BRIDGE_PSZ_REXIT(s); if (_bif == NULL) goto out; @@ -1809,9 +1801,9 @@ out: bridge_release_member(sc, bif, &psref); if (_ifp != NULL) { m->m_flags &= ~M_PROMISC; - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); ether_input(_ifp, m); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); } else m_freem(m); return; @@ -1832,9 +1824,9 @@ out: */ if (bstp_state_before_learning(bif)) { bridge_release_member(sc, bif, &psref); - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); return; } @@ -1859,6 +1851,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, struct ifnet *dst_if; bool bmcast; int s; + DECLARE_LOCK_VARIABLE; bmcast = m->m_flags & (M_BCAST|M_MCAST); @@ -1866,9 +1859,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, BRIDGE_IFLIST_READER_FOREACH(bif, sc) { struct psref psref; - bif = bridge_try_hold_bif(sc, bif, &psref); - if (bif == NULL) - continue; + bridge_acquire_member(sc, bif, &psref); BRIDGE_PSZ_REXIT(s); dst_if = bif->bif_ifp; @@ -1893,9 +1884,9 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, sc->sc_if.if_oerrors++; goto next; } - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); bridge_enqueue(sc, dst_if, mc, 1); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); } if (bmcast) { @@ -1908,9 +1899,9 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, mc->m_pkthdr.rcvif = dst_if; mc->m_flags &= ~M_PROMISC; - ACQUIRE_GLOBAL_LOCKS(s); + ACQUIRE_GLOBAL_LOCKS(); ether_input(dst_if, mc); - RELEASE_GLOBAL_LOCKS(s); + RELEASE_GLOBAL_LOCKS(); } next: BRIDGE_PSZ_RENTER(s); diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 7e8bb9c..9fba1ff 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -287,7 +287,6 @@ struct bridge_iflist_psref { struct pslist_head bip_iflist; /* member interface list */ kmutex_t bip_lock; pserialize_t bip_psz; - struct psref_class *bip_class; }; /* @@ -328,7 +327,6 @@ struct bridge_softc { struct work sc_rtage_wk; uint32_t sc_rthash_key; /* key for hash */ uint32_t sc_filter_flags; /* ipf and flags */ - bool sc_dying; /* being destroyed */ }; extern const uint8_t bstp_etheraddr[];