The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_vlan.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 1998 Massachusetts Institute of Technology
    3  * Copyright 2012 ADARA Networks, Inc.
    4  *
    5  * Portions of this software were developed by Robert N. M. Watson under
    6  * contract to ADARA Networks, Inc.
    7  *
    8  * Permission to use, copy, modify, and distribute this software and
    9  * its documentation for any purpose and without fee is hereby
   10  * granted, provided that both the above copyright notice and this
   11  * permission notice appear in all copies, that both the above
   12  * copyright notice and this permission notice appear in all
   13  * supporting documentation, and that the name of M.I.T. not be used
   14  * in advertising or publicity pertaining to distribution of the
   15  * software without specific, written prior permission.  M.I.T. makes
   16  * no representations about the suitability of this software for any
   17  * purpose.  It is provided "as is" without express or implied
   18  * warranty.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
   21  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
   22  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
   24  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   27  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   30  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
   36  * This is sort of sneaky in the implementation, since
   37  * we need to pretend to be enough of an Ethernet implementation
   38  * to make arp work.  The way we do this is by telling everyone
   39  * that we are an Ethernet, and then catch the packets that
   40  * ether_output() sends to us via if_transmit(), rewrite them for
   41  * use by the real outgoing interface, and ask it to send them.
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: releng/11.0/sys/net/if_vlan.c 302054 2016-06-21 13:48:49Z bz $");
   46 
   47 #include "opt_inet.h"
   48 #include "opt_vlan.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/eventhandler.h>
   52 #include <sys/kernel.h>
   53 #include <sys/lock.h>
   54 #include <sys/malloc.h>
   55 #include <sys/mbuf.h>
   56 #include <sys/module.h>
   57 #include <sys/rmlock.h>
   58 #include <sys/priv.h>
   59 #include <sys/queue.h>
   60 #include <sys/socket.h>
   61 #include <sys/sockio.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/systm.h>
   64 #include <sys/sx.h>
   65 
   66 #include <net/bpf.h>
   67 #include <net/ethernet.h>
   68 #include <net/if.h>
   69 #include <net/if_var.h>
   70 #include <net/if_clone.h>
   71 #include <net/if_dl.h>
   72 #include <net/if_types.h>
   73 #include <net/if_vlan_var.h>
   74 #include <net/vnet.h>
   75 
   76 #ifdef INET
   77 #include <netinet/in.h>
   78 #include <netinet/if_ether.h>
   79 #endif
   80 
   81 #define VLAN_DEF_HWIDTH 4
   82 #define VLAN_IFFLAGS    (IFF_BROADCAST | IFF_MULTICAST)
   83 
   84 #define UP_AND_RUNNING(ifp) \
   85     ((ifp)->if_flags & IFF_UP && (ifp)->if_drv_flags & IFF_DRV_RUNNING)
   86 
   87 LIST_HEAD(ifvlanhead, ifvlan);
   88 
   89 struct ifvlantrunk {
   90         struct  ifnet   *parent;        /* parent interface of this trunk */
   91         struct  rmlock  lock;
   92 #ifdef VLAN_ARRAY
   93 #define VLAN_ARRAY_SIZE (EVL_VLID_MASK + 1)
   94         struct  ifvlan  *vlans[VLAN_ARRAY_SIZE]; /* static table */
   95 #else
   96         struct  ifvlanhead *hash;       /* dynamic hash-list table */
   97         uint16_t        hmask;
   98         uint16_t        hwidth;
   99 #endif
  100         int             refcnt;
  101 };
  102 
  103 struct vlan_mc_entry {
  104         struct sockaddr_dl              mc_addr;
  105         SLIST_ENTRY(vlan_mc_entry)      mc_entries;
  106 };
  107 
  108 struct  ifvlan {
  109         struct  ifvlantrunk *ifv_trunk;
  110         struct  ifnet *ifv_ifp;
  111 #define TRUNK(ifv)      ((ifv)->ifv_trunk)
  112 #define PARENT(ifv)     ((ifv)->ifv_trunk->parent)
  113         void    *ifv_cookie;
  114         int     ifv_pflags;     /* special flags we have set on parent */
  115         struct  ifv_linkmib {
  116                 int     ifvm_encaplen;  /* encapsulation length */
  117                 int     ifvm_mtufudge;  /* MTU fudged by this much */
  118                 int     ifvm_mintu;     /* min transmission unit */
  119                 uint16_t ifvm_proto;    /* encapsulation ethertype */
  120                 uint16_t ifvm_tag;      /* tag to apply on packets leaving if */
  121                 uint16_t ifvm_vid;      /* VLAN ID */
  122                 uint8_t ifvm_pcp;       /* Priority Code Point (PCP). */
  123         }       ifv_mib;
  124         SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
  125 #ifndef VLAN_ARRAY
  126         LIST_ENTRY(ifvlan) ifv_list;
  127 #endif
  128 };
  129 #define ifv_proto       ifv_mib.ifvm_proto
  130 #define ifv_tag         ifv_mib.ifvm_tag
  131 #define ifv_vid         ifv_mib.ifvm_vid
  132 #define ifv_pcp         ifv_mib.ifvm_pcp
  133 #define ifv_encaplen    ifv_mib.ifvm_encaplen
  134 #define ifv_mtufudge    ifv_mib.ifvm_mtufudge
  135 #define ifv_mintu       ifv_mib.ifvm_mintu
  136 
  137 /* Special flags we should propagate to parent. */
  138 static struct {
  139         int flag;
  140         int (*func)(struct ifnet *, int);
  141 } vlan_pflags[] = {
  142         {IFF_PROMISC, ifpromisc},
  143         {IFF_ALLMULTI, if_allmulti},
  144         {0, NULL}
  145 };
  146 
  147 SYSCTL_DECL(_net_link);
  148 static SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0,
  149     "IEEE 802.1Q VLAN");
  150 static SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0,
  151     "for consistency");
  152 
  153 static VNET_DEFINE(int, soft_pad);
  154 #define V_soft_pad      VNET(soft_pad)
  155 SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW | CTLFLAG_VNET,
  156     &VNET_NAME(soft_pad), 0, "pad short frames before tagging");
  157 
  158 /*
  159  * For now, make preserving PCP via an mbuf tag optional, as it increases
  160  * per-packet memory allocations and frees.  In the future, it would be
  161  * preferable to reuse ether_vtag for this, or similar.
  162  */
  163 static int vlan_mtag_pcp = 0;
  164 SYSCTL_INT(_net_link_vlan, OID_AUTO, mtag_pcp, CTLFLAG_RW, &vlan_mtag_pcp, 0,
  165         "Retain VLAN PCP information as packets are passed up the stack");
  166 
  167 static const char vlanname[] = "vlan";
  168 static MALLOC_DEFINE(M_VLAN, vlanname, "802.1Q Virtual LAN Interface");
  169 
  170 static eventhandler_tag ifdetach_tag;
  171 static eventhandler_tag iflladdr_tag;
  172 
  173 /*
  174  * We have a global mutex, that is used to serialize configuration
  175  * changes and isn't used in normal packet delivery.
  176  *
  177  * We also have a per-trunk rmlock(9), that is locked shared on packet
  178  * processing and exclusive when configuration is changed.
  179  *
  180  * The VLAN_ARRAY substitutes the dynamic hash with a static array
  181  * with 4096 entries. In theory this can give a boost in processing,
  182  * however on practice it does not. Probably this is because array
  183  * is too big to fit into CPU cache.
  184  */
  185 static struct sx ifv_lock;
  186 #define VLAN_LOCK_INIT()        sx_init(&ifv_lock, "vlan_global")
  187 #define VLAN_LOCK_DESTROY()     sx_destroy(&ifv_lock)
  188 #define VLAN_LOCK_ASSERT()      sx_assert(&ifv_lock, SA_LOCKED)
  189 #define VLAN_LOCK()             sx_xlock(&ifv_lock)
  190 #define VLAN_UNLOCK()           sx_xunlock(&ifv_lock)
  191 #define TRUNK_LOCK_INIT(trunk)  rm_init(&(trunk)->lock, vlanname)
  192 #define TRUNK_LOCK_DESTROY(trunk) rm_destroy(&(trunk)->lock)
  193 #define TRUNK_LOCK(trunk)       rm_wlock(&(trunk)->lock)
  194 #define TRUNK_UNLOCK(trunk)     rm_wunlock(&(trunk)->lock)
  195 #define TRUNK_LOCK_ASSERT(trunk) rm_assert(&(trunk)->lock, RA_WLOCKED)
  196 #define TRUNK_RLOCK(trunk)      rm_rlock(&(trunk)->lock, &tracker)
  197 #define TRUNK_RUNLOCK(trunk)    rm_runlock(&(trunk)->lock, &tracker)
  198 #define TRUNK_LOCK_RASSERT(trunk) rm_assert(&(trunk)->lock, RA_RLOCKED)
  199 #define TRUNK_LOCK_READER       struct rm_priotracker tracker
  200 
  201 #ifndef VLAN_ARRAY
  202 static  void vlan_inithash(struct ifvlantrunk *trunk);
  203 static  void vlan_freehash(struct ifvlantrunk *trunk);
  204 static  int vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv);
  205 static  int vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv);
  206 static  void vlan_growhash(struct ifvlantrunk *trunk, int howmuch);
  207 static __inline struct ifvlan * vlan_gethash(struct ifvlantrunk *trunk,
  208         uint16_t vid);
  209 #endif
  210 static  void trunk_destroy(struct ifvlantrunk *trunk);
  211 
  212 static  void vlan_init(void *foo);
  213 static  void vlan_input(struct ifnet *ifp, struct mbuf *m);
  214 static  int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
  215 static  void vlan_qflush(struct ifnet *ifp);
  216 static  int vlan_setflag(struct ifnet *ifp, int flag, int status,
  217     int (*func)(struct ifnet *, int));
  218 static  int vlan_setflags(struct ifnet *ifp, int status);
  219 static  int vlan_setmulti(struct ifnet *ifp);
  220 static  int vlan_transmit(struct ifnet *ifp, struct mbuf *m);
  221 static  void vlan_unconfig(struct ifnet *ifp);
  222 static  void vlan_unconfig_locked(struct ifnet *ifp, int departing);
  223 static  int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
  224 static  void vlan_link_state(struct ifnet *ifp);
  225 static  void vlan_capabilities(struct ifvlan *ifv);
  226 static  void vlan_trunk_capabilities(struct ifnet *ifp);
  227 
  228 static  struct ifnet *vlan_clone_match_ethervid(const char *, int *);
  229 static  int vlan_clone_match(struct if_clone *, const char *);
  230 static  int vlan_clone_create(struct if_clone *, char *, size_t, caddr_t);
  231 static  int vlan_clone_destroy(struct if_clone *, struct ifnet *);
  232 
  233 static  void vlan_ifdetach(void *arg, struct ifnet *ifp);
  234 static  void vlan_iflladdr(void *arg, struct ifnet *ifp);
  235 
  236 static struct if_clone *vlan_cloner;
  237 
  238 #ifdef VIMAGE
  239 static VNET_DEFINE(struct if_clone *, vlan_cloner);
  240 #define V_vlan_cloner   VNET(vlan_cloner)
  241 #endif
  242 
  243 #ifndef VLAN_ARRAY
  244 #define HASH(n, m)      ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m))
  245 
  246 static void
  247 vlan_inithash(struct ifvlantrunk *trunk)
  248 {
  249         int i, n;
  250         
  251         /*
  252          * The trunk must not be locked here since we call malloc(M_WAITOK).
  253          * It is OK in case this function is called before the trunk struct
  254          * gets hooked up and becomes visible from other threads.
  255          */
  256 
  257         KASSERT(trunk->hwidth == 0 && trunk->hash == NULL,
  258             ("%s: hash already initialized", __func__));
  259 
  260         trunk->hwidth = VLAN_DEF_HWIDTH;
  261         n = 1 << trunk->hwidth;
  262         trunk->hmask = n - 1;
  263         trunk->hash = malloc(sizeof(struct ifvlanhead) * n, M_VLAN, M_WAITOK);
  264         for (i = 0; i < n; i++)
  265                 LIST_INIT(&trunk->hash[i]);
  266 }
  267 
  268 static void
  269 vlan_freehash(struct ifvlantrunk *trunk)
  270 {
  271 #ifdef INVARIANTS
  272         int i;
  273 
  274         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  275         for (i = 0; i < (1 << trunk->hwidth); i++)
  276                 KASSERT(LIST_EMPTY(&trunk->hash[i]),
  277                     ("%s: hash table not empty", __func__));
  278 #endif
  279         free(trunk->hash, M_VLAN);
  280         trunk->hash = NULL;
  281         trunk->hwidth = trunk->hmask = 0;
  282 }
  283 
  284 static int
  285 vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  286 {
  287         int i, b;
  288         struct ifvlan *ifv2;
  289 
  290         TRUNK_LOCK_ASSERT(trunk);
  291         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  292 
  293         b = 1 << trunk->hwidth;
  294         i = HASH(ifv->ifv_vid, trunk->hmask);
  295         LIST_FOREACH(ifv2, &trunk->hash[i], ifv_list)
  296                 if (ifv->ifv_vid == ifv2->ifv_vid)
  297                         return (EEXIST);
  298 
  299         /*
  300          * Grow the hash when the number of vlans exceeds half of the number of
  301          * hash buckets squared. This will make the average linked-list length
  302          * buckets/2.
  303          */
  304         if (trunk->refcnt > (b * b) / 2) {
  305                 vlan_growhash(trunk, 1);
  306                 i = HASH(ifv->ifv_vid, trunk->hmask);
  307         }
  308         LIST_INSERT_HEAD(&trunk->hash[i], ifv, ifv_list);
  309         trunk->refcnt++;
  310 
  311         return (0);
  312 }
  313 
  314 static int
  315 vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  316 {
  317         int i, b;
  318         struct ifvlan *ifv2;
  319 
  320         TRUNK_LOCK_ASSERT(trunk);
  321         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  322         
  323         b = 1 << trunk->hwidth;
  324         i = HASH(ifv->ifv_vid, trunk->hmask);
  325         LIST_FOREACH(ifv2, &trunk->hash[i], ifv_list)
  326                 if (ifv2 == ifv) {
  327                         trunk->refcnt--;
  328                         LIST_REMOVE(ifv2, ifv_list);
  329                         if (trunk->refcnt < (b * b) / 2)
  330                                 vlan_growhash(trunk, -1);
  331                         return (0);
  332                 }
  333 
  334         panic("%s: vlan not found\n", __func__);
  335         return (ENOENT); /*NOTREACHED*/
  336 }
  337 
  338 /*
  339  * Grow the hash larger or smaller if memory permits.
  340  */
  341 static void
  342 vlan_growhash(struct ifvlantrunk *trunk, int howmuch)
  343 {
  344         struct ifvlan *ifv;
  345         struct ifvlanhead *hash2;
  346         int hwidth2, i, j, n, n2;
  347 
  348         TRUNK_LOCK_ASSERT(trunk);
  349         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  350 
  351         if (howmuch == 0) {
  352                 /* Harmless yet obvious coding error */
  353                 printf("%s: howmuch is 0\n", __func__);
  354                 return;
  355         }
  356 
  357         hwidth2 = trunk->hwidth + howmuch;
  358         n = 1 << trunk->hwidth;
  359         n2 = 1 << hwidth2;
  360         /* Do not shrink the table below the default */
  361         if (hwidth2 < VLAN_DEF_HWIDTH)
  362                 return;
  363 
  364         /* M_NOWAIT because we're called with trunk mutex held */
  365         hash2 = malloc(sizeof(struct ifvlanhead) * n2, M_VLAN, M_NOWAIT);
  366         if (hash2 == NULL) {
  367                 printf("%s: out of memory -- hash size not changed\n",
  368                     __func__);
  369                 return;         /* We can live with the old hash table */
  370         }
  371         for (j = 0; j < n2; j++)
  372                 LIST_INIT(&hash2[j]);
  373         for (i = 0; i < n; i++)
  374                 while ((ifv = LIST_FIRST(&trunk->hash[i])) != NULL) {
  375                         LIST_REMOVE(ifv, ifv_list);
  376                         j = HASH(ifv->ifv_vid, n2 - 1);
  377                         LIST_INSERT_HEAD(&hash2[j], ifv, ifv_list);
  378                 }
  379         free(trunk->hash, M_VLAN);
  380         trunk->hash = hash2;
  381         trunk->hwidth = hwidth2;
  382         trunk->hmask = n2 - 1;
  383 
  384         if (bootverbose)
  385                 if_printf(trunk->parent,
  386                     "VLAN hash table resized from %d to %d buckets\n", n, n2);
  387 }
  388 
  389 static __inline struct ifvlan *
  390 vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid)
  391 {
  392         struct ifvlan *ifv;
  393 
  394         TRUNK_LOCK_RASSERT(trunk);
  395 
  396         LIST_FOREACH(ifv, &trunk->hash[HASH(vid, trunk->hmask)], ifv_list)
  397                 if (ifv->ifv_vid == vid)
  398                         return (ifv);
  399         return (NULL);
  400 }
  401 
  402 #if 0
  403 /* Debugging code to view the hashtables. */
  404 static void
  405 vlan_dumphash(struct ifvlantrunk *trunk)
  406 {
  407         int i;
  408         struct ifvlan *ifv;
  409 
  410         for (i = 0; i < (1 << trunk->hwidth); i++) {
  411                 printf("%d: ", i);
  412                 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list)
  413                         printf("%s ", ifv->ifv_ifp->if_xname);
  414                 printf("\n");
  415         }
  416 }
  417 #endif /* 0 */
  418 #else
  419 
  420 static __inline struct ifvlan *
  421 vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid)
  422 {
  423 
  424         return trunk->vlans[vid];
  425 }
  426 
  427 static __inline int
  428 vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  429 {
  430 
  431         if (trunk->vlans[ifv->ifv_vid] != NULL)
  432                 return EEXIST;
  433         trunk->vlans[ifv->ifv_vid] = ifv;
  434         trunk->refcnt++;
  435 
  436         return (0);
  437 }
  438 
  439 static __inline int
  440 vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  441 {
  442 
  443         trunk->vlans[ifv->ifv_vid] = NULL;
  444         trunk->refcnt--;
  445 
  446         return (0);
  447 }
  448 
  449 static __inline void
  450 vlan_freehash(struct ifvlantrunk *trunk)
  451 {
  452 }
  453 
  454 static __inline void
  455 vlan_inithash(struct ifvlantrunk *trunk)
  456 {
  457 }
  458 
  459 #endif /* !VLAN_ARRAY */
  460 
  461 static void
  462 trunk_destroy(struct ifvlantrunk *trunk)
  463 {
  464         VLAN_LOCK_ASSERT();
  465 
  466         TRUNK_LOCK(trunk);
  467         vlan_freehash(trunk);
  468         trunk->parent->if_vlantrunk = NULL;
  469         TRUNK_UNLOCK(trunk);
  470         TRUNK_LOCK_DESTROY(trunk);
  471         free(trunk, M_VLAN);
  472 }
  473 
  474 /*
  475  * Program our multicast filter. What we're actually doing is
  476  * programming the multicast filter of the parent. This has the
  477  * side effect of causing the parent interface to receive multicast
  478  * traffic that it doesn't really want, which ends up being discarded
  479  * later by the upper protocol layers. Unfortunately, there's no way
  480  * to avoid this: there really is only one physical interface.
  481  */
  482 static int
  483 vlan_setmulti(struct ifnet *ifp)
  484 {
  485         struct ifnet            *ifp_p;
  486         struct ifmultiaddr      *ifma;
  487         struct ifvlan           *sc;
  488         struct vlan_mc_entry    *mc;
  489         int                     error;
  490 
  491         /* Find the parent. */
  492         sc = ifp->if_softc;
  493         TRUNK_LOCK_ASSERT(TRUNK(sc));
  494         ifp_p = PARENT(sc);
  495 
  496         CURVNET_SET_QUIET(ifp_p->if_vnet);
  497 
  498         /* First, remove any existing filter entries. */
  499         while ((mc = SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) {
  500                 SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries);
  501                 (void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr);
  502                 free(mc, M_VLAN);
  503         }
  504 
  505         /* Now program new ones. */
  506         IF_ADDR_WLOCK(ifp);
  507         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
  508                 if (ifma->ifma_addr->sa_family != AF_LINK)
  509                         continue;
  510                 mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT);
  511                 if (mc == NULL) {
  512                         IF_ADDR_WUNLOCK(ifp);
  513                         return (ENOMEM);
  514                 }
  515                 bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len);
  516                 mc->mc_addr.sdl_index = ifp_p->if_index;
  517                 SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries);
  518         }
  519         IF_ADDR_WUNLOCK(ifp);
  520         SLIST_FOREACH (mc, &sc->vlan_mc_listhead, mc_entries) {
  521                 error = if_addmulti(ifp_p, (struct sockaddr *)&mc->mc_addr,
  522                     NULL);
  523                 if (error)
  524                         return (error);
  525         }
  526 
  527         CURVNET_RESTORE();
  528         return (0);
  529 }
  530 
  531 /*
  532  * A handler for parent interface link layer address changes.
  533  * If the parent interface link layer address is changed we
  534  * should also change it on all children vlans.
  535  */
  536 static void
  537 vlan_iflladdr(void *arg __unused, struct ifnet *ifp)
  538 {
  539         struct ifvlan *ifv;
  540 #ifndef VLAN_ARRAY
  541         struct ifvlan *next;
  542 #endif
  543         int i;
  544 
  545         /*
  546          * Check if it's a trunk interface first of all
  547          * to avoid needless locking.
  548          */
  549         if (ifp->if_vlantrunk == NULL)
  550                 return;
  551 
  552         VLAN_LOCK();
  553         /*
  554          * OK, it's a trunk.  Loop over and change all vlan's lladdrs on it.
  555          */
  556 #ifdef VLAN_ARRAY
  557         for (i = 0; i < VLAN_ARRAY_SIZE; i++)
  558                 if ((ifv = ifp->if_vlantrunk->vlans[i])) {
  559 #else /* VLAN_ARRAY */
  560         for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
  561                 LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) {
  562 #endif /* VLAN_ARRAY */
  563                         VLAN_UNLOCK();
  564                         if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp),
  565                             ifp->if_addrlen);
  566                         VLAN_LOCK();
  567                 }
  568         VLAN_UNLOCK();
  569 
  570 }
  571 
  572 /*
  573  * A handler for network interface departure events.
  574  * Track departure of trunks here so that we don't access invalid
  575  * pointers or whatever if a trunk is ripped from under us, e.g.,
  576  * by ejecting its hot-plug card.  However, if an ifnet is simply
  577  * being renamed, then there's no need to tear down the state.
  578  */
  579 static void
  580 vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
  581 {
  582         struct ifvlan *ifv;
  583         int i;
  584 
  585         /*
  586          * Check if it's a trunk interface first of all
  587          * to avoid needless locking.
  588          */
  589         if (ifp->if_vlantrunk == NULL)
  590                 return;
  591 
  592         /* If the ifnet is just being renamed, don't do anything. */
  593         if (ifp->if_flags & IFF_RENAMING)
  594                 return;
  595 
  596         VLAN_LOCK();
  597         /*
  598          * OK, it's a trunk.  Loop over and detach all vlan's on it.
  599          * Check trunk pointer after each vlan_unconfig() as it will
  600          * free it and set to NULL after the last vlan was detached.
  601          */
  602 #ifdef VLAN_ARRAY
  603         for (i = 0; i < VLAN_ARRAY_SIZE; i++)
  604                 if ((ifv = ifp->if_vlantrunk->vlans[i])) {
  605                         vlan_unconfig_locked(ifv->ifv_ifp, 1);
  606                         if (ifp->if_vlantrunk == NULL)
  607                                 break;
  608                 }
  609 #else /* VLAN_ARRAY */
  610 restart:
  611         for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
  612                 if ((ifv = LIST_FIRST(&ifp->if_vlantrunk->hash[i]))) {
  613                         vlan_unconfig_locked(ifv->ifv_ifp, 1);
  614                         if (ifp->if_vlantrunk)
  615                                 goto restart;   /* trunk->hwidth can change */
  616                         else
  617                                 break;
  618                 }
  619 #endif /* VLAN_ARRAY */
  620         /* Trunk should have been destroyed in vlan_unconfig(). */
  621         KASSERT(ifp->if_vlantrunk == NULL, ("%s: purge failed", __func__));
  622         VLAN_UNLOCK();
  623 }
  624 
  625 /*
  626  * Return the trunk device for a virtual interface.
  627  */
  628 static struct ifnet  *
  629 vlan_trunkdev(struct ifnet *ifp)
  630 {
  631         struct ifvlan *ifv;
  632 
  633         if (ifp->if_type != IFT_L2VLAN)
  634                 return (NULL);
  635         ifv = ifp->if_softc;
  636         ifp = NULL;
  637         VLAN_LOCK();
  638         if (ifv->ifv_trunk)
  639                 ifp = PARENT(ifv);
  640         VLAN_UNLOCK();
  641         return (ifp);
  642 }
  643 
  644 /*
  645  * Return the 12-bit VLAN VID for this interface, for use by external
  646  * components such as Infiniband.
  647  *
  648  * XXXRW: Note that the function name here is historical; it should be named
  649  * vlan_vid().
  650  */
  651 static int
  652 vlan_tag(struct ifnet *ifp, uint16_t *vidp)
  653 {
  654         struct ifvlan *ifv;
  655 
  656         if (ifp->if_type != IFT_L2VLAN)
  657                 return (EINVAL);
  658         ifv = ifp->if_softc;
  659         *vidp = ifv->ifv_vid;
  660         return (0);
  661 }
  662 
  663 /*
  664  * Return a driver specific cookie for this interface.  Synchronization
  665  * with setcookie must be provided by the driver. 
  666  */
  667 static void *
  668 vlan_cookie(struct ifnet *ifp)
  669 {
  670         struct ifvlan *ifv;
  671 
  672         if (ifp->if_type != IFT_L2VLAN)
  673                 return (NULL);
  674         ifv = ifp->if_softc;
  675         return (ifv->ifv_cookie);
  676 }
  677 
  678 /*
  679  * Store a cookie in our softc that drivers can use to store driver
  680  * private per-instance data in.
  681  */
  682 static int
  683 vlan_setcookie(struct ifnet *ifp, void *cookie)
  684 {
  685         struct ifvlan *ifv;
  686 
  687         if (ifp->if_type != IFT_L2VLAN)
  688                 return (EINVAL);
  689         ifv = ifp->if_softc;
  690         ifv->ifv_cookie = cookie;
  691         return (0);
  692 }
  693 
  694 /*
  695  * Return the vlan device present at the specific VID.
  696  */
  697 static struct ifnet *
  698 vlan_devat(struct ifnet *ifp, uint16_t vid)
  699 {
  700         struct ifvlantrunk *trunk;
  701         struct ifvlan *ifv;
  702         TRUNK_LOCK_READER;
  703 
  704         trunk = ifp->if_vlantrunk;
  705         if (trunk == NULL)
  706                 return (NULL);
  707         ifp = NULL;
  708         TRUNK_RLOCK(trunk);
  709         ifv = vlan_gethash(trunk, vid);
  710         if (ifv)
  711                 ifp = ifv->ifv_ifp;
  712         TRUNK_RUNLOCK(trunk);
  713         return (ifp);
  714 }
  715 
  716 /*
  717  * Recalculate the cached VLAN tag exposed via the MIB.
  718  */
  719 static void
  720 vlan_tag_recalculate(struct ifvlan *ifv)
  721 {
  722 
  723        ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
  724 }
  725 
  726 /*
  727  * VLAN support can be loaded as a module.  The only place in the
  728  * system that's intimately aware of this is ether_input.  We hook
  729  * into this code through vlan_input_p which is defined there and
  730  * set here.  No one else in the system should be aware of this so
  731  * we use an explicit reference here.
  732  */
  733 extern  void (*vlan_input_p)(struct ifnet *, struct mbuf *);
  734 
  735 /* For if_link_state_change() eyes only... */
  736 extern  void (*vlan_link_state_p)(struct ifnet *);
  737 
  738 static int
  739 vlan_modevent(module_t mod, int type, void *data)
  740 {
  741 
  742         switch (type) {
  743         case MOD_LOAD:
  744                 ifdetach_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
  745                     vlan_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
  746                 if (ifdetach_tag == NULL)
  747                         return (ENOMEM);
  748                 iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
  749                     vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
  750                 if (iflladdr_tag == NULL)
  751                         return (ENOMEM);
  752                 VLAN_LOCK_INIT();
  753                 vlan_input_p = vlan_input;
  754                 vlan_link_state_p = vlan_link_state;
  755                 vlan_trunk_cap_p = vlan_trunk_capabilities;
  756                 vlan_trunkdev_p = vlan_trunkdev;
  757                 vlan_cookie_p = vlan_cookie;
  758                 vlan_setcookie_p = vlan_setcookie;
  759                 vlan_tag_p = vlan_tag;
  760                 vlan_devat_p = vlan_devat;
  761 #ifndef VIMAGE
  762                 vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
  763                     vlan_clone_create, vlan_clone_destroy);
  764 #endif
  765                 if (bootverbose)
  766                         printf("vlan: initialized, using "
  767 #ifdef VLAN_ARRAY
  768                                "full-size arrays"
  769 #else
  770                                "hash tables with chaining"
  771 #endif
  772                         
  773                                "\n");
  774                 break;
  775         case MOD_UNLOAD:
  776 #ifndef VIMAGE
  777                 if_clone_detach(vlan_cloner);
  778 #endif
  779                 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag);
  780                 EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag);
  781                 vlan_input_p = NULL;
  782                 vlan_link_state_p = NULL;
  783                 vlan_trunk_cap_p = NULL;
  784                 vlan_trunkdev_p = NULL;
  785                 vlan_tag_p = NULL;
  786                 vlan_cookie_p = NULL;
  787                 vlan_setcookie_p = NULL;
  788                 vlan_devat_p = NULL;
  789                 VLAN_LOCK_DESTROY();
  790                 if (bootverbose)
  791                         printf("vlan: unloaded\n");
  792                 break;
  793         default:
  794                 return (EOPNOTSUPP);
  795         }
  796         return (0);
  797 }
  798 
  799 static moduledata_t vlan_mod = {
  800         "if_vlan",
  801         vlan_modevent,
  802         0
  803 };
  804 
  805 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  806 MODULE_VERSION(if_vlan, 3);
  807 
  808 #ifdef VIMAGE
  809 static void
  810 vnet_vlan_init(const void *unused __unused)
  811 {
  812 
  813         vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
  814                     vlan_clone_create, vlan_clone_destroy);
  815         V_vlan_cloner = vlan_cloner;
  816 }
  817 VNET_SYSINIT(vnet_vlan_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
  818     vnet_vlan_init, NULL);
  819 
  820 static void
  821 vnet_vlan_uninit(const void *unused __unused)
  822 {
  823 
  824         if_clone_detach(V_vlan_cloner);
  825 }
  826 VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
  827     vnet_vlan_uninit, NULL);
  828 #endif
  829 
  830 /*
  831  * Check for <etherif>.<vlan> style interface names.
  832  */
  833 static struct ifnet *
  834 vlan_clone_match_ethervid(const char *name, int *vidp)
  835 {
  836         char ifname[IFNAMSIZ];
  837         char *cp;
  838         struct ifnet *ifp;
  839         int vid;
  840 
  841         strlcpy(ifname, name, IFNAMSIZ);
  842         if ((cp = strchr(ifname, '.')) == NULL)
  843                 return (NULL);
  844         *cp = '\0';
  845         if ((ifp = ifunit(ifname)) == NULL)
  846                 return (NULL);
  847         /* Parse VID. */
  848         if (*++cp == '\0')
  849                 return (NULL);
  850         vid = 0;
  851         for(; *cp >= '' && *cp <= '9'; cp++)
  852                 vid = (vid * 10) + (*cp - '');
  853         if (*cp != '\0')
  854                 return (NULL);
  855         if (vidp != NULL)
  856                 *vidp = vid;
  857 
  858         return (ifp);
  859 }
  860 
  861 static int
  862 vlan_clone_match(struct if_clone *ifc, const char *name)
  863 {
  864         const char *cp;
  865 
  866         if (vlan_clone_match_ethervid(name, NULL) != NULL)
  867                 return (1);
  868 
  869         if (strncmp(vlanname, name, strlen(vlanname)) != 0)
  870                 return (0);
  871         for (cp = name + 4; *cp != '\0'; cp++) {
  872                 if (*cp < '' || *cp > '9')
  873                         return (0);
  874         }
  875 
  876         return (1);
  877 }
  878 
  879 static int
  880 vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
  881 {
  882         char *dp;
  883         int wildcard;
  884         int unit;
  885         int error;
  886         int vid;
  887         int ethertag;
  888         struct ifvlan *ifv;
  889         struct ifnet *ifp;
  890         struct ifnet *p;
  891         struct ifaddr *ifa;
  892         struct sockaddr_dl *sdl;
  893         struct vlanreq vlr;
  894         static const u_char eaddr[ETHER_ADDR_LEN];      /* 00:00:00:00:00:00 */
  895 
  896         /*
  897          * There are 3 (ugh) ways to specify the cloned device:
  898          * o pass a parameter block with the clone request.
  899          * o specify parameters in the text of the clone device name
  900          * o specify no parameters and get an unattached device that
  901          *   must be configured separately.
  902          * The first technique is preferred; the latter two are
  903          * supported for backwards compatibility.
  904          *
  905          * XXXRW: Note historic use of the word "tag" here.  New ioctls may be
  906          * called for.
  907          */
  908         if (params) {
  909                 error = copyin(params, &vlr, sizeof(vlr));
  910                 if (error)
  911                         return error;
  912                 p = ifunit(vlr.vlr_parent);
  913                 if (p == NULL)
  914                         return (ENXIO);
  915                 error = ifc_name2unit(name, &unit);
  916                 if (error != 0)
  917                         return (error);
  918 
  919                 ethertag = 1;
  920                 vid = vlr.vlr_tag;
  921                 wildcard = (unit < 0);
  922         } else if ((p = vlan_clone_match_ethervid(name, &vid)) != NULL) {
  923                 ethertag = 1;
  924                 unit = -1;
  925                 wildcard = 0;
  926         } else {
  927                 ethertag = 0;
  928 
  929                 error = ifc_name2unit(name, &unit);
  930                 if (error != 0)
  931                         return (error);
  932 
  933                 wildcard = (unit < 0);
  934         }
  935 
  936         error = ifc_alloc_unit(ifc, &unit);
  937         if (error != 0)
  938                 return (error);
  939 
  940         /* In the wildcard case, we need to update the name. */
  941         if (wildcard) {
  942                 for (dp = name; *dp != '\0'; dp++);
  943                 if (snprintf(dp, len - (dp-name), "%d", unit) >
  944                     len - (dp-name) - 1) {
  945                         panic("%s: interface name too long", __func__);
  946                 }
  947         }
  948 
  949         ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
  950         ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER);
  951         if (ifp == NULL) {
  952                 ifc_free_unit(ifc, unit);
  953                 free(ifv, M_VLAN);
  954                 return (ENOSPC);
  955         }
  956         SLIST_INIT(&ifv->vlan_mc_listhead);
  957         ifp->if_softc = ifv;
  958         /*
  959          * Set the name manually rather than using if_initname because
  960          * we don't conform to the default naming convention for interfaces.
  961          */
  962         strlcpy(ifp->if_xname, name, IFNAMSIZ);
  963         ifp->if_dname = vlanname;
  964         ifp->if_dunit = unit;
  965         /* NB: flags are not set here */
  966         ifp->if_linkmib = &ifv->ifv_mib;
  967         ifp->if_linkmiblen = sizeof(ifv->ifv_mib);
  968         /* NB: mtu is not set here */
  969 
  970         ifp->if_init = vlan_init;
  971         ifp->if_transmit = vlan_transmit;
  972         ifp->if_qflush = vlan_qflush;
  973         ifp->if_ioctl = vlan_ioctl;
  974         ifp->if_flags = VLAN_IFFLAGS;
  975         ether_ifattach(ifp, eaddr);
  976         /* Now undo some of the damage... */
  977         ifp->if_baudrate = 0;
  978         ifp->if_type = IFT_L2VLAN;
  979         ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN;
  980         ifa = ifp->if_addr;
  981         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  982         sdl->sdl_type = IFT_L2VLAN;
  983 
  984         if (ethertag) {
  985                 error = vlan_config(ifv, p, vid);
  986                 if (error != 0) {
  987                         /*
  988                          * Since we've partially failed, we need to back
  989                          * out all the way, otherwise userland could get
  990                          * confused.  Thus, we destroy the interface.
  991                          */
  992                         ether_ifdetach(ifp);
  993                         vlan_unconfig(ifp);
  994                         if_free(ifp);
  995                         ifc_free_unit(ifc, unit);
  996                         free(ifv, M_VLAN);
  997 
  998                         return (error);
  999                 }
 1000 
 1001                 /* Update flags on the parent, if necessary. */
 1002                 vlan_setflags(ifp, 1);
 1003         }
 1004 
 1005         return (0);
 1006 }
 1007 
 1008 static int
 1009 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
 1010 {
 1011         struct ifvlan *ifv = ifp->if_softc;
 1012         int unit = ifp->if_dunit;
 1013 
 1014         ether_ifdetach(ifp);    /* first, remove it from system-wide lists */
 1015         vlan_unconfig(ifp);     /* now it can be unconfigured and freed */
 1016         if_free(ifp);
 1017         free(ifv, M_VLAN);
 1018         ifc_free_unit(ifc, unit);
 1019 
 1020         return (0);
 1021 }
 1022 
 1023 /*
 1024  * The ifp->if_init entry point for vlan(4) is a no-op.
 1025  */
 1026 static void
 1027 vlan_init(void *foo __unused)
 1028 {
 1029 }
 1030 
 1031 /*
 1032  * The if_transmit method for vlan(4) interface.
 1033  */
 1034 static int
 1035 vlan_transmit(struct ifnet *ifp, struct mbuf *m)
 1036 {
 1037         struct ifvlan *ifv;
 1038         struct ifnet *p;
 1039         struct m_tag *mtag;
 1040         uint16_t tag;
 1041         int error, len, mcast;
 1042 
 1043         ifv = ifp->if_softc;
 1044         p = PARENT(ifv);
 1045         len = m->m_pkthdr.len;
 1046         mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
 1047 
 1048         BPF_MTAP(ifp, m);
 1049 
 1050         /*
 1051          * Do not run parent's if_transmit() if the parent is not up,
 1052          * or parent's driver will cause a system crash.
 1053          */
 1054         if (!UP_AND_RUNNING(p)) {
 1055                 m_freem(m);
 1056                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1057                 return (ENETDOWN);
 1058         }
 1059 
 1060         /*
 1061          * Pad the frame to the minimum size allowed if told to.
 1062          * This option is in accord with IEEE Std 802.1Q, 2003 Ed.,
 1063          * paragraph C.4.4.3.b.  It can help to work around buggy
 1064          * bridges that violate paragraph C.4.4.3.a from the same
 1065          * document, i.e., fail to pad short frames after untagging.
 1066          * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but
 1067          * untagging it will produce a 62-byte frame, which is a runt
 1068          * and requires padding.  There are VLAN-enabled network
 1069          * devices that just discard such runts instead or mishandle
 1070          * them somehow.
 1071          */
 1072         if (V_soft_pad && p->if_type == IFT_ETHER) {
 1073                 static char pad[8];     /* just zeros */
 1074                 int n;
 1075 
 1076                 for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len;
 1077                      n > 0; n -= sizeof(pad))
 1078                         if (!m_append(m, min(n, sizeof(pad)), pad))
 1079                                 break;
 1080 
 1081                 if (n > 0) {
 1082                         if_printf(ifp, "cannot pad short frame\n");
 1083                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1084                         m_freem(m);
 1085                         return (0);
 1086                 }
 1087         }
 1088 
 1089         /*
 1090          * If underlying interface can do VLAN tag insertion itself,
 1091          * just pass the packet along. However, we need some way to
 1092          * tell the interface where the packet came from so that it
 1093          * knows how to find the VLAN tag to use, so we attach a
 1094          * packet tag that holds it.
 1095          */
 1096         if (vlan_mtag_pcp && (mtag = m_tag_locate(m, MTAG_8021Q,
 1097             MTAG_8021Q_PCP_OUT, NULL)) != NULL)
 1098                 tag = EVL_MAKETAG(ifv->ifv_vid, *(uint8_t *)(mtag + 1), 0);
 1099         else
 1100               tag = ifv->ifv_tag;
 1101         if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
 1102                 m->m_pkthdr.ether_vtag = tag;
 1103                 m->m_flags |= M_VLANTAG;
 1104         } else {
 1105                 m = ether_vlanencap(m, tag);
 1106                 if (m == NULL) {
 1107                         if_printf(ifp, "unable to prepend VLAN header\n");
 1108                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1109                         return (0);
 1110                 }
 1111         }
 1112 
 1113         /*
 1114          * Send it, precisely as ether_output() would have.
 1115          */
 1116         error = (p->if_transmit)(p, m);
 1117         if (error == 0) {
 1118                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
 1119                 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
 1120                 if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
 1121         } else
 1122                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1123         return (error);
 1124 }
 1125 
 1126 /*
 1127  * The ifp->if_qflush entry point for vlan(4) is a no-op.
 1128  */
 1129 static void
 1130 vlan_qflush(struct ifnet *ifp __unused)
 1131 {
 1132 }
 1133 
 1134 static void
 1135 vlan_input(struct ifnet *ifp, struct mbuf *m)
 1136 {
 1137         struct ifvlantrunk *trunk = ifp->if_vlantrunk;
 1138         struct ifvlan *ifv;
 1139         TRUNK_LOCK_READER;
 1140         struct m_tag *mtag;
 1141         uint16_t vid, tag;
 1142 
 1143         KASSERT(trunk != NULL, ("%s: no trunk", __func__));
 1144 
 1145         if (m->m_flags & M_VLANTAG) {
 1146                 /*
 1147                  * Packet is tagged, but m contains a normal
 1148                  * Ethernet frame; the tag is stored out-of-band.
 1149                  */
 1150                 tag = m->m_pkthdr.ether_vtag;
 1151                 m->m_flags &= ~M_VLANTAG;
 1152         } else {
 1153                 struct ether_vlan_header *evl;
 1154 
 1155                 /*
 1156                  * Packet is tagged in-band as specified by 802.1q.
 1157                  */
 1158                 switch (ifp->if_type) {
 1159                 case IFT_ETHER:
 1160                         if (m->m_len < sizeof(*evl) &&
 1161                             (m = m_pullup(m, sizeof(*evl))) == NULL) {
 1162                                 if_printf(ifp, "cannot pullup VLAN header\n");
 1163                                 return;
 1164                         }
 1165                         evl = mtod(m, struct ether_vlan_header *);
 1166                         tag = ntohs(evl->evl_tag);
 1167 
 1168                         /*
 1169                          * Remove the 802.1q header by copying the Ethernet
 1170                          * addresses over it and adjusting the beginning of
 1171                          * the data in the mbuf.  The encapsulated Ethernet
 1172                          * type field is already in place.
 1173                          */
 1174                         bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
 1175                               ETHER_HDR_LEN - ETHER_TYPE_LEN);
 1176                         m_adj(m, ETHER_VLAN_ENCAP_LEN);
 1177                         break;
 1178 
 1179                 default:
 1180 #ifdef INVARIANTS
 1181                         panic("%s: %s has unsupported if_type %u",
 1182                               __func__, ifp->if_xname, ifp->if_type);
 1183 #endif
 1184                         m_freem(m);
 1185                         if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
 1186                         return;
 1187                 }
 1188         }
 1189 
 1190         vid = EVL_VLANOFTAG(tag);
 1191 
 1192         TRUNK_RLOCK(trunk);
 1193         ifv = vlan_gethash(trunk, vid);
 1194         if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) {
 1195                 TRUNK_RUNLOCK(trunk);
 1196                 m_freem(m);
 1197                 if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
 1198                 return;
 1199         }
 1200         TRUNK_RUNLOCK(trunk);
 1201 
 1202         if (vlan_mtag_pcp) {
 1203                 /*
 1204                  * While uncommon, it is possible that we will find a 802.1q
 1205                  * packet encapsulated inside another packet that also had an
 1206                  * 802.1q header.  For example, ethernet tunneled over IPSEC
 1207                  * arriving over ethernet.  In that case, we replace the
 1208                  * existing 802.1q PCP m_tag value.
 1209                  */
 1210                 mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_IN, NULL);
 1211                 if (mtag == NULL) {
 1212                         mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_IN,
 1213                             sizeof(uint8_t), M_NOWAIT);
 1214                         if (mtag == NULL) {
 1215                                 m_freem(m);
 1216                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 1217                                 return;
 1218                         }
 1219                         m_tag_prepend(m, mtag);
 1220                 }
 1221                 *(uint8_t *)(mtag + 1) = EVL_PRIOFTAG(tag);
 1222         }
 1223 
 1224         m->m_pkthdr.rcvif = ifv->ifv_ifp;
 1225         if_inc_counter(ifv->ifv_ifp, IFCOUNTER_IPACKETS, 1);
 1226 
 1227         /* Pass it back through the parent's input routine. */
 1228         (*ifp->if_input)(ifv->ifv_ifp, m);
 1229 }
 1230 
 1231 static int
 1232 vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
 1233 {
 1234         struct ifvlantrunk *trunk;
 1235         struct ifnet *ifp;
 1236         int error = 0;
 1237 
 1238         /*
 1239          * We can handle non-ethernet hardware types as long as
 1240          * they handle the tagging and headers themselves.
 1241          */
 1242         if (p->if_type != IFT_ETHER &&
 1243             (p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
 1244                 return (EPROTONOSUPPORT);
 1245         if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS)
 1246                 return (EPROTONOSUPPORT);
 1247         /*
 1248          * Don't let the caller set up a VLAN VID with
 1249          * anything except VLID bits.
 1250          * VID numbers 0x0 and 0xFFF are reserved.
 1251          */
 1252         if (vid == 0 || vid == 0xFFF || (vid & ~EVL_VLID_MASK))
 1253                 return (EINVAL);
 1254         if (ifv->ifv_trunk)
 1255                 return (EBUSY);
 1256 
 1257         if (p->if_vlantrunk == NULL) {
 1258                 trunk = malloc(sizeof(struct ifvlantrunk),
 1259                     M_VLAN, M_WAITOK | M_ZERO);
 1260                 vlan_inithash(trunk);
 1261                 VLAN_LOCK();
 1262                 if (p->if_vlantrunk != NULL) {
 1263                         /* A race that is very unlikely to be hit. */
 1264                         vlan_freehash(trunk);
 1265                         free(trunk, M_VLAN);
 1266                         goto exists;
 1267                 }
 1268                 TRUNK_LOCK_INIT(trunk);
 1269                 TRUNK_LOCK(trunk);
 1270                 p->if_vlantrunk = trunk;
 1271                 trunk->parent = p;
 1272         } else {
 1273                 VLAN_LOCK();
 1274 exists:
 1275                 trunk = p->if_vlantrunk;
 1276                 TRUNK_LOCK(trunk);
 1277         }
 1278 
 1279         ifv->ifv_vid = vid;     /* must set this before vlan_inshash() */
 1280         ifv->ifv_pcp = 0;       /* Default: best effort delivery. */
 1281         vlan_tag_recalculate(ifv);
 1282         error = vlan_inshash(trunk, ifv);
 1283         if (error)
 1284                 goto done;
 1285         ifv->ifv_proto = ETHERTYPE_VLAN;
 1286         ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
 1287         ifv->ifv_mintu = ETHERMIN;
 1288         ifv->ifv_pflags = 0;
 1289 
 1290         /*
 1291          * If the parent supports the VLAN_MTU capability,
 1292          * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames,
 1293          * use it.
 1294          */
 1295         if (p->if_capenable & IFCAP_VLAN_MTU) {
 1296                 /*
 1297                  * No need to fudge the MTU since the parent can
 1298                  * handle extended frames.
 1299                  */
 1300                 ifv->ifv_mtufudge = 0;
 1301         } else {
 1302                 /*
 1303                  * Fudge the MTU by the encapsulation size.  This
 1304                  * makes us incompatible with strictly compliant
 1305                  * 802.1Q implementations, but allows us to use
 1306                  * the feature with other NetBSD implementations,
 1307                  * which might still be useful.
 1308                  */
 1309                 ifv->ifv_mtufudge = ifv->ifv_encaplen;
 1310         }
 1311 
 1312         ifv->ifv_trunk = trunk;
 1313         ifp = ifv->ifv_ifp;
 1314         /*
 1315          * Initialize fields from our parent.  This duplicates some
 1316          * work with ether_ifattach() but allows for non-ethernet
 1317          * interfaces to also work.
 1318          */
 1319         ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge;
 1320         ifp->if_baudrate = p->if_baudrate;
 1321         ifp->if_output = p->if_output;
 1322         ifp->if_input = p->if_input;
 1323         ifp->if_resolvemulti = p->if_resolvemulti;
 1324         ifp->if_addrlen = p->if_addrlen;
 1325         ifp->if_broadcastaddr = p->if_broadcastaddr;
 1326 
 1327         /*
 1328          * Copy only a selected subset of flags from the parent.
 1329          * Other flags are none of our business.
 1330          */
 1331 #define VLAN_COPY_FLAGS (IFF_SIMPLEX)
 1332         ifp->if_flags &= ~VLAN_COPY_FLAGS;
 1333         ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS;
 1334 #undef VLAN_COPY_FLAGS
 1335 
 1336         ifp->if_link_state = p->if_link_state;
 1337 
 1338         vlan_capabilities(ifv);
 1339 
 1340         /*
 1341          * Set up our interface address to reflect the underlying
 1342          * physical interface's.
 1343          */
 1344         bcopy(IF_LLADDR(p), IF_LLADDR(ifp), p->if_addrlen);
 1345         ((struct sockaddr_dl *)ifp->if_addr->ifa_addr)->sdl_alen =
 1346             p->if_addrlen;
 1347 
 1348         /*
 1349          * Configure multicast addresses that may already be
 1350          * joined on the vlan device.
 1351          */
 1352         (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */
 1353 
 1354         /* We are ready for operation now. */
 1355         ifp->if_drv_flags |= IFF_DRV_RUNNING;
 1356 done:
 1357         TRUNK_UNLOCK(trunk);
 1358         if (error == 0)
 1359                 EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid);
 1360         VLAN_UNLOCK();
 1361 
 1362         return (error);
 1363 }
 1364 
 1365 static void
 1366 vlan_unconfig(struct ifnet *ifp)
 1367 {
 1368 
 1369         VLAN_LOCK();
 1370         vlan_unconfig_locked(ifp, 0);
 1371         VLAN_UNLOCK();
 1372 }
 1373 
 1374 static void
 1375 vlan_unconfig_locked(struct ifnet *ifp, int departing)
 1376 {
 1377         struct ifvlantrunk *trunk;
 1378         struct vlan_mc_entry *mc;
 1379         struct ifvlan *ifv;
 1380         struct ifnet  *parent;
 1381         int error;
 1382 
 1383         VLAN_LOCK_ASSERT();
 1384 
 1385         ifv = ifp->if_softc;
 1386         trunk = ifv->ifv_trunk;
 1387         parent = NULL;
 1388 
 1389         if (trunk != NULL) {
 1390 
 1391                 TRUNK_LOCK(trunk);
 1392                 parent = trunk->parent;
 1393 
 1394                 /*
 1395                  * Since the interface is being unconfigured, we need to
 1396                  * empty the list of multicast groups that we may have joined
 1397                  * while we were alive from the parent's list.
 1398                  */
 1399                 while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
 1400                         /*
 1401                          * If the parent interface is being detached,
 1402                          * all its multicast addresses have already
 1403                          * been removed.  Warn about errors if
 1404                          * if_delmulti() does fail, but don't abort as
 1405                          * all callers expect vlan destruction to
 1406                          * succeed.
 1407                          */
 1408                         if (!departing) {
 1409                                 error = if_delmulti(parent,
 1410                                     (struct sockaddr *)&mc->mc_addr);
 1411                                 if (error)
 1412                                         if_printf(ifp,
 1413                     "Failed to delete multicast address from parent: %d\n",
 1414                                             error);
 1415                         }
 1416                         SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
 1417                         free(mc, M_VLAN);
 1418                 }
 1419 
 1420                 vlan_setflags(ifp, 0); /* clear special flags on parent */
 1421                 vlan_remhash(trunk, ifv);
 1422                 ifv->ifv_trunk = NULL;
 1423 
 1424                 /*
 1425                  * Check if we were the last.
 1426                  */
 1427                 if (trunk->refcnt == 0) {
 1428                         parent->if_vlantrunk = NULL;
 1429                         /*
 1430                          * XXXGL: If some ithread has already entered
 1431                          * vlan_input() and is now blocked on the trunk
 1432                          * lock, then it should preempt us right after
 1433                          * unlock and finish its work. Then we will acquire
 1434                          * lock again in trunk_destroy().
 1435                          */
 1436                         TRUNK_UNLOCK(trunk);
 1437                         trunk_destroy(trunk);
 1438                 } else
 1439                         TRUNK_UNLOCK(trunk);
 1440         }
 1441 
 1442         /* Disconnect from parent. */
 1443         if (ifv->ifv_pflags)
 1444                 if_printf(ifp, "%s: ifv_pflags unclean\n", __func__);
 1445         ifp->if_mtu = ETHERMTU;
 1446         ifp->if_link_state = LINK_STATE_UNKNOWN;
 1447         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 1448 
 1449         /*
 1450          * Only dispatch an event if vlan was
 1451          * attached, otherwise there is nothing
 1452          * to cleanup anyway.
 1453          */
 1454         if (parent != NULL)
 1455                 EVENTHANDLER_INVOKE(vlan_unconfig, parent, ifv->ifv_vid);
 1456 }
 1457 
 1458 /* Handle a reference counted flag that should be set on the parent as well */
 1459 static int
 1460 vlan_setflag(struct ifnet *ifp, int flag, int status,
 1461              int (*func)(struct ifnet *, int))
 1462 {
 1463         struct ifvlan *ifv;
 1464         int error;
 1465 
 1466         /* XXX VLAN_LOCK_ASSERT(); */
 1467 
 1468         ifv = ifp->if_softc;
 1469         status = status ? (ifp->if_flags & flag) : 0;
 1470         /* Now "status" contains the flag value or 0 */
 1471 
 1472         /*
 1473          * See if recorded parent's status is different from what
 1474          * we want it to be.  If it is, flip it.  We record parent's
 1475          * status in ifv_pflags so that we won't clear parent's flag
 1476          * we haven't set.  In fact, we don't clear or set parent's
 1477          * flags directly, but get or release references to them.
 1478          * That's why we can be sure that recorded flags still are
 1479          * in accord with actual parent's flags.
 1480          */
 1481         if (status != (ifv->ifv_pflags & flag)) {
 1482                 error = (*func)(PARENT(ifv), status);
 1483                 if (error)
 1484                         return (error);
 1485                 ifv->ifv_pflags &= ~flag;
 1486                 ifv->ifv_pflags |= status;
 1487         }
 1488         return (0);
 1489 }
 1490 
 1491 /*
 1492  * Handle IFF_* flags that require certain changes on the parent:
 1493  * if "status" is true, update parent's flags respective to our if_flags;
 1494  * if "status" is false, forcedly clear the flags set on parent.
 1495  */
 1496 static int
 1497 vlan_setflags(struct ifnet *ifp, int status)
 1498 {
 1499         int error, i;
 1500         
 1501         for (i = 0; vlan_pflags[i].flag; i++) {
 1502                 error = vlan_setflag(ifp, vlan_pflags[i].flag,
 1503                                      status, vlan_pflags[i].func);
 1504                 if (error)
 1505                         return (error);
 1506         }
 1507         return (0);
 1508 }
 1509 
 1510 /* Inform all vlans that their parent has changed link state */
 1511 static void
 1512 vlan_link_state(struct ifnet *ifp)
 1513 {
 1514         struct ifvlantrunk *trunk = ifp->if_vlantrunk;
 1515         struct ifvlan *ifv;
 1516         int i;
 1517 
 1518         TRUNK_LOCK(trunk);
 1519 #ifdef VLAN_ARRAY
 1520         for (i = 0; i < VLAN_ARRAY_SIZE; i++)
 1521                 if (trunk->vlans[i] != NULL) {
 1522                         ifv = trunk->vlans[i];
 1523 #else
 1524         for (i = 0; i < (1 << trunk->hwidth); i++)
 1525                 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list) {
 1526 #endif
 1527                         ifv->ifv_ifp->if_baudrate = trunk->parent->if_baudrate;
 1528                         if_link_state_change(ifv->ifv_ifp,
 1529                             trunk->parent->if_link_state);
 1530                 }
 1531         TRUNK_UNLOCK(trunk);
 1532 }
 1533 
 1534 static void
 1535 vlan_capabilities(struct ifvlan *ifv)
 1536 {
 1537         struct ifnet *p = PARENT(ifv);
 1538         struct ifnet *ifp = ifv->ifv_ifp;
 1539         struct ifnet_hw_tsomax hw_tsomax;
 1540 
 1541         TRUNK_LOCK_ASSERT(TRUNK(ifv));
 1542 
 1543         /*
 1544          * If the parent interface can do checksum offloading
 1545          * on VLANs, then propagate its hardware-assisted
 1546          * checksumming flags. Also assert that checksum
 1547          * offloading requires hardware VLAN tagging.
 1548          */
 1549         if (p->if_capabilities & IFCAP_VLAN_HWCSUM)
 1550                 ifp->if_capabilities = p->if_capabilities & IFCAP_HWCSUM;
 1551 
 1552         if (p->if_capenable & IFCAP_VLAN_HWCSUM &&
 1553             p->if_capenable & IFCAP_VLAN_HWTAGGING) {
 1554                 ifp->if_capenable = p->if_capenable & IFCAP_HWCSUM;
 1555                 ifp->if_hwassist = p->if_hwassist & (CSUM_IP | CSUM_TCP |
 1556                     CSUM_UDP | CSUM_SCTP);
 1557         } else {
 1558                 ifp->if_capenable = 0;
 1559                 ifp->if_hwassist = 0;
 1560         }
 1561         /*
 1562          * If the parent interface can do TSO on VLANs then
 1563          * propagate the hardware-assisted flag. TSO on VLANs
 1564          * does not necessarily require hardware VLAN tagging.
 1565          */
 1566         memset(&hw_tsomax, 0, sizeof(hw_tsomax));
 1567         if_hw_tsomax_common(p, &hw_tsomax);
 1568         if_hw_tsomax_update(ifp, &hw_tsomax);
 1569         if (p->if_capabilities & IFCAP_VLAN_HWTSO)
 1570                 ifp->if_capabilities |= p->if_capabilities & IFCAP_TSO;
 1571         if (p->if_capenable & IFCAP_VLAN_HWTSO) {
 1572                 ifp->if_capenable |= p->if_capenable & IFCAP_TSO;
 1573                 ifp->if_hwassist |= p->if_hwassist & CSUM_TSO;
 1574         } else {
 1575                 ifp->if_capenable &= ~(p->if_capenable & IFCAP_TSO);
 1576                 ifp->if_hwassist &= ~(p->if_hwassist & CSUM_TSO);
 1577         }
 1578 
 1579         /*
 1580          * If the parent interface can offload TCP connections over VLANs then
 1581          * propagate its TOE capability to the VLAN interface.
 1582          *
 1583          * All TOE drivers in the tree today can deal with VLANs.  If this
 1584          * changes then IFCAP_VLAN_TOE should be promoted to a full capability
 1585          * with its own bit.
 1586          */
 1587 #define IFCAP_VLAN_TOE IFCAP_TOE
 1588         if (p->if_capabilities & IFCAP_VLAN_TOE)
 1589                 ifp->if_capabilities |= p->if_capabilities & IFCAP_TOE;
 1590         if (p->if_capenable & IFCAP_VLAN_TOE) {
 1591                 TOEDEV(ifp) = TOEDEV(p);
 1592                 ifp->if_capenable |= p->if_capenable & IFCAP_TOE;
 1593         }
 1594 }
 1595 
 1596 static void
 1597 vlan_trunk_capabilities(struct ifnet *ifp)
 1598 {
 1599         struct ifvlantrunk *trunk = ifp->if_vlantrunk;
 1600         struct ifvlan *ifv;
 1601         int i;
 1602 
 1603         TRUNK_LOCK(trunk);
 1604 #ifdef VLAN_ARRAY
 1605         for (i = 0; i < VLAN_ARRAY_SIZE; i++)
 1606                 if (trunk->vlans[i] != NULL) {
 1607                         ifv = trunk->vlans[i];
 1608 #else
 1609         for (i = 0; i < (1 << trunk->hwidth); i++) {
 1610                 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list)
 1611 #endif
 1612                         vlan_capabilities(ifv);
 1613         }
 1614         TRUNK_UNLOCK(trunk);
 1615 }
 1616 
 1617 static int
 1618 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1619 {
 1620         struct ifnet *p;
 1621         struct ifreq *ifr;
 1622         struct ifaddr *ifa;
 1623         struct ifvlan *ifv;
 1624         struct ifvlantrunk *trunk;
 1625         struct vlanreq vlr;
 1626         int error = 0;
 1627 
 1628         ifr = (struct ifreq *)data;
 1629         ifa = (struct ifaddr *) data;
 1630         ifv = ifp->if_softc;
 1631 
 1632         switch (cmd) {
 1633         case SIOCSIFADDR:
 1634                 ifp->if_flags |= IFF_UP;
 1635 #ifdef INET
 1636                 if (ifa->ifa_addr->sa_family == AF_INET)
 1637                         arp_ifinit(ifp, ifa);
 1638 #endif
 1639                 break;
 1640         case SIOCGIFADDR:
 1641                 {
 1642                         struct sockaddr *sa;
 1643 
 1644                         sa = (struct sockaddr *)&ifr->ifr_data;
 1645                         bcopy(IF_LLADDR(ifp), sa->sa_data, ifp->if_addrlen);
 1646                 }
 1647                 break;
 1648         case SIOCGIFMEDIA:
 1649                 VLAN_LOCK();
 1650                 if (TRUNK(ifv) != NULL) {
 1651                         p = PARENT(ifv);
 1652                         VLAN_UNLOCK();
 1653                         error = (*p->if_ioctl)(p, SIOCGIFMEDIA, data);
 1654                         /* Limit the result to the parent's current config. */
 1655                         if (error == 0) {
 1656                                 struct ifmediareq *ifmr;
 1657 
 1658                                 ifmr = (struct ifmediareq *)data;
 1659                                 if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) {
 1660                                         ifmr->ifm_count = 1;
 1661                                         error = copyout(&ifmr->ifm_current,
 1662                                                 ifmr->ifm_ulist,
 1663                                                 sizeof(int));
 1664                                 }
 1665                         }
 1666                 } else {
 1667                         VLAN_UNLOCK();
 1668                         error = EINVAL;
 1669                 }
 1670                 break;
 1671 
 1672         case SIOCSIFMEDIA:
 1673                 error = EINVAL;
 1674                 break;
 1675 
 1676         case SIOCSIFMTU:
 1677                 /*
 1678                  * Set the interface MTU.
 1679                  */
 1680                 VLAN_LOCK();
 1681                 if (TRUNK(ifv) != NULL) {
 1682                         if (ifr->ifr_mtu >
 1683                              (PARENT(ifv)->if_mtu - ifv->ifv_mtufudge) ||
 1684                             ifr->ifr_mtu <
 1685                              (ifv->ifv_mintu - ifv->ifv_mtufudge))
 1686                                 error = EINVAL;
 1687                         else
 1688                                 ifp->if_mtu = ifr->ifr_mtu;
 1689                 } else
 1690                         error = EINVAL;
 1691                 VLAN_UNLOCK();
 1692                 break;
 1693 
 1694         case SIOCSETVLAN:
 1695 #ifdef VIMAGE
 1696                 /*
 1697                  * XXXRW/XXXBZ: The goal in these checks is to allow a VLAN
 1698                  * interface to be delegated to a jail without allowing the
 1699                  * jail to change what underlying interface/VID it is
 1700                  * associated with.  We are not entirely convinced that this
 1701                  * is the right way to accomplish that policy goal.
 1702                  */
 1703                 if (ifp->if_vnet != ifp->if_home_vnet) {
 1704                         error = EPERM;
 1705                         break;
 1706                 }
 1707 #endif
 1708                 error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
 1709                 if (error)
 1710                         break;
 1711                 if (vlr.vlr_parent[0] == '\0') {
 1712                         vlan_unconfig(ifp);
 1713                         break;
 1714                 }
 1715                 p = ifunit(vlr.vlr_parent);
 1716                 if (p == NULL) {
 1717                         error = ENOENT;
 1718                         break;
 1719                 }
 1720                 error = vlan_config(ifv, p, vlr.vlr_tag);
 1721                 if (error)
 1722                         break;
 1723 
 1724                 /* Update flags on the parent, if necessary. */
 1725                 vlan_setflags(ifp, 1);
 1726                 break;
 1727 
 1728         case SIOCGETVLAN:
 1729 #ifdef VIMAGE
 1730                 if (ifp->if_vnet != ifp->if_home_vnet) {
 1731                         error = EPERM;
 1732                         break;
 1733                 }
 1734 #endif
 1735                 bzero(&vlr, sizeof(vlr));
 1736                 VLAN_LOCK();
 1737                 if (TRUNK(ifv) != NULL) {
 1738                         strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname,
 1739                             sizeof(vlr.vlr_parent));
 1740                         vlr.vlr_tag = ifv->ifv_vid;
 1741                 }
 1742                 VLAN_UNLOCK();
 1743                 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr));
 1744                 break;
 1745                 
 1746         case SIOCSIFFLAGS:
 1747                 /*
 1748                  * We should propagate selected flags to the parent,
 1749                  * e.g., promiscuous mode.
 1750                  */
 1751                 if (TRUNK(ifv) != NULL)
 1752                         error = vlan_setflags(ifp, 1);
 1753                 break;
 1754 
 1755         case SIOCADDMULTI:
 1756         case SIOCDELMULTI:
 1757                 /*
 1758                  * If we don't have a parent, just remember the membership for
 1759                  * when we do.
 1760                  */
 1761                 trunk = TRUNK(ifv);
 1762                 if (trunk != NULL) {
 1763                         TRUNK_LOCK(trunk);
 1764                         error = vlan_setmulti(ifp);
 1765                         TRUNK_UNLOCK(trunk);
 1766                 }
 1767                 break;
 1768 
 1769         case SIOCGVLANPCP:
 1770 #ifdef VIMAGE
 1771                 if (ifp->if_vnet != ifp->if_home_vnet) {
 1772                         error = EPERM;
 1773                         break;
 1774                 }
 1775 #endif
 1776                 ifr->ifr_vlan_pcp = ifv->ifv_pcp;
 1777                 break;
 1778 
 1779         case SIOCSVLANPCP:
 1780 #ifdef VIMAGE
 1781                 if (ifp->if_vnet != ifp->if_home_vnet) {
 1782                         error = EPERM;
 1783                         break;
 1784                 }
 1785 #endif
 1786                 error = priv_check(curthread, PRIV_NET_SETVLANPCP);
 1787                 if (error)
 1788                         break;
 1789                 if (ifr->ifr_vlan_pcp > 7) {
 1790                         error = EINVAL;
 1791                         break;
 1792                 }
 1793                 ifv->ifv_pcp = ifr->ifr_vlan_pcp;
 1794                 vlan_tag_recalculate(ifv);
 1795                 break;
 1796 
 1797         default:
 1798                 error = EINVAL;
 1799                 break;
 1800         }
 1801 
 1802         return (error);
 1803 }

Cache object: 9e01dc5dd621d55026c18957b75d2a44


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.