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