NetBSD Problem Report #18102

Received: (qmail 21429 invoked by uid 605); 29 Aug 2002 09:56:51 -0000
Message-Id: <20020829095618.CEDEC22E0D@trangie.ilink.sony.co.jp>
Date: Thu, 29 Aug 2002 18:56:18 +0900 (JST)
From: haya@ilink.sony.co.jp
Sender: gnats-bugs-owner@netbsd.org
Reply-To: haya@ilink.sony.co.jp
To: gnats-bugs@gnats.netbsd.org
Subject: Network interfaces do not receive VLAN-tagged packet with VLAN id 0.
X-Send-Pr-Version: 3.95

>Number:         18102
>Category:       kern
>Synopsis:       Network i/f does not receive VLAN-tagged packet w/ VLAN id 0.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 29 09:57:00 +0000 2002
>Closed-Date:    
>Last-Modified:  
>Originator:     HAYAKAWA Koichi
>Release:        NetBSD 1.6E
>Organization:

>Environment:


System: NetBSD trangie 1.6E NetBSD 1.6E (TRANGIE) #20: Tue Aug 20 19:00:22 JST 2002 haya@trangie:/home/haya/src/NetBSD/syssrc/sys/arch/i386/compile/TRANGIE i386
Architecture: i386
Machine: i386
>Description:


All VLAN-tagged packets with VLAN id 0 are not received by
NetBSD kernel.

IEEE 802.1D spec says a packet which VLAN tag ID is 0 should
be treated as an untagged packet when it is received.

>How-To-Repeat:


1. make NetBSD kernel with pseudodevice vlan enabled.
2. enable a network interface which has vlan capability.
3. send VLAN-tagged packets w/ VLAN id 0 to the network interface.
4. NetBSD wont receive VLAN-tagged packets w/ VLAN id 0.

>Fix:


This patch would fix this problem.

-- 
Index: sys/net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ethersubr.c,v
retrieving revision 1.98
diff -c -r1.98 if_ethersubr.c
*** sys/net/if_ethersubr.c	2002/08/26 01:39:39	1.98
--- sys/net/if_ethersubr.c	2002/08/27 11:38:15
***************
*** 762,798 ****
  	 * see if the device performed the decapsulation and
  	 * provided us with the tag.
  	 */
! 	if (ec->ec_nvlans &&
! 	    (n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN)) != NULL) {
  #if NVLAN > 0
  		/*
! 		 * vlan_input() will either recursively call ether_input()
! 		 * or drop the packet.
  		 */
- 		vlan_input(ifp, m);
  #else
  		m_freem(m);
- #endif
  		return;
  	}

  	/*
  	 * Handle protocols that expect to have the Ethernet header
  	 * (and possibly FCS) intact.
  	 */
  	switch (etype) {
- #if NVLAN > 0
- 	case ETHERTYPE_VLAN:
- 		/*
- 		 * vlan_input() will either recursively call ether_input()
- 		 * or drop the packet.
- 		 */
- 		if (((struct ethercom *)ifp)->ec_nvlans != 0)
- 			vlan_input(ifp, m);
- 		else
- 			m_freem(m);
- 		return;
- #endif /* NVLAN > 0 */
  #if NPPPOE > 0
  	case ETHERTYPE_PPPOEDISC:
  	case ETHERTYPE_PPPOE:
--- 762,846 ----
  	 * see if the device performed the decapsulation and
  	 * provided us with the tag.
  	 */
! 	if ((n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN)) != NULL) {
  #if NVLAN > 0
+ 		u_int tag;
+ 
+ 		/* m contains a normal ethernet frame, the tag is in m_aux */
+ 		tag = EVL_VLANOFTAG(*mtod(n, int *));
+ 		m_aux_delete(m, n);
+ 
+ 		if (tag != 0) {
+ 			/* VLAN-tagged frame (IEEE 802.1D 3.18) */
+ 			if (ec->ec_nvlans > 0) {
+ 				vlan_input(ifp, m, tag);
+ 			} else {
+ 				m_freem(m);
+ 			}
+ 			return;
+ 		}
  		/*
! 		 * priority-tagged frame (IEEE 802.1D 3.8) must be
! 		 * treated same as non-tagged frame.
  		 */
  #else
  		m_freem(m);
  		return;
+ #endif
  	}

