From owner-freebsd-net@FreeBSD.ORG Sat Dec 31 05:49:08 2011 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6C3BF106564A for ; Sat, 31 Dec 2011 05:49:08 +0000 (UTC) (envelope-from rozhuk.im@gmail.com) Received: from mail-wi0-f182.google.com (mail-wi0-f182.google.com [209.85.212.182]) by mx1.freebsd.org (Postfix) with ESMTP id E0DE78FC08 for ; Sat, 31 Dec 2011 05:49:07 +0000 (UTC) Received: by wibhr1 with SMTP id hr1so13568590wib.13 for ; Fri, 30 Dec 2011 21:49:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=reply-to:from:to:references:in-reply-to:subject:date:message-id :mime-version:content-type:x-mailer:thread-index:content-language; bh=f8zYPIf/Jxkm11KwiM1WAsA4qzjhMv/6o+ayWEs6z78=; b=aAcQFK4Ev8M5W4FlDKRCh7OAPjEvNblrhLUDa3W5DYKLuHhEJKkew9CkhtUtBrN/2o YGfVoAy113GxW4CTYBbuXN/lm9oR3DmePG+oLrzWxZUP/y7YMBljBRbt9IsS/l4b+qSK LK9q+Fkl6fv5evjAhemV+9VxND2Et+jf4je/0= Received: by 10.180.19.138 with SMTP id f10mr115225896wie.3.1325310546804; Fri, 30 Dec 2011 21:49:06 -0800 (PST) Received: from rimwks1w7x64 ([31.47.165.90]) by mx.google.com with ESMTPS id ei9sm98117630wid.0.2011.12.30.21.49.04 (version=SSLv3 cipher=OTHER); Fri, 30 Dec 2011 21:49:05 -0800 (PST) From: rozhuk.im@gmail.com To: References: <201110232234.p9NMYer5039763@freefall.freebsd.org> In-Reply-To: <201110232234.p9NMYer5039763@freefall.freebsd.org> Date: Sat, 31 Dec 2011 14:48:56 +0900 Message-ID: <4efea251.890bb50a.4fb2.4076@mx.google.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0011_01CCC7CB.546BA110" X-Mailer: Microsoft Office Outlook 12.0 thread-index: AcyR0/3akjaCaX1bRXmhqztKzYBhfw1qilHw Content-Language: ru Cc: Subject: RE: kern/161908: [netgraph] [patch] ng_vlan update for QinQ support X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Rozhuk.IM@gmail.com List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Dec 2011 05:49:08 -0000 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 =0A= * All rights reserved.=0A= *=0A= * Redistribution and use in source and binary forms, with or without=0A= @@ -46,6 +47,22 @@=0A= #include =0A= #include =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 =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--