M_PROTO1 is used by if_bridge on the input path.  On the output path it's 
used now only by if_bridge for if_gif.  I think we can use it generically 
to mark packets as "processed by bridge" in the output path.

The diff simplifies things and avoids mtag checking and allocation so is 
more efficient too.

The old code checks if a packet has passed the _same_ bridge already, but 
as an interface can only be a member of one bridge I think the flag is 
sufficient.

It looks like the only other user of M_PROTO1 is netbt/hci_link.c, but 
that can be fixed if the diff is acceptable otherwise.

Tested lightly in a bridge/gif setup, but could use some more testing.
(especially with ipsec in the mix too)


Index: if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.193
diff -u -p -r1.193 if_bridge.c
--- if_bridge.c 4 Jul 2011 06:54:49 -0000       1.193
+++ if_bridge.c 28 Oct 2011 17:55:04 -0000
@@ -2813,9 +2813,8 @@ bridge_ifenqueue(struct bridge_softc *sc
 #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 */
+               /* XXX do this in if_gif? */
                ifp->if_ipackets++;
                ifp->if_ibytes += m->m_pkthdr.len;
        }
@@ -2844,6 +2843,7 @@ bridge_ifenqueue(struct bridge_softc *sc
        }
 #endif
        len = m->m_pkthdr.len;
+       m->m_flags |= M_PROTO1;
        mflags = m->m_flags;
        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        if (error) {
Index: if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.151
diff -u -p -r1.151 if_ethersubr.c
--- if_ethersubr.c      9 Jul 2011 00:47:18 -0000       1.151
+++ if_ethersubr.c      28 Oct 2011 17:55:04 -0000
@@ -382,40 +382,8 @@ ether_output(ifp0, m0, dst, rt0)
         * Interfaces that are bridge members need special handling
         * for output.
         */
-       if (ifp->if_bridge) {
-               struct m_tag *mtag;
-
-               /*
-                * Check if this packet has already been sent out through
-                * this bridge, 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 (!bcmp(&ifp->if_bridge, 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;
-                       }
-                       bcopy(&ifp->if_bridge, mtag + 1, sizeof(caddr_t));
-                       m_tag_prepend(m, mtag);
-                       error = bridge_output(ifp, m, NULL, NULL);
-                       return (error);
-               }
-       }
+       if (ifp->if_bridge && !(m->m_flags & M_PROTO1))
+               return (bridge_output(ifp, m, NULL, NULL));
 #endif
        mflags = m->m_flags;
        len = m->m_pkthdr.len;

Reply via email to