Module Name:    src
Committed By:   yamaguchi
Date:           Mon Jun 20 08:02:26 UTC 2022

Modified Files:
        src/sys/net: if.h if_ethersubr.c if_vlan.c if_vlanvar.h
        src/sys/net/agr: if_agr.c

Log Message:
Handling frames that vlan id is 0 as non-VLAN frames
even if a vlan tag is stripped by harware offloading


To generate a diff of this commit:
cvs rdiff -u -r1.296 -r1.297 src/sys/net/if.h
cvs rdiff -u -r1.311 -r1.312 src/sys/net/if_ethersubr.c
cvs rdiff -u -r1.167 -r1.168 src/sys/net/if_vlan.c
cvs rdiff -u -r1.16 -r1.17 src/sys/net/if_vlanvar.h
cvs rdiff -u -r1.54 -r1.55 src/sys/net/agr/if_agr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.296 src/sys/net/if.h:1.297
--- src/sys/net/if.h:1.296	Fri Dec 31 14:24:26 2021
+++ src/sys/net/if.h	Mon Jun 20 08:02:25 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.296 2021/12/31 14:24:26 riastradh Exp $	*/
+/*	$NetBSD: if.h,v 1.297 2022/06/20 08:02:25 yamaguchi Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -1409,7 +1409,8 @@ int	sysctl_ifq(int *name, u_int namelen,
 /* 
  * Hook for if_vlan - needed by if_agr
  */
-MODULE_HOOK(if_vlan_vlan_input_hook, void, (struct ifnet *, struct mbuf *));
+MODULE_HOOK(if_vlan_vlan_input_hook,
+    struct mbuf *, (struct ifnet *, struct mbuf *));
 
 #endif /* _KERNEL */
 

