Date: Sat, 25 Jun 2011 02:08:17 +0900 From: rozhuk.im@gmail.com To: <freebsd-net@freebsd.org> Subject: ng_vlan improvements Message-ID: <4e04c489.d899cc0a.43e4.4ad6@mx.google.com>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. ------=_NextPart_000_0001_01CC32DC.C33B2950 Content-Type: text/plain; charset="windows-1251" Content-Transfer-Encoding: quoted-printable Diffs =A0 -- Rozhuk Ivan =A0=20 ------=_NextPart_000_0001_01CC32DC.C33B2950 Content-Type: application/octet-stream; name="ng_vlan.h.orig.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ng_vlan.h.orig.patch" --- ng_vlan.h.orig 2009-08-03 17:13:06.000000000 +0900=0A= +++ ng_vlan.h 2011-06-24 05:35:05.000000000 +0900=0A= @@ -43,7 +43,9 @@=0A= enum {=0A= NGM_VLAN_ADD_FILTER =3D 1,=0A= NGM_VLAN_DEL_FILTER,=0A= - NGM_VLAN_GET_TABLE=0A= + NGM_VLAN_GET_TABLE,=0A= + NGM_VLAN_GET_ENCAP,=0A= + NGM_VLAN_SET_ENCAP=0A= };=0A= =0A= /* For NGM_VLAN_ADD_FILTER control message. */=0A= ------=_NextPart_000_0001_01CC32DC.C33B2950 Content-Type: application/octet-stream; name="ng_vlan.c.orig.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ng_vlan.c.orig.patch" --- ng_vlan.c.orig 2009-08-03 17:13:06.000000000 +0900=0A= +++ ng_vlan.c 2011-06-24 21:00:22.000000000 +0900=0A= @@ -110,6 +110,20 @@=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_int32_type=0A= + },=0A= + {=0A= + NGM_VLAN_COOKIE,=0A= + NGM_VLAN_SET_ENCAP,=0A= + "setencap",=0A= + &ng_parse_int32_type,=0A= + NULL=0A= + },=0A= { 0 }=0A= };=0A= =0A= @@ -126,47 +140,27 @@=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= + hook_p vlan_hook[(EVL_VLID_MASK + 1)];=0A= + int vlan_encap;=0A= } *priv_p;=0A= +#define HOOK_VLAN_SET_MASK ((uintptr_t)((~0) & ~(EVL_VLID_MASK)))=0A= =0A= -static struct filter *=0A= -ng_vlan_findentry(priv_p priv, u_int16_t vlan)=0A= -{=0A= - struct filterhead *chain =3D &priv->hashtable[HASH(vlan)];=0A= - struct filter *f;=0A= -=0A= - LIST_FOREACH(f, chain, next)=0A= - if (f->vlan =3D=3D vlan)=0A= - return (f);=0A= - return (NULL);=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= - NG_NODE_SET_PRIVATE(node, priv);=0A= + priv->vlan_encap =3D 1;=0A= +=0A= return (0);=0A= }=0A= =0A= @@ -193,13 +187,12 @@=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 vlan, vlan_count;=0A= + int error =3D 0;=0A= =0A= NGI_GET_MSG(item, msg);=0A= /* Deal with message according to cookie and command. */=0A= @@ -231,30 +224,18 @@=0A= break;=0A= }=0A= /* And is not already in service. */=0A= - if (NG_HOOK_PRIVATE(hook) !=3D NULL) {=0A= + if (((uintptr_t)NG_HOOK_PRIVATE(hook) & HOOK_VLAN_SET_MASK) =3D=3D = HOOK_VLAN_SET_MASK) {=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->vlan] !=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= + priv->vlan_hook[vf->vlan] =3D hook;=0A= + NG_HOOK_SET_PRIVATE(hook, (void *)(HOOK_VLAN_SET_MASK | vf->vlan));=0A= break;=0A= case NGM_VLAN_DEL_FILTER:=0A= /* Check that message is long enough. */=0A= @@ -264,35 +245,64 @@=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= + vlan =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A= + if ((vlan & HOOK_VLAN_SET_MASK) !=3D HOOK_VLAN_SET_MASK) {=0A= error =3D ENOENT;=0A= break;=0A= }=0A= + vlan &=3D EVL_VLID_MASK; /* remove HOOK_VLAN_SET_MASK from vlan num = */=0A= +=0A= /* Purge a rule that refers to this hook. */=0A= NG_HOOK_SET_PRIVATE(hook, NULL);=0A= - LIST_REMOVE(f, next);=0A= - priv->nent--;=0A= - free(f, M_NETGRAPH);=0A= + priv->vlan_hook[vlan] =3D NULL;=0A= break;=0A= case NGM_VLAN_GET_TABLE:=0A= + /* calculate vlans */=0A= + vlan_count =3D 0;=0A= + for (vlan =3D 0; vlan < (EVL_VLID_MASK + 1); vlan ++) {=0A= + if (priv->vlan_hook[vlan] !=3D NULL)=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 vlan_count;=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 (vlan =3D 0; vlan < (EVL_VLID_MASK + 1); vlan ++) {=0A= + if (priv->vlan_hook[vlan] =3D=3D NULL)=0A= + continue;=0A= +=0A= + vf->vlan =3D vlan;=0A= + strncpy(vf->hook, NG_HOOK_NAME(priv->vlan_hook[vlan]),=0A= NG_HOOKSIZ);=0A= - vf++;=0A= - }=0A= + vf ++;=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->vlan_encap;=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->vlan_encap =3D ((*((u_int32_t *)msg->data)) !=3D 0);=0A= break;=0A= default: /* Unknown command. */=0A= error =3D EINVAL;=0A= @@ -302,8 +312,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= @@ -316,15 +324,15 @@=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 (vlan =3D 0; vlan < (EVL_VLID_MASK + 1); vlan ++) {=0A= + if (priv->vlan_hook[vlan] =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[vlan], 0);=0A= }=0A= -=0A= break;=0A= }=0A= default: /* Unknown type cookie. */=0A= @@ -343,9 +351,9 @@=0A= struct ether_header *eh;=0A= struct ether_vlan_header *evl =3D NULL;=0A= int error;=0A= - u_int16_t vlan;=0A= + uintptr_t vlan;=0A= struct mbuf *m;=0A= - struct filter *f;=0A= + hook_p vlan_hook;=0A= =0A= /* Make sure we have an entire header. */=0A= NGI_GET_M(item, m);=0A= @@ -360,6 +368,7 @@=0A= * If from downstream, select between a match hook=0A= * or the nomatch hook.=0A= */=0A= + vlan_hook =3D priv->nomatch_hook;=0A= if (m->m_flags & M_VLANTAG ||=0A= eh->ether_type =3D=3D htons(ETHERTYPE_VLAN)) {=0A= if (m->m_flags & M_VLANTAG) {=0A= @@ -377,25 +386,20 @@=0A= evl =3D mtod(m, struct ether_vlan_header *);=0A= vlan =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[vlan] !=3D NULL) {=0A= + vlan_hook =3D priv->vlan_hook[vlan];=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= + bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,=0A= + (ETHER_HDR_LEN - ETHER_TYPE_LEN));=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= + NG_FWD_NEW_DATA(error, item, vlan_hook, m);=0A= } else {=0A= /*=0A= * It is heading towards the downstream.=0A= @@ -403,28 +407,35 @@=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= + vlan =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A= + if ((vlan & HOOK_VLAN_SET_MASK) !=3D HOOK_VLAN_SET_MASK) {=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= + vlan &=3D EVL_VLID_MASK; /* remove HOOK_VLAN_SET_MASK from vlan num = */=0A= + =0A= + if (priv->vlan_encap =3D=3D 0) {=0A= + m->m_flags |=3D M_VLANTAG;=0A= + m->m_pkthdr.ether_vtag =3D vlan;=0A= + } else {=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= + }=0A= + /*=0A= + * Transform the Ethernet header into an Ethernet header=0A= + * with 802.1Q encapsulation.=0A= + */=0A= + evl =3D mtod(m, struct ether_vlan_header *);=0A= + bcopy((char *)evl + ETHER_VLAN_ENCAP_LEN,=0A= + (char *)evl, (ETHER_HDR_LEN - ETHER_TYPE_LEN));=0A= + evl->evl_encap_proto =3D htons(ETHERTYPE_VLAN);=0A= + evl->evl_tag =3D htons(vlan);=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= @@ -446,7 +457,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 vlan;=0A= =0A= if (hook =3D=3D priv->downstream_hook)=0A= priv->downstream_hook =3D NULL;=0A= @@ -454,11 +465,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= + vlan =3D (uintptr_t)NG_HOOK_PRIVATE(hook);=0A= + if ((vlan & HOOK_VLAN_SET_MASK) =3D=3D HOOK_VLAN_SET_MASK)=0A= + priv->vlan_hook[(vlan & EVL_VLID_MASK)] =3D NULL;=0A= }=0A= NG_HOOK_SET_PRIVATE(hook, NULL);=0A= if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) =3D=3D 0) &&=0A= ------=_NextPart_000_0001_01CC32DC.C33B2950--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4e04c489.d899cc0a.43e4.4ad6>