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: