Diff below moves bridge_output() to if_output().  It fixes the case I
already described some weeks ago where you have a physical interface
in a bridge and a vlan on top of it which is not in the bridge.

It also change the loop prevention code to use M_PROTO1 like in the
input path.

Tests, comments and oks welcome.

Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.338
diff -u -p -r1.338 if.c
--- net/if.c    7 Jun 2015 12:02:28 -0000       1.338
+++ net/if.c    8 Jun 2015 13:46:19 -0000
@@ -449,6 +449,19 @@ if_output(struct ifnet *ifp, struct mbuf
        int s, length, error = 0;
        unsigned short mflags;
 
+#ifdef DIAGNOSTIC
+       if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
+               printf("%s: trying to send packet on wrong domain. "
+                   "if %d vs. mbuf %d\n", ifp->if_xname, ifp->if_rdomain,
+                   rtable_l2(m->m_pkthdr.ph_rtableid));
+       }
+#endif
+
+#if NBRIDGE > 0
+       if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0)
+               return (bridge_output(ifp, m, NULL, NULL));
+#endif
+
        length = m->m_pkthdr.len;
        mflags = m->m_flags;
 
Index: net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.241
diff -u -p -r1.241 if_bridge.c
--- net/if_bridge.c     8 Jun 2015 13:44:08 -0000       1.241
+++ net/if_bridge.c     8 Jun 2015 13:46:19 -0000
@@ -2665,10 +2665,12 @@ bridge_ifenqueue(struct bridge_softc *sc
 {
        int error, len;
 
+       /* Loop prevention. */
+       m->m_flags |= M_PROTO1;
+
 #if NGIF > 0
        /* Packet needs etherip encapsulation. */
        if (ifp->if_type == IFT_GIF) {
-               m->m_flags |= M_PROTO1;
 
                /* Count packets input into the gif from outside */
                ifp->if_ipackets++;
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.204
diff -u -p -r1.204 if_ethersubr.c
--- net/if_ethersubr.c  8 Jun 2015 13:44:08 -0000       1.204
+++ net/if_ethersubr.c  8 Jun 2015 13:46:20 -0000
@@ -181,15 +181,6 @@ ether_output(struct ifnet *ifp, struct m
        struct arpcom *ac = (struct arpcom *)ifp;
        int error = 0;
 
-#ifdef DIAGNOSTIC
-       if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
-               printf("%s: trying to send packet on wrong domain. "
-                   "if %d vs. mbuf %d, AF %d\n", ifp->if_xname,
-                   ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid),
-                   dst->sa_family);
-       }
-#endif
-
        esrc = ac->ac_enaddr;
 
        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
@@ -276,47 +267,6 @@ ether_output(struct ifnet *ifp, struct m
        eh->ether_type = etype;
        memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
        memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
-
-#if NBRIDGE > 0
-       /*
-        * Interfaces that are bridgeports need special handling for output.
-        */
-       if (ifp->if_bridgeport) {
-               struct m_tag *mtag;
-
-               /*
-                * Check if this packet has already been sent out through
-                * this bridgeport, in which case we simply send it out
-                * without further bridge processing.
-                */
-               for (mtag = m_tag_find(m, PACKET_TAG_BRIDGE, NULL); mtag;
-                   mtag = m_tag_find(m, PACKET_TAG_BRIDGE, mtag)) {
-#ifdef DEBUG
-                       /* Check that the information is there */
-                       if (mtag->m_tag_len != sizeof(caddr_t)) {
-                               error = EINVAL;
-                               goto bad;
-                       }
-#endif
-                       if (!memcmp(&ifp->if_bridgeport, mtag + 1,
-                           sizeof(caddr_t)))
-                               break;
-               }
-               if (mtag == NULL) {
-                       /* Attach a tag so we can detect loops */
-                       mtag = m_tag_get(PACKET_TAG_BRIDGE, sizeof(caddr_t),
-                           M_NOWAIT);
-                       if (mtag == NULL) {
-                               error = ENOBUFS;
-                               goto bad;
-                       }
-                       memcpy(mtag + 1, &ifp->if_bridgeport, sizeof(caddr_t));
-                       m_tag_prepend(m, mtag);
-                       error = bridge_output(ifp, m, NULL, NULL);
-                       return (error);
-               }
-       }
-#endif
 
        return (if_output(ifp, m));
 bad:
Index: sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.191
diff -u -p -r1.191 mbuf.h
--- sys/mbuf.h  23 May 2015 12:52:59 -0000      1.191
+++ sys/mbuf.h  8 Jun 2015 13:46:20 -0000
@@ -454,7 +454,6 @@ struct m_tag *m_tag_next(struct mbuf *, 
 /* Packet tag types */
 #define PACKET_TAG_IPSEC_IN_DONE       0x0001  /* IPsec applied, in */
 #define PACKET_TAG_IPSEC_OUT_DONE      0x0002  /* IPsec applied, out */
-#define PACKET_TAG_BRIDGE              0x0020  /* Bridge processing done */
 #define PACKET_TAG_GIF                 0x0040  /* GIF processing done */
 #define PACKET_TAG_GRE                 0x0080  /* GRE processing done */
 #define PACKET_TAG_DLT                 0x0100 /* data link layer type */

Reply via email to