Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Dec 2011 14:48:56 +0900
From:      rozhuk.im@gmail.com
To:        <freebsd-net@FreeBSD.org>
Subject:   RE: kern/161908: [netgraph] [patch] ng_vlan update for QinQ support
Message-ID:  <4efea251.890bb50a.4fb2.4076@mx.google.com>
In-Reply-To: <201110232234.p9NMYer5039763@freefall.freebsd.org>
References:  <201110232234.p9NMYer5039763@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_0011_01CCC7CB.546BA110
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit


Who can commit?


> -----Original Message-----
> From: owner-freebsd-net@freebsd.org [mailto:owner-freebsd-
> net@freebsd.org] On Behalf Of eadler@FreeBSD.org
> Sent: Monday, October 24, 2011 7:35 AM
> To: eadler@FreeBSD.org; freebsd-bugs@FreeBSD.org; freebsd-
> net@FreeBSD.org
> Subject: Re: kern/161908: [netgraph] [patch] ng_vlan update for QinQ
> support
> 
> Old Synopsis: ng_vlan update for QinQ support New Synopsis: [netgraph]
> [patch] ng_vlan update for QinQ support
> 
> Responsible-Changed-From-To: freebsd-bugs->freebsd-net
> Responsible-Changed-By: eadler
> Responsible-Changed-When: Sun Oct 23 22:34:17 UTC 2011
> Responsible-Changed-Why:
> assign and add tags
> 
> http://www.freebsd.org/cgi/query-pr.cgi?pr=161908
> _______________________________________________
> freebsd-net@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"

------=_NextPart_000_0011_01CCC7CB.546BA110
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@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@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_0011_01CCC7CB.546BA110--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4efea251.890bb50a.4fb2.4076>