From owner-svn-src-all@freebsd.org Sun Jul 26 17:44:03 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E530B366A77; Sun, 26 Jul 2020 17:44:03 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BF9Kb69sfz3b4h; Sun, 26 Jul 2020 17:44:03 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id B801210A0E; Sun, 26 Jul 2020 17:44:03 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 06QHi3Yi011160; Sun, 26 Jul 2020 17:44:03 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06QHi3iB011159; Sun, 26 Jul 2020 17:44:03 GMT (envelope-from kp@FreeBSD.org) Message-Id: <202007261744.06QHi3iB011159@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Sun, 26 Jul 2020 17:44:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r363568 - stable/12/sys/net X-SVN-Group: stable-12 X-SVN-Commit-Author: kp X-SVN-Commit-Paths: stable/12/sys/net X-SVN-Commit-Revision: 363568 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 26 Jul 2020 17:44:04 -0000 Author: kp Date: Sun Jul 26 17:44:03 2020 New Revision: 363568 URL: https://svnweb.freebsd.org/changeset/base/363568 Log: Revert bridge epochification Revert r363492, r363491, r363430, r363429 and r362650. The introduction of epoch in the network stack is incomplete in stable/12, and there are simply too many limitations to make the bridge epoch code work there. The final problem is capability configuration of the bridge member interfaces. if_bridge needs to enable promiscuous mode, which for certain drivers (e1000 for example) can sleep. In stable/12 we may not sleep within epoch. Modified: stable/12/sys/net/if_bridge.c Modified: stable/12/sys/net/if_bridge.c ============================================================================== --- stable/12/sys/net/if_bridge.c Sun Jul 26 17:21:24 2020 (r363567) +++ stable/12/sys/net/if_bridge.c Sun Jul 26 17:44:03 2020 (r363568) @@ -189,14 +189,41 @@ extern void nd6_setmtu(struct ifnet *); */ #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) /* * Bridge interface list entry. @@ -210,8 +237,6 @@ struct bridge_iflist { 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; }; /* @@ -225,9 +250,6 @@ struct bridge_rtnode { 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 @@ -238,10 +260,13 @@ struct bridge_softc { 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 */ CK_LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */ CK_LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */ CK_LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */ @@ -251,8 +276,6 @@ struct bridge_softc { 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); @@ -572,11 +595,6 @@ vnet_bridge_uninit(const void *unused __unused) if_clone_detach(V_bridge_cloner); V_bridge_cloner = NULL; BRIDGE_LIST_LOCK_DESTROY(); - - /* Before we can destroy the uma zone, because there are callbacks that - * use it. */ - epoch_drain_callbacks(net_epoch_preempt); - uma_zdestroy(V_bridge_rtnode_zone); } VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, @@ -739,17 +757,6 @@ bridge_clone_create(struct if_clone *ifc, int unit, ca 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: * @@ -760,9 +767,7 @@ bridge_clone_destroy(struct ifnet *ifp) { 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); @@ -787,12 +792,11 @@ bridge_clone_destroy(struct ifnet *ifp) BRIDGE_LIST_UNLOCK(); bstp_detach(&sc->sc_stp); - NET_EPOCH_EXIT_ET(et); - ether_ifdetach(ifp); if_free(ifp); - epoch_call(net_epoch_preempt, &sc->sc_epoch_ctx, bridge_clone_destroy_cb); + BRIDGE_LOCK_DESTROY(sc); + free(sc, M_DEVBUF); } /* @@ -818,10 +822,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t da struct ifdrv *ifd = (struct ifdrv *) data; const struct bridge_control *bc; int error = 0, oldmtu; - struct epoch_tracker et; - NET_EPOCH_ENTER_ET(et); - switch (cmd) { case SIOCADDMULTI: @@ -942,8 +943,6 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t da break; } - NET_EPOCH_EXIT_ET(et); - return (error); } @@ -958,8 +957,6 @@ bridge_mutecaps(struct bridge_softc *sc) struct bridge_iflist *bif; int enabled, mask; - BRIDGE_LOCK_ASSERT(sc); - /* Initial bitmask of capabilities to test */ mask = BRIDGE_IFCAPS_MASK; @@ -968,6 +965,7 @@ bridge_mutecaps(struct bridge_softc *sc) mask &= bif->bif_savedcaps; } + BRIDGE_XLOCK(sc); CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { enabled = bif->bif_ifp->if_capenable; enabled &= ~BRIDGE_IFCAPS_STRIP; @@ -978,6 +976,8 @@ bridge_mutecaps(struct bridge_softc *sc) bridge_set_ifcap(sc, bif, enabled); BRIDGE_LOCK(sc); } + BRIDGE_XDROP(sc); + } static void @@ -1018,7 +1018,7 @@ bridge_lookup_member(struct bridge_softc *sc, const ch struct bridge_iflist *bif; struct ifnet *ifp; - MPASS(in_epoch(net_epoch_preempt)); + BRIDGE_LOCK_ASSERT(sc); CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { ifp = bif->bif_ifp; @@ -1039,7 +1039,7 @@ bridge_lookup_member_if(struct bridge_softc *sc, struc { struct bridge_iflist *bif; - MPASS(in_epoch(net_epoch_preempt)); + BRIDGE_LOCK_ASSERT(sc); CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (bif->bif_ifp == member_ifp) @@ -1049,16 +1049,6 @@ bridge_lookup_member_if(struct bridge_softc *sc, struc 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: * @@ -1078,7 +1068,9 @@ bridge_delete_member(struct bridge_softc *sc, struct b bstp_disable(&bif->bif_stp); ifs->if_bridge = NULL; + BRIDGE_XLOCK(sc); CK_LIST_REMOVE(bif, bif_next); + BRIDGE_XDROP(sc); /* * If removing the interface that gave the bridge its mac address, set @@ -1137,9 +1129,7 @@ bridge_delete_member(struct bridge_softc *sc, struct b } bstp_destroy(&bif->bif_stp); /* prepare to free */ BRIDGE_LOCK(sc); - - epoch_call(net_epoch_preempt, &bif->bif_epoch_ctx, - bridge_delete_member_cb); + free(bif, M_DEVBUF); } /* @@ -1156,9 +1146,7 @@ bridge_delete_span(struct bridge_softc *sc, struct bri ("%s: not a span interface", __func__)); CK_LIST_REMOVE(bif, bif_next); - - epoch_call(net_epoch_preempt, &bif->bif_epoch_ctx, - bridge_delete_member_cb); + free(bif, M_DEVBUF); } static int @@ -1214,6 +1202,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * If any, remove all inet6 addresses from the member * interfaces. */ + BRIDGE_XLOCK(sc); CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { if (in6ifa_llaonifp(bif->bif_ifp)) { BRIDGE_UNLOCK(sc); @@ -1226,6 +1215,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) bif->bif_ifp->if_xname); } } + BRIDGE_XDROP(sc); if (in6ifa_llaonifp(ifs)) { BRIDGE_UNLOCK(sc); in6_ifdetach(ifs); @@ -1434,9 +1424,9 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) bifc->ifbic_len = buflen; return (0); } - outbuf = malloc(buflen, M_TEMP, M_NOWAIT | M_ZERO); - if (outbuf == NULL) - return (ENOMEM); + BRIDGE_UNLOCK(sc); + outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + BRIDGE_LOCK(sc); count = 0; buf = outbuf; @@ -1496,9 +1486,9 @@ bridge_ioctl_rts(struct bridge_softc *sc, void *arg) count++; buflen = sizeof(bareq) * count; - outbuf = malloc(buflen, M_TEMP, M_NOWAIT | M_ZERO); - if (outbuf == NULL) - return (ENOMEM); + BRIDGE_UNLOCK(sc); + outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + BRIDGE_LOCK(sc); count = 0; buf = outbuf; @@ -1539,17 +1529,12 @@ bridge_ioctl_saddr(struct bridge_softc *sc, void *arg) struct bridge_iflist *bif; int error; - MPASS(in_epoch(net_epoch_preempt)); - 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); } @@ -1824,9 +1809,9 @@ bridge_ioctl_gifsstp(struct bridge_softc *sc, void *ar return (0); } - outbuf = malloc(buflen, M_TEMP, M_NOWAIT | M_ZERO); - if (outbuf == NULL) - return (ENOMEM); + BRIDGE_UNLOCK(sc); + outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); + BRIDGE_LOCK(sc); count = 0; buf = outbuf; @@ -1888,7 +1873,6 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp) { struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif; - struct epoch_tracker et; if (ifp->if_flags & IFF_RENAMING) return; @@ -1899,7 +1883,6 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp) */ return; } - NET_EPOCH_ENTER_ET(et); /* Check if the interface is a bridge member */ if (sc != NULL) { BRIDGE_LOCK(sc); @@ -1909,7 +1892,6 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp) bridge_delete_member(sc, bif, 1); BRIDGE_UNLOCK(sc); - NET_EPOCH_EXIT_ET(et); return; } @@ -1926,7 +1908,6 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp) BRIDGE_UNLOCK(sc); } BRIDGE_LIST_UNLOCK(); - NET_EPOCH_EXIT_ET(et); } /* @@ -2081,26 +2062,23 @@ static int bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, struct rtentry *rt) { - struct epoch_tracker et; struct ether_header *eh; struct ifnet *dst_if; struct bridge_softc *sc; uint16_t vlan; - NET_EPOCH_ENTER_ET(et); - if (m->m_len < ETHER_HDR_LEN) { m = m_pullup(m, ETHER_HDR_LEN); - if (m == NULL) { - NET_EPOCH_EXIT_ET(et); + if (m == NULL) return (0); - } } eh = mtod(m, struct ether_header *); 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 @@ -2122,10 +2100,16 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struc if (dst_if == NULL) { struct bridge_iflist *bif; struct mbuf *mc; - int used = 0; + int error = 0, used = 0; bridge_span(sc, m); + BRIDGE_LOCK2REF(sc, error); + if (error) { + m_freem(m); + return (0); + } + CK_LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { dst_if = bif->bif_ifp; @@ -2159,7 +2143,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struc } if (used == 0) m_freem(m); - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNREF(sc); return (0); } @@ -2171,12 +2155,12 @@ sendunicast: bridge_span(sc, m); if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0) { m_freem(m); - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (0); } + BRIDGE_UNLOCK(sc); bridge_enqueue(sc, dst_if, m); - NET_EPOCH_EXIT_ET(et); return (0); } @@ -2189,28 +2173,25 @@ sendunicast: static int bridge_transmit(struct ifnet *ifp, struct mbuf *m) { - struct epoch_tracker et; struct bridge_softc *sc; struct ether_header *eh; struct ifnet *dst_if; int error = 0; - NET_EPOCH_ENTER_ET(et); - sc = ifp->if_softc; ETHER_BPF_MTAP(ifp, m); 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); - NET_EPOCH_EXIT_ET(et); - return (error); } @@ -2240,8 +2221,6 @@ bridge_forward(struct bridge_softc *sc, struct bridge_ uint8_t *dst; int error; - MPASS(in_epoch(net_epoch_preempt)); - src_if = m->m_pkthdr.rcvif; ifp = sc->sc_ifp; @@ -2320,10 +2299,12 @@ bridge_forward(struct bridge_softc *sc, struct bridge_ || 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) { @@ -2351,6 +2332,8 @@ bridge_forward(struct bridge_softc *sc, struct bridge_ 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) @@ -2366,6 +2349,7 @@ bridge_forward(struct bridge_softc *sc, struct bridge_ return; drop: + BRIDGE_UNLOCK(sc); m_freem(m); } @@ -2378,7 +2362,6 @@ drop: static struct mbuf * bridge_input(struct ifnet *ifp, struct mbuf *m) { - struct epoch_tracker et; struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif, *bif2; struct ifnet *bifp; @@ -2387,12 +2370,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) uint16_t vlan; int error; - NET_EPOCH_ENTER_ET(et); - - if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - NET_EPOCH_EXIT_ET(et); + if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return (m); - } bifp = sc->sc_ifp; vlan = VLANTAGOF(m); @@ -2409,12 +2388,12 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) if_inc_counter(bifp, IFCOUNTER_IPACKETS, 1); if_inc_counter(bifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); m_freem(m); - NET_EPOCH_EXIT_ET(et); return (NULL); } + BRIDGE_LOCK(sc); bif = bridge_lookup_member_if(sc, ifp); if (bif == NULL) { - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (m); } @@ -2427,13 +2406,13 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) if (memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) { bstp_input(&bif->bif_stp, ifp, m); /* consumes mbuf */ - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (NULL); } if ((bif->bif_flags & IFBIF_STP) && bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) { - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (m); } @@ -2444,7 +2423,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) */ mc = m_dup(m, M_NOWAIT); if (mc == NULL) { - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (m); } @@ -2471,13 +2450,12 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) } /* Return the original packet for local processing. */ - NET_EPOCH_EXIT_ET(et); return (m); } if ((bif->bif_flags & IFBIF_STP) && bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) { - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return (m); } @@ -2517,6 +2495,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) 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 *); \ @@ -2526,13 +2505,13 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) error = bridge_rtupdate(sc, eh->ether_shost, \ vlan, bif, 0, IFBAF_DYNAMIC); \ if (error && bif->bif_addrmax) { \ + BRIDGE_UNLOCK(sc); \ m_freem(m); \ - NET_EPOCH_EXIT_ET(et); \ return (NULL); \ } \ } \ m->m_pkthdr.rcvif = iface; \ - NET_EPOCH_EXIT_ET(et); \ + BRIDGE_UNLOCK(sc); \ return (m); \ } \ \ @@ -2540,8 +2519,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) 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); \ - NET_EPOCH_EXIT_ET(et); \ return (NULL); \ } @@ -2572,7 +2551,6 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) /* Perform the bridge forwarding function. */ bridge_forward(sc, bif, m); - NET_EPOCH_EXIT_ET(et); return (NULL); } @@ -2592,12 +2570,16 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet struct bridge_iflist *dbif, *sbif; struct mbuf *mc; struct ifnet *dst_if; - int used = 0, i; + int error = 0, used = 0, i; - MPASS(in_epoch(net_epoch_preempt)); - 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 @@ -2605,9 +2587,9 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet #endif )) { if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0) - return; + goto out; if (m == NULL) - return; + goto out; } CK_LIST_FOREACH(dbif, &sc->sc_iflist, bif_next) { @@ -2670,6 +2652,9 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet } if (used == 0) m_freem(m); + +out: + BRIDGE_UNREF(sc); } /* @@ -2685,8 +2670,6 @@ bridge_span(struct bridge_softc *sc, struct mbuf *m) struct ifnet *dst_if; struct mbuf *mc; - MPASS(in_epoch(net_epoch_preempt)); - if (CK_LIST_EMPTY(&sc->sc_spanlist)) return; @@ -2718,8 +2701,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t struct bridge_rtnode *brt; int error; - MPASS(in_epoch(net_epoch_preempt)); - BRIDGE_UNLOCK_ASSERT(sc); + BRIDGE_LOCK_ASSERT(sc); /* Check the source address is valid and not multicast. */ if (ETHER_IS_MULTICAST(dst) || @@ -2736,24 +2718,13 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t * 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); } @@ -2763,11 +2734,8 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t * address. */ brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO); - if (brt == NULL) { - BRIDGE_UNLOCK(sc); + if (brt == NULL) return (ENOMEM); - } - brt->brt_vnet = curvnet; if (bif->bif_flags & IFBIF_STICKY) brt->brt_flags = IFBAF_STICKY; @@ -2779,22 +2747,17 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t 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) @@ -2815,7 +2778,7 @@ bridge_rtlookup(struct bridge_softc *sc, const uint8_t { struct bridge_rtnode *brt; - MPASS(in_epoch(net_epoch_preempt)); + BRIDGE_LOCK_ASSERT(sc); if ((brt = bridge_rtnode_lookup(sc, addr, vlan)) == NULL) return (NULL); @@ -3054,7 +3017,7 @@ bridge_rtnode_lookup(struct bridge_softc *sc, const ui uint32_t hash; int dir; - MPASS(in_epoch(net_epoch_preempt)); + BRIDGE_LOCK_ASSERT(sc); hash = bridge_rthash(sc, addr); CK_LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { @@ -3117,18 +3080,6 @@ out: 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: * @@ -3144,9 +3095,7 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct CK_LIST_REMOVE(brt, brt_list); sc->sc_brtcnt--; brt->brt_dst->bif_addrcnt--; - - epoch_call(net_epoch_preempt, &brt->brt_epoch_ctx, - bridge_rtnode_destroy_cb); + uma_zfree(V_bridge_rtnode_zone, brt); } /* @@ -3691,20 +3640,17 @@ bridge_linkstate(struct ifnet *ifp) { struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif; - struct epoch_tracker et; - NET_EPOCH_ENTER_ET(et); - + BRIDGE_LOCK(sc); bif = bridge_lookup_member_if(sc, ifp); if (bif == NULL) { - NET_EPOCH_EXIT_ET(et); + BRIDGE_UNLOCK(sc); return; } bridge_linkcheck(sc); + BRIDGE_UNLOCK(sc); bstp_linkstate(&bif->bif_stp); - - NET_EPOCH_EXIT_ET(et); } static void @@ -3713,8 +3659,7 @@ bridge_linkcheck(struct bridge_softc *sc) struct bridge_iflist *bif; int new_link, hasls; - MPASS(in_epoch(net_epoch_preempt)); - + BRIDGE_LOCK_ASSERT(sc); new_link = LINK_STATE_DOWN; hasls = 0; /* Our link is considered up if at least one of our ports is active */