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