Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Handling frames that vlan id is 0 as non-VLAN frames



details:   https://anonhg.NetBSD.org/src/rev/bb506c6bce0b
branches:  trunk
changeset: 367257:bb506c6bce0b
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Mon Jun 20 08:02:25 2022 +0000

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

diffstat:

 sys/net/agr/if_agr.c   |   14 +++--
 sys/net/if.h           |    5 +-
 sys/net/if_ethersubr.c |  114 ++++++++++++++++++++++++------------------------
 sys/net/if_vlan.c      |   25 +++++-----
 sys/net/if_vlanvar.h   |    4 +-
 5 files changed, 83 insertions(+), 79 deletions(-)

diffs (truncated from 316 to 300 lines):

diff -r 4b3f481e184d -r bb506c6bce0b sys/net/agr/if_agr.c
--- a/sys/net/agr/if_agr.c      Sun Jun 19 18:51:06 2022 +0000
+++ b/sys/net/agr/if_agr.c      Mon Jun 20 08:02:25 2022 +0000
@@ -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 @@
         * 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);
diff -r 4b3f481e184d -r bb506c6bce0b sys/net/if.h
--- a/sys/net/if.h      Sun Jun 19 18:51:06 2022 +0000
+++ b/sys/net/if.h      Mon Jun 20 08:02:25 2022 +0000
@@ -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 @@
 /* 
  * 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 */
 
diff -r 4b3f481e184d -r bb506c6bce0b sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c    Sun Jun 19 18:51:06 2022 +0000
+++ b/sys/net/if_ethersubr.c    Mon Jun 20 08:02:25 2022 +0000
@@ -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 @@
 
        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 @@
                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 @@
 #endif
 
        /*
-        * If VLANs are configured on the interface, check to
-        * see if the device performed the decapsulation and
-        * provided us with the tag.
+        * 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().
         */
-       if (ec->ec_nvlans && vlan_has_tag(m)) {
+       if (vlan_has_tag(m) || etype == ETHERTYPE_VLAN) {
+               struct ether_vlan_header *evl = (void *)eh;
+               uint16_t vlan_id;
+
+               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 (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.
                 */
-               vlan_input(ifp, m);
-               return;
-#else
-               goto noproto;
+               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
-       }
 
        /*
         * Handle protocols that expect to have the Ethernet header
         * (and possibly FCS) intact.
         */
        switch (etype) {
-       case ETHERTYPE_VLAN: {
-               struct ether_vlan_header *evl = (void *)eh;
-
-               /*
-                * 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) {
-                       etype = ntohs(evl->evl_proto);
-                       ehlen = sizeof(*evl);
-                       if ((m->m_flags & M_PROMISC) == 0 &&
-                           (etype == ETHERTYPE_IP ||
-                            etype == ETHERTYPE_IPV6))
-                               break;
-               }
-
-#if NVLAN > 0
-               /*
-                * vlan_input() will either recursively call ether_input()
-                * or drop the packet.
-                */
-               if (ec->ec_nvlans != 0) {
-                       vlan_input(ifp, m);
-                       return;
-               } else
-#endif
-                       goto noproto;
-       }
-
 #if NPPPOE > 0
        case ETHERTYPE_PPPOEDISC:
                pppoedisc_input(ifp, m);
diff -r 4b3f481e184d -r bb506c6bce0b sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Sun Jun 19 18:51:06 2022 +0000
+++ b/sys/net/if_vlan.c Mon Jun 20 08:02:25 2022 +0000
@@ -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 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 @@
  * 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 @@
                     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 @@
                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 @@
        if_input(&ifv->ifv_if, m);
 out:
        vlan_putref_linkmib(mib, &psref);
+       return NULL;
 }
 
 /*
diff -r 4b3f481e184d -r bb506c6bce0b sys/net/if_vlanvar.h
--- a/sys/net/if_vlanvar.h      Sun Jun 19 18:51:06 2022 +0000



Home | Main Index | Thread Index | Old Index