Index: src/sys/net/if_ethersubr.c
diff -u src/sys/net/if_ethersubr.c:1.311 src/sys/net/if_ethersubr.c:1.312
--- src/sys/net/if_ethersubr.c:1.311	Mon Apr  4 06:10:00 2022
+++ src/sys/net/if_ethersubr.c	Mon Jun 20 08:02:25 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ethersubr.c,v 1.311 2022/04/04 06:10:00 yamaguchi Exp $	*/
+/*	$NetBSD: if_ethersubr.c,v 1.312 2022/06/20 08:02:25 yamaguchi Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.311 2022/04/04 06:10:00 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.312 2022/06/20 08:02:25 yamaguchi Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -725,19 +725,6 @@ ether_input(struct ifnet *ifp, struct mb
 
 	if_statadd(ifp, if_ibytes, m->m_pkthdr.len);
 
-#if NCARP > 0
-	if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) {
-		/*
-		 * Clear M_PROMISC, in case the packet comes from a
-		 * vlan.
-		 */
-		m->m_flags &= ~M_PROMISC;
-		if (carp_input(m, (uint8_t *)&eh->ether_shost,
-		    (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0)
-			return;
-	}
-#endif
-
 	if ((m->m_flags & (M_BCAST | M_MCAST | M_PROMISC)) == 0 &&
 	    (ifp->if_flags & IFF_PROMISC) != 0 &&
 	    memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
@@ -755,6 +742,10 @@ ether_input(struct ifnet *ifp, struct mb
 		etype = ntohs(eh->ether_type);
 	}
 
+	/*
+	 * Processing a logical interfaces that are able
+	 * to configure vlan(4).
+	*/
 #if NAGR > 0
 	if (ifp->if_lagg != NULL &&
 	    __predict_true(etype != ETHERTYPE_SLOWPROTOCOLS)) {
@@ -765,59 +756,68 @@ ether_input(struct ifnet *ifp, struct mb
 #endif
 
 	/*
-	 * If VLANs are configured on the interface, check to
-	 * see if the device performed the decapsulation and
-	 * provided us with the tag.
-	 */
-	if (ec->ec_nvlans && vlan_has_tag(m)) {
-#if NVLAN > 0
-		/*
-		 * vlan_input() will either recursively call ether_input()
-		 * or drop the packet.
-		 */
-		vlan_input(ifp, m);
-		return;
-#else
-		goto noproto;
-#endif
-	}
-
-	/*
-	 * Handle protocols that expect to have the Ethernet header
-	 * (and possibly FCS) intact.
+	 * VLAN processing.
+	 *
+	 * VLAN provides service delimiting so the frames are
+	 * processed before other handlings. If a VLAN interface
+	 * does not exist to take those frames, they're returned
+	 * to ether_input().
 	 */
-	switch (etype) {
-	case ETHERTYPE_VLAN: {
+	if (vlan_has_tag(m) || etype == ETHERTYPE_VLAN) {
 		struct ether_vlan_header *evl = (void *)eh;
+		uint16_t vlan_id;
 
-		/*
-		 * If there is a tag of 0, then the VLAN header was probably
-		 * just being used to store the priority.  Extract the ether
-		 * type, and if IP or IPV6, let them deal with it.
-		 */
-		if (m->m_len >= sizeof(*evl) &&
-		    EVL_VLANOFTAG(ntohs(evl->evl_tag)) == 0) {
+		if (vlan_has_tag(m)) {
+			vlan_id = EVL_VLANOFTAG(vlan_get_tag(m));
+		} else {
+			if (m->m_len < sizeof(*evl))
+				goto error;
+
+			vlan_id = EVL_VLANOFTAG(ntohs(evl->evl_tag));
 			etype = ntohs(evl->evl_proto);
 			ehlen = sizeof(*evl);
-			if ((m->m_flags & M_PROMISC) == 0 &&
-			    (etype == ETHERTYPE_IP ||
-			     etype == ETHERTYPE_IPV6))
-				break;
 		}
 
+		if (vlan_id == 0) {
+			if (etype == ETHERTYPE_VLAN ||
+			     etype == ETHERTYPE_QINQ)
+				goto drop;
+
+			/* XXX we should actually use the prio value? */
+			m->m_flags &= ~M_VLANTAG;
+		} else {
 #if NVLAN > 0
+			if (ec->ec_nvlans > 0) {
+				m = vlan_input(ifp, m);
+
+				/* vlan_input() called ether_input() recursively */
+				if (m == NULL)
+					return;
+			}
+#endif
+			/* drop VLAN frames not for this port. */
+			goto noproto;
+		}
+	}
+
+#if NCARP > 0
+	if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) {
 		/*
-		 * vlan_input() will either recursively call ether_input()
-		 * or drop the packet.
+		 * Clear M_PROMISC, in case the packet comes from a
+		 * vlan.
 		 */
-		if (ec->ec_nvlans != 0) {
-			vlan_input(ifp, m);
+		m->m_flags &= ~M_PROMISC;
+		if (carp_input(m, (uint8_t *)&eh->ether_shost,
+		    (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0)
 			return;
-		} else
-#endif
-			goto noproto;
 	}
+#endif
 
+	/*
+	 * Handle protocols that expect to have the Ethernet header
+	 * (and possibly FCS) intact.
+	 */
+	switch (etype) {
 #if NPPPOE > 0
 	case ETHERTYPE_PPPOEDISC:
 		pppoedisc_input(ifp, m);

Index: src/sys/net/if_vlan.c
diff -u src/sys/net/if_vlan.c:1.167 src/sys/net/if_vlan.c:1.168
--- src/sys/net/if_vlan.c:1.167	Fri Dec 24 04:50:40 2021
+++ src/sys/net/if_vlan.c	Mon Jun 20 08:02:25 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_vlan.c,v 1.167 2021/12/24 04:50:40 yamaguchi Exp $	*/
+/*	$NetBSD: if_vlan.c,v 1.168 2022/06/20 08:02:25 yamaguchi Exp $	*/
 
 /*
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.167 2021/12/24 04:50:40 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.168 2022/06/20 08:02:25 yamaguchi Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -204,12 +204,13 @@ static int	vlan_unconfig_locked(struct i
 static void	vlan_hash_init(void);
 static int	vlan_hash_fini(void);
 static int	vlan_tag_hash(uint16_t, u_long);
-static struct ifvlan_linkmib*	vlan_getref_linkmib(struct ifvlan *,
-    struct psref *);
+static struct ifvlan_linkmib*
+		vlan_getref_linkmib(struct ifvlan *, struct psref *);
 static void	vlan_putref_linkmib(struct ifvlan_linkmib *, struct psref *);
 static void	vlan_linkmib_update(struct ifvlan *, struct ifvlan_linkmib *);
-static struct ifvlan_linkmib*	vlan_lookup_tag_psref(struct ifnet *,
-    uint16_t, struct psref *);
+static struct ifvlan_linkmib*
+		vlan_lookup_tag_psref(struct ifnet *, uint16_t,
+		    struct psref *);
 
 #if !defined(VLAN_TAG_HASH_SIZE)
 #define VLAN_TAG_HASH_SIZE 32
@@ -1518,7 +1519,7 @@ out:
  * given source interface and tag, then run the real packet through the
  * parent's input routine.
  */
-void
+struct mbuf *
 vlan_input(struct ifnet *ifp, struct mbuf *m)
 {
 	struct ifvlan *ifv;
@@ -1543,14 +1544,14 @@ vlan_input(struct ifnet *ifp, struct mbu
 		     sizeof(struct ether_vlan_header))) == NULL) {
 			printf("%s: no memory for VLAN header, "
 			    "dropping packet.\n", ifp->if_xname);
-			return;
+			return NULL;
 		}
 
 		if (m_makewritable(&m, 0,
 		    sizeof(struct ether_vlan_header), M_DONTWAIT)) {
 			m_freem(m);
 			if_statinc(ifp, if_ierrors);
-			return;
+			return NULL;
 		}
 
 		evl = mtod(m, struct ether_vlan_header *);
@@ -1566,11 +1567,10 @@ vlan_input(struct ifnet *ifp, struct mbu
 		evl->evl_encap_proto = evl->evl_proto;
 	}
 
+	KASSERT(vid != 0);
 	mib = vlan_lookup_tag_psref(ifp, vid, &psref);
 	if (mib == NULL) {
-		m_freem(m);
-		if_statinc(ifp, if_noproto);
-		return;
+		return m;
 	}
 	KASSERT(mib->ifvm_encaplen == ETHER_VLAN_ENCAP_LEN);
 
@@ -1621,6 +1621,7 @@ vlan_input(struct ifnet *ifp, struct mbu
 	if_input(&ifv->ifv_if, m);
 out:
 	vlan_putref_linkmib(mib, &psref);
+	return NULL;
 }
 
 /*

Index: src/sys/net/if_vlanvar.h
diff -u src/sys/net/if_vlanvar.h:1.16 src/sys/net/if_vlanvar.h:1.17
--- src/sys/net/if_vlanvar.h:1.16	Thu Sep 30 04:13:42 2021
+++ src/sys/net/if_vlanvar.h	Mon Jun 20 08:02:25 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_vlanvar.h,v 1.16 2021/09/30 04:13:42 yamaguchi Exp $	*/
+/*	$NetBSD: if_vlanvar.h,v 1.17 2022/06/20 08:02:25 yamaguchi Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -81,7 +81,7 @@ struct vlanreq {
 #define	SIOCGETVLAN	SIOCGIFGENERIC
 
 #ifdef _KERNEL
-void	vlan_input(struct ifnet *, struct mbuf *);
+struct mbuf *	vlan_input(struct ifnet *, struct mbuf *);
 
 /*
  * Locking notes:

Index: src/sys/net/agr/if_agr.c
diff -u src/sys/net/agr/if_agr.c:1.54 src/sys/net/agr/if_agr.c:1.55
--- src/sys/net/agr/if_agr.c:1.54	Fri Dec 31 14:25:24 2021
+++ src/sys/net/agr/if_agr.c	Mon Jun 20 08:02:25 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_agr.c,v 1.54 2021/12/31 14:25:24 riastradh Exp $	*/
+/*	$NetBSD: if_agr.c,v 1.55 2022/06/20 08:02:25 yamaguchi Exp $	*/
 
 /*-
  * Copyright (c)2005 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_agr.c,v 1.54 2021/12/31 14:25:24 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_agr.c,v 1.55 2022/06/20 08:02:25 yamaguchi Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -167,10 +167,12 @@ agr_input(struct ifnet *ifp_port, struct
 	 * see if the device performed the decapsulation and
 	 * provided us with the tag.
 	 */
-	if (ec->ec_nvlans && vlan_has_tag(m)) {
-		MODULE_HOOK_CALL_VOID(if_vlan_vlan_input_hook, (ifp, m),
-		    m_freem(m));
-		return;
+	if (ec->ec_nvlans && vlan_has_tag(m) &&
+	    EVL_VLANOFTAG(vlan_get_tag(m)) != 0) {
+		MODULE_HOOK_CALL(if_vlan_vlan_input_hook, (ifp, m),
+		    m, m);
+		if (m == NULL)
+			return;
 	}
 
 	if_percpuq_enqueue(ifp->if_percpuq, m);

Reply via email to