Index: sys/net/if_bridge.c =================================================================== --- sys/net/if_bridge.c (revision 360985) +++ sys/net/if_bridge.c (working copy) @@ -165,6 +165,9 @@ #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60) #endif +#define NET_EPOCH_ASSERT() MPASS(in_epoch(net_epoch_preempt)) +#define NET_EPOCH_CALL(f, c) epoch_call(net_epoch_preempt, (c), (f)) + /* * List of capabilities to possibly mask on the member interface. */ @@ -188,6 +191,7 @@ uint32_t bif_addrmax; /* max # of addresses */ uint32_t bif_addrcnt; /* cur. # of addresses */ uint32_t bif_addrexceeded;/* # of address violations */ + struct epoch_context bif_epoch_ctx; }; /* @@ -201,6 +205,8 @@ uint8_t brt_flags; /* address flags */ uint8_t brt_addr[ETHER_ADDR_LEN]; uint16_t brt_vlan; /* vlan id */ + struct vnet *brt_vnet; + struct epoch_context brt_epoch_ctx; }; #define brt_ifp brt_dst->bif_ifp @@ -211,13 +217,10 @@ struct ifnet *sc_ifp; /* make this an interface */ LIST_ENTRY(bridge_softc) sc_list; struct mtx sc_mtx; - struct cv sc_cv; uint32_t sc_brtmax; /* max # of addresses */ uint32_t sc_brtcnt; /* cur. # of addresses */ uint32_t sc_brttimeout; /* rt timeout in seconds */ struct callout sc_brcallout; /* bridge callout */ - uint32_t sc_iflist_ref; /* refcount for sc_iflist */ - uint32_t sc_iflist_xcnt; /* refcount for sc_iflist */ LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */ LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */ LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */ @@ -227,6 +230,7 @@ uint32_t sc_brtexceeded; /* # of cache drops */ struct ifnet *sc_ifaddr; /* member mac copied from */ struct ether_addr sc_defaddr; /* Default MAC address */ + struct epoch_context sc_epoch_ctx; }; VNET_DEFINE_STATIC(struct mtx, bridge_list_mtx); @@ -546,6 +550,10 @@ if_clone_detach(V_bridge_cloner); V_bridge_cloner = NULL; BRIDGE_LIST_LOCK_DESTROY(); + + /* Callbacks may use UMA zone. */ + epoch_drain_callbacks(net_epoch_preempt); + uma_zdestroy(V_bridge_rtnode_zone); } VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, @@ -708,6 +716,17 @@ return (0); } +static void +bridge_clone_destroy_cb(struct epoch_context *ctx) +{ + struct bridge_softc *sc; + + sc = __containerof(ctx, struct bridge_softc, sc_epoch_ctx); + + BRIDGE_LOCK_DESTROY(sc); + free(sc, M_DEVBUF); +} + /* * bridge_clone_destroy: * @@ -718,7 +737,9 @@ { struct bridge_softc *sc = ifp->if_softc; struct bridge_iflist *bif; + struct epoch_tracker et; + NET_EPOCH_ENTER_ET(et); BRIDGE_LOCK(sc); bridge_stop(ifp, 1); @@ -743,11 +764,12 @@ BRIDGE_LIST_UNLOCK(); bstp_detach(&sc->sc_stp); + NET_EPOCH_EXIT_ET(et); + ether_ifdetach(ifp); if_free(ifp); - BRIDGE_LOCK_DESTROY(sc); - free(sc, M_DEVBUF); + NET_EPOCH_CALL(bridge_clone_destroy_cb, &sc->sc_epoch_ctx); } /* @@ -773,7 +795,10 @@ struct ifdrv *ifd = (struct ifdrv *) data; const struct bridge_control *bc; int error = 0; + struct epoch_tracker et; + NET_EPOCH_ENTER_ET(et); + switch (cmd) { case SIOCADDMULTI: @@ -882,6 +907,8 @@ break; } + NET_EPOCH_EXIT_ET(et); + return (error); } @@ -896,6 +923,8 @@ struct bridge_iflist *bif; int enabled, mask; + BRIDGE_LOCK_ASSERT(sc); + /* Initial bitmask of capabilities to test */ mask = BRIDGE_IFCAPS_MASK; @@ -904,7 +933,6 @@ mask &= bif->bif_savedcaps; } - BRIDGE_XLOCK(sc); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { enabled = bif->bif_ifp->if_capenable; enabled &= ~BRIDGE_IFCAPS_STRIP; @@ -915,8 +943,6 @@ bridge_set_ifcap(sc, bif, enabled); BRIDGE_LOCK(sc); } - BRIDGE_XDROP(sc); - } static void @@ -957,7 +983,7 @@ struct bridge_iflist *bif; struct ifnet *ifp; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { ifp = bif->bif_ifp; @@ -978,7 +1004,7 @@ { struct bridge_iflist *bif; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (bif->bif_ifp == member_ifp) @@ -988,6 +1014,16 @@ return (NULL); } +static void +bridge_delete_member_cb(struct epoch_context *ctx) +{ + struct bridge_iflist *bif; + + bif = __containerof(ctx, struct bridge_iflist, bif_epoch_ctx); + + free(bif, M_DEVBUF); +} + /* * bridge_delete_member: * @@ -1006,9 +1042,7 @@ bstp_disable(&bif->bif_stp); ifs->if_bridge = NULL; - BRIDGE_XLOCK(sc); LIST_REMOVE(bif, bif_next); - BRIDGE_XDROP(sc); /* * If removing the interface that gave the bridge its mac address, set @@ -1066,7 +1100,8 @@ } bstp_destroy(&bif->bif_stp); /* prepare to free */ BRIDGE_LOCK(sc); - free(bif, M_DEVBUF); + + NET_EPOCH_CALL(bridge_delete_member_cb, &bif->bif_epoch_ctx); } /* @@ -1083,7 +1118,8 @@ ("%s: not a span interface", __func__)); LIST_REMOVE(bif, bif_next); - free(bif, M_DEVBUF); + + NET_EPOCH_CALL(bridge_delete_member_cb, &bif->bif_epoch_ctx); } static int @@ -1139,7 +1175,6 @@ * If any, remove all inet6 addresses from the member * interfaces. */ - BRIDGE_XLOCK(sc); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (in6ifa_llaonifp(bif->bif_ifp)) { BRIDGE_UNLOCK(sc); @@ -1152,7 +1187,6 @@ bif->bif_ifp->if_xname); } } - BRIDGE_XDROP(sc); if (in6ifa_llaonifp(ifs)) { BRIDGE_UNLOCK(sc); in6_ifdetach(ifs); @@ -1466,12 +1500,17 @@ struct bridge_iflist *bif; int error; + NET_EPOCH_ASSERT(); + bif = bridge_lookup_member(sc, req->ifba_ifsname); if (bif == NULL) return (ENOENT); + /* bridge_rtupdate() may acquire the lock. */ + BRIDGE_UNLOCK(sc); error = bridge_rtupdate(sc, req->ifba_dst, req->ifba_vlan, bif, 1, req->ifba_flags); + BRIDGE_LOCK(sc); return (error); } @@ -1810,6 +1849,7 @@ { struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif; + struct epoch_tracker et; if (ifp->if_flags & IFF_RENAMING) return; @@ -1820,6 +1860,7 @@ */ return; } + NET_EPOCH_ENTER_ET(et); /* Check if the interface is a bridge member */ if (sc != NULL) { BRIDGE_LOCK(sc); @@ -1829,6 +1870,7 @@ bridge_delete_member(sc, bif, 1); BRIDGE_UNLOCK(sc); + NET_EPOCH_EXIT_ET(et); return; } @@ -1845,6 +1887,7 @@ BRIDGE_UNLOCK(sc); } BRIDGE_LIST_UNLOCK(); + NET_EPOCH_EXIT_ET(et); } /* @@ -1881,6 +1924,7 @@ { struct bridge_softc *sc = ifp->if_softc; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) @@ -2004,6 +2048,8 @@ struct bridge_softc *sc; uint16_t vlan; + NET_EPOCH_ASSERT(); + if (m->m_len < ETHER_HDR_LEN) { m = m_pullup(m, ETHER_HDR_LEN); if (m == NULL) @@ -2014,8 +2060,6 @@ sc = ifp->if_bridge; vlan = VLANTAGOF(m); - BRIDGE_LOCK(sc); - /* * If bridge is down, but the original output interface is up, * go ahead and send out that interface. Otherwise, the packet @@ -2037,16 +2081,10 @@ if (dst_if == NULL) { struct bridge_iflist *bif; struct mbuf *mc; - int error = 0, used = 0; + int used = 0; bridge_span(sc, m); - BRIDGE_LOCK2REF(sc, error); - if (error) { - m_freem(m); - return (0); - } - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { dst_if = bif->bif_ifp; @@ -2080,7 +2118,6 @@ } if (used == 0) m_freem(m); - BRIDGE_UNREF(sc); return (0); } @@ -2092,11 +2129,9 @@ bridge_span(sc, m); if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0) { m_freem(m); - BRIDGE_UNLOCK(sc); return (0); } - BRIDGE_UNLOCK(sc); bridge_enqueue(sc, dst_if, m); return (0); } @@ -2121,10 +2156,8 @@ eh = mtod(m, struct ether_header *); - BRIDGE_LOCK(sc); if (((m->m_flags & (M_BCAST|M_MCAST)) == 0) && (dst_if = bridge_rtlookup(sc, eh->ether_dhost, 1)) != NULL) { - BRIDGE_UNLOCK(sc); error = bridge_enqueue(sc, dst_if, m); } else bridge_broadcast(sc, ifp, m, 0); @@ -2158,6 +2191,8 @@ uint8_t *dst; int error; + NET_EPOCH_ASSERT(); + src_if = m->m_pkthdr.rcvif; ifp = sc->sc_ifp; @@ -2236,12 +2271,10 @@ || PFIL_HOOKED(&V_inet6_pfil_hook) #endif ) { - BRIDGE_UNLOCK(sc); if (bridge_pfil(&m, ifp, src_if, PFIL_IN) != 0) return; if (m == NULL) return; - BRIDGE_LOCK(sc); } if (dst_if == NULL) { @@ -2269,8 +2302,6 @@ dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) goto drop; - BRIDGE_UNLOCK(sc); - if (PFIL_HOOKED(&V_inet_pfil_hook) #ifdef INET6 || PFIL_HOOKED(&V_inet6_pfil_hook) @@ -2286,7 +2317,6 @@ return; drop: - BRIDGE_UNLOCK(sc); m_freem(m); } @@ -2307,6 +2337,8 @@ uint16_t vlan; int error; + NET_EPOCH_ASSERT(); + if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return (m); @@ -2327,10 +2359,8 @@ m_freem(m); return (NULL); } - BRIDGE_LOCK(sc); bif = bridge_lookup_member_if(sc, ifp); if (bif == NULL) { - BRIDGE_UNLOCK(sc); return (m); } @@ -2343,13 +2373,11 @@ if (memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) { bstp_input(&bif->bif_stp, ifp, m); /* consumes mbuf */ - BRIDGE_UNLOCK(sc); return (NULL); } if ((bif->bif_flags & IFBIF_STP) && bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) { - BRIDGE_UNLOCK(sc); return (m); } @@ -2360,7 +2388,6 @@ */ mc = m_dup(m, M_NOWAIT); if (mc == NULL) { - BRIDGE_UNLOCK(sc); return (m); } @@ -2392,7 +2419,6 @@ if ((bif->bif_flags & IFBIF_STP) && bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) { - BRIDGE_UNLOCK(sc); return (m); } @@ -2432,7 +2458,6 @@ OR_PFIL_HOOKED_INET6)) { \ if (bridge_pfil(&m, NULL, ifp, \ PFIL_IN) != 0 || m == NULL) { \ - BRIDGE_UNLOCK(sc); \ return (NULL); \ } \ eh = mtod(m, struct ether_header *); \ @@ -2442,13 +2467,11 @@ error = bridge_rtupdate(sc, eh->ether_shost, \ vlan, bif, 0, IFBAF_DYNAMIC); \ if (error && bif->bif_addrmax) { \ - BRIDGE_UNLOCK(sc); \ m_freem(m); \ return (NULL); \ } \ } \ m->m_pkthdr.rcvif = iface; \ - BRIDGE_UNLOCK(sc); \ return (m); \ } \ \ @@ -2456,7 +2479,6 @@ if (memcmp(IF_LLADDR((iface)), eh->ether_shost, ETHER_ADDR_LEN) == 0 \ OR_CARP_CHECK_WE_ARE_SRC((iface)) \ ) { \ - BRIDGE_UNLOCK(sc); \ m_freem(m); \ return (NULL); \ } @@ -2507,16 +2529,12 @@ struct bridge_iflist *dbif, *sbif; struct mbuf *mc; struct ifnet *dst_if; - int error = 0, used = 0, i; + int used = 0, i; + NET_EPOCH_ASSERT(); + sbif = bridge_lookup_member_if(sc, src_if); - BRIDGE_LOCK2REF(sc, error); - if (error) { - m_freem(m); - return; - } - /* Filter on the bridge interface before broadcasting */ if (runfilt && (PFIL_HOOKED(&V_inet_pfil_hook) #ifdef INET6 @@ -2524,9 +2542,9 @@ #endif )) { if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0) - goto out; + return; if (m == NULL) - goto out; + return; } LIST_FOREACH(dbif, &sc->sc_iflist, bif_next) { @@ -2589,9 +2607,6 @@ } if (used == 0) m_freem(m); - -out: - BRIDGE_UNREF(sc); } /* @@ -2607,6 +2622,8 @@ struct ifnet *dst_if; struct mbuf *mc; + NET_EPOCH_ASSERT(); + if (LIST_EMPTY(&sc->sc_spanlist)) return; @@ -2638,7 +2655,8 @@ struct bridge_rtnode *brt; int error; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); + BRIDGE_UNLOCK_ASSERT(sc); /* Check the source address is valid and not multicast. */ if (ETHER_IS_MULTICAST(dst) || @@ -2655,13 +2673,24 @@ * update it, otherwise create a new one. */ if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) == NULL) { + BRIDGE_LOCK(sc); + + /* Check again, now that we have the lock. There could have + * been a race and we only want to insert this once. */ + if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) != NULL) { + BRIDGE_UNLOCK(sc); + return (0); + } + if (sc->sc_brtcnt >= sc->sc_brtmax) { sc->sc_brtexceeded++; + BRIDGE_UNLOCK(sc); return (ENOSPC); } /* Check per interface address limits (if enabled) */ if (bif->bif_addrmax && bif->bif_addrcnt >= bif->bif_addrmax) { bif->bif_addrexceeded++; + BRIDGE_UNLOCK(sc); return (ENOSPC); } @@ -2671,8 +2700,11 @@ * address. */ brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO); - if (brt == NULL) + if (brt == NULL) { + BRIDGE_UNLOCK(sc); return (ENOMEM); + } + brt->brt_vnet = curvnet; if (bif->bif_flags & IFBIF_STICKY) brt->brt_flags = IFBAF_STICKY; @@ -2684,17 +2716,22 @@ if ((error = bridge_rtnode_insert(sc, brt)) != 0) { uma_zfree(V_bridge_rtnode_zone, brt); + BRIDGE_UNLOCK(sc); return (error); } brt->brt_dst = bif; bif->bif_addrcnt++; + + BRIDGE_UNLOCK(sc); } if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC && brt->brt_dst != bif) { + BRIDGE_LOCK(sc); brt->brt_dst->bif_addrcnt--; brt->brt_dst = bif; brt->brt_dst->bif_addrcnt++; + BRIDGE_UNLOCK(sc); } if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) @@ -2715,7 +2752,7 @@ { struct bridge_rtnode *brt; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); if ((brt = bridge_rtnode_lookup(sc, addr, vlan)) == NULL) return (NULL); @@ -2735,6 +2772,7 @@ { struct bridge_rtnode *brt, *nbrt; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); /* Make sure we actually need to do this. */ @@ -2764,7 +2802,9 @@ bridge_timer(void *arg) { struct bridge_softc *sc = arg; + struct epoch_tracker et; + NET_EPOCH_ENTER_ET(et); BRIDGE_LOCK_ASSERT(sc); /* Destruction of rtnodes requires a proper vnet context */ @@ -2775,6 +2815,7 @@ callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz, bridge_timer, sc); CURVNET_RESTORE(); + NET_EPOCH_EXIT_ET(et); } /* @@ -2787,6 +2828,7 @@ { struct bridge_rtnode *brt, *nbrt; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { @@ -2807,6 +2849,7 @@ { struct bridge_rtnode *brt, *nbrt; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { @@ -2826,6 +2869,7 @@ struct bridge_rtnode *brt; int found = 0; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); /* @@ -2850,6 +2894,7 @@ { struct bridge_rtnode *brt, *nbrt; + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) { @@ -2954,7 +2999,7 @@ uint32_t hash; int dir; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); hash = bridge_rthash(sc, addr); LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { @@ -3017,6 +3062,18 @@ return (0); } +static void +bridge_rtnode_destroy_cb(struct epoch_context *ctx) +{ + struct bridge_rtnode *brt; + + brt = __containerof(ctx, struct bridge_rtnode, brt_epoch_ctx); + + CURVNET_SET(brt->brt_vnet); + uma_zfree(V_bridge_rtnode_zone, brt); + CURVNET_RESTORE(); +} + /* * bridge_rtnode_destroy: * @@ -3025,6 +3082,7 @@ static void bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt) { + NET_EPOCH_ASSERT(); BRIDGE_LOCK_ASSERT(sc); LIST_REMOVE(brt, brt_hash); @@ -3032,7 +3090,8 @@ LIST_REMOVE(brt, brt_list); sc->sc_brtcnt--; brt->brt_dst->bif_addrcnt--; - uma_zfree(V_bridge_rtnode_zone, brt); + + NET_EPOCH_CALL(bridge_rtnode_destroy_cb, &brt->brt_epoch_ctx); } /* @@ -3045,7 +3104,9 @@ { struct bridge_softc *sc = ifp->if_bridge; struct bridge_rtnode *brt; + struct epoch_tracker et; + NET_EPOCH_ENTER_ET(et); CURVNET_SET(ifp->if_vnet); BRIDGE_LOCK(sc); @@ -3066,6 +3127,7 @@ } BRIDGE_UNLOCK(sc); CURVNET_RESTORE(); + NET_EPOCH_EXIT_ET(et); } /* @@ -3577,17 +3639,20 @@ { struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif; + struct epoch_tracker et; - BRIDGE_LOCK(sc); + NET_EPOCH_ENTER_ET(et); + bif = bridge_lookup_member_if(sc, ifp); if (bif == NULL) { - BRIDGE_UNLOCK(sc); + NET_EPOCH_EXIT_ET(et); return; } bridge_linkcheck(sc); - BRIDGE_UNLOCK(sc); bstp_linkstate(&bif->bif_stp); + + NET_EPOCH_EXIT_ET(et); } static void @@ -3596,7 +3661,8 @@ struct bridge_iflist *bif; int new_link, hasls; - BRIDGE_LOCK_ASSERT(sc); + NET_EPOCH_ASSERT(); + new_link = LINK_STATE_DOWN; hasls = 0; /* Our link is considered up if at least one of our ports is active */ Index: sys/net/if_bridgevar.h =================================================================== --- sys/net/if_bridgevar.h (revision 360985) +++ sys/net/if_bridgevar.h (working copy) @@ -273,41 +273,14 @@ #define BRIDGE_LOCK_INIT(_sc) do { \ mtx_init(&(_sc)->sc_mtx, "if_bridge", NULL, MTX_DEF); \ - cv_init(&(_sc)->sc_cv, "if_bridge_cv"); \ } while (0) #define BRIDGE_LOCK_DESTROY(_sc) do { \ mtx_destroy(&(_sc)->sc_mtx); \ - cv_destroy(&(_sc)->sc_cv); \ } while (0) #define BRIDGE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define BRIDGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define BRIDGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) #define BRIDGE_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED) -#define BRIDGE_LOCK2REF(_sc, _err) do { \ - mtx_assert(&(_sc)->sc_mtx, MA_OWNED); \ - if ((_sc)->sc_iflist_xcnt > 0) \ - (_err) = EBUSY; \ - else \ - (_sc)->sc_iflist_ref++; \ - mtx_unlock(&(_sc)->sc_mtx); \ -} while (0) -#define BRIDGE_UNREF(_sc) do { \ - mtx_lock(&(_sc)->sc_mtx); \ - (_sc)->sc_iflist_ref--; \ - if (((_sc)->sc_iflist_xcnt > 0) && ((_sc)->sc_iflist_ref == 0)) \ - cv_broadcast(&(_sc)->sc_cv); \ - mtx_unlock(&(_sc)->sc_mtx); \ -} while (0) -#define BRIDGE_XLOCK(_sc) do { \ - mtx_assert(&(_sc)->sc_mtx, MA_OWNED); \ - (_sc)->sc_iflist_xcnt++; \ - while ((_sc)->sc_iflist_ref > 0) \ - cv_wait(&(_sc)->sc_cv, &(_sc)->sc_mtx); \ -} while (0) -#define BRIDGE_XDROP(_sc) do { \ - mtx_assert(&(_sc)->sc_mtx, MA_OWNED); \ - (_sc)->sc_iflist_xcnt--; \ -} while (0) #define BRIDGE_INPUT(_ifp, _m) do { \ KASSERT((_ifp)->if_bridge_input != NULL, \