svn commit: r363568 - stable/12/sys/net
mike tancsa
mike at sentex.net
Sun Jul 26 19:21:42 UTC 2020
Hi Kristof,
First off, thank you for all your efforts in pf and if_bridge. I
have trying to track down a problem with a golang app (sysutils/zrepl)
that started acting up around the time the if_bridge stuff was commited
(june 26th). The problem would manifest in stalls of the daemon and am
wondering this might have played a role. The june 10th kernel I had
seemed to work just fine with the app, although I just rebooted to that
to confirm as around that time we added more RAM to the server in
question and put the app under slightly higher load too. I have yet to
boot to a kernel post this being reverted. But apart from the panics
some people saw could other 'odd' things pop up as well if traffic was
coming in a bridge interface using an igb0 nic ?
---Mike
On 7/26/2020 1:44 PM, Kristof Provost wrote:
> 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 */
> _______________________________________________
> svn-src-stable-12 at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-stable-12
> To unsubscribe, send any mail to "svn-src-stable-12-unsubscribe at freebsd.org"
>
More information about the svn-src-stable
mailing list