Hi,

This problem has always existed but now in RELENG_7+ since the vlan tag
is always stripped on the incoming packet its a little more obvious.

The bridging output function puts the mbuf directly on the interfaces
send queue so only network cards with VLAN_HWTAGGING will properly
re-tag any outgoing vlan frames.

The attached patch fixes this as well as putting the common vlan
encapsulation code in to ether_vlanencap().

Any comments please, I want to commit this soon so I have more chance of
getting it into 7.0


Andrew
Index: ethernet.h
===================================================================
RCS file: /home/ncvs/src/sys/net/ethernet.h,v
retrieving revision 1.32
diff -u -p -r1.32 ethernet.h
--- ethernet.h  29 May 2007 12:40:45 -0000      1.32
+++ ethernet.h  16 Oct 2007 01:18:28 -0000
@@ -386,6 +386,7 @@ extern      int  ether_output_frame(struct if
 extern char *ether_sprintf(const u_int8_t *);
 void   ether_vlan_mtap(struct bpf_if *, struct mbuf *,
            void *, u_int);
+struct mbuf * ether_vlanencap(struct mbuf *, int);
 
 #else /* _KERNEL */
 
Index: if_bridge.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_bridge.c,v
retrieving revision 1.103
diff -u -p -r1.103 if_bridge.c
--- if_bridge.c 16 Sep 2007 21:09:15 -0000      1.103
+++ if_bridge.c 16 Oct 2007 04:03:43 -0000
@@ -1653,7 +1653,23 @@ bridge_enqueue(struct bridge_softc *sc, 
        for (; m; m = m0) {
                m0 = m->m_nextpkt;
                m->m_nextpkt = NULL;
-               
+
+               /*
+                * If underlying interface can not do VLAN tag insertion itself
+                * then attach a packet tag that holds it.
+                */
+               if ((m->m_flags & M_VLANTAG) &&
+                   (dst_ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) {
+                       m = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
+                       if (m == NULL) {
+                               if_printf(dst_ifp,
+                                   "unable to prepend VLAN header\n");
+                               dst_ifp->if_oerrors++;
+                               continue;
+                       }
+                       m->m_flags &= ~M_VLANTAG;
+               }
+
                if (err == 0)
                        IFQ_ENQUEUE(&dst_ifp->if_snd, m, err);
        }
Index: if_ethersubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.236
diff -u -p -r1.236 if_ethersubr.c
--- if_ethersubr.c      14 Sep 2007 06:57:28 -0000      1.236
+++ if_ethersubr.c      16 Oct 2007 04:03:58 -0000
@@ -1249,5 +1249,33 @@ ether_vlan_mtap(struct bpf_if *bp, struc
        m->m_data -= sizeof(struct ether_header);
 }
 
+struct mbuf *
+ether_vlanencap(struct mbuf *m, int tag)
+{
+       struct ether_vlan_header *evl;
+
+       M_PREPEND(m, ETHER_VLAN_ENCAP_LEN, M_DONTWAIT);
+       if (m == NULL)
+               return (NULL);
+       /* M_PREPEND takes care of m_len, m_pkthdr.len for us */
+
+       if (m->m_len < sizeof(*evl)) {
+               m = m_pullup(m, sizeof(*evl));
+               if (m == NULL)
+                       return (NULL);
+       }
+
+       /*
+        * Transform the Ethernet header into an Ethernet header
+        * with 802.1Q encapsulation.
+        */
+       evl = mtod(m, struct ether_vlan_header *);
+       bcopy((char *)evl + ETHER_VLAN_ENCAP_LEN,
+           (char *)evl, ETHER_HDR_LEN - ETHER_TYPE_LEN);
+       evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
+       evl->evl_tag = htons(tag);
+       return (m);
+}
+
 DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
 MODULE_VERSION(ether, 1);
Index: if_vlan.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vlan.c,v
retrieving revision 1.124
diff -u -p -r1.124 if_vlan.c
--- if_vlan.c   19 Mar 2007 18:01:39 -0000      1.124
+++ if_vlan.c   16 Oct 2007 04:03:50 -0000
@@ -850,40 +850,13 @@ vlan_start(struct ifnet *ifp)
                        m->m_pkthdr.ether_vtag = ifv->ifv_tag;
                        m->m_flags |= M_VLANTAG;
                } else {
-                       struct ether_vlan_header *evl;
-
-                       M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT);
+                       m = ether_vlanencap(m, ifv->ifv_tag);
                        if (m == NULL) {
                                if_printf(ifp,
                                    "unable to prepend VLAN header\n");
                                ifp->if_oerrors++;
                                continue;
                        }
-                       /* M_PREPEND takes care of m_len, m_pkthdr.len for us */
-
-                       if (m->m_len < sizeof(*evl)) {
-                               m = m_pullup(m, sizeof(*evl));
-                               if (m == NULL) {
-                                       if_printf(ifp,
-                                           "cannot pullup VLAN header\n");
-                                       ifp->if_oerrors++;
-                                       continue;
-                               }
-                       }
-
-                       /*
-                        * Transform the Ethernet header into an Ethernet header
-                        * with 802.1Q encapsulation.
-                        */
-                       evl = mtod(m, struct ether_vlan_header *);
-                       bcopy((char *)evl + ifv->ifv_encaplen,
-                             (char *)evl, ETHER_HDR_LEN - ETHER_TYPE_LEN);
-                       evl->evl_encap_proto = htons(ifv->ifv_proto);
-                       evl->evl_tag = htons(ifv->ifv_tag);
-#ifdef DEBUG
-                       printf("%s: %*D\n", __func__, (int)sizeof(*evl),
-                           (unsigned char *)evl, ":");
-#endif
                }
 
                /*
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to