Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Restructure bridge_input and bridge_broadcast



details:   https://anonhg.NetBSD.org/src/rev/ebdd9a53e680
branches:  trunk
changeset: 330031:ebdd9a53e680
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Wed Jun 18 10:51:03 2014 +0000

description:
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.

diffstat:

 sys/net/if_bridge.c |  97 ++++++++++++++++++++++------------------------------
 1 files changed, 41 insertions(+), 56 deletions(-)

diffs (167 lines):

diff -r 8fb3fe37434d -r ebdd9a53e680 sys/net/if_bridge.c
--- a/sys/net/if_bridge.c       Wed Jun 18 09:41:29 2014 +0000
+++ b/sys/net/if_bridge.c       Wed Jun 18 10:51:03 2014 +0000
@@ -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 @@
        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 @@
                        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);
+       /* 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;
        }
 
+       /*
+        * A normal switch would discard the packet here, but that's not what
+        * we've done historically. This also prevents some obnoxious behaviour.
+        */
        if (bstp_state_before_learning(bif)) {
                ether_input(ifp, m);
                return;
        }
 
-       /*
-        * Unicast.  Make sure it's not for us.
-        */
-       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;
-               }
-       }
-
-       /* 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 @@
        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 @@
                        }
                }
 
-               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_enqueue(sc, dst_if, mc, 1);
        }
-       if (used == 0)
+
+       if (bmcast)
+               ether_input(src_if, m);
+       else if (!used)
                m_freem(m);
 }
 



Home | Main Index | Thread Index | Old Index