+ 	if (etype == ETHERTYPE_VLAN) {
+ #if NVLAN > 0
+ 		u_int tag;
+ 		struct ether_vlan_header *evl;
+ 
+ 		if (m->m_len < sizeof(struct ether_vlan_header) &&
+ 		    (m = m_pullup(m,
+ 			sizeof(struct ether_vlan_header))) == NULL) {
+ 			printf("%s: no memory for VLAN header, "
+ 			    "dropping packet.\n", ifp->if_xname);
+ 			return;
+ 		}
+ 		evl = mtod(m, struct ether_vlan_header *);
+ 		KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN);
+ 
+ 		tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
+ 
+ 		/* Find a VLAN-tagged frame but no VLAN if */
+ 		if (tag != 0 && ec->ec_nvlans == 0) {
+ 			m_freem(m);
+ 			return;
+ 		}
+ 
+ 		/*
+ 		 * Restore the original ethertype.  We'll remove
+ 		 * the encapsulation.
+ 		 */
+ 		etype = evl->evl_encap_proto = evl->evl_proto;
+ 
+ 		memmove(mtod(m, caddr_t) + ETHER_VLAN_ENCAP_LEN,
+ 		    mtod(m, caddr_t), sizeof(struct ether_header));
+ 		m_adj(m, ETHER_VLAN_ENCAP_LEN);
+ 
+ 		if (tag != 0) {
+ 			/* VLAN-tagged frame (IEEE 802.1D 3.18) */
+ 			vlan_input(ifp, m, tag);
+ 			return;
+ 		}
+ 		/*
+ 		 * priority-tagged frame (IEEE 802.1D 3.8) must be
+ 		 * treated same as non-tagged frame.
+ 		 */
+ #else
+ 		m_freem(m);
+ #endif /* NVLAN > 0 */
+ 	}
+ 
  	/*
  	 * Handle protocols that expect to have the Ethernet header
  	 * (and possibly FCS) intact.
  	 */
  	switch (etype) {
  #if NPPPOE > 0
  	case ETHERTYPE_PPPOEDISC:
  	case ETHERTYPE_PPPOE:
Index: sys/net/if_vlan.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_vlan.c,v
retrieving revision 1.34
diff -c -r1.34 if_vlan.c
*** sys/net/if_vlan.c	2002/06/11 06:00:57	1.34
--- sys/net/if_vlan.c	2002/08/27 11:38:16
***************
*** 812,882 ****
   * the parent's input routine.
   */
  void
! vlan_input(struct ifnet *ifp, struct mbuf *m)
  {
  	struct ifvlan *ifv;
- 	u_int tag;
- 	struct mbuf *n;

! 	n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN);
! 	if (n) {
! 		/* m contains a normal ethernet frame, the tag is in m_aux */
! 		tag = *mtod(n, int *);
! 		m_aux_delete(m, n);
! 		for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
! 		    ifv = LIST_NEXT(ifv, ifv_list))
! 			if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
! 				break;
! 	} else {
! 		switch (ifp->if_type) {
! 		case IFT_ETHER:
! 		    {
! 			struct ether_vlan_header *evl;
! 
! 			if (m->m_len < sizeof(struct ether_vlan_header) &&
! 			    (m = m_pullup(m,
! 			     sizeof(struct ether_vlan_header))) == NULL) {
! 				printf("%s: no memory for VLAN header, "
! 				    "dropping packet.\n", ifp->if_xname);
! 				return;
! 			}
! 			evl = mtod(m, struct ether_vlan_header *);
! 			KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN);
! 
! 			tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
! 
! 			/*
! 			 * Restore the original ethertype.  We'll remove
! 			 * the encapsulation after we've found the vlan
! 			 * interface corresponding to the tag.
! 			 */
! 			evl->evl_encap_proto = evl->evl_proto;
  			break;
- 		    }
- 
- 		default:
- 			tag = (u_int) -1;	/* XXX GCC */
- #ifdef DIAGNOSTIC
- 			panic("vlan_input: impossible");
- #endif
- 		}
- 
- 		for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
- 		     ifv = LIST_NEXT(ifv, ifv_list))
- 			if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
- 				break;
- 
- 
- 		/*
- 		 * Now, remove the encapsulation header.  The original
- 		 * header has already been fixed up above.
- 		 */
- 		if (ifv) {
- 			memmove(mtod(m, caddr_t) + ifv->ifv_encaplen,
- 			    mtod(m, caddr_t), sizeof(struct ether_header));
- 			m_adj(m, ifv->ifv_encaplen);
- 		}
- 	}

  	if (ifv == NULL ||
  	    (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
--- 812,825 ----
   * the parent's input routine.
   */
  void
! vlan_input(struct ifnet *ifp, struct mbuf *m, u_int tag)
  {
  	struct ifvlan *ifv;

! 	for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
! 	     ifv = LIST_NEXT(ifv, ifv_list))
! 		if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
  			break;

  	if (ifv == NULL ||
  	    (ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
Index: sys/net/if_vlanvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_vlanvar.h,v
retrieving revision 1.4
diff -c -r1.4 if_vlanvar.h
*** sys/net/if_vlanvar.h	2000/10/03 23:50:52	1.4
--- sys/net/if_vlanvar.h	2002/08/27 11:38:16
***************
*** 91,97 ****
  #define	SIOCGETVLAN	SIOCGIFGENERIC

  #ifdef _KERNEL
! void	vlan_input(struct ifnet *, struct mbuf *);
  void	vlan_ifdetach(struct ifnet *);
  #endif	/* _KERNEL */

--- 91,97 ----
  #define	SIOCGETVLAN	SIOCGIFGENERIC

  #ifdef _KERNEL
! void	vlan_input(struct ifnet *, struct mbuf *, u_int);
  void	vlan_ifdetach(struct ifnet *);
  #endif	/* _KERNEL */

-- 
>Release-Note:
>Audit-Trail:
>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.