kern/161908: [netgraph] [patch] ng_vlan update for QinQ support

rozhuk.im at gmail.com rozhuk.im at gmail.com
Tue Oct 25 12:40:11 UTC 2011


The following reply was made to PR kern/161908; it has been noted by GNATS.

From: rozhuk.im at gmail.com
To: <bug-followup at FreeBSD.org>,
	<rozhuk.im at gmail.com>
Cc:  
Subject: Re: kern/161908: [netgraph] [patch] ng_vlan update for QinQ support
Date: Tue, 25 Oct 2011 21:38:40 +0900

 This is a multi-part message in MIME format.
 
 ------=_NextPart_000_033B_01CC935E.7927C480
 Content-Type: text/plain;
 	charset="windows-1251"
 Content-Transfer-Encoding: quoted-printable
 
 
 Fixed ng_parce_types in struct ng_cmdlist ng_vlan_cmdlist:
 
 "delvidflt": ng_parse_int16_type -> ng_parse_uint16_type
 "getencap": ng_parse_int32_type -> ng_parse_uint32_type
 "setencap": ng_parse_int32_type -> ng_parse_uint32_type
 "getencapproto": ng_parse_int32_type -> ng_parse_uint16_type
 "setencapproto": ng_parse_int32_type -> ng_parse_uint16_type
 
 
 
 --
 Rozhuk Ivan
 =A0=20
 
 
 
 ------=_NextPart_000_033B_01CC935E.7927C480
 Content-Type: application/octet-stream;
 	name="ng_vlan.patch"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
 	filename="ng_vlan.patch"
 
 --- /usr/src/sys/netgraph/ng_vlan.c.orig	2009-08-03 17:13:06.000000000 =
 +0900=0A=
 +++ /usr/src/sys/netgraph/ng_vlan.c	2011-10-23 03:41:00.000000000 +0900=0A=
 @@ -1,5 +1,6 @@=0A=
  /*-=0A=
   * Copyright (c) 2003 IPNET Internet Communication Company=0A=
 + * Copyright (c) 2011 Rozhuk Ivan <rozhuk.im at gmail.com>=0A=
   * All rights reserved.=0A=
   *=0A=
   * Redistribution and use in source and binary forms, with or without=0A=
 @@ -46,6 +47,22 @@=0A=
  #include <netgraph/ng_vlan.h>=0A=
  #include <netgraph/netgraph.h>=0A=
  =0A=
 +=0A=
 +=0A=
 +struct ng_vlan_private {=0A=
 +	hook_p		downstream_hook;=0A=
 +	hook_p		nomatch_hook;=0A=
 +	int		encap_enable;=0A=
 +	u_int16_t	encap_proto;=0A=
 +	hook_p		vlan_hook[(EVL_VLID_MASK + 1)];=0A=
 +};=0A=
 +typedef struct ng_vlan_private *priv_p;=0A=
 +=0A=
 +#define VLAN_TAG_MASK	0xFFFF=0A=
 +#define HOOK_VLAN_TAG_SET_MASK ((uintptr_t)((~0) & ~(VLAN_TAG_MASK)))=0A=
 +#define IS_HOOK_VLAN_SET(hook_data) ((((uintptr_t)hook_data) & =
 HOOK_VLAN_TAG_SET_MASK) =3D=3D HOOK_VLAN_TAG_SET_MASK)=0A=
 +=0A=
 +=0A=
  static ng_constructor_t	ng_vlan_constructor;=0A=
  static ng_rcvmsg_t	ng_vlan_rcvmsg;=0A=
  static ng_shutdown_t	ng_vlan_shutdown;=0A=
 @@ -105,11 +122,46 @@=0A=
  	},=0A=
  	{=0A=
  	  NGM_VLAN_COOKIE,=0A=
 +	  NGM_VLAN_DEL_VID_FLT,=0A=
 +	  "delvidflt",=0A=
 +	  &ng_parse_uint16_type,=0A=
 +	  NULL=0A=
 +	},=0A=
 +	{=0A=
 +	  NGM_VLAN_COOKIE,=0A=
  	  NGM_VLAN_GET_TABLE,=0A=
  	  "gettable",=0A=
  	  NULL,=0A=
  	  &ng_vlan_table_type=0A=
  	},=0A=
 +	{=0A=
 +	  NGM_VLAN_COOKIE,=0A=
 +	  NGM_VLAN_GET_ENCAP,=0A=
 +	  "getencap",=0A=
 +	  NULL,=0A=
 +	  &ng_parse_uint32_type=0A=
 +	},=0A=
 +	{=0A=
 +	  NGM_VLAN_COOKIE,=0A=
 +	  NGM_VLAN_SET_ENCAP,=0A=
 +	  "setencap",=0A=
 +	  &ng_parse_uint32_type,=0A=
 +	  NULL=0A=
 +	},=0A=
 +	{=0A=
 +	  NGM_VLAN_COOKIE,=0A=
 +	  NGM_VLAN_GET_ENCAP_PROTO,=0A=
 +	  "getencapproto",=0A=
 +	  NULL,=0A=
 +	  &ng_parse_uint16_type=0A=
 +	},=0A=
 +	{=0A=
 +	  NGM_VLAN_COOKIE,=0A=
 +	  NGM_VLAN_SET_ENCAP_PROTO,=0A=
 +	  "setencapproto",=0A=
 +	  &ng_parse_uint16_type,=0A=
 +	  NULL=0A=
 +	},=0A=
  	{ 0 }=0A=
  };=0A=
  =0A=
 @@ -126,47 +178,43 @@=0A=
  };=0A=
  NETGRAPH_INIT(vlan, &ng_vlan_typestruct);=0A=
  =0A=
 -struct filter {=0A=
 -	LIST_ENTRY(filter) next;=0A=
 -	u_int16_t	vlan;=0A=
 -	hook_p		hook;=0A=
 -};=0A=
  =0A=
 -#define	HASHSIZE	16=0A=
 -#define	HASH(id)	((((id) >> 8) ^ ((id) >> 4) ^ (id)) & 0x0f)=0A=
 -LIST_HEAD(filterhead, filter);=0A=
  =0A=
 -typedef struct {=0A=
 -	hook_p		downstream_hook;=0A=
 -	hook_p		nomatch_hook;=0A=
 -	struct filterhead hashtable[HASHSIZE];=0A=
 -	u_int32_t	nent;=0A=
 -} *priv_p;=0A=
 +//**********************************************************************=
 **=0A=
 +//			HELPER STUFF=0A=
 +//**********************************************************************=
 **=0A=
  =0A=
 -static struct filter *=0A=
 -ng_vlan_findentry(priv_p priv, u_int16_t vlan)=0A=
 +static __inline int=0A=
 +m_chk(struct mbuf **mp, int len)=0A=
  {=0A=
 -	struct filterhead *chain =3D &priv->hashtable[HASH(vlan)];=0A=
 -	struct filter *f;=0A=
 +	if ((*mp)->m_pkthdr.len < len) {=0A=
 +		m_freem((*mp));=0A=
 +		(*mp) =3D NULL;=0A=
 +		return (EINVAL);=0A=
 +	}=0A=
 +	if ((*mp)->m_len < len && ((*mp) =3D m_pullup((*mp), len)) =3D=3D NULL)=0A=
 +		return (ENOBUFS);=0A=
  =0A=
 -	LIST_FOREACH(f, chain, next)=0A=
 -		if (f->vlan =3D=3D vlan)=0A=
 -			return (f);=0A=
 -	return (NULL);=0A=
 +return (0);=0A=
  }=0A=
  =0A=
 +//**********************************************************************=
 **=0A=
 +//			NETGRAPH NODE STUFF=0A=
 +//**********************************************************************=
 **=0A=
 +=0A=
  static int=0A=
  ng_vlan_constructor(node_p node)=0A=
  {=0A=
  	priv_p priv;=0A=
 -	int i;=0A=
  =0A=
  	priv =3D malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);=0A=
  	if (priv =3D=3D NULL)=0A=
  		return (ENOMEM);=0A=
 -	for (i =3D 0; i < HASHSIZE; i++)=0A=
 -		LIST_INIT(&priv->hashtable[i]);=0A=
 +	priv->encap_enable =3D 1;=0A=
 +	priv->encap_proto =3D htons(ETHERTYPE_VLAN);=0A=
 +	=0A=
  	NG_NODE_SET_PRIVATE(node, priv);=0A=
 +=0A=
  	return (0);=0A=
  }=0A=
  =0A=
 @@ -193,13 +241,14 @@=0A=
  ng_vlan_rcvmsg(node_p node, item_p item, hook_p lasthook)=0A=
  {=0A=
  	const priv_p priv =3D NG_NODE_PRIVATE(node);=0A=
 -	int error =3D 0;=0A=
  	struct ng_mesg *msg, *resp =3D NULL;=0A=
  	struct ng_vlan_filter *vf;=0A=
 -	struct filter *f;=0A=
  	hook_p hook;=0A=
  	struct ng_vlan_table *t;=0A=
 -	int i;=0A=
 +	uintptr_t hook_data;=0A=
 +	int i, vlan_count;=0A=
 +	u_int16_t vid;=0A=
 +	int error =3D 0;=0A=
  =0A=
  	NGI_GET_MSG(item, msg);=0A=
  	/* Deal with message according to cookie and command. */=0A=
 @@ -214,12 +263,12 @@=0A=
  			}=0A=
  			vf =3D (struct ng_vlan_filter *)msg->data;=0A=
  			/* Sanity check the VLAN ID value. */=0A=
 -			if (vf->vlan & ~EVL_VLID_MASK) {=0A=
 +			if (vf->vid & ~EVL_VLID_MASK || vf->pcp & ~7 || vf->cfi & ~1) {=0A=
  				error =3D EINVAL;=0A=
  				break;=0A=
  			}=0A=
  			/* Check that a referenced hook exists. */=0A=
 -			hook =3D ng_findhook(node, vf->hook);=0A=
 +			hook =3D ng_findhook(node, vf->hook_name);=0A=
  			if (hook =3D=3D NULL) {=0A=
  				error =3D ENOENT;=0A=
  				break;=0A=
 @@ -231,30 +280,18 @@=0A=
  				break;=0A=
  			}=0A=
  			/* And is not already in service. */=0A=
 -			if (NG_HOOK_PRIVATE(hook) !=3D NULL) {=0A=
 +			if (IS_HOOK_VLAN_SET(NG_HOOK_PRIVATE(hook))) {=0A=
  				error =3D EEXIST;=0A=
  				break;=0A=
  			}=0A=
  			/* Check we don't already trap this VLAN. */=0A=
 -			if (ng_vlan_findentry(priv, vf->vlan)) {=0A=
 +			if (priv->vlan_hook[vf->vid] !=3D NULL) {=0A=
  				error =3D EEXIST;=0A=
  				break;=0A=
  			}=0A=
 -			/* Create filter. */=0A=
 -			f =3D malloc(sizeof(*f),=0A=
 -			    M_NETGRAPH, M_NOWAIT | M_ZERO);=0A=
 -			if (f =3D=3D NULL) {=0A=
 -				error =3D ENOMEM;=0A=
 -				break;=0A=
 -			}=0A=
 -			/* Link filter and hook together. */=0A=
 -			f->hook =3D hook;=0A=
 -			f->vlan =3D vf->vlan;=0A=
 -			NG_HOOK_SET_PRIVATE(hook, f);=0A=
 -			/* Register filter in a hash table. */=0A=
 -			LIST_INSERT_HEAD(=0A=
 -			    &priv->hashtable[HASH(f->vlan)], f, next);=0A=
 -			priv->nent++;=0A=
 +			/* Link vlan and hook together. */=0A=
 +			NG_HOOK_SET_PRIVATE(hook, (void *)(HOOK_VLAN_TAG_SET_MASK | =
 EVL_MAKETAG(vf->vid, vf->pcp, vf->cfi)));=0A=
 +			priv->vlan_hook[vf->vid] =3D hook;=0A=
  			break;=0A=
  		case NGM_VLAN_DEL_FILTER:=0A=
  			/* Check that message is long enough. */=0A=
 @@ -264,35 +301,125 @@=0A=
  			}=0A=
  			/* Check that hook exists and is active. */=0A=
  			hook =3D ng_findhook(node, (char *)msg->data);=0A=
 -			if (hook =3D=3D NULL ||=0A=
 -			    (f =3D NG_HOOK_PRIVATE(hook)) =3D=3D NULL) {=0A=
 +			if (hook =3D=3D NULL) {=0A=
 +				error =3D ENOENT;=0A=
 +				break;=0A=
 +			}=0A=
 +			hook_data =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A=
 +			if (IS_HOOK_VLAN_SET(hook_data) =3D=3D 0) {=0A=
 +				error =3D ENOENT;=0A=
 +				break;=0A=
 +			}=0A=
 +#ifdef NETGRAPH_DEBUG=0A=
 +			if (priv->vlan_hook[EVL_VLANOFTAG(hook_data)] !=3D hook)=0A=
 +				printf("%s: NGM_VLAN_DEL_FILTER: Invalid VID for Hook =3D %s\n", =
 __func__, (char *)msg->data);=0A=
 +#endif=0A=
 +			/* Purge a rule that refers to this hook. */=0A=
 +			priv->vlan_hook[EVL_VLANOFTAG(hook_data)] =3D NULL;=0A=
 +			NG_HOOK_SET_PRIVATE(hook, NULL);=0A=
 +			break;=0A=
 +		case NGM_VLAN_DEL_VID_FLT:=0A=
 +			/* Check that message is long enough. */=0A=
 +			if (msg->header.arglen !=3D sizeof(u_int16_t)) {=0A=
 +				error =3D EINVAL;=0A=
 +				break;=0A=
 +			}=0A=
 +			vid =3D (*((u_int16_t *)msg->data));=0A=
 +			/* Sanity check the VLAN ID value. */=0A=
 +			if (vid & ~EVL_VLID_MASK) {=0A=
 +				error =3D EINVAL;=0A=
 +				break;=0A=
 +			}=0A=
 +			/* Check that hook exists and is active. */=0A=
 +			hook =3D priv->vlan_hook[vid];=0A=
 +			if (hook =3D=3D NULL) {=0A=
 +				error =3D ENOENT;=0A=
 +				break;=0A=
 +			}=0A=
 +			hook_data =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A=
 +			if (IS_HOOK_VLAN_SET(hook_data) =3D=3D 0) {=0A=
  				error =3D ENOENT;=0A=
  				break;=0A=
  			}=0A=
 +#ifdef NETGRAPH_DEBUG=0A=
 +			if (EVL_VLANOFTAG(hook_data) !=3D vid)=0A=
 +				printf("%s: NGM_VLAN_DEL_VID_FLT: Invalid VID Hook =3D %us, must =
 be: %us\n", __func__, (u_int16_t)EVL_VLANOFTAG(hook_data), vid);=0A=
 +#endif=0A=
  			/* Purge a rule that refers to this hook. */=0A=
 +			priv->vlan_hook[vid] =3D NULL;=0A=
  			NG_HOOK_SET_PRIVATE(hook, NULL);=0A=
 -			LIST_REMOVE(f, next);=0A=
 -			priv->nent--;=0A=
 -			free(f, M_NETGRAPH);=0A=
  			break;=0A=
  		case NGM_VLAN_GET_TABLE:=0A=
 +			/* calculate vlans */=0A=
 +			vlan_count =3D 0;=0A=
 +			for (i =3D 0; i < (EVL_VLID_MASK + 1); i ++) {=0A=
 +				if (priv->vlan_hook[i] !=3D NULL=0A=
 +				   && NG_HOOK_IS_VALID(priv->vlan_hook[i]))=0A=
 +					vlan_count ++;=0A=
 +			}=0A=
 +=0A=
 +			/* allocate memory for responce */=0A=
  			NG_MKRESPONSE(resp, msg, sizeof(*t) +=0A=
 -			    priv->nent * sizeof(*t->filter), M_NOWAIT);=0A=
 +			    vlan_count * sizeof(*t->filter), M_NOWAIT);=0A=
  			if (resp =3D=3D NULL) {=0A=
  				error =3D ENOMEM;=0A=
  				break;=0A=
  			}=0A=
 +=0A=
 +			/* pack data to responce */=0A=
  			t =3D (struct ng_vlan_table *)resp->data;=0A=
 -			t->n =3D priv->nent;=0A=
 +			t->n =3D 0;=0A=
  			vf =3D &t->filter[0];=0A=
 -			for (i =3D 0; i < HASHSIZE; i++) {=0A=
 -				LIST_FOREACH(f, &priv->hashtable[i], next) {=0A=
 -					vf->vlan =3D f->vlan;=0A=
 -					strncpy(vf->hook, NG_HOOK_NAME(f->hook),=0A=
 +			for (i =3D 0; i < (EVL_VLID_MASK + 1); i ++) {=0A=
 +				hook =3D priv->vlan_hook[i];=0A=
 +				if (hook =3D=3D NULL=0A=
 +				   || NG_HOOK_NOT_VALID(hook))=0A=
 +					continue;=0A=
 +				hook_data =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A=
 +				if (IS_HOOK_VLAN_SET(hook_data) =3D=3D 0)=0A=
 +					continue;=0A=
 +#ifdef NETGRAPH_DEBUG=0A=
 +				if (EVL_VLANOFTAG(hook_data) !=3D i)=0A=
 +					printf("%s: NGM_VLAN_GET_TABLE: hook %s VID =3D %us, must be: =
 %i\n", __func__, NG_HOOK_NAME(hook), =
 (u_int16_t)EVL_VLANOFTAG(hook_data), i);=0A=
 +#endif=0A=
 +				vf->vid =3D i;=0A=
 +				vf->pcp =3D EVL_PRIOFTAG(hook_data);=0A=
 +				vf->cfi =3D EVL_CFIOFTAG(hook_data);=0A=
 +				strncpy(vf->hook_name, NG_HOOK_NAME(hook),=0A=
  					    NG_HOOKSIZ);=0A=
 -					vf++;=0A=
 -				}=0A=
 +				vf ++;=0A=
 +				t->n ++;=0A=
 +			}=0A=
 +			break;=0A=
 +		case NGM_VLAN_GET_ENCAP:=0A=
 +			NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);=0A=
 +			if (resp =3D=3D NULL) {=0A=
 +				error =3D ENOMEM;=0A=
 +				break;=0A=
 +			}=0A=
 +			(*((u_int32_t *)resp->data)) =3D priv->encap_enable;=0A=
 +			break;=0A=
 +		case NGM_VLAN_SET_ENCAP:=0A=
 +			if (msg->header.arglen !=3D sizeof(u_int32_t)) {=0A=
 +				error =3D EINVAL;=0A=
 +				break;=0A=
 +			}=0A=
 +			priv->encap_enable =3D ((*((u_int32_t *)msg->data)) !=3D 0);=0A=
 +			break;=0A=
 +		case NGM_VLAN_GET_ENCAP_PROTO:=0A=
 +			NG_MKRESPONSE(resp, msg, sizeof(u_int16_t), M_NOWAIT);=0A=
 +			if (resp =3D=3D NULL) {=0A=
 +				error =3D ENOMEM;=0A=
 +				break;=0A=
 +			}=0A=
 +			(*((u_int16_t *)resp->data)) =3D ntohs(priv->encap_proto);=0A=
 +			break;=0A=
 +		case NGM_VLAN_SET_ENCAP_PROTO:=0A=
 +			if (msg->header.arglen !=3D sizeof(u_int16_t)) {=0A=
 +				error =3D EINVAL;=0A=
 +				break;=0A=
  			}=0A=
 +			priv->encap_proto =3D htons((*((u_int16_t *)msg->data)));=0A=
  			break;=0A=
  		default:		/* Unknown command. */=0A=
  			error =3D EINVAL;=0A=
 @@ -302,8 +429,6 @@=0A=
  	case NGM_FLOW_COOKIE:=0A=
  	    {=0A=
  		struct ng_mesg *copy;=0A=
 -		struct filterhead *chain;=0A=
 -		struct filter *f;=0A=
  =0A=
  		/*=0A=
  		 * Flow control messages should come only=0A=
 @@ -314,17 +439,16 @@=0A=
  			break;=0A=
  		if (lasthook !=3D priv->downstream_hook)=0A=
  			break;=0A=
 -=0A=
  		/* Broadcast the event to all uplinks. */=0A=
 -		for (i =3D 0, chain =3D priv->hashtable; i < HASHSIZE;=0A=
 -		    i++, chain++)=0A=
 -		LIST_FOREACH(f, chain, next) {=0A=
 +		for (i =3D 0; i < (EVL_VLID_MASK + 1); i ++) {=0A=
 +			if (priv->vlan_hook[i] =3D=3D NULL)=0A=
 +				continue;=0A=
 +=0A=
  			NG_COPYMESSAGE(copy, msg, M_NOWAIT);=0A=
  			if (copy =3D=3D NULL)=0A=
 -				continue;=0A=
 -			NG_SEND_MSG_HOOK(error, node, copy, f->hook, 0);=0A=
 +					continue;=0A=
 +			NG_SEND_MSG_HOOK(error, node, copy, priv->vlan_hook[i], 0);=0A=
  		}=0A=
 -=0A=
  		break;=0A=
  	    }=0A=
  	default:			/* Unknown type cookie. */=0A=
 @@ -343,16 +467,19 @@=0A=
  	struct ether_header *eh;=0A=
  	struct ether_vlan_header *evl =3D NULL;=0A=
  	int error;=0A=
 -	u_int16_t vlan;=0A=
 +	uintptr_t hook_data;=0A=
 +	u_int16_t vid;=0A=
  	struct mbuf *m;=0A=
 -	struct filter *f;=0A=
 +	hook_p dst_hook;=0A=
 +=0A=
  =0A=
 -	/* Make sure we have an entire header. */=0A=
  	NGI_GET_M(item, m);=0A=
 -	if (m->m_len < sizeof(*eh) &&=0A=
 -	    (m =3D m_pullup(m, sizeof(*eh))) =3D=3D NULL) {=0A=
 +=0A=
 +	/* Make sure we have an entire header. */=0A=
 +	error =3D m_chk(&m, ETHER_HDR_LEN);=0A=
 +	if (error !=3D 0) {=0A=
  		NG_FREE_ITEM(item);=0A=
 -		return (EINVAL);=0A=
 +		return (error);=0A=
  	}=0A=
  	eh =3D mtod(m, struct ether_header *);=0A=
  	if (hook =3D=3D priv->downstream_hook) {=0A=
 @@ -360,75 +487,104 @@=0A=
  		 * If from downstream, select between a match hook=0A=
  		 * or the nomatch hook.=0A=
  		 */=0A=
 +		dst_hook =3D priv->nomatch_hook;=0A=
  		if (m->m_flags & M_VLANTAG ||=0A=
 -		    eh->ether_type =3D=3D htons(ETHERTYPE_VLAN)) {=0A=
 +		    eh->ether_type =3D=3D priv->encap_proto) {=0A=
  			if (m->m_flags & M_VLANTAG) {=0A=
  				/*=0A=
  				 * Packet is tagged, m contains a normal=0A=
  				 * Ethernet frame; tag is stored out-of-band.=0A=
  				 */=0A=
 -				vlan =3D EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);=0A=
 -			} else {=0A=
 -				if (m->m_len < sizeof(*evl) &&=0A=
 -				    (m =3D m_pullup(m, sizeof(*evl))) =3D=3D NULL) {=0A=
 +				vid =3D EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);=0A=
 +			} else { /* eh->ether_type =3D=3D priv->encap_proto */=0A=
 +				error =3D m_chk(&m, (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN));=0A=
 +				if (error !=3D 0) {=0A=
  					NG_FREE_ITEM(item);=0A=
 -					return (EINVAL);=0A=
 +					return (error);=0A=
  				}=0A=
  				evl =3D mtod(m, struct ether_vlan_header *);=0A=
 -				vlan =3D EVL_VLANOFTAG(ntohs(evl->evl_tag));=0A=
 +				vid =3D EVL_VLANOFTAG(ntohs(evl->evl_tag));=0A=
  			}=0A=
 -			if ((f =3D ng_vlan_findentry(priv, vlan)) !=3D NULL) {=0A=
 +=0A=
 +			if (priv->vlan_hook[vid] !=3D NULL) {=0A=
 +				dst_hook =3D priv->vlan_hook[vid];=0A=
  				if (m->m_flags & M_VLANTAG) {=0A=
  					m->m_pkthdr.ether_vtag =3D 0;=0A=
  					m->m_flags &=3D ~M_VLANTAG;=0A=
  				} else {=0A=
 -					evl->evl_encap_proto =3D evl->evl_proto;=0A=
 -					bcopy(mtod(m, caddr_t),=0A=
 -					    mtod(m, caddr_t) +=0A=
 -					    ETHER_VLAN_ENCAP_LEN,=0A=
 -					    ETHER_HDR_LEN);=0A=
 +					/* =0A=
 +					 * move DstMAC and SrcMAC to ETHER_TYPE=0A=
 +					 * before: [dst_mac] [src_mac] [ether_type_encap(TPID)] =
 [PCP/CFI/VID] [ether_type] [payload]=0A=
 +					 *         |-----------------| =
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |---------------------|=0A=
 +					 * after: [free space] [dst_mac] [src_mac] [ether_type] [payload]=0A=
 +					 *                     |-----------------| |---------------------|=0A=
 +					 */=0A=
 +					bcopy((char *)evl, ((char *)evl + ETHER_VLAN_ENCAP_LEN),=0A=
 +						(ETHER_ADDR_LEN * 2));=0A=
  					m_adj(m, ETHER_VLAN_ENCAP_LEN);=0A=
  				}=0A=
  			}=0A=
 -		} else=0A=
 -			f =3D NULL;=0A=
 -		if (f !=3D NULL)=0A=
 -			NG_FWD_NEW_DATA(error, item, f->hook, m);=0A=
 -		else=0A=
 -			NG_FWD_NEW_DATA(error, item, priv->nomatch_hook, m);=0A=
 +		}=0A=
  	} else {=0A=
  		/*=0A=
  		 * It is heading towards the downstream.=0A=
  		 * If from nomatch, pass it unmodified.=0A=
  		 * Otherwise, do the VLAN encapsulation.=0A=
  		 */=0A=
 -		if (hook !=3D priv->nomatch_hook) {=0A=
 -			if ((f =3D NG_HOOK_PRIVATE(hook)) =3D=3D NULL) {=0A=
 +		dst_hook =3D priv->downstream_hook;=0A=
 +		if (dst_hook !=3D NULL && hook !=3D priv->nomatch_hook) {=0A=
 +			hook_data =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A=
 +			if (IS_HOOK_VLAN_SET(hook_data) =3D=3D 0) {=0A=
 +				m_freem(m);=0A=
  				NG_FREE_ITEM(item);=0A=
 -				NG_FREE_M(m);=0A=
  				return (EOPNOTSUPP);=0A=
  			}=0A=
 -			M_PREPEND(m, ETHER_VLAN_ENCAP_LEN, M_DONTWAIT);=0A=
 -			/* M_PREPEND takes care of m_len and m_pkthdr.len. */=0A=
 -			if (m =3D=3D NULL || (m->m_len < sizeof(*evl) &&=0A=
 -			    (m =3D m_pullup(m, sizeof(*evl))) =3D=3D NULL)) {=0A=
 -				NG_FREE_ITEM(item);=0A=
 -				return (ENOMEM);=0A=
 +			if (priv->encap_enable =3D=3D 0) {=0A=
 +				/* just set packet header tag */=0A=
 +				m->m_flags |=3D M_VLANTAG;=0A=
 +				m->m_pkthdr.ether_vtag =3D (hook_data & VLAN_TAG_MASK);=0A=
 +			} else {=0A=
 +				/*=0A=
 +				 * Transform the Ethernet header into an Ethernet header=0A=
 +				 * with 802.1Q encapsulation.=0A=
 +				 * mod of: ether_vlanencap =0A=
 +				 */=0A=
 +				M_PREPEND(m, ETHER_VLAN_ENCAP_LEN, M_DONTWAIT);=0A=
 +				/* M_PREPEND takes care of m_len and m_pkthdr.len. */=0A=
 +				if (m =3D=3D NULL)=0A=
 +					error =3D ENOMEM;=0A=
 +				else=0A=
 +					error =3D m_chk(&m, (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN));=0A=
 +				if (error !=3D 0) {=0A=
 +					NG_FREE_ITEM(item);=0A=
 +					return (error);=0A=
 +				}=0A=
 +				/* move DstMAC and SrcMAC from ETHER_TYPE=0A=
 +				 * before: [free - prepended space] [dst_mac] [src_mac] =
 [ether_type] [payload]=0A=
 +				 *          <<<<<<<<<<<<<<<<<<<<<<  |-----------------| =
 |--------------------|=0A=
 +				 * after: [dst_mac] [src_mac] [ether_type_encap(TPID)] =
 [PCP/CFI/VID] [ether_type] [payload]=0A=
 +				 *        |-----------------| |----------- inserted tag =
 -----------| |--------------------| =0A=
 +				 */=0A=
 +				evl =3D mtod(m, struct ether_vlan_header *);=0A=
 +				bcopy(((char *)evl + ETHER_VLAN_ENCAP_LEN),=0A=
 +					(char *)evl, (ETHER_ADDR_LEN * 2));=0A=
 +				evl->evl_encap_proto =3D priv->encap_proto;=0A=
 +				evl->evl_tag =3D htons((hook_data & VLAN_TAG_MASK));=0A=
  			}=0A=
 -			/*=0A=
 -			 * Transform the Ethernet header into an Ethernet header=0A=
 -			 * with 802.1Q encapsulation.=0A=
 -			 */=0A=
 -			bcopy(mtod(m, char *) + ETHER_VLAN_ENCAP_LEN,=0A=
 -			    mtod(m, char *), ETHER_HDR_LEN);=0A=
 -			evl =3D mtod(m, struct ether_vlan_header *);=0A=
 -			evl->evl_proto =3D evl->evl_encap_proto;=0A=
 -			evl->evl_encap_proto =3D htons(ETHERTYPE_VLAN);=0A=
 -			evl->evl_tag =3D htons(f->vlan);=0A=
  		}=0A=
 -		NG_FWD_NEW_DATA(error, item, priv->downstream_hook, m);=0A=
  	}=0A=
 -	return (error);=0A=
 +=0A=
 +	/* send packet */=0A=
 +	if (dst_hook !=3D NULL) {=0A=
 +		NG_FWD_NEW_DATA(error, item, dst_hook, m);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	/* no hook to send */=0A=
 +	m_freem(m);=0A=
 +	NG_FREE_ITEM(item);=0A=
 +=0A=
 +	return (ENETDOWN);=0A=
  }=0A=
  =0A=
  static int=0A=
 @@ -446,7 +602,7 @@=0A=
  ng_vlan_disconnect(hook_p hook)=0A=
  {=0A=
  	const priv_p priv =3D NG_NODE_PRIVATE(NG_HOOK_NODE(hook));=0A=
 -	struct filter *f;=0A=
 +	uintptr_t hook_data;=0A=
  =0A=
  	if (hook =3D=3D priv->downstream_hook)=0A=
  		priv->downstream_hook =3D NULL;=0A=
 @@ -454,11 +610,9 @@=0A=
  		priv->nomatch_hook =3D NULL;=0A=
  	else {=0A=
  		/* Purge a rule that refers to this hook. */=0A=
 -		if ((f =3D NG_HOOK_PRIVATE(hook)) !=3D NULL) {=0A=
 -			LIST_REMOVE(f, next);=0A=
 -			priv->nent--;=0A=
 -			free(f, M_NETGRAPH);=0A=
 -		}=0A=
 +		hook_data =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A=
 +		if (IS_HOOK_VLAN_SET(hook_data))=0A=
 +			priv->vlan_hook[EVL_VLANOFTAG(hook_data)] =3D NULL;=0A=
  	}=0A=
  	NG_HOOK_SET_PRIVATE(hook, NULL);=0A=
  	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) =3D=3D 0) &&=0A=
 =0A=
 =0A=
 --- /usr/src/sys/netgraph/ng_vlan.h.orig	2009-08-03 17:13:06.000000000 =
 +0900=0A=
 +++ /usr/src/sys/netgraph/ng_vlan.h	2011-10-22 19:11:01.000000000 +0900=0A=
 @@ -1,5 +1,6 @@=0A=
  /*-=0A=
   * Copyright (c) 2003 IPNET Internet Communication Company=0A=
 + * Copyright (c) 2011 Rozhuk Ivan <rozhuk.im at gmail.com>=0A=
   * All rights reserved.=0A=
   *=0A=
   * Redistribution and use in source and binary forms, with or without=0A=
 @@ -43,19 +44,28 @@=0A=
  enum {=0A=
  	NGM_VLAN_ADD_FILTER =3D 1,=0A=
  	NGM_VLAN_DEL_FILTER,=0A=
 -	NGM_VLAN_GET_TABLE=0A=
 +	NGM_VLAN_DEL_VID_FLT,=0A=
 +	NGM_VLAN_GET_TABLE,=0A=
 +	NGM_VLAN_GET_ENCAP,=0A=
 +	NGM_VLAN_SET_ENCAP,=0A=
 +	NGM_VLAN_GET_ENCAP_PROTO,=0A=
 +	NGM_VLAN_SET_ENCAP_PROTO,=0A=
  };=0A=
  =0A=
  /* For NGM_VLAN_ADD_FILTER control message. */=0A=
  struct ng_vlan_filter {=0A=
 -	char		hook[NG_HOOKSIZ];=0A=
 -	u_int16_t	vlan;=0A=
 -};	=0A=
 +	char		hook_name[NG_HOOKSIZ];=0A=
 +	u_int16_t	vid;	/* VID - VLAN Identifier */=0A=
 +	u_int8_t	pcp;	/* PCP - Priority Code Point */=0A=
 +	u_int8_t	cfi;	/* CFI - Canonical Format Indicator */=0A=
 +};=0A=
  =0A=
  /* Keep this in sync with the above structure definition.  */=0A=
  #define	NG_VLAN_FILTER_FIELDS	{				\=0A=
 -	{ "hook",	&ng_parse_hookbuf_type  },		\=0A=
 -	{ "vlan",	&ng_parse_uint16_type   },		\=0A=
 +	{ "hook",	&ng_parse_hookbuf_type	},		\=0A=
 +	{ "vid",	&ng_parse_uint16_type	},		\=0A=
 +	{ "pcp",	&ng_parse_uint8_type	},		\=0A=
 +	{ "cfi",	&ng_parse_uint8_type	},		\=0A=
  	{ NULL }						\=0A=
  }=0A=
  =0A=
 
 ------=_NextPart_000_033B_01CC935E.7927C480--
 


More information about the freebsd-net mailing list