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 /*      $OpenBSD: if_vlan.c,v 1.210 2022/08/10 09:01:48 mvs Exp $       */
    2 
    3 /*
    4  * Copyright 1998 Massachusetts Institute of Technology
    5  *
    6  * Permission to use, copy, modify, and distribute this software and
    7  * its documentation for any purpose and without fee is hereby
    8  * granted, provided that both the above copyright notice and this
    9  * permission notice appear in all copies, that both the above
   10  * copyright notice and this permission notice appear in all
   11  * supporting documentation, and that the name of M.I.T. not be used
   12  * in advertising or publicity pertaining to distribution of the
   13  * software without specific, written prior permission.  M.I.T. makes
   14  * no representations about the suitability of this software for any
   15  * purpose.  It is provided "as is" without express or implied
   16  * warranty.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
   19  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
   20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
   22  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   25  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $FreeBSD: src/sys/net/if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp $
   32  */
   33 
   34 /*
   35  * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
   36  * This is sort of sneaky in the implementation, since
   37  * we need to pretend to be enough of an Ethernet implementation
   38  * to make arp work.  The way we do this is by telling everyone
   39  * that we are an Ethernet, and then catch the packets that
   40  * ether_output() left on our output queue when it calls
   41  * if_start(), rewrite them for use by the real outgoing interface,
   42  * and ask it to send them.
   43  *
   44  * Some devices support 802.1Q tag insertion in firmware.  The
   45  * vlan interface behavior changes when the IFCAP_VLAN_HWTAGGING
   46  * capability is set on the parent.  In this case, vlan_start()
   47  * will not modify the ethernet header.
   48  */
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/malloc.h>
   53 #include <sys/mbuf.h>
   54 #include <sys/queue.h>
   55 #include <sys/socket.h>
   56 #include <sys/sockio.h>
   57 #include <sys/systm.h>
   58 #include <sys/rwlock.h>
   59 #include <sys/percpu.h>
   60 #include <sys/refcnt.h>
   61 #include <sys/smr.h>
   62 
   63 #include <net/if.h>
   64 #include <net/if_dl.h>
   65 #include <net/if_types.h>
   66 
   67 #include <netinet/in.h>
   68 #include <netinet/if_ether.h>
   69 
   70 #include <net/if_vlan_var.h>
   71 
   72 #include "bpfilter.h"
   73 #if NBPFILTER > 0
   74 #include <net/bpf.h>
   75 #endif
   76 
   77 struct vlan_mc_entry {
   78         LIST_ENTRY(vlan_mc_entry)       mc_entries;
   79         union {
   80                 struct ether_multi      *mcu_enm;
   81         } mc_u;
   82 #define mc_enm  mc_u.mcu_enm
   83         struct sockaddr_storage         mc_addr;
   84 };
   85 
   86 struct vlan_softc {
   87         struct arpcom            sc_ac;
   88 #define sc_if                    sc_ac.ac_if
   89         unsigned int             sc_dead;
   90         unsigned int             sc_ifidx0;     /* parent interface */
   91         int                      sc_txprio;
   92         int                      sc_rxprio;
   93         uint16_t                 sc_proto; /* encapsulation ethertype */
   94         uint16_t                 sc_tag;
   95         uint16_t                 sc_type; /* non-standard ethertype or 0x8100 */
   96         LIST_HEAD(__vlan_mchead, vlan_mc_entry)
   97                                  sc_mc_listhead;
   98         SMR_SLIST_ENTRY(vlan_softc) sc_list;
   99         int                      sc_flags;
  100         struct refcnt            sc_refcnt;
  101         struct task              sc_ltask;
  102         struct task              sc_dtask;
  103 };
  104 
  105 SMR_SLIST_HEAD(vlan_list, vlan_softc);
  106 
  107 #define IFVF_PROMISC    0x01    /* the parent should be made promisc */
  108 #define IFVF_LLADDR     0x02    /* don't inherit the parents mac */
  109 
  110 #define TAG_HASH_BITS           5
  111 #define TAG_HASH_SIZE           (1 << TAG_HASH_BITS)
  112 #define TAG_HASH_MASK           (TAG_HASH_SIZE - 1)
  113 #define TAG_HASH(tag)           (tag & TAG_HASH_MASK)
  114 struct vlan_list *vlan_tagh, *svlan_tagh;
  115 struct rwlock vlan_tagh_lk = RWLOCK_INITIALIZER("vlantag");
  116 
  117 void    vlanattach(int count);
  118 int     vlan_clone_create(struct if_clone *, int);
  119 int     vlan_clone_destroy(struct ifnet *);
  120 
  121 int     vlan_enqueue(struct ifnet *, struct mbuf *);
  122 void    vlan_start(struct ifqueue *ifq);
  123 int     vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
  124 
  125 int     vlan_up(struct vlan_softc *);
  126 int     vlan_down(struct vlan_softc *);
  127 
  128 void    vlan_ifdetach(void *);
  129 void    vlan_link_hook(void *);
  130 void    vlan_link_state(struct vlan_softc *, u_char, uint64_t);
  131 
  132 int     vlan_set_vnetid(struct vlan_softc *, uint16_t);
  133 int     vlan_set_parent(struct vlan_softc *, const char *);
  134 int     vlan_del_parent(struct vlan_softc *);
  135 int     vlan_inuse(uint16_t, unsigned int, uint16_t);
  136 int     vlan_inuse_locked(uint16_t, unsigned int, uint16_t);
  137 
  138 int     vlan_multi_add(struct vlan_softc *, struct ifreq *);
  139 int     vlan_multi_del(struct vlan_softc *, struct ifreq *);
  140 void    vlan_multi_apply(struct vlan_softc *, struct ifnet *, u_long);
  141 void    vlan_multi_free(struct vlan_softc *);
  142 
  143 int     vlan_media_get(struct vlan_softc *, struct ifreq *);
  144 
  145 int     vlan_iff(struct vlan_softc *);
  146 int     vlan_setlladdr(struct vlan_softc *, struct ifreq *);
  147 
  148 int     vlan_set_compat(struct ifnet *, struct ifreq *);
  149 int     vlan_get_compat(struct ifnet *, struct ifreq *);
  150 
  151 struct if_clone vlan_cloner =
  152     IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
  153 struct if_clone svlan_cloner =
  154     IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy);
  155 
  156 void
  157 vlanattach(int count)
  158 {
  159         unsigned int i;
  160 
  161         /* Normal VLAN */
  162         vlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*vlan_tagh),
  163             M_DEVBUF, M_NOWAIT);
  164         if (vlan_tagh == NULL)
  165                 panic("vlanattach: hashinit");
  166 
  167         /* Service-VLAN for QinQ/802.1ad provider bridges */
  168         svlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*svlan_tagh),
  169             M_DEVBUF, M_NOWAIT);
  170         if (svlan_tagh == NULL)
  171                 panic("vlanattach: hashinit");
  172 
  173         for (i = 0; i < TAG_HASH_SIZE; i++) {
  174                 SMR_SLIST_INIT(&vlan_tagh[i]);
  175                 SMR_SLIST_INIT(&svlan_tagh[i]);
  176         }
  177 
  178         if_clone_attach(&vlan_cloner);
  179         if_clone_attach(&svlan_cloner);
  180 }
  181 
  182 int
  183 vlan_clone_create(struct if_clone *ifc, int unit)
  184 {
  185         struct vlan_softc *sc;
  186         struct ifnet *ifp;
  187 
  188         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
  189         sc->sc_dead = 0;
  190         LIST_INIT(&sc->sc_mc_listhead);
  191         task_set(&sc->sc_ltask, vlan_link_hook, sc);
  192         task_set(&sc->sc_dtask, vlan_ifdetach, sc);
  193         ifp = &sc->sc_if;
  194         ifp->if_softc = sc;
  195         snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
  196             unit);
  197         /* NB: flags are not set here */
  198         /* NB: mtu is not set here */
  199 
  200         /* Special handling for the IEEE 802.1ad QinQ variant */
  201         if (strcmp("svlan", ifc->ifc_name) == 0)
  202                 sc->sc_type = ETHERTYPE_QINQ;
  203         else
  204                 sc->sc_type = ETHERTYPE_VLAN;
  205 
  206         refcnt_init(&sc->sc_refcnt);
  207         sc->sc_txprio = IF_HDRPRIO_PACKET;
  208         sc->sc_rxprio = IF_HDRPRIO_OUTER;
  209 
  210         ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
  211         ifp->if_xflags = IFXF_CLONED|IFXF_MPSAFE;
  212         ifp->if_qstart = vlan_start;
  213         ifp->if_enqueue = vlan_enqueue;
  214         ifp->if_ioctl = vlan_ioctl;
  215         ifp->if_hardmtu = 0xffff;
  216         ifp->if_link_state = LINK_STATE_DOWN;
  217 
  218         if_counters_alloc(ifp);
  219         if_attach(ifp);
  220         ether_ifattach(ifp);
  221         ifp->if_hdrlen = EVL_ENCAPLEN;
  222 
  223         return (0);
  224 }
  225 
  226 int
  227 vlan_clone_destroy(struct ifnet *ifp)
  228 {
  229         struct vlan_softc *sc = ifp->if_softc;
  230 
  231         NET_LOCK();
  232         sc->sc_dead = 1;
  233 
  234         if (ISSET(ifp->if_flags, IFF_RUNNING))
  235                 vlan_down(sc);
  236         NET_UNLOCK();
  237 
  238         ether_ifdetach(ifp);
  239         if_detach(ifp);
  240         smr_barrier();
  241         refcnt_finalize(&sc->sc_refcnt, "vlanrefs");
  242         vlan_multi_free(sc);
  243         free(sc, M_DEVBUF, sizeof(*sc));
  244 
  245         return (0);
  246 }
  247 
  248 void
  249 vlan_transmit(struct vlan_softc *sc, struct ifnet *ifp0, struct mbuf *m)
  250 {
  251         struct ifnet *ifp = &sc->sc_if;
  252         int txprio = sc->sc_txprio;
  253         uint8_t prio;
  254 
  255 #if NBPFILTER > 0
  256         if (ifp->if_bpf)
  257                 bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
  258 #endif /* NBPFILTER > 0 */
  259 
  260         prio = (txprio == IF_HDRPRIO_PACKET) ?
  261             m->m_pkthdr.pf.prio : txprio;
  262 
  263         /* IEEE 802.1p has prio 0 and 1 swapped */
  264         if (prio <= 1)
  265                 prio = !prio;
  266 
  267         /*
  268          * If the underlying interface cannot do VLAN tag insertion
  269          * itself, create an encapsulation header.
  270          */
  271         if ((ifp0->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
  272             (sc->sc_type == ETHERTYPE_VLAN)) {
  273                 m->m_pkthdr.ether_vtag = sc->sc_tag +
  274                     (prio << EVL_PRIO_BITS);
  275                 m->m_flags |= M_VLANTAG;
  276         } else {
  277                 m = vlan_inject(m, sc->sc_type, sc->sc_tag |
  278                     (prio << EVL_PRIO_BITS));
  279                 if (m == NULL) {
  280                         counters_inc(ifp->if_counters, ifc_oerrors);
  281                         return;
  282                 }
  283         }
  284 
  285         if (if_enqueue(ifp0, m))
  286                 counters_inc(ifp->if_counters, ifc_oerrors);
  287 }
  288 
  289 int
  290 vlan_enqueue(struct ifnet *ifp, struct mbuf *m)
  291 {
  292         struct ifnet *ifp0;
  293         struct vlan_softc *sc;
  294         int error = 0;
  295 
  296         if (!ifq_is_priq(&ifp->if_snd))
  297                 return (if_enqueue_ifq(ifp, m));
  298 
  299         sc = ifp->if_softc;
  300         ifp0 = if_get(sc->sc_ifidx0);
  301 
  302         if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) {
  303                 m_freem(m);
  304                 error = ENETDOWN;
  305         } else {
  306                 counters_pkt(ifp->if_counters,
  307                     ifc_opackets, ifc_obytes, m->m_pkthdr.len);
  308                 vlan_transmit(sc, ifp0, m);
  309         }
  310 
  311         if_put(ifp0);
  312 
  313         return (error);
  314 }
  315 
  316 void
  317 vlan_start(struct ifqueue *ifq)
  318 {
  319         struct ifnet *ifp = ifq->ifq_if;
  320         struct vlan_softc *sc = ifp->if_softc;
  321         struct ifnet *ifp0;
  322         struct mbuf *m;
  323 
  324         ifp0 = if_get(sc->sc_ifidx0);
  325         if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) {
  326                 ifq_purge(ifq);
  327                 goto leave;
  328         }
  329 
  330         while ((m = ifq_dequeue(ifq)) != NULL)
  331                 vlan_transmit(sc, ifp0, m);
  332 
  333 leave:
  334         if_put(ifp0);
  335 }
  336 
  337 struct mbuf *
  338 vlan_strip(struct mbuf *m)
  339 {
  340         if (ISSET(m->m_flags, M_VLANTAG)) {
  341                 CLR(m->m_flags, M_VLANTAG);
  342         } else {
  343                 struct ether_vlan_header *evl;
  344 
  345                 evl = mtod(m, struct ether_vlan_header *);
  346                 memmove((caddr_t)evl + EVL_ENCAPLEN, evl,
  347                     offsetof(struct ether_vlan_header, evl_encap_proto));
  348                 m_adj(m, EVL_ENCAPLEN);
  349         }
  350 
  351         return (m);
  352 }
  353 
  354 struct mbuf *
  355 vlan_inject(struct mbuf *m, uint16_t type, uint16_t tag)
  356 {
  357         struct ether_vlan_header evh;
  358 
  359         m_copydata(m, 0, ETHER_HDR_LEN, &evh);
  360         evh.evl_proto = evh.evl_encap_proto;
  361         evh.evl_encap_proto = htons(type);
  362         evh.evl_tag = htons(tag);
  363         m_adj(m, ETHER_HDR_LEN);
  364         M_PREPEND(m, sizeof(evh) + ETHER_ALIGN, M_DONTWAIT);
  365         if (m == NULL)
  366                 return (NULL);
  367 
  368         m_adj(m, ETHER_ALIGN);
  369 
  370         m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
  371         CLR(m->m_flags, M_VLANTAG);
  372 
  373         return (m);
  374 }
  375 
  376 struct mbuf *
  377 vlan_input(struct ifnet *ifp0, struct mbuf *m, unsigned int *sdelim)
  378 {
  379         struct vlan_softc *sc;
  380         struct ifnet *ifp;
  381         struct ether_vlan_header *evl;
  382         struct vlan_list *tagh, *list;
  383         uint16_t vtag, tag;
  384         uint16_t etype;
  385         int rxprio;
  386 
  387         if (m->m_flags & M_VLANTAG) {
  388                 vtag = m->m_pkthdr.ether_vtag;
  389                 etype = ETHERTYPE_VLAN;
  390                 tagh = vlan_tagh;
  391         } else {
  392                 if (m->m_len < sizeof(*evl)) {
  393                         m = m_pullup(m, sizeof(*evl));
  394                         if (m == NULL)
  395                                 return (NULL);
  396                 }
  397 
  398                 evl = mtod(m, struct ether_vlan_header *);
  399                 vtag = bemtoh16(&evl->evl_tag);
  400                 etype = bemtoh16(&evl->evl_encap_proto);
  401                 switch (etype) {
  402                 case ETHERTYPE_VLAN:
  403                         tagh = vlan_tagh;
  404                         break;
  405                 case ETHERTYPE_QINQ:
  406                         tagh = svlan_tagh;
  407                         break;
  408                 default:
  409                         panic("%s: unexpected etype 0x%04x", __func__, etype);
  410                         /* NOTREACHED */
  411                 }
  412         }
  413 
  414         tag = EVL_VLANOFTAG(vtag);
  415         list = &tagh[TAG_HASH(tag)];
  416         smr_read_enter();
  417         SMR_SLIST_FOREACH(sc, list, sc_list) {
  418                 if (ifp0->if_index == sc->sc_ifidx0 && tag == sc->sc_tag &&
  419                     etype == sc->sc_type) {
  420                         refcnt_take(&sc->sc_refcnt);
  421                         break;
  422                 }
  423         }
  424         smr_read_leave();
  425 
  426         if (sc == NULL) {
  427                 /* VLAN 0 Priority Tagging */
  428                 if (tag == 0 && etype == ETHERTYPE_VLAN) {
  429                         struct ether_header *eh;
  430 
  431                         /* XXX we should actually use the prio value? */
  432                         m = vlan_strip(m);
  433 
  434                         eh = mtod(m, struct ether_header *);
  435                         if (eh->ether_type == htons(ETHERTYPE_VLAN) ||
  436                             eh->ether_type == htons(ETHERTYPE_QINQ)) {
  437                                 m_freem(m);
  438                                 return (NULL);
  439                         }
  440                 } else
  441                         *sdelim = 1;
  442 
  443                 return (m); /* decline */
  444         }
  445 
  446         ifp = &sc->sc_if;
  447         if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
  448                 m_freem(m);
  449                 goto leave;
  450         }
  451 
  452         /*
  453          * Having found a valid vlan interface corresponding to
  454          * the given source interface and vlan tag, remove the
  455          * encapsulation.
  456          */
  457         m = vlan_strip(m);
  458 
  459         rxprio = sc->sc_rxprio;
  460         switch (rxprio) {
  461         case IF_HDRPRIO_PACKET:
  462                 break;
  463         case IF_HDRPRIO_OUTER:
  464                 m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
  465                 /* IEEE 802.1p has prio 0 and 1 swapped */
  466                 if (m->m_pkthdr.pf.prio <= 1)
  467                         m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio;
  468                 break;
  469         default:
  470                 m->m_pkthdr.pf.prio = rxprio;
  471                 break;
  472         }
  473 
  474         if_vinput(ifp, m);
  475 leave:
  476         refcnt_rele_wake(&sc->sc_refcnt);
  477         return (NULL);
  478 }
  479 
  480 int
  481 vlan_up(struct vlan_softc *sc)
  482 {
  483         struct vlan_list *tagh, *list;
  484         struct ifnet *ifp = &sc->sc_if;
  485         struct ifnet *ifp0;
  486         int error = 0;
  487         unsigned int hardmtu;
  488 
  489         KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING));
  490 
  491         tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
  492         list = &tagh[TAG_HASH(sc->sc_tag)];
  493 
  494         ifp0 = if_get(sc->sc_ifidx0);
  495         if (ifp0 == NULL)
  496                 return (ENXIO);
  497 
  498         /* check vlan will work on top of the parent */
  499         if (ifp0->if_type != IFT_ETHER) {
  500                 error = EPROTONOSUPPORT;
  501                 goto put;
  502         }
  503 
  504         hardmtu = ifp0->if_hardmtu;
  505         if (!ISSET(ifp0->if_capabilities, IFCAP_VLAN_MTU))
  506                 hardmtu -= EVL_ENCAPLEN;
  507 
  508         if (ifp->if_mtu > hardmtu) {
  509                 error = ENOBUFS;
  510                 goto put;
  511         }
  512 
  513         /* parent is fine, let's prepare the sc to handle packets */
  514         ifp->if_hardmtu = hardmtu;
  515         SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX);
  516 
  517         if (ISSET(sc->sc_flags, IFVF_PROMISC)) {
  518                 error = ifpromisc(ifp0, 1);
  519                 if (error != 0)
  520                         goto scrub;
  521         }
  522 
  523         /*
  524          * Note: In cases like vio(4) and em(4) where the offsets of the
  525          * csum can be freely defined, we could actually do csum offload
  526          * for VLAN and QINQ packets.
  527          */
  528         if (sc->sc_type != ETHERTYPE_VLAN) {
  529                 /*
  530                  * Hardware offload only works with the default VLAN
  531                  * ethernet type (0x8100).
  532                  */
  533                 ifp->if_capabilities = 0;
  534         } else if (ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWTAGGING)) {
  535                 /*
  536                  * Chips that can do hardware-assisted VLAN encapsulation, can
  537                  * calculate the correct checksum for VLAN tagged packets.
  538                  */
  539                 ifp->if_capabilities = ifp0->if_capabilities & IFCAP_CSUM_MASK;
  540         }
  541 
  542         /* commit the sc */
  543         error = rw_enter(&vlan_tagh_lk, RW_WRITE | RW_INTR);
  544         if (error != 0)
  545                 goto unpromisc;
  546 
  547         error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, sc->sc_tag);
  548         if (error != 0)
  549                 goto leave;
  550 
  551         SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list);
  552         rw_exit(&vlan_tagh_lk);
  553 
  554         /* Register callback for physical link state changes */
  555         if_linkstatehook_add(ifp0, &sc->sc_ltask);
  556 
  557         /* Register callback if parent wants to unregister */
  558         if_detachhook_add(ifp0, &sc->sc_dtask);
  559 
  560         /* configure the parent to handle packets for this vlan */
  561         vlan_multi_apply(sc, ifp0, SIOCADDMULTI);
  562 
  563         /* we're running now */
  564         SET(ifp->if_flags, IFF_RUNNING);
  565         vlan_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate);
  566 
  567         if_put(ifp0);
  568 
  569         return (ENETRESET);
  570 
  571 leave:
  572         rw_exit(&vlan_tagh_lk);
  573 unpromisc:
  574         if (ISSET(sc->sc_flags, IFVF_PROMISC))
  575                 (void)ifpromisc(ifp0, 0); /* XXX */
  576 scrub:
  577         ifp->if_capabilities = 0;
  578         CLR(ifp->if_flags, IFF_SIMPLEX);
  579         ifp->if_hardmtu = 0xffff;
  580 put:
  581         if_put(ifp0);
  582 
  583         return (error);
  584 }
  585 
  586 int
  587 vlan_down(struct vlan_softc *sc)
  588 {
  589         struct vlan_list *tagh, *list;
  590         struct ifnet *ifp = &sc->sc_if;
  591         struct ifnet *ifp0;
  592 
  593         tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
  594         list = &tagh[TAG_HASH(sc->sc_tag)];
  595 
  596         KASSERT(ISSET(ifp->if_flags, IFF_RUNNING));
  597 
  598         vlan_link_state(sc, LINK_STATE_DOWN, 0);
  599         CLR(ifp->if_flags, IFF_RUNNING);
  600 
  601         ifq_barrier(&ifp->if_snd);
  602 
  603         ifp0 = if_get(sc->sc_ifidx0);
  604         if (ifp0 != NULL) {
  605                 if (ISSET(sc->sc_flags, IFVF_PROMISC))
  606                         ifpromisc(ifp0, 0);
  607                 vlan_multi_apply(sc, ifp0, SIOCDELMULTI);
  608                 if_detachhook_del(ifp0, &sc->sc_dtask);
  609                 if_linkstatehook_del(ifp0, &sc->sc_ltask);
  610         }
  611         if_put(ifp0);
  612 
  613         rw_enter_write(&vlan_tagh_lk);
  614         SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list);
  615         rw_exit_write(&vlan_tagh_lk);
  616 
  617         ifp->if_capabilities = 0;
  618         CLR(ifp->if_flags, IFF_SIMPLEX);
  619         ifp->if_hardmtu = 0xffff;
  620 
  621         return (0);
  622 }
  623 
  624 void
  625 vlan_ifdetach(void *v)
  626 {
  627         struct vlan_softc *sc = v;
  628         struct ifnet *ifp = &sc->sc_if;
  629 
  630         if (ISSET(ifp->if_flags, IFF_RUNNING)) {
  631                 vlan_down(sc);
  632                 CLR(ifp->if_flags, IFF_UP);
  633         }
  634 
  635         sc->sc_ifidx0 = 0;
  636 }
  637 
  638 void
  639 vlan_link_hook(void *v)
  640 {
  641         struct vlan_softc *sc = v;
  642         struct ifnet *ifp0;
  643 
  644         u_char link = LINK_STATE_DOWN;
  645         uint64_t baud = 0;
  646 
  647         ifp0 = if_get(sc->sc_ifidx0);
  648         if (ifp0 != NULL) {
  649                 link = ifp0->if_link_state;
  650                 baud = ifp0->if_baudrate;
  651         }
  652         if_put(ifp0);
  653 
  654         vlan_link_state(sc, link, baud);
  655 }
  656 
  657 void
  658 vlan_link_state(struct vlan_softc *sc, u_char link, uint64_t baud)
  659 {
  660         if (sc->sc_if.if_link_state == link)
  661                 return;
  662 
  663         sc->sc_if.if_link_state = link;
  664         sc->sc_if.if_baudrate = baud;
  665 
  666         if_link_state_change(&sc->sc_if);
  667 }
  668 
  669 int
  670 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  671 {
  672         struct vlan_softc *sc = ifp->if_softc;
  673         struct ifreq *ifr = (struct ifreq *)data;
  674         struct if_parent *parent = (struct if_parent *)data;
  675         struct ifnet *ifp0;
  676         uint16_t tag;
  677         int error = 0;
  678 
  679         if (sc->sc_dead)
  680                 return (ENXIO);
  681 
  682         switch (cmd) {
  683         case SIOCSIFADDR:
  684                 ifp->if_flags |= IFF_UP;
  685                 /* FALLTHROUGH */
  686 
  687         case SIOCSIFFLAGS:
  688                 if (ISSET(ifp->if_flags, IFF_UP)) {
  689                         if (!ISSET(ifp->if_flags, IFF_RUNNING))
  690                                 error = vlan_up(sc);
  691                         else
  692                                 error = ENETRESET;
  693                 } else {
  694                         if (ISSET(ifp->if_flags, IFF_RUNNING))
  695                                 error = vlan_down(sc);
  696                 }
  697                 break;
  698 
  699         case SIOCSVNETID:
  700                 if (ifr->ifr_vnetid < EVL_VLID_MIN ||
  701                     ifr->ifr_vnetid > EVL_VLID_MAX) {
  702                         error = EINVAL;
  703                         break;
  704                 }
  705 
  706                 tag = ifr->ifr_vnetid;
  707                 if (tag == sc->sc_tag)
  708                         break;
  709 
  710                 error = vlan_set_vnetid(sc, tag);
  711                 break;
  712 
  713         case SIOCGVNETID:
  714                 if (sc->sc_tag == EVL_VLID_NULL)
  715                         error = EADDRNOTAVAIL;
  716                 else
  717                         ifr->ifr_vnetid = (int64_t)sc->sc_tag;
  718                 break;
  719 
  720         case SIOCDVNETID:
  721                 error = vlan_set_vnetid(sc, 0);
  722                 break;
  723 
  724         case SIOCSIFPARENT:
  725                 error = vlan_set_parent(sc, parent->ifp_parent);
  726                 break;
  727 
  728         case SIOCGIFPARENT:
  729                 ifp0 = if_get(sc->sc_ifidx0);
  730                 if (ifp0 == NULL)
  731                         error = EADDRNOTAVAIL;
  732                 else {
  733                         memcpy(parent->ifp_parent, ifp0->if_xname,
  734                             sizeof(parent->ifp_parent));
  735                 }
  736                 if_put(ifp0);
  737                 break;
  738 
  739         case SIOCDIFPARENT:
  740                 error = vlan_del_parent(sc);
  741                 break;
  742 
  743         case SIOCADDMULTI:
  744                 error = vlan_multi_add(sc, ifr);
  745                 break;
  746 
  747         case SIOCDELMULTI:
  748                 error = vlan_multi_del(sc, ifr);
  749                 break;
  750 
  751         case SIOCGIFMEDIA:
  752                 error = vlan_media_get(sc, ifr);
  753                 break;
  754 
  755         case SIOCSIFMEDIA:
  756                 error = ENOTTY;
  757                 break;
  758 
  759         case SIOCSIFLLADDR:
  760                 error = vlan_setlladdr(sc, ifr);
  761                 break;
  762 
  763         case SIOCSETVLAN:
  764                 error = vlan_set_compat(ifp, ifr);
  765                 break;
  766         case SIOCGETVLAN:
  767                 error = vlan_get_compat(ifp, ifr);
  768                 break;
  769 
  770         case SIOCSTXHPRIO:
  771                 error = if_txhprio_l2_check(ifr->ifr_hdrprio);
  772                 if (error != 0)
  773                         break;
  774 
  775                 sc->sc_txprio = ifr->ifr_hdrprio;
  776                 break;
  777         case SIOCGTXHPRIO:
  778                 ifr->ifr_hdrprio = sc->sc_txprio;
  779                 break;
  780 
  781         case SIOCSRXHPRIO:
  782                 error = if_rxhprio_l2_check(ifr->ifr_hdrprio);
  783                 if (error != 0)
  784                         break;
  785 
  786                 sc->sc_rxprio = ifr->ifr_hdrprio;
  787                 break;
  788         case SIOCGRXHPRIO:
  789                 ifr->ifr_hdrprio = sc->sc_rxprio;
  790                 break;
  791 
  792         default:
  793                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
  794                 break;
  795         }
  796 
  797         if (error == ENETRESET)
  798                 error = vlan_iff(sc);
  799 
  800         return error;
  801 }
  802 
  803 int
  804 vlan_iff(struct vlan_softc *sc)
  805 {
  806         struct ifnet *ifp0;
  807         int promisc = 0;
  808         int error = 0;
  809 
  810         if (ISSET(sc->sc_if.if_flags, IFF_PROMISC) ||
  811             ISSET(sc->sc_flags, IFVF_LLADDR))
  812                 promisc = IFVF_PROMISC;
  813 
  814         if (ISSET(sc->sc_flags, IFVF_PROMISC) == promisc)
  815                 return (0);
  816 
  817         if (ISSET(sc->sc_if.if_flags, IFF_RUNNING)) {
  818                 ifp0 = if_get(sc->sc_ifidx0);
  819                 if (ifp0 != NULL)
  820                         error = ifpromisc(ifp0, promisc);
  821                 if_put(ifp0);
  822         }
  823 
  824         if (error == 0) {
  825                 CLR(sc->sc_flags, IFVF_PROMISC);
  826                 SET(sc->sc_flags, promisc);
  827         }
  828 
  829         return (error);
  830 }
  831 
  832 int
  833 vlan_setlladdr(struct vlan_softc *sc, struct ifreq *ifr)
  834 {
  835         struct ifnet *ifp = &sc->sc_if;
  836         struct ifnet *ifp0;
  837         uint8_t lladdr[ETHER_ADDR_LEN];
  838         int flag;
  839 
  840         memcpy(lladdr, ifr->ifr_addr.sa_data, sizeof(lladdr));
  841 
  842         /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */
  843         if (memcmp(lladdr, etheranyaddr, sizeof(lladdr)) == 0) {
  844                 ifp0 = if_get(sc->sc_ifidx0);
  845                 if (ifp0 != NULL)
  846                         memcpy(lladdr, LLADDR(ifp0->if_sadl), sizeof(lladdr));
  847                 if_put(ifp0);
  848 
  849                 flag = 0;
  850         } else
  851                 flag = IFVF_LLADDR;
  852 
  853         if (memcmp(lladdr, LLADDR(ifp->if_sadl), sizeof(lladdr)) == 0 &&
  854             ISSET(sc->sc_flags, IFVF_LLADDR) == flag) {
  855                 /* nop */
  856                 return (0);
  857         }
  858 
  859         /* commit */
  860         if_setlladdr(ifp, lladdr);
  861         CLR(sc->sc_flags, IFVF_LLADDR);
  862         SET(sc->sc_flags, flag);
  863 
  864         return (ENETRESET);
  865 }
  866 
  867 int
  868 vlan_set_vnetid(struct vlan_softc *sc, uint16_t tag)
  869 {
  870         struct ifnet *ifp = &sc->sc_if;
  871         struct vlan_list *tagh, *list;
  872         u_char link = ifp->if_link_state;
  873         uint64_t baud = ifp->if_baudrate;
  874         int error;
  875 
  876         tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
  877 
  878         if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
  879                 vlan_link_state(sc, LINK_STATE_DOWN, 0);
  880 
  881         error = rw_enter(&vlan_tagh_lk, RW_WRITE);
  882         if (error != 0)
  883                 return (error);
  884 
  885         error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, tag);
  886         if (error != 0)
  887                 goto unlock;
  888 
  889         if (ISSET(ifp->if_flags, IFF_RUNNING)) {
  890                 list = &tagh[TAG_HASH(sc->sc_tag)];
  891                 SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list);
  892 
  893                 sc->sc_tag = tag;
  894 
  895                 list = &tagh[TAG_HASH(sc->sc_tag)];
  896                 SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list);
  897         } else
  898                 sc->sc_tag = tag;
  899 
  900 unlock:
  901         rw_exit(&vlan_tagh_lk);
  902 
  903         if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
  904                 vlan_link_state(sc, link, baud);
  905 
  906         return (error);
  907 }
  908 
  909 int
  910 vlan_set_parent(struct vlan_softc *sc, const char *parent)
  911 {
  912         struct ifnet *ifp = &sc->sc_if;
  913         struct ifnet *ifp0;
  914         int error = 0;
  915 
  916         ifp0 = if_unit(parent);
  917         if (ifp0 == NULL)
  918                 return (EINVAL);
  919 
  920         if (ifp0->if_type != IFT_ETHER) {
  921                 error = EPROTONOSUPPORT;
  922                 goto put;
  923         }
  924 
  925         if (sc->sc_ifidx0 == ifp0->if_index) {
  926                 /* nop */
  927                 goto put;
  928         }
  929 
  930         if (ISSET(ifp->if_flags, IFF_RUNNING)) {
  931                 error = EBUSY;
  932                 goto put;
  933         }
  934 
  935         error = vlan_inuse(sc->sc_type, ifp0->if_index, sc->sc_tag);
  936         if (error != 0)
  937                 goto put;
  938 
  939         /* commit */
  940         sc->sc_ifidx0 = ifp0->if_index;
  941         if (!ISSET(sc->sc_flags, IFVF_LLADDR))
  942                 if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
  943 
  944 put:
  945         if_put(ifp0);
  946         return (error);
  947 }
  948 
  949 int
  950 vlan_del_parent(struct vlan_softc *sc)
  951 {
  952         struct ifnet *ifp = &sc->sc_if;
  953 
  954         if (ISSET(ifp->if_flags, IFF_RUNNING))
  955                 return (EBUSY);
  956 
  957         /* commit */
  958         sc->sc_ifidx0 = 0;
  959         if (!ISSET(sc->sc_flags, IFVF_LLADDR))
  960                 if_setlladdr(ifp, etheranyaddr);
  961 
  962         return (0);
  963 }
  964 
  965 int
  966 vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr)
  967 {
  968         struct vlanreq vlr;
  969         struct ifreq req;
  970         struct if_parent parent;
  971 
  972         int error;
  973 
  974         error = suser(curproc);
  975         if (error != 0)
  976                 return (error);
  977 
  978         error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
  979         if (error != 0)
  980                 return (error);
  981 
  982         if (vlr.vlr_parent[0] == '\0')
  983                 return (vlan_ioctl(ifp, SIOCDIFPARENT, (caddr_t)ifr));
  984 
  985         memset(&req, 0, sizeof(req));
  986         memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
  987         req.ifr_vnetid = vlr.vlr_tag;
  988 
  989         error = vlan_ioctl(ifp, SIOCSVNETID, (caddr_t)&req);
  990         if (error != 0)
  991                 return (error);
  992 
  993         memset(&parent, 0, sizeof(parent));
  994         memcpy(parent.ifp_name, ifp->if_xname, sizeof(parent.ifp_name));
  995         memcpy(parent.ifp_parent, vlr.vlr_parent, sizeof(parent.ifp_parent));
  996         error = vlan_ioctl(ifp, SIOCSIFPARENT, (caddr_t)&parent);
  997         if (error != 0)
  998                 return (error);
  999 
 1000         memset(&req, 0, sizeof(req));
 1001         memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
 1002         SET(ifp->if_flags, IFF_UP);
 1003         return (vlan_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&req));
 1004 }
 1005 
 1006 int
 1007 vlan_get_compat(struct ifnet *ifp, struct ifreq *ifr)
 1008 {
 1009         struct vlan_softc *sc = ifp->if_softc;
 1010         struct vlanreq vlr;
 1011         struct ifnet *p;
 1012 
 1013         memset(&vlr, 0, sizeof(vlr));
 1014         p = if_get(sc->sc_ifidx0);
 1015         if (p != NULL)
 1016                 memcpy(vlr.vlr_parent, p->if_xname, sizeof(vlr.vlr_parent));
 1017         if_put(p);
 1018 
 1019         vlr.vlr_tag = sc->sc_tag;
 1020 
 1021         return (copyout(&vlr, ifr->ifr_data, sizeof(vlr)));
 1022 }
 1023 
 1024 /*
 1025  * do a quick check of up and running vlans for existing configurations.
 1026  *
 1027  * NOTE: this does allow the same config on down vlans, but vlan_up()
 1028  * will catch them.
 1029  */
 1030 int
 1031 vlan_inuse(uint16_t type, unsigned int ifidx, uint16_t tag)
 1032 {
 1033         int error = 0;
 1034 
 1035         error = rw_enter(&vlan_tagh_lk, RW_READ | RW_INTR);
 1036         if (error != 0)
 1037                 return (error);
 1038 
 1039         error = vlan_inuse_locked(type, ifidx, tag);
 1040 
 1041         rw_exit(&vlan_tagh_lk);
 1042 
 1043         return (error);
 1044 }
 1045 
 1046 int
 1047 vlan_inuse_locked(uint16_t type, unsigned int ifidx, uint16_t tag)
 1048 {
 1049         struct vlan_list *tagh, *list;
 1050         struct vlan_softc *sc;
 1051 
 1052         tagh = type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
 1053         list = &tagh[TAG_HASH(tag)];
 1054 
 1055         SMR_SLIST_FOREACH_LOCKED(sc, list, sc_list) {
 1056                 if (sc->sc_tag == tag &&
 1057                     sc->sc_type == type && /* wat */
 1058                     sc->sc_ifidx0 == ifidx)
 1059                         return (EADDRINUSE);
 1060         }
 1061 
 1062         return (0);
 1063 }
 1064 
 1065 int
 1066 vlan_multi_add(struct vlan_softc *sc, struct ifreq *ifr)
 1067 {
 1068         struct ifnet *ifp0;
 1069         struct vlan_mc_entry *mc;
 1070         uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
 1071         int error;
 1072 
 1073         error = ether_addmulti(ifr, &sc->sc_ac);
 1074         if (error != ENETRESET)
 1075                 return (error);
 1076 
 1077         /*
 1078          * This is new multicast address.  We have to tell parent
 1079          * about it.  Also, remember this multicast address so that
 1080          * we can delete them on unconfigure.
 1081          */
 1082         if ((mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT)) == NULL) {
 1083                 error = ENOMEM;
 1084                 goto alloc_failed;
 1085         }
 1086 
 1087         /*
 1088          * As ether_addmulti() returns ENETRESET, following two
 1089          * statement shouldn't fail.
 1090          */
 1091         (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
 1092         ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, mc->mc_enm);
 1093         memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
 1094         LIST_INSERT_HEAD(&sc->sc_mc_listhead, mc, mc_entries);
 1095 
 1096         ifp0 = if_get(sc->sc_ifidx0);
 1097         error = (ifp0 == NULL) ? 0 :
 1098             (*ifp0->if_ioctl)(ifp0, SIOCADDMULTI, (caddr_t)ifr);
 1099         if_put(ifp0);
 1100 
 1101         if (error != 0)
 1102                 goto ioctl_failed;
 1103 
 1104         return (error);
 1105 
 1106  ioctl_failed:
 1107         LIST_REMOVE(mc, mc_entries);
 1108         free(mc, M_DEVBUF, sizeof(*mc));
 1109  alloc_failed:
 1110         (void)ether_delmulti(ifr, &sc->sc_ac);
 1111 
 1112         return (error);
 1113 }
 1114 
 1115 int
 1116 vlan_multi_del(struct vlan_softc *sc, struct ifreq *ifr)
 1117 {
 1118         struct ifnet *ifp0;
 1119         struct ether_multi *enm;
 1120         struct vlan_mc_entry *mc;
 1121         uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
 1122         int error;
 1123 
 1124         /*
 1125          * Find a key to lookup vlan_mc_entry.  We have to do this
 1126          * before calling ether_delmulti for obvious reason.
 1127          */
 1128         if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
 1129                 return (error);
 1130         ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, enm);
 1131         if (enm == NULL)
 1132                 return (EINVAL);
 1133 
 1134         LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) {
 1135                 if (mc->mc_enm == enm)
 1136                         break;
 1137         }
 1138 
 1139         /* We won't delete entries we didn't add */
 1140         if (mc == NULL)
 1141                 return (EINVAL);
 1142 
 1143         error = ether_delmulti(ifr, &sc->sc_ac);
 1144         if (error != ENETRESET)
 1145                 return (error);
 1146 
 1147         if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING))
 1148                 goto forget;
 1149 
 1150         ifp0 = if_get(sc->sc_ifidx0);
 1151         error = (ifp0 == NULL) ? 0 :
 1152             (*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr);
 1153         if_put(ifp0);
 1154 
 1155         if (error != 0) {
 1156                 (void)ether_addmulti(ifr, &sc->sc_ac);
 1157                 return (error);
 1158         }
 1159 
 1160 forget:
 1161         /* forget about this address */
 1162         LIST_REMOVE(mc, mc_entries);
 1163         free(mc, M_DEVBUF, sizeof(*mc));
 1164 
 1165         return (0);
 1166 }
 1167 
 1168 int
 1169 vlan_media_get(struct vlan_softc *sc, struct ifreq *ifr)
 1170 {
 1171         struct ifnet *ifp0;
 1172         int error;
 1173 
 1174         ifp0 = if_get(sc->sc_ifidx0);
 1175         error = (ifp0 == NULL) ? ENOTTY :
 1176             (*ifp0->if_ioctl)(ifp0, SIOCGIFMEDIA, (caddr_t)ifr);
 1177         if_put(ifp0);
 1178 
 1179         return (error);
 1180 }
 1181 
 1182 void
 1183 vlan_multi_apply(struct vlan_softc *sc, struct ifnet *ifp0, u_long cmd)
 1184 {
 1185         struct vlan_mc_entry *mc;
 1186         union {
 1187                 struct ifreq ifreq;
 1188                 struct {
 1189                         char                    ifr_name[IFNAMSIZ];
 1190                         struct sockaddr_storage ifr_ss;
 1191                 } ifreq_storage;
 1192         } ifreq;
 1193         struct ifreq *ifr = &ifreq.ifreq;
 1194 
 1195         memcpy(ifr->ifr_name, ifp0->if_xname, IFNAMSIZ);
 1196         LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) {
 1197                 memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
 1198 
 1199                 (void)(*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)ifr);
 1200         }
 1201 }
 1202 
 1203 void
 1204 vlan_multi_free(struct vlan_softc *sc)
 1205 {
 1206         struct vlan_mc_entry *mc;
 1207 
 1208         while ((mc = LIST_FIRST(&sc->sc_mc_listhead)) != NULL) {
 1209                 LIST_REMOVE(mc, mc_entries);
 1210                 free(mc, M_DEVBUF, sizeof(*mc));
 1211         }
 1212 }

Cache object: 572b174e02dc6e491fa3490c66942efe


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