Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Feb 2007 18:28:41 +0000
From:      "Bruce M. Simpson" <bms@FreeBSD.org>
To:        freebsd-net@freebsd.org
Subject:   [PATCH] Part 2 of low level 802.1p priority support
Message-ID:  <45CE0ED9.1010905@FreeBSD.org>
In-Reply-To: <45CDFA18.3030102@incunabulum.net>
References:  <45CDFA18.3030102@incunabulum.net>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------010103080400010007000103
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

This updated patch moves VLAN tag decapsulation into if_ethersubr.c and 
always uses M_VLANTAG, which is also passed to the upper layer.

Tests with ping:
fxp (no VLAN_HWTAGGING support)      OK
msk (VLAN_HWTAGGING enabled)         OK
msk (VLAN_HWTAGGING disanabled)     FAIL

I am concerned that this may need review and testing to support 
situations where we do nested VLANs or with bridge(4) before it can be 
committed.

Further testing with drivers is needed (I can't be 100% sure it fails 
with msk(4) because something strange is happening when vlan tagging is 
turned off). Perhaps Pyun knows?

Regards,
BMS



--------------010103080400010007000103
Content-Type: text/x-patch;
 name="8021q-part2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="8021q-part2.diff"

Index: if_ethersubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.222
diff -u -p -r1.222 if_ethersubr.c
--- if_ethersubr.c	24 Dec 2006 08:52:13 -0000	1.222
+++ if_ethersubr.c	10 Feb 2007 18:16:54 -0000
@@ -701,43 +701,50 @@ post_stats:
 		}
 	}
 #endif
-
 	/*
-	 * Check to see if the device performed the VLAN decapsulation and
-	 * provided us with the tag.
+	 * If the device did not perform decapsulation of the 802.1q VLAN
+	 * header itself, do this now, and tag the mbuf with M_VLANTAG.
+	 * Remove the 802.1q header by copying the Ethernet addresses over
+	 * it and adjusting the beginning of the data in the mbuf.
+	 * Re-inspect the ether_type field so we do the right thing
+	 * for VLAN 0.
 	 */
-	if (m->m_flags & M_VLANTAG) {
-		/*
-		 * If no VLANs are configured, drop.
-		 */
-		if (ifp->if_vlantrunk == NULL) {
-			ifp->if_noproto++;
-			m_freem(m);
+	if ((ether_type == ETHERTYPE_VLAN) && !(m->m_flags & M_VLANTAG)) {
+		struct ether_vlan_header *evl;
+
+		if (m->m_len < sizeof(*evl) &&
+		    (m = m_pullup(m, sizeof(*evl))) == NULL) {
+			if_printf(ifp, "cannot pullup VLAN header\n");
 			return;
 		}
-		/*
-		 * vlan_input() will either recursively call ether_input()
-		 * or drop the packet.
-		 */
-		KASSERT(vlan_input_p != NULL,("ether_input: VLAN not loaded!"));
-		(*vlan_input_p)(ifp, m);
-		return;
+
+		evl = mtod(m, struct ether_vlan_header *);
+		m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag);
+		m->m_flags |= M_VLANTAG;
+		bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
+		      ETHER_HDR_LEN - ETHER_TYPE_LEN);
+		m_adj(m, ETHER_VLAN_ENCAP_LEN);
+		/* We need to see the inner type field in case of reentry. */
+		eh = mtod(m, struct ether_header *);
+		ether_type = ntohs(eh->ether_type);
 	}
 
 	/*
-	 * Handle protocols that expect to have the Ethernet header
-	 * (and possibly FCS) intact.
+	 * Deal with numbered 802.1q VLANs, by passing these frames to
+	 * the VLAN input handler. Frames destined for VLAN 0 are for
+	 * the main input path. Otherwise, drop frames with VLAN tags.
 	 */
-	switch (ether_type) {
-	case ETHERTYPE_VLAN:
+	if ((m->m_flags & M_VLANTAG) &&
+	    EVL_VLANOFTAG(m->m_pkthdr.ether_vtag) != EVL_VLAN_ZERO) {
 		if (ifp->if_vlantrunk != NULL) {
-			KASSERT(vlan_input_p,("ether_input: VLAN not loaded!"));
+			KASSERT(vlan_input_p,
+			    ("ether_input: VLAN not loaded!"));
 			(*vlan_input_p)(ifp, m);
 		} else {
 			ifp->if_noproto++;
 			m_freem(m);
+			return;
 		}
-		return;
 	}
 
 	/* Strip off Ethernet header. */
Index: if_vlan.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vlan.c,v
retrieving revision 1.117
diff -u -p -r1.117 if_vlan.c
--- if_vlan.c	30 Dec 2006 21:10:25 -0000	1.117
+++ if_vlan.c	10 Feb 2007 18:16:54 -0000
@@ -911,51 +911,9 @@ vlan_input(struct ifnet *ifp, struct mbu
 	uint16_t tag;
 
 	KASSERT(trunk != NULL, ("%s: no trunk", __func__));
+	KASSERT((m->m_flags & M_VLANTAG),("%s: M_VLANTAG not set", __func__));
 
-	if (m->m_flags & M_VLANTAG) {
-		/*
-		 * Packet is tagged, but m contains a normal
-		 * Ethernet frame; the tag is stored out-of-band.
-		 */
-		tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
-		m->m_flags &= ~M_VLANTAG;
-	} else {
-		struct ether_vlan_header *evl;
-
-		/*
-		 * Packet is tagged in-band as specified by 802.1q.
-		 */
-		switch (ifp->if_type) {
-		case IFT_ETHER:
-			if (m->m_len < sizeof(*evl) &&
-			    (m = m_pullup(m, sizeof(*evl))) == NULL) {
-				if_printf(ifp, "cannot pullup VLAN header\n");
-				return;
-			}
-			evl = mtod(m, struct ether_vlan_header *);
-			tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
-
-			/*
-			 * Remove the 802.1q header by copying the Ethernet
-			 * addresses over it and adjusting the beginning of
-			 * the data in the mbuf.  The encapsulated Ethernet
-			 * type field is already in place.
-			 */
-			bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
-			      ETHER_HDR_LEN - ETHER_TYPE_LEN);
-			m_adj(m, ETHER_VLAN_ENCAP_LEN);
-			break;
-
-		default:
-#ifdef INVARIANTS
-			panic("%s: %s has unsupported if_type %u",
-			      __func__, ifp->if_xname, ifp->if_type);
-#endif
-			m_freem(m);
-			ifp->if_noproto++;
-			return;
-		}
-	}
+	tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
 
 	TRUNK_RLOCK(trunk);
 #ifdef VLAN_ARRAY
Index: if_vlan_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vlan_var.h,v
retrieving revision 1.25
diff -u -p -r1.25 if_vlan_var.h
--- if_vlan_var.h	17 Sep 2006 13:33:29 -0000	1.25
+++ if_vlan_var.h	10 Feb 2007 18:16:54 -0000
@@ -43,6 +43,7 @@ struct	ether_vlan_header {
 #define EVL_VLID_MASK	0x0FFF
 #define	EVL_VLANOFTAG(tag) ((tag) & EVL_VLID_MASK)
 #define	EVL_PRIOFTAG(tag) (((tag) >> 13) & 7)
+#define	EVL_VLAN_ZERO	0	/* 802.1p priority frames use VLAN 0. */
 
 /* sysctl(3) tags, for compatibility purposes */
 #define	VLANCTL_PROTO	1

--------------010103080400010007000103--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45CE0ED9.1010905>