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

From: rozhuk...@gmail.com
To: <bug-follo...@freebsd.org>,
        <rozhuk...@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...@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...@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--
 
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to