if_vlan.c revision 1.121 1 /* $NetBSD: if_vlan.c,v 1.121 2017/12/19 03:32:35 ozaki-r Exp $ */
2
3 /*-
4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright 1998 Massachusetts Institute of Technology
34 *
35 * Permission to use, copy, modify, and distribute this software and
36 * its documentation for any purpose and without fee is hereby
37 * granted, provided that both the above copyright notice and this
38 * permission notice appear in all copies, that both the above
39 * copyright notice and this permission notice appear in all
40 * supporting documentation, and that the name of M.I.T. not be used
41 * in advertising or publicity pertaining to distribution of the
42 * software without specific, written prior permission. M.I.T. makes
43 * no representations about the suitability of this software for any
44 * purpose. It is provided "as is" without express or implied
45 * warranty.
46 *
47 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
48 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
49 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
50 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
51 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
54 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
56 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * from FreeBSD: if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp
61 * via OpenBSD: if_vlan.c,v 1.4 2000/05/15 19:15:00 chris Exp
62 */
63
64 /*
65 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs. Might be
66 * extended some day to also handle IEEE 802.1P priority tagging. This is
67 * sort of sneaky in the implementation, since we need to pretend to be
68 * enough of an Ethernet implementation to make ARP work. The way we do
69 * this is by telling everyone that we are an Ethernet interface, and then
70 * catch the packets that ether_output() left on our output queue when it
71 * calls if_start(), rewrite them for use by the real outgoing interface,
72 * and ask it to send them.
73 *
74 * TODO:
75 *
76 * - Need some way to notify vlan interfaces when the parent
77 * interface changes MTU.
78 */
79
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.121 2017/12/19 03:32:35 ozaki-r Exp $");
82
83 #ifdef _KERNEL_OPT
84 #include "opt_inet.h"
85 #include "opt_net_mpsafe.h"
86 #endif
87
88 #include <sys/param.h>
89 #include <sys/systm.h>
90 #include <sys/kernel.h>
91 #include <sys/mbuf.h>
92 #include <sys/queue.h>
93 #include <sys/socket.h>
94 #include <sys/sockio.h>
95 #include <sys/systm.h>
96 #include <sys/proc.h>
97 #include <sys/kauth.h>
98 #include <sys/mutex.h>
99 #include <sys/kmem.h>
100 #include <sys/cpu.h>
101 #include <sys/pserialize.h>
102 #include <sys/psref.h>
103 #include <sys/pslist.h>
104 #include <sys/atomic.h>
105 #include <sys/device.h>
106 #include <sys/module.h>
107
108 #include <net/bpf.h>
109 #include <net/if.h>
110 #include <net/if_dl.h>
111 #include <net/if_types.h>
112 #include <net/if_ether.h>
113 #include <net/if_vlanvar.h>
114
115 #ifdef INET
116 #include <netinet/in.h>
117 #include <netinet/if_inarp.h>
118 #endif
119 #ifdef INET6
120 #include <netinet6/in6_ifattach.h>
121 #include <netinet6/in6_var.h>
122 #endif
123
124 #include "ioconf.h"
125
126 struct vlan_mc_entry {
127 LIST_ENTRY(vlan_mc_entry) mc_entries;
128 /*
129 * A key to identify this entry. The mc_addr below can't be
130 * used since multiple sockaddr may mapped into the same
131 * ether_multi (e.g., AF_UNSPEC).
132 */
133 union {
134 struct ether_multi *mcu_enm;
135 } mc_u;
136 struct sockaddr_storage mc_addr;
137 };
138
139 #define mc_enm mc_u.mcu_enm
140
141
142 struct ifvlan_linkmib {
143 struct ifvlan *ifvm_ifvlan;
144 const struct vlan_multisw *ifvm_msw;
145 int ifvm_encaplen; /* encapsulation length */
146 int ifvm_mtufudge; /* MTU fudged by this much */
147 int ifvm_mintu; /* min transmission unit */
148 uint16_t ifvm_proto; /* encapsulation ethertype */
149 uint16_t ifvm_tag; /* tag to apply on packets */
150 struct ifnet *ifvm_p; /* parent interface of this vlan */
151
152 struct psref_target ifvm_psref;
153 };
154
155 struct ifvlan {
156 union {
157 struct ethercom ifvu_ec;
158 } ifv_u;
159 struct ifvlan_linkmib *ifv_mib; /*
160 * reader must use vlan_getref_linkmib()
161 * instead of direct dereference
162 */
163 kmutex_t ifv_lock; /* writer lock for ifv_mib */
164
165 LIST_HEAD(__vlan_mchead, vlan_mc_entry) ifv_mc_listhead;
166 LIST_ENTRY(ifvlan) ifv_list;
167 struct pslist_entry ifv_hash;
168 int ifv_flags;
169 };
170
171 #define IFVF_PROMISC 0x01 /* promiscuous mode enabled */
172
173 #define ifv_ec ifv_u.ifvu_ec
174
175 #define ifv_if ifv_ec.ec_if
176
177 #define ifv_msw ifv_mib.ifvm_msw
178 #define ifv_encaplen ifv_mib.ifvm_encaplen
179 #define ifv_mtufudge ifv_mib.ifvm_mtufudge
180 #define ifv_mintu ifv_mib.ifvm_mintu
181 #define ifv_tag ifv_mib.ifvm_tag
182
183 struct vlan_multisw {
184 int (*vmsw_addmulti)(struct ifvlan *, struct ifreq *);
185 int (*vmsw_delmulti)(struct ifvlan *, struct ifreq *);
186 void (*vmsw_purgemulti)(struct ifvlan *);
187 };
188
189 static int vlan_ether_addmulti(struct ifvlan *, struct ifreq *);
190 static int vlan_ether_delmulti(struct ifvlan *, struct ifreq *);
191 static void vlan_ether_purgemulti(struct ifvlan *);
192
193 const struct vlan_multisw vlan_ether_multisw = {
194 vlan_ether_addmulti,
195 vlan_ether_delmulti,
196 vlan_ether_purgemulti,
197 };
198
199 static int vlan_clone_create(struct if_clone *, int);
200 static int vlan_clone_destroy(struct ifnet *);
201 static int vlan_config(struct ifvlan *, struct ifnet *,
202 uint16_t);
203 static int vlan_ioctl(struct ifnet *, u_long, void *);
204 static void vlan_start(struct ifnet *);
205 static int vlan_transmit(struct ifnet *, struct mbuf *);
206 static void vlan_unconfig(struct ifnet *);
207 static int vlan_unconfig_locked(struct ifvlan *,
208 struct ifvlan_linkmib *);
209 static void vlan_hash_init(void);
210 static int vlan_hash_fini(void);
211 static int vlan_tag_hash(uint16_t, u_long);
212 static struct ifvlan_linkmib* vlan_getref_linkmib(struct ifvlan *,
213 struct psref *);
214 static void vlan_putref_linkmib(struct ifvlan_linkmib *,
215 struct psref *);
216 static void vlan_linkmib_update(struct ifvlan *,
217 struct ifvlan_linkmib *);
218 static struct ifvlan_linkmib* vlan_lookup_tag_psref(struct ifnet *,
219 uint16_t, struct psref *);
220
221 LIST_HEAD(vlan_ifvlist, ifvlan);
222 static struct {
223 kmutex_t lock;
224 struct vlan_ifvlist list;
225 } ifv_list __cacheline_aligned;
226
227
228 #if !defined(VLAN_TAG_HASH_SIZE)
229 #define VLAN_TAG_HASH_SIZE 32
230 #endif
231 static struct {
232 kmutex_t lock;
233 struct pslist_head *lists;
234 u_long mask;
235 } ifv_hash __cacheline_aligned = {
236 .lists = NULL,
237 .mask = 0,
238 };
239
240 pserialize_t vlan_psz __read_mostly;
241 static struct psref_class *ifvm_psref_class __read_mostly;
242
243 struct if_clone vlan_cloner =
244 IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
245
246 /* Used to pad ethernet frames with < ETHER_MIN_LEN bytes */
247 static char vlan_zero_pad_buff[ETHER_MIN_LEN];
248
249 static inline int
250 vlan_safe_ifpromisc(struct ifnet *ifp, int pswitch)
251 {
252 int e;
253 KERNEL_LOCK_UNLESS_NET_MPSAFE();
254 e = ifpromisc(ifp, pswitch);
255 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
256 return e;
257 }
258
259 static inline int
260 vlan_safe_ifpromisc_locked(struct ifnet *ifp, int pswitch)
261 {
262 int e;
263 KERNEL_LOCK_UNLESS_NET_MPSAFE();
264 e = ifpromisc_locked(ifp, pswitch);
265 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
266 return e;
267 }
268
269 void
270 vlanattach(int n)
271 {
272
273 /*
274 * Nothing to do here, initialization is handled by the
275 * module initialization code in vlaninit() below).
276 */
277 }
278
279 static void
280 vlaninit(void)
281 {
282 mutex_init(&ifv_list.lock, MUTEX_DEFAULT, IPL_NONE);
283 LIST_INIT(&ifv_list.list);
284
285 mutex_init(&ifv_hash.lock, MUTEX_DEFAULT, IPL_NONE);
286 vlan_psz = pserialize_create();
287 ifvm_psref_class = psref_class_create("vlanlinkmib", IPL_SOFTNET);
288 if_clone_attach(&vlan_cloner);
289
290 vlan_hash_init();
291 }
292
293 static int
294 vlandetach(void)
295 {
296 int error = 0;
297
298 mutex_enter(&ifv_list.lock);
299 if (!LIST_EMPTY(&ifv_list.list)) {
300 mutex_exit(&ifv_list.lock);
301 return EBUSY;
302 }
303 mutex_exit(&ifv_list.lock);
304
305 error = vlan_hash_fini();
306 if (error != 0)
307 return error;
308
309 if_clone_detach(&vlan_cloner);
310 psref_class_destroy(ifvm_psref_class);
311 pserialize_destroy(vlan_psz);
312 mutex_destroy(&ifv_hash.lock);
313 mutex_destroy(&ifv_list.lock);
314
315 return 0;
316 }
317
318 static void
319 vlan_reset_linkname(struct ifnet *ifp)
320 {
321
322 /*
323 * We start out with a "802.1Q VLAN" type and zero-length
324 * addresses. When we attach to a parent interface, we
325 * inherit its type, address length, address, and data link
326 * type.
327 */
328
329 ifp->if_type = IFT_L2VLAN;
330 ifp->if_addrlen = 0;
331 ifp->if_dlt = DLT_NULL;
332 if_alloc_sadl(ifp);
333 }
334
335 static int
336 vlan_clone_create(struct if_clone *ifc, int unit)
337 {
338 struct ifvlan *ifv;
339 struct ifnet *ifp;
340 struct ifvlan_linkmib *mib;
341 int rv;
342
343 ifv = malloc(sizeof(struct ifvlan), M_DEVBUF, M_WAITOK|M_ZERO);
344 mib = kmem_zalloc(sizeof(struct ifvlan_linkmib), KM_SLEEP);
345 ifp = &ifv->ifv_if;
346 LIST_INIT(&ifv->ifv_mc_listhead);
347
348 mib->ifvm_ifvlan = ifv;
349 mib->ifvm_p = NULL;
350 psref_target_init(&mib->ifvm_psref, ifvm_psref_class);
351
352 mutex_init(&ifv->ifv_lock, MUTEX_DEFAULT, IPL_NONE);
353 ifv->ifv_mib = mib;
354
355 mutex_enter(&ifv_list.lock);
356 LIST_INSERT_HEAD(&ifv_list.list, ifv, ifv_list);
357 mutex_exit(&ifv_list.lock);
358
359 if_initname(ifp, ifc->ifc_name, unit);
360 ifp->if_softc = ifv;
361 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
362 ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE;
363 #ifdef NET_MPSAFE
364 ifp->if_extflags |= IFEF_MPSAFE;
365 #endif
366 ifp->if_start = vlan_start;
367 ifp->if_transmit = vlan_transmit;
368 ifp->if_ioctl = vlan_ioctl;
369 IFQ_SET_READY(&ifp->if_snd);
370
371 rv = if_initialize(ifp);
372 if (rv != 0) {
373 aprint_error("%s: if_initialize failed(%d)\n", ifp->if_xname,
374 rv);
375 goto fail;
376 }
377
378 vlan_reset_linkname(ifp);
379 if_register(ifp);
380 return 0;
381
382 fail:
383 mutex_enter(&ifv_list.lock);
384 LIST_REMOVE(ifv, ifv_list);
385 mutex_exit(&ifv_list.lock);
386
387 mutex_destroy(&ifv->ifv_lock);
388 psref_target_destroy(&ifv->ifv_mib->ifvm_psref, ifvm_psref_class);
389 kmem_free(ifv->ifv_mib, sizeof(struct ifvlan_linkmib));
390 free(ifv, M_DEVBUF);
391
392 return rv;
393 }
394
395 static int
396 vlan_clone_destroy(struct ifnet *ifp)
397 {
398 struct ifvlan *ifv = ifp->if_softc;
399
400 mutex_enter(&ifv_list.lock);
401 LIST_REMOVE(ifv, ifv_list);
402 mutex_exit(&ifv_list.lock);
403
404 IFNET_LOCK(ifp);
405 vlan_unconfig(ifp);
406 IFNET_UNLOCK(ifp);
407 if_detach(ifp);
408
409 psref_target_destroy(&ifv->ifv_mib->ifvm_psref, ifvm_psref_class);
410 kmem_free(ifv->ifv_mib, sizeof(struct ifvlan_linkmib));
411 mutex_destroy(&ifv->ifv_lock);
412 free(ifv, M_DEVBUF);
413
414 return (0);
415 }
416
417 /*
418 * Configure a VLAN interface.
419 */
420 static int
421 vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag)
422 {
423 struct ifnet *ifp = &ifv->ifv_if;
424 struct ifvlan_linkmib *nmib = NULL;
425 struct ifvlan_linkmib *omib = NULL;
426 struct ifvlan_linkmib *checkmib = NULL;
427 struct psref_target *nmib_psref = NULL;
428 uint16_t vid = EVL_VLANOFTAG(tag);
429 int error = 0;
430 int idx;
431 bool omib_cleanup = false;
432 struct psref psref;
433
434 /* VLAN ID 0 and 4095 are reserved in the spec */
435 if ((vid == 0) || (vid == 0xfff))
436 return EINVAL;
437
438 nmib = kmem_alloc(sizeof(*nmib), KM_SLEEP);
439
440 mutex_enter(&ifv->ifv_lock);
441 omib = ifv->ifv_mib;
442
443 if (omib->ifvm_p != NULL) {
444 error = EBUSY;
445 goto done;
446 }
447
448 /* Duplicate check */
449 checkmib = vlan_lookup_tag_psref(p, vid, &psref);
450 if (checkmib != NULL) {
451 vlan_putref_linkmib(checkmib, &psref);
452 error = EEXIST;
453 goto done;
454 }
455
456 *nmib = *omib;
457 nmib_psref = &nmib->ifvm_psref;
458
459 psref_target_init(nmib_psref, ifvm_psref_class);
460
461 switch (p->if_type) {
462 case IFT_ETHER:
463 {
464 struct ethercom *ec = (void *) p;
465 nmib->ifvm_msw = &vlan_ether_multisw;
466 nmib->ifvm_encaplen = ETHER_VLAN_ENCAP_LEN;
467 nmib->ifvm_mintu = ETHERMIN;
468
469 if (ec->ec_nvlans++ == 0) {
470 IFNET_LOCK(p);
471 error = ether_enable_vlan_mtu(p);
472 IFNET_UNLOCK(p);
473 if (error >= 0) {
474 if (error) {
475 ec->ec_nvlans--;
476 goto done;
477 }
478 nmib->ifvm_mtufudge = 0;
479 } else {
480 /*
481 * Fudge the MTU by the encapsulation size. This
482 * makes us incompatible with strictly compliant
483 * 802.1Q implementations, but allows us to use
484 * the feature with other NetBSD
485 * implementations, which might still be useful.
486 */
487 nmib->ifvm_mtufudge = nmib->ifvm_encaplen;
488 }
489 error = 0;
490 }
491
492 /*
493 * If the parent interface can do hardware-assisted
494 * VLAN encapsulation, then propagate its hardware-
495 * assisted checksumming flags and tcp segmentation
496 * offload.
497 */
498 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) {
499 ec->ec_capenable |= ETHERCAP_VLAN_HWTAGGING;
500 ifp->if_capabilities = p->if_capabilities &
501 (IFCAP_TSOv4 | IFCAP_TSOv6 |
502 IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
503 IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
504 IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx|
505 IFCAP_CSUM_TCPv6_Tx|IFCAP_CSUM_TCPv6_Rx|
506 IFCAP_CSUM_UDPv6_Tx|IFCAP_CSUM_UDPv6_Rx);
507 }
508 /*
509 * We inherit the parent's Ethernet address.
510 */
511 ether_ifattach(ifp, CLLADDR(p->if_sadl));
512 ifp->if_hdrlen = sizeof(struct ether_vlan_header); /* XXX? */
513 break;
514 }
515
516 default:
517 error = EPROTONOSUPPORT;
518 goto done;
519 }
520
521 nmib->ifvm_p = p;
522 nmib->ifvm_tag = vid;
523 ifv->ifv_if.if_mtu = p->if_mtu - nmib->ifvm_mtufudge;
524 ifv->ifv_if.if_flags = p->if_flags &
525 (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
526
527 /*
528 * Inherit the if_type from the parent. This allows us
529 * to participate in bridges of that type.
530 */
531 ifv->ifv_if.if_type = p->if_type;
532
533 PSLIST_ENTRY_INIT(ifv, ifv_hash);
534 idx = vlan_tag_hash(vid, ifv_hash.mask);
535
536 mutex_enter(&ifv_hash.lock);
537 PSLIST_WRITER_INSERT_HEAD(&ifv_hash.lists[idx], ifv, ifv_hash);
538 mutex_exit(&ifv_hash.lock);
539
540 vlan_linkmib_update(ifv, nmib);
541 nmib = NULL;
542 nmib_psref = NULL;
543 omib_cleanup = true;
544
545 done:
546 mutex_exit(&ifv->ifv_lock);
547
548 if (nmib_psref)
549 psref_target_destroy(nmib_psref, ifvm_psref_class);
550
551 if (nmib)
552 kmem_free(nmib, sizeof(*nmib));
553
554 if (omib_cleanup)
555 kmem_free(omib, sizeof(*omib));
556
557 return error;
558 }
559
560 /*
561 * Unconfigure a VLAN interface.
562 */
563 static void
564 vlan_unconfig(struct ifnet *ifp)
565 {
566 struct ifvlan *ifv = ifp->if_softc;
567 struct ifvlan_linkmib *nmib = NULL;
568 int error;
569
570 KASSERT(IFNET_LOCKED(ifp));
571
572 nmib = kmem_alloc(sizeof(*nmib), KM_SLEEP);
573
574 mutex_enter(&ifv->ifv_lock);
575 error = vlan_unconfig_locked(ifv, nmib);
576 mutex_exit(&ifv->ifv_lock);
577
578 if (error)
579 kmem_free(nmib, sizeof(*nmib));
580 }
581 static int
582 vlan_unconfig_locked(struct ifvlan *ifv, struct ifvlan_linkmib *nmib)
583 {
584 struct ifnet *p;
585 struct ifnet *ifp = &ifv->ifv_if;
586 struct psref_target *nmib_psref = NULL;
587 struct ifvlan_linkmib *omib;
588 int error = 0;
589
590 KASSERT(IFNET_LOCKED(ifp));
591 KASSERT(mutex_owned(&ifv->ifv_lock));
592
593 ifp->if_flags &= ~(IFF_UP|IFF_RUNNING);
594
595 omib = ifv->ifv_mib;
596 p = omib->ifvm_p;
597
598 if (p == NULL) {
599 error = -1;
600 goto done;
601 }
602
603 *nmib = *omib;
604 nmib_psref = &nmib->ifvm_psref;
605 psref_target_init(nmib_psref, ifvm_psref_class);
606
607 /*
608 * Since the interface is being unconfigured, we need to empty the
609 * list of multicast groups that we may have joined while we were
610 * alive and remove them from the parent's list also.
611 */
612 (*nmib->ifvm_msw->vmsw_purgemulti)(ifv);
613
614 /* Disconnect from parent. */
615 switch (p->if_type) {
616 case IFT_ETHER:
617 {
618 struct ethercom *ec = (void *)p;
619 if (--ec->ec_nvlans == 0) {
620 IFNET_LOCK(p);
621 (void) ether_disable_vlan_mtu(p);
622 IFNET_UNLOCK(p);
623 }
624
625 ether_ifdetach(ifp);
626 /* Restore vlan_ioctl overwritten by ether_ifdetach */
627 ifp->if_ioctl = vlan_ioctl;
628 vlan_reset_linkname(ifp);
629 break;
630 }
631
632 #ifdef DIAGNOSTIC
633 default:
634 panic("vlan_unconfig: impossible");
635 #endif
636 }
637
638 nmib->ifvm_p = NULL;
639 ifv->ifv_if.if_mtu = 0;
640 ifv->ifv_flags = 0;
641
642 mutex_enter(&ifv_hash.lock);
643 PSLIST_WRITER_REMOVE(ifv, ifv_hash);
644 pserialize_perform(vlan_psz);
645 mutex_exit(&ifv_hash.lock);
646 PSLIST_ENTRY_DESTROY(ifv, ifv_hash);
647
648 vlan_linkmib_update(ifv, nmib);
649
650 mutex_exit(&ifv->ifv_lock);
651
652 nmib_psref = NULL;
653 kmem_free(omib, sizeof(*omib));
654
655 #ifdef INET6
656 KERNEL_LOCK_UNLESS_NET_MPSAFE();
657 /* To delete v6 link local addresses */
658 if (in6_present)
659 in6_ifdetach(ifp);
660 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
661 #endif
662
663 if ((ifp->if_flags & IFF_PROMISC) != 0)
664 vlan_safe_ifpromisc_locked(ifp, 0);
665 if_down_locked(ifp);
666 ifp->if_capabilities = 0;
667 mutex_enter(&ifv->ifv_lock);
668 done:
669
670 if (nmib_psref)
671 psref_target_destroy(nmib_psref, ifvm_psref_class);
672
673 return error;
674 }
675
676 static void
677 vlan_hash_init(void)
678 {
679
680 ifv_hash.lists = hashinit(VLAN_TAG_HASH_SIZE, HASH_PSLIST, true,
681 &ifv_hash.mask);
682 }
683
684 static int
685 vlan_hash_fini(void)
686 {
687 int i;
688
689 mutex_enter(&ifv_hash.lock);
690
691 for (i = 0; i < ifv_hash.mask + 1; i++) {
692 if (PSLIST_WRITER_FIRST(&ifv_hash.lists[i], struct ifvlan,
693 ifv_hash) != NULL) {
694 mutex_exit(&ifv_hash.lock);
695 return EBUSY;
696 }
697 }
698
699 for (i = 0; i < ifv_hash.mask + 1; i++)
700 PSLIST_DESTROY(&ifv_hash.lists[i]);
701
702 mutex_exit(&ifv_hash.lock);
703
704 hashdone(ifv_hash.lists, HASH_PSLIST, ifv_hash.mask);
705
706 ifv_hash.lists = NULL;
707 ifv_hash.mask = 0;
708
709 return 0;
710 }
711
712 static int
713 vlan_tag_hash(uint16_t tag, u_long mask)
714 {
715 uint32_t hash;
716
717 hash = (tag >> 8) ^ tag;
718 hash = (hash >> 2) ^ hash;
719
720 return hash & mask;
721 }
722
723 static struct ifvlan_linkmib *
724 vlan_getref_linkmib(struct ifvlan *sc, struct psref *psref)
725 {
726 struct ifvlan_linkmib *mib;
727 int s;
728
729 s = pserialize_read_enter();
730 mib = sc->ifv_mib;
731 if (mib == NULL) {
732 pserialize_read_exit(s);
733 return NULL;
734 }
735 membar_datadep_consumer();
736 psref_acquire(psref, &mib->ifvm_psref, ifvm_psref_class);
737 pserialize_read_exit(s);
738
739 return mib;
740 }
741
742 static void
743 vlan_putref_linkmib(struct ifvlan_linkmib *mib, struct psref *psref)
744 {
745 if (mib == NULL)
746 return;
747 psref_release(psref, &mib->ifvm_psref, ifvm_psref_class);
748 }
749
750 static struct ifvlan_linkmib *
751 vlan_lookup_tag_psref(struct ifnet *ifp, uint16_t tag, struct psref *psref)
752 {
753 int idx;
754 int s;
755 struct ifvlan *sc;
756
757 idx = vlan_tag_hash(tag, ifv_hash.mask);
758
759 s = pserialize_read_enter();
760 PSLIST_READER_FOREACH(sc, &ifv_hash.lists[idx], struct ifvlan,
761 ifv_hash) {
762 struct ifvlan_linkmib *mib = sc->ifv_mib;
763 if (mib == NULL)
764 continue;
765 if (mib->ifvm_tag != tag)
766 continue;
767 if (mib->ifvm_p != ifp)
768 continue;
769
770 psref_acquire(psref, &mib->ifvm_psref, ifvm_psref_class);
771 pserialize_read_exit(s);
772 return mib;
773 }
774 pserialize_read_exit(s);
775 return NULL;
776 }
777
778 static void
779 vlan_linkmib_update(struct ifvlan *ifv, struct ifvlan_linkmib *nmib)
780 {
781 struct ifvlan_linkmib *omib = ifv->ifv_mib;
782
783 KASSERT(mutex_owned(&ifv->ifv_lock));
784
785 membar_producer();
786 ifv->ifv_mib = nmib;
787
788 pserialize_perform(vlan_psz);
789 psref_target_destroy(&omib->ifvm_psref, ifvm_psref_class);
790 }
791
792 /*
793 * Called when a parent interface is detaching; destroy any VLAN
794 * configuration for the parent interface.
795 */
796 void
797 vlan_ifdetach(struct ifnet *p)
798 {
799 struct ifvlan *ifv;
800 struct ifvlan_linkmib *mib, **nmibs;
801 struct psref psref;
802 int error;
803 int bound;
804 int i, cnt = 0;
805
806 bound = curlwp_bind();
807 mutex_enter(&ifv_list.lock);
808 LIST_FOREACH(ifv, &ifv_list.list, ifv_list) {
809 mib = vlan_getref_linkmib(ifv, &psref);
810 if (mib == NULL)
811 continue;
812
813 if (mib->ifvm_p == p)
814 cnt++;
815
816 vlan_putref_linkmib(mib, &psref);
817 }
818 mutex_exit(&ifv_list.lock);
819
820 /*
821 * The value of "cnt" does not increase while ifv_list.lock
822 * and ifv->ifv_lock are released here, because the parent
823 * interface is detaching.
824 */
825 nmibs = kmem_alloc(sizeof(*nmibs) * cnt, KM_SLEEP);
826 for (i=0; i < cnt; i++) {
827 nmibs[i] = kmem_alloc(sizeof(*nmibs[i]), KM_SLEEP);
828 }
829
830 mutex_enter(&ifv_list.lock);
831
832 i = 0;
833 LIST_FOREACH(ifv, &ifv_list.list, ifv_list) {
834 struct ifnet *ifp = &ifv->ifv_if;
835
836 /* Need IFNET_LOCK that must be held before ifv_lock. */
837 IFNET_LOCK(ifp);
838 mutex_enter(&ifv->ifv_lock);
839 if (ifv->ifv_mib->ifvm_p == p) {
840 KASSERTMSG(i < cnt, "no memory for unconfig, parent=%s",
841 p->if_xname);
842 error = vlan_unconfig_locked(ifv, nmibs[i]);
843 if (!error) {
844 nmibs[i] = NULL;
845 i++;
846 }
847
848 }
849 mutex_exit(&ifv->ifv_lock);
850 IFNET_UNLOCK(ifp);
851 }
852
853 mutex_exit(&ifv_list.lock);
854 curlwp_bindx(bound);
855
856 for (i=0; i < cnt; i++) {
857 if (nmibs[i])
858 kmem_free(nmibs[i], sizeof(*nmibs[i]));
859 }
860
861 kmem_free(nmibs, sizeof(*nmibs) * cnt);
862
863 return;
864 }
865
866 static int
867 vlan_set_promisc(struct ifnet *ifp)
868 {
869 struct ifvlan *ifv = ifp->if_softc;
870 struct ifvlan_linkmib *mib;
871 struct psref psref;
872 int error = 0;
873 int bound;
874
875 bound = curlwp_bind();
876 mib = vlan_getref_linkmib(ifv, &psref);
877 if (mib == NULL) {
878 curlwp_bindx(bound);
879 return EBUSY;
880 }
881
882 if ((ifp->if_flags & IFF_PROMISC) != 0) {
883 if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
884 error = vlan_safe_ifpromisc(mib->ifvm_p, 1);
885 if (error == 0)
886 ifv->ifv_flags |= IFVF_PROMISC;
887 }
888 } else {
889 if ((ifv->ifv_flags & IFVF_PROMISC) != 0) {
890 error = vlan_safe_ifpromisc(mib->ifvm_p, 0);
891 if (error == 0)
892 ifv->ifv_flags &= ~IFVF_PROMISC;
893 }
894 }
895 vlan_putref_linkmib(mib, &psref);
896 curlwp_bindx(bound);
897
898 return (error);
899 }
900
901 static int
902 vlan_ioctl(struct ifnet *ifp, u_long cmd, void *data)
903 {
904 struct lwp *l = curlwp; /* XXX */
905 struct ifvlan *ifv = ifp->if_softc;
906 struct ifaddr *ifa = (struct ifaddr *) data;
907 struct ifreq *ifr = (struct ifreq *) data;
908 struct ifnet *pr;
909 struct ifcapreq *ifcr;
910 struct vlanreq vlr;
911 struct ifvlan_linkmib *mib;
912 struct psref psref;
913 int error = 0;
914 int bound;
915
916 switch (cmd) {
917 case SIOCSIFMTU:
918 bound = curlwp_bind();
919 mib = vlan_getref_linkmib(ifv, &psref);
920 if (mib == NULL) {
921 curlwp_bindx(bound);
922 error = EBUSY;
923 break;
924 }
925
926 if (mib->ifvm_p == NULL) {
927 vlan_putref_linkmib(mib, &psref);
928 curlwp_bindx(bound);
929 error = EINVAL;
930 } else if (
931 ifr->ifr_mtu > (mib->ifvm_p->if_mtu - mib->ifvm_mtufudge) ||
932 ifr->ifr_mtu < (mib->ifvm_mintu - mib->ifvm_mtufudge)) {
933 vlan_putref_linkmib(mib, &psref);
934 curlwp_bindx(bound);
935 error = EINVAL;
936 } else {
937 vlan_putref_linkmib(mib, &psref);
938 curlwp_bindx(bound);
939
940 error = ifioctl_common(ifp, cmd, data);
941 if (error == ENETRESET)
942 error = 0;
943 }
944
945 break;
946
947 case SIOCSETVLAN:
948 if ((error = kauth_authorize_network(l->l_cred,
949 KAUTH_NETWORK_INTERFACE,
950 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
951 NULL)) != 0)
952 break;
953 if ((error = copyin(ifr->ifr_data, &vlr, sizeof(vlr))) != 0)
954 break;
955
956 if (vlr.vlr_parent[0] == '\0') {
957 bound = curlwp_bind();
958 mib = vlan_getref_linkmib(ifv, &psref);
959 if (mib == NULL) {
960 curlwp_bindx(bound);
961 error = EBUSY;
962 break;
963 }
964
965 if (mib->ifvm_p != NULL &&
966 (ifp->if_flags & IFF_PROMISC) != 0)
967 error = vlan_safe_ifpromisc(mib->ifvm_p, 0);
968
969 vlan_putref_linkmib(mib, &psref);
970 curlwp_bindx(bound);
971
972 vlan_unconfig(ifp);
973 break;
974 }
975 if (vlr.vlr_tag != EVL_VLANOFTAG(vlr.vlr_tag)) {
976 error = EINVAL; /* check for valid tag */
977 break;
978 }
979 if ((pr = ifunit(vlr.vlr_parent)) == NULL) {
980 error = ENOENT;
981 break;
982 }
983 error = vlan_config(ifv, pr, vlr.vlr_tag);
984 if (error != 0) {
985 break;
986 }
987
988 /* Update promiscuous mode, if necessary. */
989 vlan_set_promisc(ifp);
990
991 ifp->if_flags |= IFF_RUNNING;
992 break;
993
994 case SIOCGETVLAN:
995 memset(&vlr, 0, sizeof(vlr));
996 bound = curlwp_bind();
997 mib = vlan_getref_linkmib(ifv, &psref);
998 if (mib == NULL) {
999 curlwp_bindx(bound);
1000 error = EBUSY;
1001 break;
1002 }
1003 if (mib->ifvm_p != NULL) {
1004 snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent), "%s",
1005 mib->ifvm_p->if_xname);
1006 vlr.vlr_tag = mib->ifvm_tag;
1007 }
1008 vlan_putref_linkmib(mib, &psref);
1009 curlwp_bindx(bound);
1010 error = copyout(&vlr, ifr->ifr_data, sizeof(vlr));
1011 break;
1012
1013 case SIOCSIFFLAGS:
1014 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1015 break;
1016 /*
1017 * For promiscuous mode, we enable promiscuous mode on
1018 * the parent if we need promiscuous on the VLAN interface.
1019 */
1020 bound = curlwp_bind();
1021 mib = vlan_getref_linkmib(ifv, &psref);
1022 if (mib == NULL) {
1023 curlwp_bindx(bound);
1024 error = EBUSY;
1025 break;
1026 }
1027
1028 if (mib->ifvm_p != NULL)
1029 error = vlan_set_promisc(ifp);
1030 vlan_putref_linkmib(mib, &psref);
1031 curlwp_bindx(bound);
1032 break;
1033
1034 case SIOCADDMULTI:
1035 mutex_enter(&ifv->ifv_lock);
1036 mib = ifv->ifv_mib;
1037 if (mib == NULL) {
1038 error = EBUSY;
1039 mutex_exit(&ifv->ifv_lock);
1040 break;
1041 }
1042
1043 error = (mib->ifvm_p != NULL) ?
1044 (*mib->ifvm_msw->vmsw_addmulti)(ifv, ifr) : EINVAL;
1045 mib = NULL;
1046 mutex_exit(&ifv->ifv_lock);
1047 break;
1048
1049 case SIOCDELMULTI:
1050 mutex_enter(&ifv->ifv_lock);
1051 mib = ifv->ifv_mib;
1052 if (mib == NULL) {
1053 error = EBUSY;
1054 mutex_exit(&ifv->ifv_lock);
1055 break;
1056 }
1057 error = (mib->ifvm_p != NULL) ?
1058 (*mib->ifvm_msw->vmsw_delmulti)(ifv, ifr) : EINVAL;
1059 mib = NULL;
1060 mutex_exit(&ifv->ifv_lock);
1061 break;
1062
1063 case SIOCSIFCAP:
1064 ifcr = data;
1065 /* make sure caps are enabled on parent */
1066 bound = curlwp_bind();
1067 mib = vlan_getref_linkmib(ifv, &psref);
1068 if (mib == NULL) {
1069 curlwp_bindx(bound);
1070 error = EBUSY;
1071 break;
1072 }
1073
1074 if (mib->ifvm_p == NULL) {
1075 vlan_putref_linkmib(mib, &psref);
1076 curlwp_bindx(bound);
1077 error = EINVAL;
1078 break;
1079 }
1080 if ((mib->ifvm_p->if_capenable & ifcr->ifcr_capenable) !=
1081 ifcr->ifcr_capenable) {
1082 vlan_putref_linkmib(mib, &psref);
1083 curlwp_bindx(bound);
1084 error = EINVAL;
1085 break;
1086 }
1087
1088 vlan_putref_linkmib(mib, &psref);
1089 curlwp_bindx(bound);
1090
1091 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
1092 error = 0;
1093 break;
1094 case SIOCINITIFADDR:
1095 bound = curlwp_bind();
1096 mib = vlan_getref_linkmib(ifv, &psref);
1097 if (mib == NULL) {
1098 curlwp_bindx(bound);
1099 error = EBUSY;
1100 break;
1101 }
1102
1103 if (mib->ifvm_p == NULL) {
1104 error = EINVAL;
1105 vlan_putref_linkmib(mib, &psref);
1106 curlwp_bindx(bound);
1107 break;
1108 }
1109 vlan_putref_linkmib(mib, &psref);
1110 curlwp_bindx(bound);
1111
1112 ifp->if_flags |= IFF_UP;
1113 #ifdef INET
1114 if (ifa->ifa_addr->sa_family == AF_INET)
1115 arp_ifinit(ifp, ifa);
1116 #endif
1117 break;
1118
1119 default:
1120 error = ether_ioctl(ifp, cmd, data);
1121 }
1122
1123 return (error);
1124 }
1125
1126 static int
1127 vlan_ether_addmulti(struct ifvlan *ifv, struct ifreq *ifr)
1128 {
1129 const struct sockaddr *sa = ifreq_getaddr(SIOCADDMULTI, ifr);
1130 struct vlan_mc_entry *mc;
1131 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1132 struct ifvlan_linkmib *mib;
1133 int error;
1134
1135 KASSERT(mutex_owned(&ifv->ifv_lock));
1136
1137 if (sa->sa_len > sizeof(struct sockaddr_storage))
1138 return (EINVAL);
1139
1140 error = ether_addmulti(sa, &ifv->ifv_ec);
1141 if (error != ENETRESET)
1142 return (error);
1143
1144 /*
1145 * This is new multicast address. We have to tell parent
1146 * about it. Also, remember this multicast address so that
1147 * we can delete them on unconfigure.
1148 */
1149 mc = malloc(sizeof(struct vlan_mc_entry), M_DEVBUF, M_NOWAIT);
1150 if (mc == NULL) {
1151 error = ENOMEM;
1152 goto alloc_failed;
1153 }
1154
1155 /*
1156 * As ether_addmulti() returns ENETRESET, following two
1157 * statement shouldn't fail.
1158 */
1159 (void)ether_multiaddr(sa, addrlo, addrhi);
1160 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, mc->mc_enm);
1161 memcpy(&mc->mc_addr, sa, sa->sa_len);
1162 LIST_INSERT_HEAD(&ifv->ifv_mc_listhead, mc, mc_entries);
1163
1164 mib = ifv->ifv_mib;
1165
1166 KERNEL_LOCK_UNLESS_IFP_MPSAFE(mib->ifvm_p);
1167 IFNET_LOCK(mib->ifvm_p);
1168 error = if_mcast_op(mib->ifvm_p, SIOCADDMULTI, sa);
1169 IFNET_UNLOCK(mib->ifvm_p);
1170 KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(mib->ifvm_p);
1171
1172 if (error != 0)
1173 goto ioctl_failed;
1174 return (error);
1175
1176 ioctl_failed:
1177 LIST_REMOVE(mc, mc_entries);
1178 free(mc, M_DEVBUF);
1179 alloc_failed:
1180 (void)ether_delmulti(sa, &ifv->ifv_ec);
1181 return (error);
1182 }
1183
1184 static int
1185 vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr)
1186 {
1187 const struct sockaddr *sa = ifreq_getaddr(SIOCDELMULTI, ifr);
1188 struct ether_multi *enm;
1189 struct vlan_mc_entry *mc;
1190 struct ifvlan_linkmib *mib;
1191 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1192 int error;
1193
1194 KASSERT(mutex_owned(&ifv->ifv_lock));
1195
1196 /*
1197 * Find a key to lookup vlan_mc_entry. We have to do this
1198 * before calling ether_delmulti for obvious reason.
1199 */
1200 if ((error = ether_multiaddr(sa, addrlo, addrhi)) != 0)
1201 return (error);
1202 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ec, enm);
1203
1204 error = ether_delmulti(sa, &ifv->ifv_ec);
1205 if (error != ENETRESET)
1206 return (error);
1207
1208 /* We no longer use this multicast address. Tell parent so. */
1209 mib = ifv->ifv_mib;
1210 IFNET_LOCK(mib->ifvm_p);
1211 error = if_mcast_op(mib->ifvm_p, SIOCDELMULTI, sa);
1212 IFNET_UNLOCK(mib->ifvm_p);
1213
1214 if (error == 0) {
1215 /* And forget about this address. */
1216 for (mc = LIST_FIRST(&ifv->ifv_mc_listhead); mc != NULL;
1217 mc = LIST_NEXT(mc, mc_entries)) {
1218 if (mc->mc_enm == enm) {
1219 LIST_REMOVE(mc, mc_entries);
1220 free(mc, M_DEVBUF);
1221 break;
1222 }
1223 }
1224 KASSERT(mc != NULL);
1225 } else
1226 (void)ether_addmulti(sa, &ifv->ifv_ec);
1227 return (error);
1228 }
1229
1230 /*
1231 * Delete any multicast address we have asked to add from parent
1232 * interface. Called when the vlan is being unconfigured.
1233 */
1234 static void
1235 vlan_ether_purgemulti(struct ifvlan *ifv)
1236 {
1237 struct vlan_mc_entry *mc;
1238 struct ifvlan_linkmib *mib;
1239
1240 KASSERT(mutex_owned(&ifv->ifv_lock));
1241 mib = ifv->ifv_mib;
1242 if (mib == NULL) {
1243 return;
1244 }
1245
1246 while ((mc = LIST_FIRST(&ifv->ifv_mc_listhead)) != NULL) {
1247 IFNET_LOCK(mib->ifvm_p);
1248 (void)if_mcast_op(mib->ifvm_p, SIOCDELMULTI,
1249 (const struct sockaddr *)&mc->mc_addr);
1250 IFNET_UNLOCK(mib->ifvm_p);
1251 LIST_REMOVE(mc, mc_entries);
1252 free(mc, M_DEVBUF);
1253 }
1254 }
1255
1256 static void
1257 vlan_start(struct ifnet *ifp)
1258 {
1259 struct ifvlan *ifv = ifp->if_softc;
1260 struct ifnet *p;
1261 struct ethercom *ec;
1262 struct mbuf *m;
1263 struct ifvlan_linkmib *mib;
1264 struct psref psref;
1265 int error;
1266
1267 mib = vlan_getref_linkmib(ifv, &psref);
1268 if (mib == NULL)
1269 return;
1270 p = mib->ifvm_p;
1271 ec = (void *)mib->ifvm_p;
1272
1273 ifp->if_flags |= IFF_OACTIVE;
1274
1275 for (;;) {
1276 IFQ_DEQUEUE(&ifp->if_snd, m);
1277 if (m == NULL)
1278 break;
1279
1280 #ifdef ALTQ
1281 /*
1282 * KERNEL_LOCK is required for ALTQ even if NET_MPSAFE is defined.
1283 */
1284 KERNEL_LOCK(1, NULL);
1285 /*
1286 * If ALTQ is enabled on the parent interface, do
1287 * classification; the queueing discipline might
1288 * not require classification, but might require
1289 * the address family/header pointer in the pktattr.
1290 */
1291 if (ALTQ_IS_ENABLED(&p->if_snd)) {
1292 switch (p->if_type) {
1293 case IFT_ETHER:
1294 altq_etherclassify(&p->if_snd, m);
1295 break;
1296 #ifdef DIAGNOSTIC
1297 default:
1298 panic("vlan_start: impossible (altq)");
1299 #endif
1300 }
1301 }
1302 KERNEL_UNLOCK_ONE(NULL);
1303 #endif /* ALTQ */
1304
1305 bpf_mtap(ifp, m);
1306 /*
1307 * If the parent can insert the tag itself, just mark
1308 * the tag in the mbuf header.
1309 */
1310 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) {
1311 vlan_set_tag(m, mib->ifvm_tag);
1312 } else {
1313 /*
1314 * insert the tag ourselves
1315 */
1316 M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT);
1317 if (m == NULL) {
1318 printf("%s: unable to prepend encap header",
1319 p->if_xname);
1320 ifp->if_oerrors++;
1321 continue;
1322 }
1323
1324 switch (p->if_type) {
1325 case IFT_ETHER:
1326 {
1327 struct ether_vlan_header *evl;
1328
1329 if (m->m_len < sizeof(struct ether_vlan_header))
1330 m = m_pullup(m,
1331 sizeof(struct ether_vlan_header));
1332 if (m == NULL) {
1333 printf("%s: unable to pullup encap "
1334 "header", p->if_xname);
1335 ifp->if_oerrors++;
1336 continue;
1337 }
1338
1339 /*
1340 * Transform the Ethernet header into an
1341 * Ethernet header with 802.1Q encapsulation.
1342 */
1343 memmove(mtod(m, void *),
1344 mtod(m, char *) + mib->ifvm_encaplen,
1345 sizeof(struct ether_header));
1346 evl = mtod(m, struct ether_vlan_header *);
1347 evl->evl_proto = evl->evl_encap_proto;
1348 evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
1349 evl->evl_tag = htons(mib->ifvm_tag);
1350
1351 /*
1352 * To cater for VLAN-aware layer 2 ethernet
1353 * switches which may need to strip the tag
1354 * before forwarding the packet, make sure
1355 * the packet+tag is at least 68 bytes long.
1356 * This is necessary because our parent will
1357 * only pad to 64 bytes (ETHER_MIN_LEN) and
1358 * some switches will not pad by themselves
1359 * after deleting a tag.
1360 */
1361 if (m->m_pkthdr.len <
1362 (ETHER_MIN_LEN - ETHER_CRC_LEN +
1363 ETHER_VLAN_ENCAP_LEN)) {
1364 m_copyback(m, m->m_pkthdr.len,
1365 (ETHER_MIN_LEN - ETHER_CRC_LEN +
1366 ETHER_VLAN_ENCAP_LEN) -
1367 m->m_pkthdr.len,
1368 vlan_zero_pad_buff);
1369 }
1370 break;
1371 }
1372
1373 #ifdef DIAGNOSTIC
1374 default:
1375 panic("vlan_start: impossible");
1376 #endif
1377 }
1378 }
1379
1380 if ((p->if_flags & IFF_RUNNING) == 0) {
1381 m_freem(m);
1382 continue;
1383 }
1384
1385 error = if_transmit_lock(p, m);
1386 if (error) {
1387 /* mbuf is already freed */
1388 ifp->if_oerrors++;
1389 continue;
1390 }
1391 ifp->if_opackets++;
1392 }
1393
1394 ifp->if_flags &= ~IFF_OACTIVE;
1395
1396 /* Remove reference to mib before release */
1397 p = NULL;
1398 ec = NULL;
1399
1400 vlan_putref_linkmib(mib, &psref);
1401 }
1402
1403 static int
1404 vlan_transmit(struct ifnet *ifp, struct mbuf *m)
1405 {
1406 struct ifvlan *ifv = ifp->if_softc;
1407 struct ifnet *p;
1408 struct ethercom *ec;
1409 struct ifvlan_linkmib *mib;
1410 struct psref psref;
1411 int error;
1412 size_t pktlen = m->m_pkthdr.len;
1413 bool mcast = (m->m_flags & M_MCAST) != 0;
1414
1415 mib = vlan_getref_linkmib(ifv, &psref);
1416 if (mib == NULL) {
1417 m_freem(m);
1418 return ENETDOWN;
1419 }
1420
1421 p = mib->ifvm_p;
1422 ec = (void *)mib->ifvm_p;
1423
1424 bpf_mtap(ifp, m);
1425
1426 if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT) != 0) {
1427 if (m != NULL)
1428 m_freem(m);
1429 error = 0;
1430 goto out;
1431 }
1432
1433 /*
1434 * If the parent can insert the tag itself, just mark
1435 * the tag in the mbuf header.
1436 */
1437 if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) {
1438 vlan_set_tag(m, mib->ifvm_tag);
1439 } else {
1440 /*
1441 * insert the tag ourselves
1442 */
1443 M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT);
1444 if (m == NULL) {
1445 printf("%s: unable to prepend encap header",
1446 p->if_xname);
1447 ifp->if_oerrors++;
1448 error = ENOBUFS;
1449 goto out;
1450 }
1451
1452 switch (p->if_type) {
1453 case IFT_ETHER:
1454 {
1455 struct ether_vlan_header *evl;
1456
1457 if (m->m_len < sizeof(struct ether_vlan_header))
1458 m = m_pullup(m,
1459 sizeof(struct ether_vlan_header));
1460 if (m == NULL) {
1461 printf("%s: unable to pullup encap "
1462 "header", p->if_xname);
1463 ifp->if_oerrors++;
1464 error = ENOBUFS;
1465 goto out;
1466 }
1467
1468 /*
1469 * Transform the Ethernet header into an
1470 * Ethernet header with 802.1Q encapsulation.
1471 */
1472 memmove(mtod(m, void *),
1473 mtod(m, char *) + mib->ifvm_encaplen,
1474 sizeof(struct ether_header));
1475 evl = mtod(m, struct ether_vlan_header *);
1476 evl->evl_proto = evl->evl_encap_proto;
1477 evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
1478 evl->evl_tag = htons(mib->ifvm_tag);
1479
1480 /*
1481 * To cater for VLAN-aware layer 2 ethernet
1482 * switches which may need to strip the tag
1483 * before forwarding the packet, make sure
1484 * the packet+tag is at least 68 bytes long.
1485 * This is necessary because our parent will
1486 * only pad to 64 bytes (ETHER_MIN_LEN) and
1487 * some switches will not pad by themselves
1488 * after deleting a tag.
1489 */
1490 if (m->m_pkthdr.len <
1491 (ETHER_MIN_LEN - ETHER_CRC_LEN +
1492 ETHER_VLAN_ENCAP_LEN)) {
1493 m_copyback(m, m->m_pkthdr.len,
1494 (ETHER_MIN_LEN - ETHER_CRC_LEN +
1495 ETHER_VLAN_ENCAP_LEN) -
1496 m->m_pkthdr.len,
1497 vlan_zero_pad_buff);
1498 }
1499 break;
1500 }
1501
1502 #ifdef DIAGNOSTIC
1503 default:
1504 panic("vlan_transmit: impossible");
1505 #endif
1506 }
1507 }
1508
1509 if ((p->if_flags & IFF_RUNNING) == 0) {
1510 m_freem(m);
1511 error = ENETDOWN;
1512 goto out;
1513 }
1514
1515 error = if_transmit_lock(p, m);
1516 if (error) {
1517 /* mbuf is already freed */
1518 ifp->if_oerrors++;
1519 } else {
1520
1521 ifp->if_opackets++;
1522 ifp->if_obytes += pktlen;
1523 if (mcast)
1524 ifp->if_omcasts++;
1525 }
1526
1527 out:
1528 /* Remove reference to mib before release */
1529 p = NULL;
1530 ec = NULL;
1531
1532 vlan_putref_linkmib(mib, &psref);
1533 return error;
1534 }
1535
1536 /*
1537 * Given an Ethernet frame, find a valid vlan interface corresponding to the
1538 * given source interface and tag, then run the real packet through the
1539 * parent's input routine.
1540 */
1541 void
1542 vlan_input(struct ifnet *ifp, struct mbuf *m)
1543 {
1544 struct ifvlan *ifv;
1545 uint16_t vid;
1546 struct ifvlan_linkmib *mib;
1547 struct psref psref;
1548 bool have_vtag;
1549
1550 have_vtag = vlan_has_tag(m);
1551 if (have_vtag) {
1552 vid = EVL_VLANOFTAG(vlan_get_tag(m));
1553 m->m_flags &= ~M_VLANTAG;
1554 } else {
1555 switch (ifp->if_type) {
1556 case IFT_ETHER:
1557 {
1558 struct ether_vlan_header *evl;
1559
1560 if (m->m_len < sizeof(struct ether_vlan_header) &&
1561 (m = m_pullup(m,
1562 sizeof(struct ether_vlan_header))) == NULL) {
1563 printf("%s: no memory for VLAN header, "
1564 "dropping packet.\n", ifp->if_xname);
1565 return;
1566 }
1567 evl = mtod(m, struct ether_vlan_header *);
1568 KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN);
1569
1570 vid = EVL_VLANOFTAG(ntohs(evl->evl_tag));
1571
1572 /*
1573 * Restore the original ethertype. We'll remove
1574 * the encapsulation after we've found the vlan
1575 * interface corresponding to the tag.
1576 */
1577 evl->evl_encap_proto = evl->evl_proto;
1578 break;
1579 }
1580
1581 default:
1582 vid = (uint16_t) -1; /* XXX GCC */
1583 #ifdef DIAGNOSTIC
1584 panic("vlan_input: impossible");
1585 #endif
1586 }
1587 }
1588
1589 mib = vlan_lookup_tag_psref(ifp, vid, &psref);
1590 if (mib == NULL) {
1591 m_freem(m);
1592 ifp->if_noproto++;
1593 return;
1594 }
1595
1596 ifv = mib->ifvm_ifvlan;
1597 if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
1598 (IFF_UP|IFF_RUNNING)) {
1599 m_freem(m);
1600 ifp->if_noproto++;
1601 goto out;
1602 }
1603
1604 /*
1605 * Now, remove the encapsulation header. The original
1606 * header has already been fixed up above.
1607 */
1608 if (!have_vtag) {
1609 memmove(mtod(m, char *) + mib->ifvm_encaplen,
1610 mtod(m, void *), sizeof(struct ether_header));
1611 m_adj(m, mib->ifvm_encaplen);
1612 }
1613
1614 m_set_rcvif(m, &ifv->ifv_if);
1615 ifv->ifv_if.if_ipackets++;
1616
1617 if (pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN) != 0) {
1618 if (m != NULL)
1619 m_freem(m);
1620 goto out;
1621 }
1622
1623 m->m_flags &= ~M_PROMISC;
1624 if_input(&ifv->ifv_if, m);
1625 out:
1626 vlan_putref_linkmib(mib, &psref);
1627 }
1628
1629 /*
1630 * Module infrastructure
1631 */
1632 #include "if_module.h"
1633
1634 IF_MODULE(MODULE_CLASS_DRIVER, vlan, "")
1635