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: releng/11.2/sys/net/if_vlan.c 333101 2018-04-30 08:13:30Z hselasky $");
   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         struct  ifv_linkmib {
  166                 int     ifvm_encaplen;  /* encapsulation length */
  167                 int     ifvm_mtufudge;  /* MTU fudged by this much */
  168                 int     ifvm_mintu;     /* min transmission unit */
  169                 uint16_t ifvm_proto;    /* encapsulation ethertype */
  170                 uint16_t ifvm_tag;      /* tag to apply on packets leaving if */
  171                 uint16_t ifvm_vid;      /* VLAN ID */
  172                 uint8_t ifvm_pcp;       /* Priority Code Point (PCP). */
  173         }       ifv_mib;
  174         struct task lladdr_task;
  175         SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
  176 #ifndef VLAN_ARRAY
  177         LIST_ENTRY(ifvlan) ifv_list;
  178 #endif
  179 };
  180 #define ifv_proto       ifv_mib.ifvm_proto
  181 #define ifv_tag         ifv_mib.ifvm_tag
  182 #define ifv_vid         ifv_mib.ifvm_vid
  183 #define ifv_pcp         ifv_mib.ifvm_pcp
  184 #define ifv_encaplen    ifv_mib.ifvm_encaplen
  185 #define ifv_mtufudge    ifv_mib.ifvm_mtufudge
  186 #define ifv_mintu       ifv_mib.ifvm_mintu
  187 
  188 /* Special flags we should propagate to parent. */
  189 static struct {
  190         int flag;
  191         int (*func)(struct ifnet *, int);
  192 } vlan_pflags[] = {
  193         {IFF_PROMISC, ifpromisc},
  194         {IFF_ALLMULTI, if_allmulti},
  195         {0, NULL}
  196 };
  197 
  198 extern int vlan_mtag_pcp;
  199 
  200 static const char vlanname[] = "vlan";
  201 static MALLOC_DEFINE(M_VLAN, vlanname, "802.1Q Virtual LAN Interface");
  202 
  203 static eventhandler_tag ifdetach_tag;
  204 static eventhandler_tag iflladdr_tag;
  205 
  206 /*
  207  * if_vlan uses two module-level locks to allow concurrent modification of vlan
  208  * interfaces and (mostly) allow for vlans to be destroyed while they are being
  209  * used for tx/rx. To accomplish this in a way that has acceptable performance
  210  * and cooperation with other parts of the network stack there is a
  211  * non-sleepable rmlock(9) and an sx(9). Both locks are exclusively acquired
  212  * when destroying a vlan interface, i.e. when the if_vlantrunk field of struct
  213  * ifnet is de-allocated and NULL'd. Thus a reader holding either lock has a
  214  * guarantee that the struct ifvlantrunk references a valid vlan trunk.
  215  *
  216  * The performance-sensitive paths that warrant using the rmlock(9) are
  217  * vlan_transmit and vlan_input. Both have to check for the vlan interface's
  218  * existence using if_vlantrunk, and being in the network tx/rx paths the use
  219  * of an rmlock(9) gives a measureable improvement in performance.
  220  *
  221  * The reason for having an sx(9) is mostly because there are still areas that
  222  * must be sleepable and also have safe concurrent access to a vlan interface.
  223  * Since the sx(9) exists, it is used by default in most paths unless sleeping
  224  * is not permitted, or if it is not clear whether sleeping is permitted.
  225  *
  226  * Note that despite these protections, there is still an inherent race in the
  227  * destruction of vlans since there's no guarantee that the ifnet hasn't been
  228  * freed/reused when the tx/rx functions are called by the stack. This can only
  229  * be fixed by addressing ifnet's lifetime issues.
  230  */
  231 #define _VLAN_RM_ID ifv_rm_lock
  232 #define _VLAN_SX_ID ifv_sx
  233 
  234 static struct rmlock _VLAN_RM_ID;
  235 static struct sx _VLAN_SX_ID;
  236 
  237 #define VLAN_LOCKING_INIT() \
  238         rm_init(&_VLAN_RM_ID, "vlan_rm"); \
  239         sx_init(&_VLAN_SX_ID, "vlan_sx")
  240 
  241 #define VLAN_LOCKING_DESTROY() \
  242         rm_destroy(&_VLAN_RM_ID); \
  243         sx_destroy(&_VLAN_SX_ID)
  244 
  245 #define _VLAN_RM_TRACKER                _vlan_rm_tracker
  246 #define VLAN_RLOCK()                    rm_rlock(&_VLAN_RM_ID, \
  247                                             &_VLAN_RM_TRACKER)
  248 #define VLAN_RUNLOCK()                  rm_runlock(&_VLAN_RM_ID, \
  249                                             &_VLAN_RM_TRACKER)
  250 #define VLAN_WLOCK()                    rm_wlock(&_VLAN_RM_ID)
  251 #define VLAN_WUNLOCK()                  rm_wunlock(&_VLAN_RM_ID)
  252 #define VLAN_RLOCK_ASSERT()             rm_assert(&_VLAN_RM_ID, RA_RLOCKED)
  253 #define VLAN_WLOCK_ASSERT()             rm_assert(&_VLAN_RM_ID, RA_WLOCKED)
  254 #define VLAN_RWLOCK_ASSERT()            rm_assert(&_VLAN_RM_ID, RA_LOCKED)
  255 #define VLAN_LOCK_READER                struct rm_priotracker _VLAN_RM_TRACKER
  256 
  257 #define VLAN_SLOCK()                    sx_slock(&_VLAN_SX_ID)
  258 #define VLAN_SUNLOCK()                  sx_sunlock(&_VLAN_SX_ID)
  259 #define VLAN_XLOCK()                    sx_xlock(&_VLAN_SX_ID)
  260 #define VLAN_XUNLOCK()                  sx_xunlock(&_VLAN_SX_ID)
  261 #define VLAN_SLOCK_ASSERT()             sx_assert(&_VLAN_SX_ID, SA_SLOCKED)
  262 #define VLAN_XLOCK_ASSERT()             sx_assert(&_VLAN_SX_ID, SA_XLOCKED)
  263 #define VLAN_SXLOCK_ASSERT()            sx_assert(&_VLAN_SX_ID, SA_LOCKED)
  264 
  265 
  266 /*
  267  * We also have a per-trunk rmlock(9), that is locked shared on packet
  268  * processing and exclusive when configuration is changed. Note: This should
  269  * only be acquired while there is a shared lock on either of the global locks
  270  * via VLAN_SLOCK or VLAN_RLOCK. Thus, an exclusive lock on the global locks
  271  * makes a call to TRUNK_RLOCK/TRUNK_WLOCK technically superfluous.
  272  */
  273 #define _TRUNK_RM_TRACKER               _trunk_rm_tracker
  274 #define TRUNK_LOCK_INIT(trunk)          rm_init(&(trunk)->lock, vlanname)
  275 #define TRUNK_LOCK_DESTROY(trunk)       rm_destroy(&(trunk)->lock)
  276 #define TRUNK_RLOCK(trunk)              rm_rlock(&(trunk)->lock, \
  277     &_TRUNK_RM_TRACKER)
  278 #define TRUNK_WLOCK(trunk)              rm_wlock(&(trunk)->lock)
  279 #define TRUNK_RUNLOCK(trunk)            rm_runlock(&(trunk)->lock, \
  280     &_TRUNK_RM_TRACKER)
  281 #define TRUNK_WUNLOCK(trunk)            rm_wunlock(&(trunk)->lock)
  282 #define TRUNK_RLOCK_ASSERT(trunk)       rm_assert(&(trunk)->lock, RA_RLOCKED)
  283 #define TRUNK_LOCK_ASSERT(trunk)        rm_assert(&(trunk)->lock, RA_LOCKED)
  284 #define TRUNK_WLOCK_ASSERT(trunk)       rm_assert(&(trunk)->lock, RA_WLOCKED)
  285 #define TRUNK_LOCK_READER               struct rm_priotracker _TRUNK_RM_TRACKER
  286 
  287 /*
  288  * The VLAN_ARRAY substitutes the dynamic hash with a static array
  289  * with 4096 entries. In theory this can give a boost in processing,
  290  * however in practice it does not. Probably this is because the array
  291  * is too big to fit into CPU cache.
  292  */
  293 #ifndef VLAN_ARRAY
  294 static  void vlan_inithash(struct ifvlantrunk *trunk);
  295 static  void vlan_freehash(struct ifvlantrunk *trunk);
  296 static  int vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv);
  297 static  int vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv);
  298 static  void vlan_growhash(struct ifvlantrunk *trunk, int howmuch);
  299 static __inline struct ifvlan * vlan_gethash(struct ifvlantrunk *trunk,
  300         uint16_t vid);
  301 #endif
  302 static  void trunk_destroy(struct ifvlantrunk *trunk);
  303 
  304 static  void vlan_init(void *foo);
  305 static  void vlan_input(struct ifnet *ifp, struct mbuf *m);
  306 static  int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
  307 static  void vlan_qflush(struct ifnet *ifp);
  308 static  int vlan_setflag(struct ifnet *ifp, int flag, int status,
  309     int (*func)(struct ifnet *, int));
  310 static  int vlan_setflags(struct ifnet *ifp, int status);
  311 static  int vlan_setmulti(struct ifnet *ifp);
  312 static  int vlan_transmit(struct ifnet *ifp, struct mbuf *m);
  313 static  void vlan_unconfig(struct ifnet *ifp);
  314 static  void vlan_unconfig_locked(struct ifnet *ifp, int departing);
  315 static  int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
  316 static  void vlan_link_state(struct ifnet *ifp);
  317 static  void vlan_capabilities(struct ifvlan *ifv);
  318 static  void vlan_trunk_capabilities(struct ifnet *ifp);
  319 
  320 static  struct ifnet *vlan_clone_match_ethervid(const char *, int *);
  321 static  int vlan_clone_match(struct if_clone *, const char *);
  322 static  int vlan_clone_create(struct if_clone *, char *, size_t, caddr_t);
  323 static  int vlan_clone_destroy(struct if_clone *, struct ifnet *);
  324 
  325 static  void vlan_ifdetach(void *arg, struct ifnet *ifp);
  326 static  void vlan_iflladdr(void *arg, struct ifnet *ifp);
  327 
  328 static  void vlan_lladdr_fn(void *arg, int pending);
  329 
  330 static struct if_clone *vlan_cloner;
  331 
  332 #ifdef VIMAGE
  333 static VNET_DEFINE(struct if_clone *, vlan_cloner);
  334 #define V_vlan_cloner   VNET(vlan_cloner)
  335 #endif
  336 
  337 #ifndef VLAN_ARRAY
  338 #define HASH(n, m)      ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m))
  339 
  340 static void
  341 vlan_inithash(struct ifvlantrunk *trunk)
  342 {
  343         int i, n;
  344         
  345         /*
  346          * The trunk must not be locked here since we call malloc(M_WAITOK).
  347          * It is OK in case this function is called before the trunk struct
  348          * gets hooked up and becomes visible from other threads.
  349          */
  350 
  351         KASSERT(trunk->hwidth == 0 && trunk->hash == NULL,
  352             ("%s: hash already initialized", __func__));
  353 
  354         trunk->hwidth = VLAN_DEF_HWIDTH;
  355         n = 1 << trunk->hwidth;
  356         trunk->hmask = n - 1;
  357         trunk->hash = malloc(sizeof(struct ifvlanhead) * n, M_VLAN, M_WAITOK);
  358         for (i = 0; i < n; i++)
  359                 LIST_INIT(&trunk->hash[i]);
  360 }
  361 
  362 static void
  363 vlan_freehash(struct ifvlantrunk *trunk)
  364 {
  365 #ifdef INVARIANTS
  366         int i;
  367 
  368         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  369         for (i = 0; i < (1 << trunk->hwidth); i++)
  370                 KASSERT(LIST_EMPTY(&trunk->hash[i]),
  371                     ("%s: hash table not empty", __func__));
  372 #endif
  373         free(trunk->hash, M_VLAN);
  374         trunk->hash = NULL;
  375         trunk->hwidth = trunk->hmask = 0;
  376 }
  377 
  378 static int
  379 vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  380 {
  381         int i, b;
  382         struct ifvlan *ifv2;
  383 
  384         TRUNK_WLOCK_ASSERT(trunk);
  385         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  386 
  387         b = 1 << trunk->hwidth;
  388         i = HASH(ifv->ifv_vid, trunk->hmask);
  389         LIST_FOREACH(ifv2, &trunk->hash[i], ifv_list)
  390                 if (ifv->ifv_vid == ifv2->ifv_vid)
  391                         return (EEXIST);
  392 
  393         /*
  394          * Grow the hash when the number of vlans exceeds half of the number of
  395          * hash buckets squared. This will make the average linked-list length
  396          * buckets/2.
  397          */
  398         if (trunk->refcnt > (b * b) / 2) {
  399                 vlan_growhash(trunk, 1);
  400                 i = HASH(ifv->ifv_vid, trunk->hmask);
  401         }
  402         LIST_INSERT_HEAD(&trunk->hash[i], ifv, ifv_list);
  403         trunk->refcnt++;
  404 
  405         return (0);
  406 }
  407 
  408 static int
  409 vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  410 {
  411         int i, b;
  412         struct ifvlan *ifv2;
  413 
  414         TRUNK_WLOCK_ASSERT(trunk);
  415         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  416         
  417         b = 1 << trunk->hwidth;
  418         i = HASH(ifv->ifv_vid, trunk->hmask);
  419         LIST_FOREACH(ifv2, &trunk->hash[i], ifv_list)
  420                 if (ifv2 == ifv) {
  421                         trunk->refcnt--;
  422                         LIST_REMOVE(ifv2, ifv_list);
  423                         if (trunk->refcnt < (b * b) / 2)
  424                                 vlan_growhash(trunk, -1);
  425                         return (0);
  426                 }
  427 
  428         panic("%s: vlan not found\n", __func__);
  429         return (ENOENT); /*NOTREACHED*/
  430 }
  431 
  432 /*
  433  * Grow the hash larger or smaller if memory permits.
  434  */
  435 static void
  436 vlan_growhash(struct ifvlantrunk *trunk, int howmuch)
  437 {
  438         struct ifvlan *ifv;
  439         struct ifvlanhead *hash2;
  440         int hwidth2, i, j, n, n2;
  441 
  442         TRUNK_WLOCK_ASSERT(trunk);
  443         KASSERT(trunk->hwidth > 0, ("%s: hwidth not positive", __func__));
  444 
  445         if (howmuch == 0) {
  446                 /* Harmless yet obvious coding error */
  447                 printf("%s: howmuch is 0\n", __func__);
  448                 return;
  449         }
  450 
  451         hwidth2 = trunk->hwidth + howmuch;
  452         n = 1 << trunk->hwidth;
  453         n2 = 1 << hwidth2;
  454         /* Do not shrink the table below the default */
  455         if (hwidth2 < VLAN_DEF_HWIDTH)
  456                 return;
  457 
  458         /* M_NOWAIT because we're called with trunk mutex held */
  459         hash2 = malloc(sizeof(struct ifvlanhead) * n2, M_VLAN, M_NOWAIT);
  460         if (hash2 == NULL) {
  461                 printf("%s: out of memory -- hash size not changed\n",
  462                     __func__);
  463                 return;         /* We can live with the old hash table */
  464         }
  465         for (j = 0; j < n2; j++)
  466                 LIST_INIT(&hash2[j]);
  467         for (i = 0; i < n; i++)
  468                 while ((ifv = LIST_FIRST(&trunk->hash[i])) != NULL) {
  469                         LIST_REMOVE(ifv, ifv_list);
  470                         j = HASH(ifv->ifv_vid, n2 - 1);
  471                         LIST_INSERT_HEAD(&hash2[j], ifv, ifv_list);
  472                 }
  473         free(trunk->hash, M_VLAN);
  474         trunk->hash = hash2;
  475         trunk->hwidth = hwidth2;
  476         trunk->hmask = n2 - 1;
  477 
  478         if (bootverbose)
  479                 if_printf(trunk->parent,
  480                     "VLAN hash table resized from %d to %d buckets\n", n, n2);
  481 }
  482 
  483 static __inline struct ifvlan *
  484 vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid)
  485 {
  486         struct ifvlan *ifv;
  487 
  488         TRUNK_RLOCK_ASSERT(trunk);
  489 
  490         LIST_FOREACH(ifv, &trunk->hash[HASH(vid, trunk->hmask)], ifv_list)
  491                 if (ifv->ifv_vid == vid)
  492                         return (ifv);
  493         return (NULL);
  494 }
  495 
  496 #if 0
  497 /* Debugging code to view the hashtables. */
  498 static void
  499 vlan_dumphash(struct ifvlantrunk *trunk)
  500 {
  501         int i;
  502         struct ifvlan *ifv;
  503 
  504         for (i = 0; i < (1 << trunk->hwidth); i++) {
  505                 printf("%d: ", i);
  506                 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list)
  507                         printf("%s ", ifv->ifv_ifp->if_xname);
  508                 printf("\n");
  509         }
  510 }
  511 #endif /* 0 */
  512 #else
  513 
  514 static __inline struct ifvlan *
  515 vlan_gethash(struct ifvlantrunk *trunk, uint16_t vid)
  516 {
  517 
  518         return trunk->vlans[vid];
  519 }
  520 
  521 static __inline int
  522 vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  523 {
  524 
  525         if (trunk->vlans[ifv->ifv_vid] != NULL)
  526                 return EEXIST;
  527         trunk->vlans[ifv->ifv_vid] = ifv;
  528         trunk->refcnt++;
  529 
  530         return (0);
  531 }
  532 
  533 static __inline int
  534 vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv)
  535 {
  536 
  537         trunk->vlans[ifv->ifv_vid] = NULL;
  538         trunk->refcnt--;
  539 
  540         return (0);
  541 }
  542 
  543 static __inline void
  544 vlan_freehash(struct ifvlantrunk *trunk)
  545 {
  546 }
  547 
  548 static __inline void
  549 vlan_inithash(struct ifvlantrunk *trunk)
  550 {
  551 }
  552 
  553 #endif /* !VLAN_ARRAY */
  554 
  555 static void
  556 trunk_destroy(struct ifvlantrunk *trunk)
  557 {
  558         VLAN_XLOCK_ASSERT();
  559         VLAN_WLOCK_ASSERT();
  560 
  561         vlan_freehash(trunk);
  562         trunk->parent->if_vlantrunk = NULL;
  563         TRUNK_LOCK_DESTROY(trunk);
  564         if_rele(trunk->parent);
  565         free(trunk, M_VLAN);
  566 }
  567 
  568 /*
  569  * Program our multicast filter. What we're actually doing is
  570  * programming the multicast filter of the parent. This has the
  571  * side effect of causing the parent interface to receive multicast
  572  * traffic that it doesn't really want, which ends up being discarded
  573  * later by the upper protocol layers. Unfortunately, there's no way
  574  * to avoid this: there really is only one physical interface.
  575  */
  576 static int
  577 vlan_setmulti(struct ifnet *ifp)
  578 {
  579         struct ifnet            *ifp_p;
  580         struct ifmultiaddr      *ifma;
  581         struct ifvlan           *sc;
  582         struct vlan_mc_entry    *mc;
  583         int                     error;
  584 
  585         /*
  586          * XXX This stupidly needs the rmlock to avoid sleeping while holding
  587          * the in6_multi_mtx (see in6_mc_join_locked).
  588          */
  589         VLAN_RWLOCK_ASSERT();
  590 
  591         /* Find the parent. */
  592         sc = ifp->if_softc;
  593         TRUNK_WLOCK_ASSERT(TRUNK(sc));
  594         ifp_p = PARENT(sc);
  595 
  596         CURVNET_SET_QUIET(ifp_p->if_vnet);
  597 
  598         /* First, remove any existing filter entries. */
  599         while ((mc = SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) {
  600                 SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries);
  601                 (void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr);
  602                 free(mc, M_VLAN);
  603         }
  604 
  605         /* Now program new ones. */
  606         IF_ADDR_WLOCK(ifp);
  607         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
  608                 if (ifma->ifma_addr->sa_family != AF_LINK)
  609                         continue;
  610                 mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT);
  611                 if (mc == NULL) {
  612                         IF_ADDR_WUNLOCK(ifp);
  613                         return (ENOMEM);
  614                 }
  615                 bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len);
  616                 mc->mc_addr.sdl_index = ifp_p->if_index;
  617                 SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries);
  618         }
  619         IF_ADDR_WUNLOCK(ifp);
  620         SLIST_FOREACH (mc, &sc->vlan_mc_listhead, mc_entries) {
  621                 error = if_addmulti(ifp_p, (struct sockaddr *)&mc->mc_addr,
  622                     NULL);
  623                 if (error)
  624                         return (error);
  625         }
  626 
  627         CURVNET_RESTORE();
  628         return (0);
  629 }
  630 
  631 /*
  632  * A handler for parent interface link layer address changes.
  633  * If the parent interface link layer address is changed we
  634  * should also change it on all children vlans.
  635  */
  636 static void
  637 vlan_iflladdr(void *arg __unused, struct ifnet *ifp)
  638 {
  639         struct ifvlan *ifv;
  640         struct ifnet *ifv_ifp;
  641         struct ifvlantrunk *trunk;
  642         struct sockaddr_dl *sdl;
  643         VLAN_LOCK_READER;
  644 
  645         /* Need the rmlock since this is run on taskqueue_swi. */
  646         VLAN_RLOCK();
  647         trunk = ifp->if_vlantrunk;
  648         if (trunk == NULL) {
  649                 VLAN_RUNLOCK();
  650                 return;
  651         }
  652 
  653         /*
  654          * OK, it's a trunk.  Loop over and change all vlan's lladdrs on it.
  655          * We need an exclusive lock here to prevent concurrent SIOCSIFLLADDR
  656          * ioctl calls on the parent garbling the lladdr of the child vlan.
  657          */
  658         TRUNK_WLOCK(trunk);
  659         VLAN_FOREACH(ifv, trunk) {
  660                 /*
  661                  * Copy new new lladdr into the ifv_ifp, enqueue a task
  662                  * to actually call if_setlladdr. if_setlladdr needs to
  663                  * be deferred to a taskqueue because it will call into
  664                  * the if_vlan ioctl path and try to acquire the global
  665                  * lock.
  666                  */
  667                 ifv_ifp = ifv->ifv_ifp;
  668                 bcopy(IF_LLADDR(ifp), IF_LLADDR(ifv_ifp),
  669                     ifp->if_addrlen);
  670                 sdl = (struct sockaddr_dl *)ifv_ifp->if_addr->ifa_addr;
  671                 sdl->sdl_alen = ifp->if_addrlen;
  672                 taskqueue_enqueue(taskqueue_thread, &ifv->lladdr_task);
  673         }
  674         TRUNK_WUNLOCK(trunk);
  675         VLAN_RUNLOCK();
  676 }
  677 
  678 /*
  679  * A handler for network interface departure events.
  680  * Track departure of trunks here so that we don't access invalid
  681  * pointers or whatever if a trunk is ripped from under us, e.g.,
  682  * by ejecting its hot-plug card.  However, if an ifnet is simply
  683  * being renamed, then there's no need to tear down the state.
  684  */
  685 static void
  686 vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
  687 {
  688         struct ifvlan *ifv;
  689         struct ifvlantrunk *trunk;
  690 
  691         /* If the ifnet is just being renamed, don't do anything. */
  692         if (ifp->if_flags & IFF_RENAMING)
  693                 return;
  694         VLAN_XLOCK();
  695         trunk = ifp->if_vlantrunk;
  696         if (trunk == NULL) {
  697                 VLAN_XUNLOCK();
  698                 return;
  699         }
  700 
  701         /*
  702          * OK, it's a trunk.  Loop over and detach all vlan's on it.
  703          * Check trunk pointer after each vlan_unconfig() as it will
  704          * free it and set to NULL after the last vlan was detached.
  705          */
  706         VLAN_FOREACH_UNTIL_SAFE(ifv, ifp->if_vlantrunk,
  707             ifp->if_vlantrunk == NULL)
  708                 vlan_unconfig_locked(ifv->ifv_ifp, 1);
  709 
  710         /* Trunk should have been destroyed in vlan_unconfig(). */
  711         KASSERT(ifp->if_vlantrunk == NULL, ("%s: purge failed", __func__));
  712         VLAN_XUNLOCK();
  713 }
  714 
  715 /*
  716  * Return the trunk device for a virtual interface.
  717  */
  718 static struct ifnet  *
  719 vlan_trunkdev(struct ifnet *ifp)
  720 {
  721         struct ifvlan *ifv;
  722         VLAN_LOCK_READER;
  723 
  724         if (ifp->if_type != IFT_L2VLAN)
  725                 return (NULL);
  726 
  727         /* Not clear if callers are sleepable, so acquire the rmlock. */
  728         VLAN_RLOCK();
  729         ifv = ifp->if_softc;
  730         ifp = NULL;
  731         if (ifv->ifv_trunk)
  732                 ifp = PARENT(ifv);
  733         VLAN_RUNLOCK();
  734         return (ifp);
  735 }
  736 
  737 /*
  738  * Return the 12-bit VLAN VID for this interface, for use by external
  739  * components such as Infiniband.
  740  *
  741  * XXXRW: Note that the function name here is historical; it should be named
  742  * vlan_vid().
  743  */
  744 static int
  745 vlan_tag(struct ifnet *ifp, uint16_t *vidp)
  746 {
  747         struct ifvlan *ifv;
  748 
  749         if (ifp->if_type != IFT_L2VLAN)
  750                 return (EINVAL);
  751         ifv = ifp->if_softc;
  752         *vidp = ifv->ifv_vid;
  753         return (0);
  754 }
  755 
  756 /*
  757  * Return a driver specific cookie for this interface.  Synchronization
  758  * with setcookie must be provided by the driver. 
  759  */
  760 static void *
  761 vlan_cookie(struct ifnet *ifp)
  762 {
  763         struct ifvlan *ifv;
  764 
  765         if (ifp->if_type != IFT_L2VLAN)
  766                 return (NULL);
  767         ifv = ifp->if_softc;
  768         return (ifv->ifv_cookie);
  769 }
  770 
  771 /*
  772  * Store a cookie in our softc that drivers can use to store driver
  773  * private per-instance data in.
  774  */
  775 static int
  776 vlan_setcookie(struct ifnet *ifp, void *cookie)
  777 {
  778         struct ifvlan *ifv;
  779 
  780         if (ifp->if_type != IFT_L2VLAN)
  781                 return (EINVAL);
  782         ifv = ifp->if_softc;
  783         ifv->ifv_cookie = cookie;
  784         return (0);
  785 }
  786 
  787 /*
  788  * Return the vlan device present at the specific VID.
  789  */
  790 static struct ifnet *
  791 vlan_devat(struct ifnet *ifp, uint16_t vid)
  792 {
  793         struct ifvlantrunk *trunk;
  794         struct ifvlan *ifv;
  795         VLAN_LOCK_READER;
  796         TRUNK_LOCK_READER;
  797 
  798         /* Not clear if callers are sleepable, so acquire the rmlock. */
  799         VLAN_RLOCK();
  800         trunk = ifp->if_vlantrunk;
  801         if (trunk == NULL) {
  802                 VLAN_RUNLOCK();
  803                 return (NULL);
  804         }
  805         ifp = NULL;
  806         TRUNK_RLOCK(trunk);
  807         ifv = vlan_gethash(trunk, vid);
  808         if (ifv)
  809                 ifp = ifv->ifv_ifp;
  810         TRUNK_RUNLOCK(trunk);
  811         VLAN_RUNLOCK();
  812         return (ifp);
  813 }
  814 
  815 /*
  816  * Recalculate the cached VLAN tag exposed via the MIB.
  817  */
  818 static void
  819 vlan_tag_recalculate(struct ifvlan *ifv)
  820 {
  821 
  822        ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
  823 }
  824 
  825 /*
  826  * VLAN support can be loaded as a module.  The only place in the
  827  * system that's intimately aware of this is ether_input.  We hook
  828  * into this code through vlan_input_p which is defined there and
  829  * set here.  No one else in the system should be aware of this so
  830  * we use an explicit reference here.
  831  */
  832 extern  void (*vlan_input_p)(struct ifnet *, struct mbuf *);
  833 
  834 /* For if_link_state_change() eyes only... */
  835 extern  void (*vlan_link_state_p)(struct ifnet *);
  836 
  837 static int
  838 vlan_modevent(module_t mod, int type, void *data)
  839 {
  840 
  841         switch (type) {
  842         case MOD_LOAD:
  843                 ifdetach_tag = EVENTHANDLER_REGISTER(ifnet_departure_event,
  844                     vlan_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
  845                 if (ifdetach_tag == NULL)
  846                         return (ENOMEM);
  847                 iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
  848                     vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
  849                 if (iflladdr_tag == NULL)
  850                         return (ENOMEM);
  851                 VLAN_LOCKING_INIT();
  852                 vlan_input_p = vlan_input;
  853                 vlan_link_state_p = vlan_link_state;
  854                 vlan_trunk_cap_p = vlan_trunk_capabilities;
  855                 vlan_trunkdev_p = vlan_trunkdev;
  856                 vlan_cookie_p = vlan_cookie;
  857                 vlan_setcookie_p = vlan_setcookie;
  858                 vlan_tag_p = vlan_tag;
  859                 vlan_devat_p = vlan_devat;
  860 #ifndef VIMAGE
  861                 vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
  862                     vlan_clone_create, vlan_clone_destroy);
  863 #endif
  864                 if (bootverbose)
  865                         printf("vlan: initialized, using "
  866 #ifdef VLAN_ARRAY
  867                                "full-size arrays"
  868 #else
  869                                "hash tables with chaining"
  870 #endif
  871                         
  872                                "\n");
  873                 break;
  874         case MOD_UNLOAD:
  875 #ifndef VIMAGE
  876                 if_clone_detach(vlan_cloner);
  877 #endif
  878                 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag);
  879                 EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag);
  880                 vlan_input_p = NULL;
  881                 vlan_link_state_p = NULL;
  882                 vlan_trunk_cap_p = NULL;
  883                 vlan_trunkdev_p = NULL;
  884                 vlan_tag_p = NULL;
  885                 vlan_cookie_p = NULL;
  886                 vlan_setcookie_p = NULL;
  887                 vlan_devat_p = NULL;
  888                 VLAN_LOCKING_DESTROY();
  889                 if (bootverbose)
  890                         printf("vlan: unloaded\n");
  891                 break;
  892         default:
  893                 return (EOPNOTSUPP);
  894         }
  895         return (0);
  896 }
  897 
  898 static moduledata_t vlan_mod = {
  899         "if_vlan",
  900         vlan_modevent,
  901         0
  902 };
  903 
  904 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  905 MODULE_VERSION(if_vlan, 3);
  906 
  907 #ifdef VIMAGE
  908 static void
  909 vnet_vlan_init(const void *unused __unused)
  910 {
  911 
  912         vlan_cloner = if_clone_advanced(vlanname, 0, vlan_clone_match,
  913                     vlan_clone_create, vlan_clone_destroy);
  914         V_vlan_cloner = vlan_cloner;
  915 }
  916 VNET_SYSINIT(vnet_vlan_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
  917     vnet_vlan_init, NULL);
  918 
  919 static void
  920 vnet_vlan_uninit(const void *unused __unused)
  921 {
  922 
  923         if_clone_detach(V_vlan_cloner);
  924 }
  925 VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
  926     vnet_vlan_uninit, NULL);
  927 #endif
  928 
  929 /*
  930  * Check for <etherif>.<vlan> style interface names.
  931  */
  932 static struct ifnet *
  933 vlan_clone_match_ethervid(const char *name, int *vidp)
  934 {
  935         char ifname[IFNAMSIZ];
  936         char *cp;
  937         struct ifnet *ifp;
  938         int vid;
  939 
  940         strlcpy(ifname, name, IFNAMSIZ);
  941         if ((cp = strchr(ifname, '.')) == NULL)
  942                 return (NULL);
  943         *cp = '\0';
  944         if ((ifp = ifunit_ref(ifname)) == NULL)
  945                 return (NULL);
  946         /* Parse VID. */
  947         if (*++cp == '\0') {
  948                 if_rele(ifp);
  949                 return (NULL);
  950         }
  951         vid = 0;
  952         for(; *cp >= '' && *cp <= '9'; cp++)
  953                 vid = (vid * 10) + (*cp - '');
  954         if (*cp != '\0') {
  955                 if_rele(ifp);
  956                 return (NULL);
  957         }
  958         if (vidp != NULL)
  959                 *vidp = vid;
  960 
  961         return (ifp);
  962 }
  963 
  964 static int
  965 vlan_clone_match(struct if_clone *ifc, const char *name)
  966 {
  967         const char *cp;
  968 
  969         if (vlan_clone_match_ethervid(name, NULL) != NULL)
  970                 return (1);
  971 
  972         if (strncmp(vlanname, name, strlen(vlanname)) != 0)
  973                 return (0);
  974         for (cp = name + 4; *cp != '\0'; cp++) {
  975                 if (*cp < '' || *cp > '9')
  976                         return (0);
  977         }
  978 
  979         return (1);
  980 }
  981 
  982 static int
  983 vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
  984 {
  985         char *dp;
  986         int wildcard;
  987         int unit;
  988         int error;
  989         int vid;
  990         struct ifvlan *ifv;
  991         struct ifnet *ifp;
  992         struct ifnet *p;
  993         struct ifaddr *ifa;
  994         struct sockaddr_dl *sdl;
  995         struct vlanreq vlr;
  996         static const u_char eaddr[ETHER_ADDR_LEN];      /* 00:00:00:00:00:00 */
  997 
  998         /*
  999          * There are 3 (ugh) ways to specify the cloned device:
 1000          * o pass a parameter block with the clone request.
 1001          * o specify parameters in the text of the clone device name
 1002          * o specify no parameters and get an unattached device that
 1003          *   must be configured separately.
 1004          * The first technique is preferred; the latter two are
 1005          * supported for backwards compatibility.
 1006          *
 1007          * XXXRW: Note historic use of the word "tag" here.  New ioctls may be
 1008          * called for.
 1009          */
 1010         if (params) {
 1011                 error = copyin(params, &vlr, sizeof(vlr));
 1012                 if (error)
 1013                         return error;
 1014                 p = ifunit_ref(vlr.vlr_parent);
 1015                 if (p == NULL)
 1016                         return (ENXIO);
 1017                 error = ifc_name2unit(name, &unit);
 1018                 if (error != 0) {
 1019                         if_rele(p);
 1020                         return (error);
 1021                 }
 1022                 vid = vlr.vlr_tag;
 1023                 wildcard = (unit < 0);
 1024         } else if ((p = vlan_clone_match_ethervid(name, &vid)) != NULL) {
 1025                 unit = -1;
 1026                 wildcard = 0;
 1027         } else {
 1028                 p = NULL;
 1029                 error = ifc_name2unit(name, &unit);
 1030                 if (error != 0)
 1031                         return (error);
 1032 
 1033                 wildcard = (unit < 0);
 1034         }
 1035 
 1036         error = ifc_alloc_unit(ifc, &unit);
 1037         if (error != 0) {
 1038                 if (p != NULL)
 1039                         if_rele(p);
 1040                 return (error);
 1041         }
 1042 
 1043         /* In the wildcard case, we need to update the name. */
 1044         if (wildcard) {
 1045                 for (dp = name; *dp != '\0'; dp++);
 1046                 if (snprintf(dp, len - (dp-name), "%d", unit) >
 1047                     len - (dp-name) - 1) {
 1048                         panic("%s: interface name too long", __func__);
 1049                 }
 1050         }
 1051 
 1052         ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
 1053         ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER);
 1054         if (ifp == NULL) {
 1055                 ifc_free_unit(ifc, unit);
 1056                 free(ifv, M_VLAN);
 1057                 if (p != NULL)
 1058                         if_rele(p);
 1059                 return (ENOSPC);
 1060         }
 1061         SLIST_INIT(&ifv->vlan_mc_listhead);
 1062         ifp->if_softc = ifv;
 1063         /*
 1064          * Set the name manually rather than using if_initname because
 1065          * we don't conform to the default naming convention for interfaces.
 1066          */
 1067         strlcpy(ifp->if_xname, name, IFNAMSIZ);
 1068         ifp->if_dname = vlanname;
 1069         ifp->if_dunit = unit;
 1070         /* NB: flags are not set here */
 1071         ifp->if_linkmib = &ifv->ifv_mib;
 1072         ifp->if_linkmiblen = sizeof(ifv->ifv_mib);
 1073         /* NB: mtu is not set here */
 1074 
 1075         ifp->if_init = vlan_init;
 1076         ifp->if_transmit = vlan_transmit;
 1077         ifp->if_qflush = vlan_qflush;
 1078         ifp->if_ioctl = vlan_ioctl;
 1079         ifp->if_flags = VLAN_IFFLAGS;
 1080         ether_ifattach(ifp, eaddr);
 1081         /* Now undo some of the damage... */
 1082         ifp->if_baudrate = 0;
 1083         ifp->if_type = IFT_L2VLAN;
 1084         ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN;
 1085         ifa = ifp->if_addr;
 1086         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 1087         sdl->sdl_type = IFT_L2VLAN;
 1088 
 1089         if (p != NULL) {
 1090                 error = vlan_config(ifv, p, vid);
 1091                 if_rele(p);
 1092                 if (error != 0) {
 1093                         /*
 1094                          * Since we've partially failed, we need to back
 1095                          * out all the way, otherwise userland could get
 1096                          * confused.  Thus, we destroy the interface.
 1097                          */
 1098                         ether_ifdetach(ifp);
 1099                         vlan_unconfig(ifp);
 1100                         if_free(ifp);
 1101                         ifc_free_unit(ifc, unit);
 1102                         free(ifv, M_VLAN);
 1103 
 1104                         return (error);
 1105                 }
 1106         }
 1107 
 1108         return (0);
 1109 }
 1110 
 1111 static int
 1112 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
 1113 {
 1114         struct ifvlan *ifv = ifp->if_softc;
 1115         int unit = ifp->if_dunit;
 1116 
 1117         ether_ifdetach(ifp);    /* first, remove it from system-wide lists */
 1118         vlan_unconfig(ifp);     /* now it can be unconfigured and freed */
 1119         /*
 1120          * We should have the only reference to the ifv now, so we can now
 1121          * drain any remaining lladdr task before freeing the ifnet and the
 1122          * ifvlan.
 1123          */
 1124         taskqueue_drain(taskqueue_thread, &ifv->lladdr_task);
 1125         if_free(ifp);
 1126         free(ifv, M_VLAN);
 1127         ifc_free_unit(ifc, unit);
 1128 
 1129         return (0);
 1130 }
 1131 
 1132 /*
 1133  * The ifp->if_init entry point for vlan(4) is a no-op.
 1134  */
 1135 static void
 1136 vlan_init(void *foo __unused)
 1137 {
 1138 }
 1139 
 1140 /*
 1141  * The if_transmit method for vlan(4) interface.
 1142  */
 1143 static int
 1144 vlan_transmit(struct ifnet *ifp, struct mbuf *m)
 1145 {
 1146         struct ifvlan *ifv;
 1147         struct ifnet *p;
 1148         int error, len, mcast;
 1149         VLAN_LOCK_READER;
 1150 
 1151         VLAN_RLOCK();
 1152         ifv = ifp->if_softc;
 1153         if (TRUNK(ifv) == NULL) {
 1154                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1155                 VLAN_RUNLOCK();
 1156                 m_freem(m);
 1157                 return (ENETDOWN);
 1158         }
 1159         p = PARENT(ifv);
 1160         len = m->m_pkthdr.len;
 1161         mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
 1162 
 1163         BPF_MTAP(ifp, m);
 1164 
 1165         /*
 1166          * Do not run parent's if_transmit() if the parent is not up,
 1167          * or parent's driver will cause a system crash.
 1168          */
 1169         if (!UP_AND_RUNNING(p)) {
 1170                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1171                 VLAN_RUNLOCK();
 1172                 m_freem(m);
 1173                 return (ENETDOWN);
 1174         }
 1175 
 1176         if (!ether_8021q_frame(&m, ifp, p, ifv->ifv_vid, ifv->ifv_pcp)) {
 1177                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1178                 VLAN_RUNLOCK();
 1179                 return (0);
 1180         }
 1181 
 1182         /*
 1183          * Send it, precisely as ether_output() would have.
 1184          */
 1185         error = (p->if_transmit)(p, m);
 1186         if (error == 0) {
 1187                 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
 1188                 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
 1189                 if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
 1190         } else
 1191                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 1192         VLAN_RUNLOCK();
 1193         return (error);
 1194 }
 1195 
 1196 /*
 1197  * The ifp->if_qflush entry point for vlan(4) is a no-op.
 1198  */
 1199 static void
 1200 vlan_qflush(struct ifnet *ifp __unused)
 1201 {
 1202 }
 1203 
 1204 static void
 1205 vlan_input(struct ifnet *ifp, struct mbuf *m)
 1206 {
 1207         struct ifvlantrunk *trunk;
 1208         struct ifvlan *ifv;
 1209         VLAN_LOCK_READER;
 1210         TRUNK_LOCK_READER;
 1211         struct m_tag *mtag;
 1212         uint16_t vid, tag;
 1213 
 1214         VLAN_RLOCK();
 1215         trunk = ifp->if_vlantrunk;
 1216         if (trunk == NULL) {
 1217                 VLAN_RUNLOCK();
 1218                 m_freem(m);
 1219                 return;
 1220         }
 1221 
 1222         if (m->m_flags & M_VLANTAG) {
 1223                 /*
 1224                  * Packet is tagged, but m contains a normal
 1225                  * Ethernet frame; the tag is stored out-of-band.
 1226                  */
 1227                 tag = m->m_pkthdr.ether_vtag;
 1228                 m->m_flags &= ~M_VLANTAG;
 1229         } else {
 1230                 struct ether_vlan_header *evl;
 1231 
 1232                 /*
 1233                  * Packet is tagged in-band as specified by 802.1q.
 1234                  */
 1235                 switch (ifp->if_type) {
 1236                 case IFT_ETHER:
 1237                         if (m->m_len < sizeof(*evl) &&
 1238                             (m = m_pullup(m, sizeof(*evl))) == NULL) {
 1239                                 if_printf(ifp, "cannot pullup VLAN header\n");
 1240                                 VLAN_RUNLOCK();
 1241                                 return;
 1242                         }
 1243                         evl = mtod(m, struct ether_vlan_header *);
 1244                         tag = ntohs(evl->evl_tag);
 1245 
 1246                         /*
 1247                          * Remove the 802.1q header by copying the Ethernet
 1248                          * addresses over it and adjusting the beginning of
 1249                          * the data in the mbuf.  The encapsulated Ethernet
 1250                          * type field is already in place.
 1251                          */
 1252                         bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
 1253                               ETHER_HDR_LEN - ETHER_TYPE_LEN);
 1254                         m_adj(m, ETHER_VLAN_ENCAP_LEN);
 1255                         break;
 1256 
 1257                 default:
 1258 #ifdef INVARIANTS
 1259                         panic("%s: %s has unsupported if_type %u",
 1260                               __func__, ifp->if_xname, ifp->if_type);
 1261 #endif
 1262                         if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
 1263                         VLAN_RUNLOCK();
 1264                         m_freem(m);
 1265                         return;
 1266                 }
 1267         }
 1268 
 1269         vid = EVL_VLANOFTAG(tag);
 1270 
 1271         TRUNK_RLOCK(trunk);
 1272         ifv = vlan_gethash(trunk, vid);
 1273         if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) {
 1274                 TRUNK_RUNLOCK(trunk);
 1275                 if_inc_counter(ifp, IFCOUNTER_NOPROTO, 1);
 1276                 VLAN_RUNLOCK();
 1277                 m_freem(m);
 1278                 return;
 1279         }
 1280         TRUNK_RUNLOCK(trunk);
 1281 
 1282         if (vlan_mtag_pcp) {
 1283                 /*
 1284                  * While uncommon, it is possible that we will find a 802.1q
 1285                  * packet encapsulated inside another packet that also had an
 1286                  * 802.1q header.  For example, ethernet tunneled over IPSEC
 1287                  * arriving over ethernet.  In that case, we replace the
 1288                  * existing 802.1q PCP m_tag value.
 1289                  */
 1290                 mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_IN, NULL);
 1291                 if (mtag == NULL) {
 1292                         mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_IN,
 1293                             sizeof(uint8_t), M_NOWAIT);
 1294                         if (mtag == NULL) {
 1295                                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 1296                                 VLAN_RUNLOCK();
 1297                                 m_freem(m);
 1298                                 return;
 1299                         }
 1300                         m_tag_prepend(m, mtag);
 1301                 }
 1302                 *(uint8_t *)(mtag + 1) = EVL_PRIOFTAG(tag);
 1303         }
 1304 
 1305         m->m_pkthdr.rcvif = ifv->ifv_ifp;
 1306         if_inc_counter(ifv->ifv_ifp, IFCOUNTER_IPACKETS, 1);
 1307         VLAN_RUNLOCK();
 1308 
 1309         /* Pass it back through the parent's input routine. */
 1310         (*ifv->ifv_ifp->if_input)(ifv->ifv_ifp, m);
 1311 }
 1312 
 1313 static void
 1314 vlan_lladdr_fn(void *arg, int pending __unused)
 1315 {
 1316         struct ifvlan *ifv;
 1317         struct ifnet *ifp;
 1318 
 1319         ifv = (struct ifvlan *)arg;
 1320         ifp = ifv->ifv_ifp;
 1321         /* The ifv_ifp already has the lladdr copied in. */
 1322         if_setlladdr(ifp, IF_LLADDR(ifp), ifp->if_addrlen);
 1323 }
 1324 
 1325 static int
 1326 vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
 1327 {
 1328         struct ifvlantrunk *trunk;
 1329         struct ifnet *ifp;
 1330         int error = 0;
 1331 
 1332         /*
 1333          * We can handle non-ethernet hardware types as long as
 1334          * they handle the tagging and headers themselves.
 1335          */
 1336         if (p->if_type != IFT_ETHER &&
 1337             (p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0)
 1338                 return (EPROTONOSUPPORT);
 1339         if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS)
 1340                 return (EPROTONOSUPPORT);
 1341         /*
 1342          * Don't let the caller set up a VLAN VID with
 1343          * anything except VLID bits.
 1344          * VID numbers 0x0 and 0xFFF are reserved.
 1345          */
 1346         if (vid == 0 || vid == 0xFFF || (vid & ~EVL_VLID_MASK))
 1347                 return (EINVAL);
 1348         if (ifv->ifv_trunk)
 1349                 return (EBUSY);
 1350 
 1351         /* Acquire rmlock after the branch so we can M_WAITOK. */
 1352         VLAN_XLOCK();
 1353         if (p->if_vlantrunk == NULL) {
 1354                 trunk = malloc(sizeof(struct ifvlantrunk),
 1355                     M_VLAN, M_WAITOK | M_ZERO);
 1356                 vlan_inithash(trunk);
 1357                 TRUNK_LOCK_INIT(trunk);
 1358                 VLAN_WLOCK();
 1359                 TRUNK_WLOCK(trunk);
 1360                 p->if_vlantrunk = trunk;
 1361                 trunk->parent = p;
 1362                 if_ref(trunk->parent);
 1363         } else {
 1364                 VLAN_WLOCK();
 1365                 trunk = p->if_vlantrunk;
 1366                 TRUNK_WLOCK(trunk);
 1367         }
 1368 
 1369         ifv->ifv_vid = vid;     /* must set this before vlan_inshash() */
 1370         ifv->ifv_pcp = 0;       /* Default: best effort delivery. */
 1371         vlan_tag_recalculate(ifv);
 1372         error = vlan_inshash(trunk, ifv);
 1373         if (error)
 1374                 goto done;
 1375         ifv->ifv_proto = ETHERTYPE_VLAN;
 1376         ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
 1377         ifv->ifv_mintu = ETHERMIN;
 1378         ifv->ifv_pflags = 0;
 1379         ifv->ifv_capenable = -1;
 1380 
 1381         /*
 1382          * If the parent supports the VLAN_MTU capability,
 1383          * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames,
 1384          * use it.
 1385          */
 1386         if (p->if_capenable & IFCAP_VLAN_MTU) {
 1387                 /*
 1388                  * No need to fudge the MTU since the parent can
 1389                  * handle extended frames.
 1390                  */
 1391                 ifv->ifv_mtufudge = 0;
 1392         } else {
 1393                 /*
 1394                  * Fudge the MTU by the encapsulation size.  This
 1395                  * makes us incompatible with strictly compliant
 1396                  * 802.1Q implementations, but allows us to use
 1397                  * the feature with other NetBSD implementations,
 1398                  * which might still be useful.
 1399                  */
 1400                 ifv->ifv_mtufudge = ifv->ifv_encaplen;
 1401         }
 1402 
 1403         ifv->ifv_trunk = trunk;
 1404         ifp = ifv->ifv_ifp;
 1405         /*
 1406          * Initialize fields from our parent.  This duplicates some
 1407          * work with ether_ifattach() but allows for non-ethernet
 1408          * interfaces to also work.
 1409          */
 1410         ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge;
 1411         ifp->if_baudrate = p->if_baudrate;
 1412         ifp->if_output = p->if_output;
 1413         ifp->if_input = p->if_input;
 1414         ifp->if_resolvemulti = p->if_resolvemulti;
 1415         ifp->if_addrlen = p->if_addrlen;
 1416         ifp->if_broadcastaddr = p->if_broadcastaddr;
 1417 
 1418         /*
 1419          * Copy only a selected subset of flags from the parent.
 1420          * Other flags are none of our business.
 1421          */
 1422 #define VLAN_COPY_FLAGS (IFF_SIMPLEX)
 1423         ifp->if_flags &= ~VLAN_COPY_FLAGS;
 1424         ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS;
 1425 #undef VLAN_COPY_FLAGS
 1426 
 1427         ifp->if_link_state = p->if_link_state;
 1428 
 1429         vlan_capabilities(ifv);
 1430 
 1431         /*
 1432          * Set up our interface address to reflect the underlying
 1433          * physical interface's.
 1434          */
 1435         bcopy(IF_LLADDR(p), IF_LLADDR(ifp), p->if_addrlen);
 1436         ((struct sockaddr_dl *)ifp->if_addr->ifa_addr)->sdl_alen =
 1437             p->if_addrlen;
 1438 
 1439         /*
 1440          * Configure multicast addresses that may already be
 1441          * joined on the vlan device.
 1442          */
 1443         (void)vlan_setmulti(ifp);
 1444 
 1445         TASK_INIT(&ifv->lladdr_task, 0, vlan_lladdr_fn, ifv);
 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: 363f2262d303e63e3fe53f6bf597331f


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