Module Name: src
Committed By: ozaki-r
Date: Mon Feb 15 01:11:41 UTC 2016
Modified Files:
src/sys/net: bridgestp.c if_bridge.c if_bridgevar.h
Log Message:
Simplify bridge(4)
Thanks to introducing softint-based if_input, the entire bridge code now
never run in hardware interrupt context. So we can simplify the code.
- Remove spin mutexes
- They were needed because some code of bridge could run in
hardware interrupt context
- We now need only an adaptive mutex for each shared object
(a member list and a forwarding table)
- Remove pktqueue
- bridge_input is already in softint, using another softint
(for bridge_forward) is useless
- Packet distribution should be down at device drivers
To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/net/bridgestp.c
cvs rdiff -u -r1.107 -r1.108 src/sys/net/if_bridge.c
cvs rdiff -u -r1.25 -r1.26 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/bridgestp.c
diff -u src/sys/net/bridgestp.c:1.18 src/sys/net/bridgestp.c:1.19
--- src/sys/net/bridgestp.c:1.18 Wed Dec 31 17:36:24 2014
+++ src/sys/net/bridgestp.c Mon Feb 15 01:11:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: bridgestp.c,v 1.18 2014/12/31 17:36:24 ozaki-r Exp $ */
+/* $NetBSD: bridgestp.c,v 1.19 2016/02/15 01:11:41 ozaki-r Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright ([email protected])
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bridgestp.c,v 1.18 2014/12/31 17:36:24 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bridgestp.c,v 1.19 2016/02/15 01:11:41 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -221,7 +221,7 @@ bstp_send_config_bpdu(struct bridge_soft
struct bstp_cbpdu bpdu;
int s;
- KASSERT(BRIDGE_INTR_LOCKED(sc));
+ KASSERT(BRIDGE_LOCKED(sc));
ifp = bif->bif_ifp;
@@ -276,11 +276,11 @@ bstp_send_config_bpdu(struct bridge_soft
memcpy(mtod(m, char *) + sizeof(*eh), &bpdu, sizeof(bpdu));
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
s = splnet();
bridge_enqueue(sc, ifp, m, 0);
splx(s);
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
}
static int
@@ -367,7 +367,7 @@ bstp_transmit_tcn(struct bridge_softc *s
struct mbuf *m;
int s;
- KASSERT(BRIDGE_INTR_LOCKED(sc));
+ KASSERT(BRIDGE_LOCKED(sc));
KASSERT(bif != NULL);
ifp = bif->bif_ifp;
@@ -396,11 +396,11 @@ bstp_transmit_tcn(struct bridge_softc *s
memcpy(mtod(m, char *) + sizeof(*eh), &bpdu, sizeof(bpdu));
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
s = splnet();
bridge_enqueue(sc, ifp, m, 0);
splx(s);
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
}
static void
@@ -634,9 +634,9 @@ bstp_input(struct bridge_softc *sc, stru
case BSTP_MSGTYPE_TCN:
tu.tu_message_type = tpdu.tbu_bpdutype;
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
bstp_received_tcn_bpdu(sc, bif, &tu);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
break;
case BSTP_MSGTYPE_CFG:
@@ -675,9 +675,9 @@ bstp_input(struct bridge_softc *sc, stru
cu.cu_topology_change =
(cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
bstp_received_config_bpdu(sc, bif, &cu);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
break;
default:
@@ -826,7 +826,7 @@ bstp_initialization(struct bridge_softc
mif = NULL;
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if ((bif->bif_flags & IFBIF_STP) == 0)
@@ -848,7 +848,7 @@ bstp_initialization(struct bridge_softc
}
if (mif == NULL) {
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
bstp_stop(sc);
return;
}
@@ -862,7 +862,7 @@ bstp_initialization(struct bridge_softc
(((uint64_t)(uint8_t)CLLADDR(mif->bif_ifp->if_sadl)[4]) << 8) |
(((uint64_t)(uint8_t)CLLADDR(mif->bif_ifp->if_sadl)[5]) << 0);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
sc->sc_designated_root = sc->sc_bridge_id;
sc->sc_root_path_cost = 0;
@@ -880,7 +880,7 @@ bstp_initialization(struct bridge_softc
callout_reset(&sc->sc_bstpcallout, hz,
bstp_tick, sc);
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if (bif->bif_flags & IFBIF_STP)
@@ -893,7 +893,7 @@ bstp_initialization(struct bridge_softc
bstp_config_bpdu_generation(sc);
bstp_timer_start(&sc->sc_hello_timer, 0);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
}
void
@@ -901,14 +901,14 @@ bstp_stop(struct bridge_softc *sc)
{
struct bridge_iflist *bif;
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
bstp_timer_stop(&bif->bif_hold_timer);
bstp_timer_stop(&bif->bif_message_age_timer);
bstp_timer_stop(&bif->bif_forward_delay_timer);
}
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
callout_stop(&sc->sc_bstpcallout);
@@ -1065,7 +1065,7 @@ bstp_tick(void *arg)
int s;
s = splnet();
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if ((bif->bif_flags & IFBIF_STP) == 0)
@@ -1113,7 +1113,7 @@ bstp_tick(void *arg)
if (sc->sc_if.if_flags & IFF_RUNNING)
callout_reset(&sc->sc_bstpcallout, hz, bstp_tick, sc);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
splx(s);
}
Index: src/sys/net/if_bridge.c
diff -u src/sys/net/if_bridge.c:1.107 src/sys/net/if_bridge.c:1.108
--- src/sys/net/if_bridge.c:1.107 Wed Feb 10 06:30:23 2016
+++ src/sys/net/if_bridge.c Mon Feb 15 01:11:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridge.c,v 1.107 2016/02/10 06:30:23 ozaki-r Exp $ */
+/* $NetBSD: if_bridge.c,v 1.108 2016/02/15 01:11:41 ozaki-r Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.107 2016/02/10 06:30:23 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.108 2016/02/15 01:11:41 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@@ -108,7 +108,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_llc.h>
-#include <net/pktqueue.h>
#include <net/if_ether.h>
#include <net/if_bridgevar.h>
@@ -181,10 +180,6 @@ __CTASSERT(offsetof(struct ifbifconf, if
#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
#endif
-#define BRIDGE_RT_INTR_LOCK(_sc) mutex_enter((_sc)->sc_rtlist_intr_lock)
-#define BRIDGE_RT_INTR_UNLOCK(_sc) mutex_exit((_sc)->sc_rtlist_intr_lock)
-#define BRIDGE_RT_INTR_LOCKED(_sc) mutex_owned((_sc)->sc_rtlist_intr_lock)
-
#define BRIDGE_RT_LOCK(_sc) if ((_sc)->sc_rtlist_lock) \
mutex_enter((_sc)->sc_rtlist_lock)
#define BRIDGE_RT_UNLOCK(_sc) if ((_sc)->sc_rtlist_lock) \
@@ -197,18 +192,8 @@ __CTASSERT(offsetof(struct ifbifconf, if
pserialize_perform((_sc)->sc_rtlist_psz);
#ifdef BRIDGE_MPSAFE
-#define BRIDGE_RT_RENTER(__s) do { \
- if (!cpu_intr_p()) \
- __s = pserialize_read_enter(); \
- else \
- __s = splhigh(); \
- } while (0)
-#define BRIDGE_RT_REXIT(__s) do { \
- if (!cpu_intr_p()) \
- pserialize_read_exit(__s); \
- else \
- splx(__s); \
- } while (0)
+#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)
@@ -227,7 +212,7 @@ static void bridge_stop(struct ifnet *,
static void bridge_start(struct ifnet *);
static void bridge_input(struct ifnet *, struct mbuf *);
-static void bridge_forward(void *);
+static void bridge_forward(struct bridge_softc *, struct mbuf *);
static void bridge_timer(void *);
@@ -297,9 +282,6 @@ static int bridge_ip6_checkbasic(struct
# endif /* INET6 */
#endif /* BRIDGE_IPF */
-static void bridge_sysctl_fwdq_setup(struct sysctllog **clog,
- struct bridge_softc *sc);
-
struct bridge_control {
int (*bc_func)(struct bridge_softc *, void *);
int bc_argsize;
@@ -424,11 +406,9 @@ bridge_clone_create(struct if_clone *ifc
LIST_INIT(&sc->sc_iflist);
#ifdef BRIDGE_MPSAFE
- sc->sc_iflist_intr_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
sc->sc_iflist_psz = pserialize_create();
sc->sc_iflist_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET);
#else
- sc->sc_iflist_intr_lock = NULL;
sc->sc_iflist_psz = NULL;
sc->sc_iflist_lock = NULL;
#endif
@@ -447,11 +427,6 @@ bridge_clone_create(struct if_clone *ifc
ifp->if_dlt = DLT_EN10MB;
ifp->if_hdrlen = ETHER_HDR_LEN;
- sc->sc_fwd_pktq = pktq_create(IFQ_MAXLEN, bridge_forward, sc);
- KASSERT(sc->sc_fwd_pktq != NULL);
-
- bridge_sysctl_fwdq_setup(&ifp->if_sysctl_log, sc);
-
if_initialize(ifp);
if_register(ifp);
@@ -476,9 +451,6 @@ bridge_clone_destroy(struct ifnet *ifp)
struct bridge_iflist *bif;
int s;
- /* Must be called during IFF_RUNNING, i.e., before bridge_stop */
- pktq_barrier(sc->sc_fwd_pktq);
-
s = splnet();
bridge_stop(ifp, 1);
@@ -496,16 +468,10 @@ bridge_clone_destroy(struct ifnet *ifp)
if_detach(ifp);
- /* Should be called after if_detach for safe */
- pktq_flush(sc->sc_fwd_pktq);
- pktq_destroy(sc->sc_fwd_pktq);
-
/* Tear down the routing table. */
bridge_rtable_fini(sc);
cv_destroy(&sc->sc_iflist_cv);
- if (sc->sc_iflist_intr_lock)
- mutex_obj_free(sc->sc_iflist_intr_lock);
if (sc->sc_iflist_psz)
pserialize_destroy(sc->sc_iflist_psz);
@@ -519,92 +485,6 @@ bridge_clone_destroy(struct ifnet *ifp)
return (0);
}
-static int
-bridge_sysctl_fwdq_maxlen(SYSCTLFN_ARGS)
-{
- struct sysctlnode node = *rnode;
- const struct bridge_softc *sc = node.sysctl_data;
- return sysctl_pktq_maxlen(SYSCTLFN_CALL(rnode), sc->sc_fwd_pktq);
-}
-
-#define SYSCTL_BRIDGE_PKTQ(cn, c) \
- static int \
- bridge_sysctl_fwdq_##cn(SYSCTLFN_ARGS) \
- { \
- struct sysctlnode node = *rnode; \
- const struct bridge_softc *sc = node.sysctl_data; \
- return sysctl_pktq_count(SYSCTLFN_CALL(rnode), \
- sc->sc_fwd_pktq, c); \
- }
-
-SYSCTL_BRIDGE_PKTQ(items, PKTQ_NITEMS)
-SYSCTL_BRIDGE_PKTQ(drops, PKTQ_DROPS)
-
-static void
-bridge_sysctl_fwdq_setup(struct sysctllog **clog, struct bridge_softc *sc)
-{
- const struct sysctlnode *cnode, *rnode;
- sysctlfn len_func = NULL, maxlen_func = NULL, drops_func = NULL;
- const char *ifname = sc->sc_if.if_xname;
-
- len_func = bridge_sysctl_fwdq_items;
- maxlen_func = bridge_sysctl_fwdq_maxlen;
- drops_func = bridge_sysctl_fwdq_drops;
-
- if (sysctl_createv(clog, 0, NULL, &rnode,
- CTLFLAG_PERMANENT,
- CTLTYPE_NODE, "interfaces",
- SYSCTL_DESCR("Per-interface controls"),
- NULL, 0, NULL, 0,
- CTL_NET, CTL_CREATE, CTL_EOL) != 0)
- goto bad;
-
- if (sysctl_createv(clog, 0, &rnode, &rnode,
- CTLFLAG_PERMANENT,
- CTLTYPE_NODE, ifname,
- SYSCTL_DESCR("Interface controls"),
- NULL, 0, NULL, 0,
- CTL_CREATE, CTL_EOL) != 0)
- goto bad;
-
- if (sysctl_createv(clog, 0, &rnode, &rnode,
- CTLFLAG_PERMANENT,
- CTLTYPE_NODE, "fwdq",
- SYSCTL_DESCR("Protocol input queue controls"),
- NULL, 0, NULL, 0,
- CTL_CREATE, CTL_EOL) != 0)
- goto bad;
-
- if (sysctl_createv(clog, 0, &rnode, &cnode,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "len",
- SYSCTL_DESCR("Current forwarding queue length"),
- len_func, 0, (void *)sc, 0,
- CTL_CREATE, IFQCTL_LEN, CTL_EOL) != 0)
- goto bad;
-
- if (sysctl_createv(clog, 0, &rnode, &cnode,
- CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
- CTLTYPE_INT, "maxlen",
- SYSCTL_DESCR("Maximum allowed forwarding queue length"),
- maxlen_func, 0, (void *)sc, 0,
- CTL_CREATE, IFQCTL_MAXLEN, CTL_EOL) != 0)
- goto bad;
-
- if (sysctl_createv(clog, 0, &rnode, &cnode,
- CTLFLAG_PERMANENT,
- CTLTYPE_INT, "drops",
- SYSCTL_DESCR("Packets dropped due to full forwarding queue"),
- drops_func, 0, (void *)sc, 0,
- CTL_CREATE, IFQCTL_DROPS, CTL_EOL) != 0)
- goto bad;
-
- return;
-bad:
- aprint_error("%s: could not attach sysctl nodes\n", ifname);
- return;
-}
-
/*
* bridge_ioctl:
*
@@ -812,9 +692,9 @@ bridge_release_member(struct bridge_soft
refs = atomic_dec_uint_nv(&bif->bif_refs);
if (__predict_false(refs == 0 && bif->bif_waiting)) {
- BRIDGE_INTR_LOCK(sc);
+ BRIDGE_LOCK(sc);
cv_broadcast(&sc->sc_iflist_cv);
- BRIDGE_INTR_UNLOCK(sc);
+ BRIDGE_UNLOCK(sc);
}
#else
(void)sc;
@@ -842,19 +722,16 @@ bridge_delete_member(struct bridge_softc
BRIDGE_PSZ_PERFORM(sc);
- BRIDGE_UNLOCK(sc);
-
#ifdef BRIDGE_MPSAFE
- BRIDGE_INTR_LOCK(sc);
bif->bif_waiting = true;
membar_sync();
while (bif->bif_refs > 0) {
aprint_debug("%s: cv_wait on iflist\n", __func__);
- cv_wait(&sc->sc_iflist_cv, sc->sc_iflist_intr_lock);
+ cv_wait(&sc->sc_iflist_cv, sc->sc_iflist_lock);
}
bif->bif_waiting = false;
- BRIDGE_INTR_UNLOCK(sc);
#endif
+ BRIDGE_UNLOCK(sc);
kmem_free(bif, sizeof(*bif));
@@ -1147,7 +1024,7 @@ bridge_ioctl_rts(struct bridge_softc *sc
if (bac->ifbac_len == 0)
return (0);
- BRIDGE_RT_INTR_LOCK(sc);
+ BRIDGE_RT_LOCK(sc);
len = bac->ifbac_len;
LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
@@ -1170,7 +1047,7 @@ bridge_ioctl_rts(struct bridge_softc *sc
len -= sizeof(bareq);
}
out:
- BRIDGE_RT_INTR_UNLOCK(sc);
+ BRIDGE_RT_UNLOCK(sc);
bac->ifbac_len = sizeof(bareq) * count;
return (error);
@@ -1692,10 +1569,8 @@ bridge_start(struct ifnet *ifp)
* The forwarding function of the bridge.
*/
static void
-bridge_forward(void *v)
+bridge_forward(struct bridge_softc *sc, struct mbuf *m)
{
- struct bridge_softc *sc = v;
- struct mbuf *m;
struct bridge_iflist *bif;
struct ifnet *src_if, *dst_if;
struct ether_header *eh;
@@ -1717,130 +1592,133 @@ bridge_forward(void *v)
#ifndef BRIDGE_MPSAFE
s = splnet();
#endif
- while ((m = pktq_dequeue(sc->sc_fwd_pktq)) != NULL) {
- src_if = m->m_pkthdr.rcvif;
- sc->sc_if.if_ipackets++;
- sc->sc_if.if_ibytes += m->m_pkthdr.len;
+ src_if = m->m_pkthdr.rcvif;
- /*
- * Look up the bridge_iflist.
- */
- bif = bridge_lookup_member_if(sc, src_if);
- if (bif == NULL) {
- /* Interface is not a bridge member (anymore?) */
- m_freem(m);
- continue;
- }
-
- if (bif->bif_flags & IFBIF_STP) {
- switch (bif->bif_state) {
- case BSTP_IFSTATE_BLOCKING:
- case BSTP_IFSTATE_LISTENING:
- case BSTP_IFSTATE_DISABLED:
- m_freem(m);
- bridge_release_member(sc, bif);
- continue;
- }
- }
-
- eh = mtod(m, struct ether_header *);
+ sc->sc_if.if_ipackets++;
+ sc->sc_if.if_ibytes += m->m_pkthdr.len;
- /*
- * If the interface is learning, and the source
- * address is valid and not multicast, record
- * the address.
- */
- if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
- ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
- (eh->ether_shost[0] == 0 &&
- eh->ether_shost[1] == 0 &&
- eh->ether_shost[2] == 0 &&
- eh->ether_shost[3] == 0 &&
- eh->ether_shost[4] == 0 &&
- eh->ether_shost[5] == 0) == 0) {
- (void) bridge_rtupdate(sc, eh->ether_shost,
- src_if, 0, IFBAF_DYNAMIC);
- }
+ /*
+ * Look up the bridge_iflist.
+ */
+ bif = bridge_lookup_member_if(sc, src_if);
+ if (bif == NULL) {
+ /* Interface is not a bridge member (anymore?) */
+ m_freem(m);
+ goto out;
+ }
- if ((bif->bif_flags & IFBIF_STP) != 0 &&
- bif->bif_state == BSTP_IFSTATE_LEARNING) {
+ if (bif->bif_flags & IFBIF_STP) {
+ switch (bif->bif_state) {
+ case BSTP_IFSTATE_BLOCKING:
+ case BSTP_IFSTATE_LISTENING:
+ case BSTP_IFSTATE_DISABLED:
m_freem(m);
bridge_release_member(sc, bif);
- continue;
+ goto out;
}
+ }
- bridge_release_member(sc, bif);
+ eh = mtod(m, struct ether_header *);
- /*
- * At this point, the port either doesn't participate
- * in spanning tree or it is in the forwarding state.
- */
+ /*
+ * If the interface is learning, and the source
+ * address is valid and not multicast, record
+ * the address.
+ */
+ if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
+ ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
+ (eh->ether_shost[0] == 0 &&
+ eh->ether_shost[1] == 0 &&
+ eh->ether_shost[2] == 0 &&
+ eh->ether_shost[3] == 0 &&
+ eh->ether_shost[4] == 0 &&
+ eh->ether_shost[5] == 0) == 0) {
+ (void) bridge_rtupdate(sc, eh->ether_shost,
+ src_if, 0, IFBAF_DYNAMIC);
+ }
- /*
- * If the packet is unicast, destined for someone on
- * "this" side of the bridge, drop it.
- */
- if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
- dst_if = bridge_rtlookup(sc, eh->ether_dhost);
- if (src_if == dst_if) {
- m_freem(m);
- continue;
- }
- } else {
- /* ...forward it to all interfaces. */
- sc->sc_if.if_imcasts++;
- dst_if = NULL;
- }
+ if ((bif->bif_flags & IFBIF_STP) != 0 &&
+ bif->bif_state == BSTP_IFSTATE_LEARNING) {
+ m_freem(m);
+ bridge_release_member(sc, bif);
+ goto out;
+ }
- if (pfil_run_hooks(sc->sc_if.if_pfil, &m,
- m->m_pkthdr.rcvif, PFIL_IN) != 0) {
- if (m != NULL)
- m_freem(m);
- continue;
- }
- if (m == NULL)
- continue;
+ bridge_release_member(sc, bif);
- if (dst_if == NULL) {
- bridge_broadcast(sc, src_if, m);
- continue;
- }
+ /*
+ * At this point, the port either doesn't participate
+ * in spanning tree or it is in the forwarding state.
+ */
- /*
- * At this point, we're dealing with a unicast frame
- * going to a different interface.
- */
- if ((dst_if->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If the packet is unicast, destined for someone on
+ * "this" side of the bridge, drop it.
+ */
+ if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
+ dst_if = bridge_rtlookup(sc, eh->ether_dhost);
+ if (src_if == dst_if) {
m_freem(m);
- continue;
+ goto out;
}
+ } else {
+ /* ...forward it to all interfaces. */
+ sc->sc_if.if_imcasts++;
+ dst_if = NULL;
+ }
- bif = bridge_lookup_member_if(sc, dst_if);
- if (bif == NULL) {
- /* Not a member of the bridge (anymore?) */
+ if (pfil_run_hooks(sc->sc_if.if_pfil, &m,
+ m->m_pkthdr.rcvif, PFIL_IN) != 0) {
+ if (m != NULL)
m_freem(m);
- continue;
- }
+ goto out;
+ }
+ if (m == NULL)
+ goto out;
- if (bif->bif_flags & IFBIF_STP) {
- switch (bif->bif_state) {
- case BSTP_IFSTATE_DISABLED:
- case BSTP_IFSTATE_BLOCKING:
- m_freem(m);
- bridge_release_member(sc, bif);
- continue;
- }
- }
+ if (dst_if == NULL) {
+ bridge_broadcast(sc, src_if, m);
+ goto out;
+ }
- bridge_release_member(sc, bif);
+ /*
+ * At this point, we're dealing with a unicast frame
+ * going to a different interface.
+ */
+ if ((dst_if->if_flags & IFF_RUNNING) == 0) {
+ m_freem(m);
+ goto out;
+ }
- bridge_enqueue(sc, dst_if, m, 1);
+ bif = bridge_lookup_member_if(sc, dst_if);
+ if (bif == NULL) {
+ /* Not a member of the bridge (anymore?) */
+ m_freem(m);
+ goto out;
}
+
+ if (bif->bif_flags & IFBIF_STP) {
+ switch (bif->bif_state) {
+ case BSTP_IFSTATE_DISABLED:
+ case BSTP_IFSTATE_BLOCKING:
+ m_freem(m);
+ bridge_release_member(sc, bif);
+ goto out;
+ }
+ }
+
+ bridge_release_member(sc, bif);
+
+ bridge_enqueue(sc, dst_if, m, 1);
+out:
#ifndef BRIDGE_MPSAFE
splx(s);
mutex_exit(softnet_lock);
KERNEL_UNLOCK_ONE(NULL);
+#else
+ /* XXX gcc */
+ return;
#endif
}
@@ -1975,17 +1853,7 @@ out:
bridge_release_member(sc, bif);
- /* Queue the packet for bridge forwarding. */
- {
- /*
- * Force to enqueue to curcpu's pktq (RX can run on a CPU
- * other than CPU#0). XXX need fundamental solution.
- */
- const unsigned hash = curcpu()->ci_index;
-
- if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, m, hash)))
- m_freem(m);
- }
+ bridge_forward(sc, m);
}
/*
@@ -2083,9 +1951,9 @@ bridge_rtalloc(struct bridge_softc *sc,
brt->brt_flags = IFBAF_DYNAMIC;
memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
- BRIDGE_RT_INTR_LOCK(sc);
+ BRIDGE_RT_LOCK(sc);
error = bridge_rtnode_insert(sc, brt);
- BRIDGE_RT_INTR_UNLOCK(sc);
+ BRIDGE_RT_UNLOCK(sc);
if (error != 0) {
pool_put(&bridge_rtnode_pool, brt);
@@ -2189,10 +2057,8 @@ retry:
brt_list = kmem_alloc(sizeof(*brt_list) * count, KM_SLEEP);
BRIDGE_RT_LOCK(sc);
- BRIDGE_RT_INTR_LOCK(sc);
if (__predict_false(sc->sc_brtcnt > count)) {
/* The rtnodes increased, we need more memory */
- BRIDGE_RT_INTR_UNLOCK(sc);
BRIDGE_RT_UNLOCK(sc);
kmem_free(brt_list, sizeof(*brt_list) * count);
goto retry;
@@ -2208,7 +2074,6 @@ retry:
if (need_break)
break;
}
- BRIDGE_RT_INTR_UNLOCK(sc);
if (i > 0)
BRIDGE_RT_PSZ_PERFORM(sc);
@@ -2348,14 +2213,11 @@ bridge_rtdaddr(struct bridge_softc *sc,
struct bridge_rtnode *brt;
BRIDGE_RT_LOCK(sc);
- BRIDGE_RT_INTR_LOCK(sc);
if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL) {
- BRIDGE_RT_INTR_UNLOCK(sc);
BRIDGE_RT_UNLOCK(sc);
return ENOENT;
}
bridge_rtnode_remove(sc, brt);
- BRIDGE_RT_INTR_UNLOCK(sc);
BRIDGE_RT_PSZ_PERFORM(sc);
BRIDGE_RT_UNLOCK(sc);
@@ -2375,18 +2237,15 @@ bridge_rtdelete(struct bridge_softc *sc,
struct bridge_rtnode *brt, *nbrt;
BRIDGE_RT_LOCK(sc);
- BRIDGE_RT_INTR_LOCK(sc);
LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) {
if (brt->brt_ifp == ifp)
break;
}
if (brt == NULL) {
- BRIDGE_RT_INTR_UNLOCK(sc);
BRIDGE_RT_UNLOCK(sc);
return;
}
bridge_rtnode_remove(sc, brt);
- BRIDGE_RT_INTR_UNLOCK(sc);
BRIDGE_RT_PSZ_PERFORM(sc);
BRIDGE_RT_UNLOCK(sc);
@@ -2413,7 +2272,6 @@ bridge_rtable_init(struct bridge_softc *
LIST_INIT(&sc->sc_rtlist);
- sc->sc_rtlist_intr_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
#ifdef BRIDGE_MPSAFE
sc->sc_rtlist_psz = pserialize_create();
sc->sc_rtlist_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET);
@@ -2433,8 +2291,6 @@ bridge_rtable_fini(struct bridge_softc *
{
kmem_free(sc->sc_rthash, sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE);
- if (sc->sc_rtlist_intr_lock)
- mutex_obj_free(sc->sc_rtlist_intr_lock);
if (sc->sc_rtlist_lock)
mutex_obj_free(sc->sc_rtlist_lock);
if (sc->sc_rtlist_psz)
@@ -2514,7 +2370,7 @@ bridge_rtnode_insert(struct bridge_softc
uint32_t hash;
int dir;
- KASSERT(BRIDGE_RT_INTR_LOCKED(sc));
+ KASSERT(BRIDGE_RT_LOCKED(sc));
hash = bridge_rthash(sc, brt->brt_addr);
@@ -2559,7 +2415,7 @@ static void
bridge_rtnode_remove(struct bridge_softc *sc, struct bridge_rtnode *brt)
{
- KASSERT(BRIDGE_RT_INTR_LOCKED(sc));
+ KASSERT(BRIDGE_RT_LOCKED(sc));
LIST_REMOVE(brt, brt_hash);
LIST_REMOVE(brt, brt_list);
Index: src/sys/net/if_bridgevar.h
diff -u src/sys/net/if_bridgevar.h:1.25 src/sys/net/if_bridgevar.h:1.26
--- src/sys/net/if_bridgevar.h:1.25 Wed Feb 10 06:30:23 2016
+++ src/sys/net/if_bridgevar.h Mon Feb 15 01:11:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bridgevar.h,v 1.25 2016/02/10 06:30:23 ozaki-r Exp $ */
+/* $NetBSD: if_bridgevar.h,v 1.26 2016/02/15 01:11:41 ozaki-r Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -312,20 +312,17 @@ struct bridge_softc {
callout_t sc_brcallout; /* bridge callout */
callout_t sc_bstpcallout; /* STP callout */
LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */
- kmutex_t *sc_iflist_intr_lock;
kcondvar_t sc_iflist_cv;
pserialize_t sc_iflist_psz;
kmutex_t *sc_iflist_lock;
LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */
LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */
- kmutex_t *sc_rtlist_intr_lock;
kmutex_t *sc_rtlist_lock;
pserialize_t sc_rtlist_psz;
struct workqueue *sc_rtage_wq;
struct work sc_rtage_wk;
uint32_t sc_rthash_key; /* key for hash */
uint32_t sc_filter_flags; /* ipf and flags */
- pktqueue_t * sc_fwd_pktq;
};
extern const uint8_t bstp_etheraddr[];
@@ -353,29 +350,12 @@ void bridge_enqueue(struct bridge_softc
#define BRIDGE_LOCKED(_sc) (!(_sc)->sc_iflist_lock || \
mutex_owned((_sc)->sc_iflist_lock))
-#define BRIDGE_INTR_LOCK(_sc) if ((_sc)->sc_iflist_intr_lock) \
- mutex_enter((_sc)->sc_iflist_intr_lock)
-#define BRIDGE_INTR_UNLOCK(_sc) if ((_sc)->sc_iflist_intr_lock) \
- mutex_exit((_sc)->sc_iflist_intr_lock)
-#define BRIDGE_INTR_LOCKED(_sc) (!(_sc)->sc_iflist_intr_lock || \
- mutex_owned((_sc)->sc_iflist_intr_lock))
-
#ifdef BRIDGE_MPSAFE
/*
* These macros can be used in both HW interrupt and softint contexts.
*/
-#define BRIDGE_PSZ_RENTER(__s) do { \
- if (!cpu_intr_p()) \
- __s = pserialize_read_enter(); \
- else \
- __s = splhigh(); \
- } while (0)
-#define BRIDGE_PSZ_REXIT(__s) do { \
- if (!cpu_intr_p()) \
- pserialize_read_exit(__s); \
- else \
- splx(__s); \
- } while (0)
+#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)
@@ -387,22 +367,14 @@ void bridge_enqueue(struct bridge_softc
/*
* Locking notes:
* - Updates of sc_iflist are serialized by sc_iflist_lock (an adaptive mutex)
+ * - The mutex is also used for STP
* - Items of sc_iflist (bridge_iflist) is protected by both pserialize
* (sc_iflist_psz) and reference counting (bridge_iflist#bif_refs)
* - Before destroying an item of sc_iflist, we have to do pserialize_perform
* and synchronize with the reference counting via a conditional variable
* (sc_iflist_cz)
- * - sc_iflist_intr_lock (a spin mutex) is used for the CV
- * - A spin mutex is required because the reference counting can be used
- * in HW interrupt context
- * - The mutex is also used for STP
- * - Once we change to execute entire Layer 2 in softint context,
- * we can get rid of sc_iflist_intr_lock
- * - Updates of sc_rtlist are serialized by sc_rtlist_intr_lock (a spin mutex)
- * - The sc_rtlist can be modified in HW interrupt context for now
- * - sc_rtlist_lock (an adaptive mutex) is only for pserialize
- * - Once we change to execute entire Layer 2 in softint context,
- * we can get rid of sc_rtlist_intr_lock
+ * - Updates of sc_rtlist are serialized by sc_rtlist_lock (an adaptive mutex)
+ * - The mutex is also used for pserialize
* - A workqueue is used to run bridge_rtage in LWP context via bridge_timer callout
* - bridge_rtage uses pserialize that requires non-interrupt context
*/