Module Name: src Committed By: ozaki-r Date: Tue Apr 19 07:03:12 UTC 2016
Modified Files: src/sys/net: if_bridge.c if_bridgevar.h Log Message: Remove BRIDGE_MPSAFE switch and enable MP-safe code by default We need to enable it by default because bridge_input now runs in softint, but bridge_input w/o BRIDGE_MPSAFE was designed as it runs in hardware interrupt. Note that there remains a racy code in bridge_output; it will be solved in the upcoming change (applying psref(9)). To generate a diff of this commit: cvs rdiff -u -r1.113 -r1.114 src/sys/net/if_bridge.c cvs rdiff -u -r1.28 -r1.29 src/sys/net/if_bridgevar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_bridge.c diff -u src/sys/net/if_bridge.c:1.113 src/sys/net/if_bridge.c:1.114 --- src/sys/net/if_bridge.c:1.113 Mon Apr 11 05:40:47 2016 +++ src/sys/net/if_bridge.c Tue Apr 19 07:03:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bridge.c,v 1.113 2016/04/11 05:40:47 ozaki-r Exp $ */ +/* $NetBSD: if_bridge.c,v 1.114 2016/04/19 07:03:12 ozaki-r Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -80,11 +80,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.113 2016/04/11 05:40:47 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.114 2016/04/19 07:03:12 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_bridge_ipf.h" #include "opt_inet.h" +#include "opt_net_mpsafe.h" #endif /* _KERNEL_OPT */ #include <sys/param.h> @@ -191,13 +192,27 @@ __CTASSERT(offsetof(struct ifbifconf, if if ((_sc)->sc_rtlist_psz != NULL) \ pserialize_perform((_sc)->sc_rtlist_psz); -#ifdef BRIDGE_MPSAFE #define BRIDGE_RT_RENTER(__s) do { __s = pserialize_read_enter(); } while (0) #define BRIDGE_RT_REXIT(__s) do { pserialize_read_exit(__s); } while (0) -#else /* BRIDGE_MPSAFE */ -#define BRIDGE_RT_RENTER(__s) do { __s = 0; } while (0) -#define BRIDGE_RT_REXIT(__s) do { (void)__s; } while (0) -#endif /* BRIDGE_MPSAFE */ + + +#ifdef NET_MPSAFE +#define DECLARE_LOCK_VARIABLE +#define ACQUIRE_GLOBAL_LOCKS() do { } while (0) +#define RELEASE_GLOBAL_LOCKS() do { } while (0) +#else +#define DECLARE_LOCK_VARIABLE int __s +#define ACQUIRE_GLOBAL_LOCKS() do { \ + KERNEL_LOCK(1, NULL); \ + mutex_enter(softnet_lock); \ + __s = splnet(); \ + } while (0) +#define RELEASE_GLOBAL_LOCKS() do { \ + splx(__s); \ + mutex_exit(softnet_lock); \ + KERNEL_UNLOCK_ONE(NULL); \ + } while (0) +#endif int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; @@ -369,7 +384,7 @@ bridge_clone_create(struct if_clone *ifc { struct bridge_softc *sc; struct ifnet *ifp; - int error, flags; + int error; sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); ifp = &sc->sc_if; @@ -386,13 +401,8 @@ bridge_clone_create(struct if_clone *ifc /* Initialize our routing table. */ bridge_rtable_init(sc); -#ifdef BRIDGE_MPSAFE - flags = WQ_MPSAFE; -#else - flags = 0; -#endif error = workqueue_create(&sc->sc_rtage_wq, "bridge_rtage", - bridge_rtage_work, sc, PRI_SOFTNET, IPL_SOFTNET, flags); + bridge_rtage_work, sc, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE); if (error) panic("%s: workqueue_create %d\n", __func__, error); @@ -400,13 +410,8 @@ bridge_clone_create(struct if_clone *ifc callout_init(&sc->sc_bstpcallout, 0); PSLIST_INIT(&sc->sc_iflist); -#ifdef BRIDGE_MPSAFE sc->sc_iflist_psz = pserialize_create(); sc->sc_iflist_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET); -#else - sc->sc_iflist_psz = NULL; - sc->sc_iflist_lock = NULL; -#endif cv_init(&sc->sc_iflist_cv, "if_bridge_cv"); if_initname(ifp, ifc->ifc_name, unit); @@ -662,14 +667,13 @@ bridge_lookup_member_if(struct bridge_so static struct bridge_iflist * bridge_try_hold_bif(struct bridge_iflist *bif) { -#ifdef BRIDGE_MPSAFE + if (bif != NULL) { if (bif->bif_waiting) bif = NULL; else atomic_inc_32(&bif->bif_refs); } -#endif return bif; } @@ -681,7 +685,6 @@ bridge_try_hold_bif(struct bridge_iflist static void bridge_release_member(struct bridge_softc *sc, struct bridge_iflist *bif) { -#ifdef BRIDGE_MPSAFE uint32_t refs; refs = atomic_dec_uint_nv(&bif->bif_refs); @@ -690,10 +693,6 @@ bridge_release_member(struct bridge_soft cv_broadcast(&sc->sc_iflist_cv); BRIDGE_UNLOCK(sc); } -#else - (void)sc; - (void)bif; -#endif } /* @@ -715,7 +714,6 @@ bridge_delete_member(struct bridge_softc PSLIST_WRITER_REMOVE(bif, bif_next); BRIDGE_PSZ_PERFORM(sc); -#ifdef BRIDGE_MPSAFE bif->bif_waiting = true; membar_sync(); while (bif->bif_refs > 0) { @@ -723,7 +721,6 @@ bridge_delete_member(struct bridge_softc cv_wait(&sc->sc_iflist_cv, sc->sc_iflist_lock); } bif->bif_waiting = false; -#endif BRIDGE_UNLOCK(sc); PSLIST_ENTRY_DESTROY(bif, bif_next); @@ -1432,9 +1429,7 @@ bridge_output(struct ifnet *ifp, struct struct ether_header *eh; struct ifnet *dst_if; struct bridge_softc *sc; -#ifndef BRIDGE_MPSAFE int s; -#endif if (m->m_len < ETHER_HDR_LEN) { m = m_pullup(m, ETHER_HDR_LEN); @@ -1445,10 +1440,6 @@ bridge_output(struct ifnet *ifp, struct eh = mtod(m, struct ether_header *); sc = ifp->if_bridge; -#ifndef BRIDGE_MPSAFE - s = splnet(); -#endif - /* * If bridge is down, but the original output interface is up, * go ahead and send out that interface. Otherwise, the packet @@ -1472,15 +1463,14 @@ bridge_output(struct ifnet *ifp, struct struct bridge_iflist *bif; struct mbuf *mc; int used = 0; - int ss; - BRIDGE_PSZ_RENTER(ss); + BRIDGE_PSZ_RENTER(s); PSLIST_READER_FOREACH(bif, &sc->sc_iflist, struct bridge_iflist, bif_next) { bif = bridge_try_hold_bif(bif); if (bif == NULL) continue; - BRIDGE_PSZ_REXIT(ss); + BRIDGE_PSZ_REXIT(s); dst_if = bif->bif_ifp; if ((dst_if->if_flags & IFF_RUNNING) == 0) @@ -1514,18 +1504,21 @@ bridge_output(struct ifnet *ifp, struct } } +#ifndef NET_MPSAFE + s = splnet(); +#endif bridge_enqueue(sc, dst_if, mc, 0); +#ifndef NET_MPSAFE + splx(s); +#endif next: bridge_release_member(sc, bif); - BRIDGE_PSZ_RENTER(ss); + BRIDGE_PSZ_RENTER(s); } - BRIDGE_PSZ_REXIT(ss); + BRIDGE_PSZ_REXIT(s); if (used == 0) m_freem(m); -#ifndef BRIDGE_MPSAFE - splx(s); -#endif return (0); } @@ -1536,17 +1529,17 @@ next: if ((dst_if->if_flags & IFF_RUNNING) == 0) { m_freem(m); -#ifndef BRIDGE_MPSAFE - splx(s); -#endif return (0); } +#ifndef NET_MPSAFE + s = splnet(); +#endif bridge_enqueue(sc, dst_if, m, 0); - -#ifndef BRIDGE_MPSAFE +#ifndef NET_MPSAFE splx(s); #endif + return (0); } @@ -1575,24 +1568,10 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *bif; struct ifnet *src_if, *dst_if; struct ether_header *eh; -#ifndef BRIDGE_MPSAFE - int s; + DECLARE_LOCK_VARIABLE; - KERNEL_LOCK(1, NULL); - mutex_enter(softnet_lock); -#endif - - if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { -#ifndef BRIDGE_MPSAFE - mutex_exit(softnet_lock); - KERNEL_UNLOCK_ONE(NULL); -#endif + if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return; - } - -#ifndef BRIDGE_MPSAFE - s = splnet(); -#endif src_if = m->m_pkthdr.rcvif; @@ -1711,16 +1690,12 @@ bridge_forward(struct bridge_softc *sc, bridge_release_member(sc, bif); + ACQUIRE_GLOBAL_LOCKS(); bridge_enqueue(sc, dst_if, m, 1); + RELEASE_GLOBAL_LOCKS(); out: -#ifndef BRIDGE_MPSAFE - splx(s); - mutex_exit(softnet_lock); - KERNEL_UNLOCK_ONE(NULL); -#else /* XXX gcc */ return; -#endif } static bool @@ -1765,18 +1740,23 @@ bridge_input(struct ifnet *ifp, struct m struct bridge_softc *sc = ifp->if_bridge; struct bridge_iflist *bif; struct ether_header *eh; + DECLARE_LOCK_VARIABLE; KASSERT(!cpu_intr_p()); if (__predict_false(sc == NULL) || (sc->sc_if.if_flags & IFF_RUNNING) == 0) { + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); + RELEASE_GLOBAL_LOCKS(); return; } bif = bridge_lookup_member_if(sc, ifp); if (bif == NULL) { + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); + RELEASE_GLOBAL_LOCKS(); return; } @@ -1828,7 +1808,9 @@ out: bridge_release_member(sc, bif); if (_ifp != NULL) { m->m_flags &= ~M_PROMISC; + ACQUIRE_GLOBAL_LOCKS(); ether_input(_ifp, m); + RELEASE_GLOBAL_LOCKS(); } else m_freem(m); return; @@ -1849,7 +1831,9 @@ out: */ if (bstp_state_before_learning(bif)) { bridge_release_member(sc, bif); + ACQUIRE_GLOBAL_LOCKS(); ether_input(ifp, m); + RELEASE_GLOBAL_LOCKS(); return; } @@ -1874,6 +1858,7 @@ bridge_broadcast(struct bridge_softc *sc struct ifnet *dst_if; bool bmcast; int s; + DECLARE_LOCK_VARIABLE; bmcast = m->m_flags & (M_BCAST|M_MCAST); @@ -1907,7 +1892,9 @@ bridge_broadcast(struct bridge_softc *sc sc->sc_if.if_oerrors++; goto next; } + ACQUIRE_GLOBAL_LOCKS(); bridge_enqueue(sc, dst_if, mc, 1); + RELEASE_GLOBAL_LOCKS(); } if (bmcast) { @@ -1919,7 +1906,10 @@ bridge_broadcast(struct bridge_softc *sc mc->m_pkthdr.rcvif = dst_if; mc->m_flags &= ~M_PROMISC; + + ACQUIRE_GLOBAL_LOCKS(); ether_input(dst_if, mc); + RELEASE_GLOBAL_LOCKS(); } next: bridge_release_member(sc, bif); @@ -2275,13 +2265,8 @@ bridge_rtable_init(struct bridge_softc * LIST_INIT(&sc->sc_rtlist); -#ifdef BRIDGE_MPSAFE sc->sc_rtlist_psz = pserialize_create(); sc->sc_rtlist_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET); -#else - sc->sc_rtlist_psz = NULL; - sc->sc_rtlist_lock = NULL; -#endif } /* Index: src/sys/net/if_bridgevar.h diff -u src/sys/net/if_bridgevar.h:1.28 src/sys/net/if_bridgevar.h:1.29 --- src/sys/net/if_bridgevar.h:1.28 Mon Apr 11 03:46:47 2016 +++ src/sys/net/if_bridgevar.h Tue Apr 19 07:03:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bridgevar.h,v 1.28 2016/04/11 03:46:47 ozaki-r Exp $ */ +/* $NetBSD: if_bridgevar.h,v 1.29 2016/04/19 07:03:12 ozaki-r Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -340,30 +340,13 @@ void bstp_input(struct bridge_softc *, s void bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *, int); -#ifdef NET_MPSAFE -#define BRIDGE_MPSAFE 1 -#endif - -#define BRIDGE_LOCK(_sc) if ((_sc)->sc_iflist_lock) \ - mutex_enter((_sc)->sc_iflist_lock) -#define BRIDGE_UNLOCK(_sc) if ((_sc)->sc_iflist_lock) \ - mutex_exit((_sc)->sc_iflist_lock) -#define BRIDGE_LOCKED(_sc) (!(_sc)->sc_iflist_lock || \ - mutex_owned((_sc)->sc_iflist_lock)) +#define BRIDGE_LOCK(_sc) mutex_enter((_sc)->sc_iflist_lock) +#define BRIDGE_UNLOCK(_sc) mutex_exit((_sc)->sc_iflist_lock) +#define BRIDGE_LOCKED(_sc) mutex_owned((_sc)->sc_iflist_lock) -#ifdef BRIDGE_MPSAFE -/* - * These macros can be used in both HW interrupt and softint contexts. - */ #define BRIDGE_PSZ_RENTER(__s) do { __s = pserialize_read_enter(); } while (0) #define BRIDGE_PSZ_REXIT(__s) do { pserialize_read_exit(__s); } while (0) -#else /* BRIDGE_MPSAFE */ -#define BRIDGE_PSZ_RENTER(__s) do { __s = 0; } while (0) -#define BRIDGE_PSZ_REXIT(__s) do { (void)__s; } while (0) -#endif /* BRIDGE_MPSAFE */ - -#define BRIDGE_PSZ_PERFORM(_sc) if ((_sc)->sc_iflist_psz) \ - pserialize_perform((_sc)->sc_iflist_psz); +#define BRIDGE_PSZ_PERFORM(_sc) pserialize_perform((_sc)->sc_iflist_psz) /* * Locking notes: