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

Cache object: c7f755873290a315d1011903dd4b5f90


[ 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.