Module Name:    src
Committed By:   ozaki-r
Date:           Wed Jun 18 10:51:03 UTC 2014

Modified Files:
        src/sys/net: if_bridge.c

Log Message:
Restructure bridge_input and bridge_broadcast

There are two changes:
- Assemble the places calling pktq_enqueue (bridge_forward)
  for unicast and {b,m}cast frames into one
- Receive {b,m}cast frames in bridge_broadcast, not in
  bridge_input

The changes make the code clear and readable. bridge_input
now doesn't need to take care of {b,m}cast frames;
bridge_forward and bridge_broadcast have the responsibility.

The changes are based on a patch of Lloyd Parkes submitted
in PR 48104, but don't fix its issue yet.


To generate a diff of this commit:
cvs rdiff -u -r1.82 -r1.83 src/sys/net/if_bridge.c

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.82 src/sys/net/if_bridge.c:1.83
--- src/sys/net/if_bridge.c:1.82	Wed Jun 18 09:20:46 2014
+++ src/sys/net/if_bridge.c	Wed Jun 18 10:51:03 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_bridge.c,v 1.82 2014/06/18 09:20:46 ozaki-r Exp $	*/
+/*	$NetBSD: if_bridge.c,v 1.83 2014/06/18 10:51:03 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.82 2014/06/18 09:20:46 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.83 2014/06/18 10:51:03 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_bridge_ipf.h"
@@ -1612,7 +1612,6 @@ bridge_input(struct ifnet *ifp, struct m
 	struct bridge_softc *sc = ifp->if_bridge;
 	struct bridge_iflist *bif;
 	struct ether_header *eh;
-	struct mbuf *mc;
 
 	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
 		ether_input(ifp, m);
@@ -1635,68 +1634,50 @@ bridge_input(struct ifnet *ifp, struct m
 			m->m_flags |= M_MCAST;
 	}
 
-	if (m->m_flags & (M_BCAST|M_MCAST)) {
-		if (bif->bif_flags & IFBIF_STP) {
-			/* Tap off 802.1D packets; they do not get forwarded. */
-			if (memcmp(eh->ether_dhost, bstp_etheraddr,
-			    ETHER_ADDR_LEN) == 0) {
-				bstp_input(sc, bif, m);
+	/*
+	 * A 'fast' path for packets addressed to interfaces that are
+	 * part of this bridge.
+	 */
+	if (!(m->m_flags & (M_BCAST|M_MCAST)) &&
+	    !bstp_state_before_learning(bif)) {
+		struct bridge_iflist *_bif;
+
+		LIST_FOREACH(_bif, &sc->sc_iflist, bif_next) {
+			/* It is destined for us. */
+			if (bridge_ourether(_bif, eh, 0)) {
+				if (_bif->bif_flags & IFBIF_LEARNING)
+					(void) bridge_rtupdate(sc,
+					    eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
+				m->m_pkthdr.rcvif = _bif->bif_ifp;
+				ether_input(_bif->bif_ifp, m);
 				return;
 			}
 
-			if (bstp_state_before_learning(bif)) {
-				ether_input(ifp, m);
+			/* We just received a packet that we sent out. */
+			if (bridge_ourether(_bif, eh, 1)) {
+				m_freem(m);
 				return;
 			}
 		}
-
-		/*
-		 * Make a deep copy of the packet and enqueue the copy
-		 * for bridge processing; return the original packet for
-		 * local processing.
-		 */
-		mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
-		if (mc == NULL) {
-			ether_input(ifp, m);
-			return;
-		}
-
-		/* Perform the bridge forwarding function with the copy. */
-		if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, mc, 0)))
-			m_freem(mc);
-
-		/* For local processing. */
-		ether_input(ifp, m);
-		return;
 	}
 
-	if (bstp_state_before_learning(bif)) {
-		ether_input(ifp, m);
+	/* Tap off 802.1D packets; they do not get forwarded. */
+	if (bif->bif_flags & IFBIF_STP &&
+	    memcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) {
+		bstp_input(sc, bif, m);
 		return;
 	}
 
 	/*
-	 * Unicast.  Make sure it's not for us.
+	 * A normal switch would discard the packet here, but that's not what
+	 * we've done historically. This also prevents some obnoxious behaviour.
 	 */
-	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
-		/* It is destined for us. */
-		if (bridge_ourether(bif, eh, 0)) {
-			if (bif->bif_flags & IFBIF_LEARNING)
-				(void) bridge_rtupdate(sc,
-				    eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
-			m->m_pkthdr.rcvif = bif->bif_ifp;
-			ether_input(bif->bif_ifp, m);
-			return;
-		}
-
-		/* We just received a packet that we sent out. */
-		if (bridge_ourether(bif, eh, 1)) {
-			m_freem(m);
-			return;
-		}
+	if (bstp_state_before_learning(bif)) {
+		ether_input(ifp, m);
+		return;
 	}
 
-	/* Perform the bridge forwarding function. */
+	/* Queue the packet for bridge forwarding. */
 	if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, m, 0)))
 		m_freem(m);
 }
@@ -1715,7 +1696,9 @@ bridge_broadcast(struct bridge_softc *sc
 	struct bridge_iflist *bif;
 	struct mbuf *mc;
 	struct ifnet *dst_if;
-	int used = 0;
+	bool used, bmcast;
+
+	used = bmcast = m->m_flags & (M_BCAST|M_MCAST);
 
 	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 		dst_if = bif->bif_ifp;
@@ -1730,16 +1713,15 @@ bridge_broadcast(struct bridge_softc *sc
 			}
 		}
 
-		if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
-		    (m->m_flags & (M_BCAST|M_MCAST)) == 0)
+		if ((bif->bif_flags & IFBIF_DISCOVER) == 0 && !bmcast)
 			continue;
 
 		if ((dst_if->if_flags & IFF_RUNNING) == 0)
 			continue;
 
-		if (LIST_NEXT(bif, bif_next) == NULL) {
+		if (!used && LIST_NEXT(bif, bif_next) == NULL) {
 			mc = m;
-			used = 1;
+			used = true;
 		} else {
 			mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
 			if (mc == NULL) {
@@ -1750,7 +1732,10 @@ bridge_broadcast(struct bridge_softc *sc
 
 		bridge_enqueue(sc, dst_if, mc, 1);
 	}
-	if (used == 0)
+
+	if (bmcast)
+		ether_input(src_if, m);
+	else if (!used)
 		m_freem(m);
 }
 

Reply via email to