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