Heya, 

So here is a crude diff, the shiffting can be improved and if we wan't
this in the future we'll need a knob to enable "don't touch the
vlanprio thingy".

Please it would be great if you can give this a spin Peter. I did some
basic tests with a re(4) (hw tagging) and a rl(4) (no hw tagging). 

Index: sys/net/if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.88
diff -d -u -p -w -r1.88 if_vlan.c
--- sys/net/if_vlan.c   20 Aug 2011 06:21:32 -0000      1.88
+++ sys/net/if_vlan.c   28 Aug 2011 05:15:37 -0000
@@ -225,6 +225,11 @@ vlan_start(struct ifnet *ifp)
                 */
                if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
                    (ifv->ifv_type == ETHERTYPE_VLAN)) {
+                       /* Don't touch the priority */
+                       if (m->m_flags & M_VLANPRIO) {
+                               m->m_pkthdr.ether_vtag &= ~EVL_VLID_MASK;
+                               m->m_pkthdr.ether_vtag |= ifv->ifv_tag;
+                       } else
                        m->m_pkthdr.ether_vtag = ifv->ifv_tag +
                            (ifv->ifv_prio << EVL_PRIO_BITS);
                        m->m_flags |= M_VLANTAG;
@@ -234,6 +239,12 @@ vlan_start(struct ifnet *ifp)
                        m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
                        evh.evl_proto = evh.evl_encap_proto;
                        evh.evl_encap_proto = htons(ifv->ifv_type);
+                       if (m->m_flags & M_VLANPRIO)
+                               /* XXX can be simpler */
+                               evh.evl_tag = htons(ifv->ifv_tag +
+                                   (EVL_PRIOFTAG(m->m_pkthdr.ether_vtag)
+                                   << EVL_PRIO_BITS));
+                       else
                        evh.evl_tag = htons(ifv->ifv_tag +
                            (ifv->ifv_prio << EVL_PRIO_BITS));
 
@@ -319,9 +330,13 @@ vlan_input(struct ether_header *eh, stru
         * reentrant!).
         */
        m->m_pkthdr.rcvif = &ifv->ifv_if;
+       m->m_flags |= M_VLANPRIO; /* XXX test only remove me */
        if (m->m_flags & M_VLANTAG) {
                m->m_flags &= ~M_VLANTAG;
        } else {
+               if (m->m_flags & M_VLANPRIO)
+                       m->m_pkthdr.ether_vtag =
+                           ntohs(*mtod(m, u_int16_t *));
                eh->ether_type = mtod(m, u_int16_t *)[1];
                m->m_len -= EVL_ENCAPLEN;
                m->m_data += EVL_ENCAPLEN;
Index: sys/sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.155
diff -d -u -p -w -r1.155 mbuf.h
--- sys/sys/mbuf.h      8 Jul 2011 18:48:51 -0000       1.155
+++ sys/sys/mbuf.h      28 Aug 2011 03:58:05 -0000
@@ -71,7 +71,7 @@ struct m_hdr {
        caddr_t mh_data;                /* location of data */
        u_int   mh_len;                 /* amount of data in this mbuf */
        short   mh_type;                /* type of data in this mbuf */
-       u_short mh_flags;               /* flags; see below */
+       u_int32_t mh_flags;             /* flags; see below */
 };
 
 /* pf stuff */
@@ -171,10 +171,12 @@ struct mbuf {
 #define M_AUTH_AH      0x2000  /* header was authenticated (AH) */
 #define M_COMP         0x4000  /* header was decompressed */
 #define M_LINK0                0x8000  /* link layer specific flag */
+#define M_VLANPRIO     0x10000 /* vlanprio bits are valid */
 
 /* flags copied when copying m_pkthdr */
 #define        M_COPYFLAGS     
(M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST|M_CONF|M_COMP|\
-                        M_AUTH|M_LOOP|M_TUNNEL|M_LINK0|M_VLANTAG|M_FILDROP)
+                        M_AUTH|M_LOOP|M_TUNNEL|M_LINK0|M_VLANTAG|M_FILDROP|\
+                        M_VLANPRIO)
 
 /* Checksumming flags */
 #define        M_IPV4_CSUM_OUT         0x0001  /* IPv4 checksum needed */

Reply via email to