1 /* $OpenBSD: if_vlan.c,v 1.219 2024/06/09 16:25:28 jan 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
vlanattach(int count)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
vlan_clone_create(struct if_clone * ifc,int unit)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
vlan_clone_destroy(struct ifnet * ifp)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
vlan_transmit(struct vlan_softc * sc,struct ifnet * ifp0,struct mbuf * m)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
vlan_enqueue(struct ifnet * ifp,struct mbuf * m)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
vlan_start(struct ifqueue * ifq)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 *
vlan_strip(struct mbuf * m)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 *
vlan_inject(struct mbuf * m,uint16_t type,uint16_t tag)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 *
vlan_input(struct ifnet * ifp0,struct mbuf * m,unsigned int * sdelim)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
vlan_up(struct vlan_softc * sc)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 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 ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWOFFLOAD)) {
536 /*
537 * Chips that can do hardware-assisted VLAN encapsulation, can
538 * calculate the correct checksum for VLAN tagged packets.
539 *
540 * Hardware which does checksum offloading, but not VLAN tag
541 * injection, have to set IFCAP_VLAN_HWOFFLOAD.
542 */
543 ifp->if_capabilities = ifp0->if_capabilities &
544 (IFCAP_CSUM_MASK | IFCAP_TSOv4 | IFCAP_TSOv6);
545 }
546
547 /* commit the sc */
548 error = rw_enter(&vlan_tagh_lk, RW_WRITE | RW_INTR);
549 if (error != 0)
550 goto unpromisc;
551
552 error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, sc->sc_tag);
553 if (error != 0)
554 goto leave;
555
556 SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list);
557 rw_exit(&vlan_tagh_lk);
558
559 /* Register callback for physical link state changes */
560 if_linkstatehook_add(ifp0, &sc->sc_ltask);
561
562 /* Register callback if parent wants to unregister */
563 if_detachhook_add(ifp0, &sc->sc_dtask);
564
565 /* configure the parent to handle packets for this vlan */
566 vlan_multi_apply(sc, ifp0, SIOCADDMULTI);
567
568 /* we're running now */
569 SET(ifp->if_flags, IFF_RUNNING);
570 vlan_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate);
571
572 if_put(ifp0);
573
574 return (ENETRESET);
575
576 leave:
577 rw_exit(&vlan_tagh_lk);
578 unpromisc:
579 if (ISSET(sc->sc_flags, IFVF_PROMISC))
580 (void)ifpromisc(ifp0, 0); /* XXX */
581 scrub:
582 ifp->if_capabilities = 0;
583 CLR(ifp->if_flags, IFF_SIMPLEX);
584 ifp->if_hardmtu = 0xffff;
585 put:
586 if_put(ifp0);
587
588 return (error);
589 }
590
591 int
vlan_down(struct vlan_softc * sc)592 vlan_down(struct vlan_softc *sc)
593 {
594 struct vlan_list *tagh, *list;
595 struct ifnet *ifp = &sc->sc_if;
596 struct ifnet *ifp0;
597
598 tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
599 list = &tagh[TAG_HASH(sc->sc_tag)];
600
601 KASSERT(ISSET(ifp->if_flags, IFF_RUNNING));
602
603 vlan_link_state(sc, LINK_STATE_DOWN, 0);
604 CLR(ifp->if_flags, IFF_RUNNING);
605
606 ifq_barrier(&ifp->if_snd);
607
608 ifp0 = if_get(sc->sc_ifidx0);
609 if (ifp0 != NULL) {
610 if (ISSET(sc->sc_flags, IFVF_PROMISC))
611 ifpromisc(ifp0, 0);
612 vlan_multi_apply(sc, ifp0, SIOCDELMULTI);
613 if_detachhook_del(ifp0, &sc->sc_dtask);
614 if_linkstatehook_del(ifp0, &sc->sc_ltask);
615 }
616 if_put(ifp0);
617
618 rw_enter_write(&vlan_tagh_lk);
619 SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list);
620 rw_exit_write(&vlan_tagh_lk);
621
622 ifp->if_capabilities = 0;
623 CLR(ifp->if_flags, IFF_SIMPLEX);
624 ifp->if_hardmtu = 0xffff;
625
626 return (0);
627 }
628
629 void
vlan_ifdetach(void * v)630 vlan_ifdetach(void *v)
631 {
632 struct vlan_softc *sc = v;
633 struct ifnet *ifp = &sc->sc_if;
634
635 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
636 vlan_down(sc);
637 CLR(ifp->if_flags, IFF_UP);
638 }
639
640 sc->sc_ifidx0 = 0;
641 }
642
643 void
vlan_link_hook(void * v)644 vlan_link_hook(void *v)
645 {
646 struct vlan_softc *sc = v;
647 struct ifnet *ifp0;
648
649 u_char link = LINK_STATE_DOWN;
650 uint64_t baud = 0;
651
652 ifp0 = if_get(sc->sc_ifidx0);
653 if (ifp0 != NULL) {
654 link = ifp0->if_link_state;
655 baud = ifp0->if_baudrate;
656 }
657 if_put(ifp0);
658
659 vlan_link_state(sc, link, baud);
660 }
661
662 void
vlan_link_state(struct vlan_softc * sc,u_char link,uint64_t baud)663 vlan_link_state(struct vlan_softc *sc, u_char link, uint64_t baud)
664 {
665 if (sc->sc_if.if_link_state == link)
666 return;
667
668 sc->sc_if.if_link_state = link;
669 sc->sc_if.if_baudrate = baud;
670
671 if_link_state_change(&sc->sc_if);
672 }
673
674 int
vlan_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)675 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
676 {
677 struct vlan_softc *sc = ifp->if_softc;
678 struct ifreq *ifr = (struct ifreq *)data;
679 struct if_parent *parent = (struct if_parent *)data;
680 struct ifnet *ifp0;
681 uint16_t tag;
682 int error = 0;
683
684 if (sc->sc_dead)
685 return (ENXIO);
686
687 switch (cmd) {
688 case SIOCSIFADDR:
689 ifp->if_flags |= IFF_UP;
690 /* FALLTHROUGH */
691
692 case SIOCSIFFLAGS:
693 if (ISSET(ifp->if_flags, IFF_UP)) {
694 if (!ISSET(ifp->if_flags, IFF_RUNNING))
695 error = vlan_up(sc);
696 else
697 error = ENETRESET;
698 } else {
699 if (ISSET(ifp->if_flags, IFF_RUNNING))
700 error = vlan_down(sc);
701 }
702 break;
703
704 case SIOCSVNETID:
705 if (ifr->ifr_vnetid < EVL_VLID_MIN ||
706 ifr->ifr_vnetid > EVL_VLID_MAX) {
707 error = EINVAL;
708 break;
709 }
710
711 tag = ifr->ifr_vnetid;
712 if (tag == sc->sc_tag)
713 break;
714
715 error = vlan_set_vnetid(sc, tag);
716 break;
717
718 case SIOCGVNETID:
719 if (sc->sc_tag == EVL_VLID_NULL)
720 error = EADDRNOTAVAIL;
721 else
722 ifr->ifr_vnetid = (int64_t)sc->sc_tag;
723 break;
724
725 case SIOCDVNETID:
726 error = vlan_set_vnetid(sc, 0);
727 break;
728
729 case SIOCSIFPARENT:
730 error = vlan_set_parent(sc, parent->ifp_parent);
731 break;
732
733 case SIOCGIFPARENT:
734 ifp0 = if_get(sc->sc_ifidx0);
735 if (ifp0 == NULL)
736 error = EADDRNOTAVAIL;
737 else {
738 memcpy(parent->ifp_parent, ifp0->if_xname,
739 sizeof(parent->ifp_parent));
740 }
741 if_put(ifp0);
742 break;
743
744 case SIOCDIFPARENT:
745 error = vlan_del_parent(sc);
746 break;
747
748 case SIOCADDMULTI:
749 error = vlan_multi_add(sc, ifr);
750 break;
751
752 case SIOCDELMULTI:
753 error = vlan_multi_del(sc, ifr);
754 break;
755
756 case SIOCGIFMEDIA:
757 error = vlan_media_get(sc, ifr);
758 break;
759
760 case SIOCSIFMEDIA:
761 error = ENOTTY;
762 break;
763
764 case SIOCSIFLLADDR:
765 error = vlan_setlladdr(sc, ifr);
766 break;
767
768 case SIOCSETVLAN:
769 error = vlan_set_compat(ifp, ifr);
770 break;
771 case SIOCGETVLAN:
772 error = vlan_get_compat(ifp, ifr);
773 break;
774
775 case SIOCSTXHPRIO:
776 error = if_txhprio_l2_check(ifr->ifr_hdrprio);
777 if (error != 0)
778 break;
779
780 sc->sc_txprio = ifr->ifr_hdrprio;
781 break;
782 case SIOCGTXHPRIO:
783 ifr->ifr_hdrprio = sc->sc_txprio;
784 break;
785
786 case SIOCSRXHPRIO:
787 error = if_rxhprio_l2_check(ifr->ifr_hdrprio);
788 if (error != 0)
789 break;
790
791 sc->sc_rxprio = ifr->ifr_hdrprio;
792 break;
793 case SIOCGRXHPRIO:
794 ifr->ifr_hdrprio = sc->sc_rxprio;
795 break;
796
797 default:
798 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
799 break;
800 }
801
802 if (error == ENETRESET)
803 error = vlan_iff(sc);
804
805 return error;
806 }
807
808 int
vlan_iff(struct vlan_softc * sc)809 vlan_iff(struct vlan_softc *sc)
810 {
811 struct ifnet *ifp0;
812 int promisc = 0;
813 int error = 0;
814
815 if (ISSET(sc->sc_if.if_flags, IFF_PROMISC) ||
816 ISSET(sc->sc_flags, IFVF_LLADDR))
817 promisc = IFVF_PROMISC;
818
819 if (ISSET(sc->sc_flags, IFVF_PROMISC) == promisc)
820 return (0);
821
822 if (ISSET(sc->sc_if.if_flags, IFF_RUNNING)) {
823 ifp0 = if_get(sc->sc_ifidx0);
824 if (ifp0 != NULL)
825 error = ifpromisc(ifp0, promisc);
826 if_put(ifp0);
827 }
828
829 if (error == 0) {
830 CLR(sc->sc_flags, IFVF_PROMISC);
831 SET(sc->sc_flags, promisc);
832 }
833
834 return (error);
835 }
836
837 int
vlan_setlladdr(struct vlan_softc * sc,struct ifreq * ifr)838 vlan_setlladdr(struct vlan_softc *sc, struct ifreq *ifr)
839 {
840 struct ifnet *ifp = &sc->sc_if;
841 struct ifnet *ifp0;
842 uint8_t lladdr[ETHER_ADDR_LEN];
843 int flag;
844
845 memcpy(lladdr, ifr->ifr_addr.sa_data, sizeof(lladdr));
846
847 /* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */
848 if (memcmp(lladdr, etheranyaddr, sizeof(lladdr)) == 0) {
849 ifp0 = if_get(sc->sc_ifidx0);
850 if (ifp0 != NULL)
851 memcpy(lladdr, LLADDR(ifp0->if_sadl), sizeof(lladdr));
852 if_put(ifp0);
853
854 flag = 0;
855 } else
856 flag = IFVF_LLADDR;
857
858 if (memcmp(lladdr, LLADDR(ifp->if_sadl), sizeof(lladdr)) == 0 &&
859 ISSET(sc->sc_flags, IFVF_LLADDR) == flag) {
860 /* nop */
861 return (0);
862 }
863
864 /* commit */
865 if_setlladdr(ifp, lladdr);
866 CLR(sc->sc_flags, IFVF_LLADDR);
867 SET(sc->sc_flags, flag);
868
869 return (ENETRESET);
870 }
871
872 int
vlan_set_vnetid(struct vlan_softc * sc,uint16_t tag)873 vlan_set_vnetid(struct vlan_softc *sc, uint16_t tag)
874 {
875 struct ifnet *ifp = &sc->sc_if;
876 struct vlan_list *tagh, *list;
877 u_char link = ifp->if_link_state;
878 uint64_t baud = ifp->if_baudrate;
879 int error;
880
881 tagh = sc->sc_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
882
883 if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
884 vlan_link_state(sc, LINK_STATE_DOWN, 0);
885
886 error = rw_enter(&vlan_tagh_lk, RW_WRITE);
887 if (error != 0)
888 return (error);
889
890 error = vlan_inuse_locked(sc->sc_type, sc->sc_ifidx0, tag);
891 if (error != 0)
892 goto unlock;
893
894 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
895 list = &tagh[TAG_HASH(sc->sc_tag)];
896 SMR_SLIST_REMOVE_LOCKED(list, sc, vlan_softc, sc_list);
897
898 sc->sc_tag = tag;
899
900 list = &tagh[TAG_HASH(sc->sc_tag)];
901 SMR_SLIST_INSERT_HEAD_LOCKED(list, sc, sc_list);
902 } else
903 sc->sc_tag = tag;
904
905 unlock:
906 rw_exit(&vlan_tagh_lk);
907
908 if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
909 vlan_link_state(sc, link, baud);
910
911 return (error);
912 }
913
914 int
vlan_set_parent(struct vlan_softc * sc,const char * parent)915 vlan_set_parent(struct vlan_softc *sc, const char *parent)
916 {
917 struct ifnet *ifp = &sc->sc_if;
918 struct ifnet *ifp0;
919 int error = 0;
920
921 ifp0 = if_unit(parent);
922 if (ifp0 == NULL)
923 return (EINVAL);
924
925 if (ifp0->if_type != IFT_ETHER) {
926 error = EPROTONOSUPPORT;
927 goto put;
928 }
929
930 if (sc->sc_ifidx0 == ifp0->if_index) {
931 /* nop */
932 goto put;
933 }
934
935 if (ISSET(ifp->if_flags, IFF_RUNNING)) {
936 error = EBUSY;
937 goto put;
938 }
939
940 error = vlan_inuse(sc->sc_type, ifp0->if_index, sc->sc_tag);
941 if (error != 0)
942 goto put;
943
944 if (ether_brport_isset(ifp))
945 ifsetlro(ifp0, 0);
946
947 /* commit */
948 sc->sc_ifidx0 = ifp0->if_index;
949 if (!ISSET(sc->sc_flags, IFVF_LLADDR))
950 if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
951
952 put:
953 if_put(ifp0);
954 return (error);
955 }
956
957 int
vlan_del_parent(struct vlan_softc * sc)958 vlan_del_parent(struct vlan_softc *sc)
959 {
960 struct ifnet *ifp = &sc->sc_if;
961
962 if (ISSET(ifp->if_flags, IFF_RUNNING))
963 return (EBUSY);
964
965 /* commit */
966 sc->sc_ifidx0 = 0;
967 if (!ISSET(sc->sc_flags, IFVF_LLADDR))
968 if_setlladdr(ifp, etheranyaddr);
969
970 return (0);
971 }
972
973 int
vlan_set_compat(struct ifnet * ifp,struct ifreq * ifr)974 vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr)
975 {
976 struct vlanreq vlr;
977 struct ifreq req;
978 struct if_parent parent;
979
980 int error;
981
982 error = suser(curproc);
983 if (error != 0)
984 return (error);
985
986 error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
987 if (error != 0)
988 return (error);
989
990 if (vlr.vlr_parent[0] == '\0')
991 return (vlan_ioctl(ifp, SIOCDIFPARENT, (caddr_t)ifr));
992
993 memset(&req, 0, sizeof(req));
994 memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
995 req.ifr_vnetid = vlr.vlr_tag;
996
997 error = vlan_ioctl(ifp, SIOCSVNETID, (caddr_t)&req);
998 if (error != 0)
999 return (error);
1000
1001 memset(&parent, 0, sizeof(parent));
1002 memcpy(parent.ifp_name, ifp->if_xname, sizeof(parent.ifp_name));
1003 memcpy(parent.ifp_parent, vlr.vlr_parent, sizeof(parent.ifp_parent));
1004 error = vlan_ioctl(ifp, SIOCSIFPARENT, (caddr_t)&parent);
1005 if (error != 0)
1006 return (error);
1007
1008 memset(&req, 0, sizeof(req));
1009 memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
1010 SET(ifp->if_flags, IFF_UP);
1011 return (vlan_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&req));
1012 }
1013
1014 int
vlan_get_compat(struct ifnet * ifp,struct ifreq * ifr)1015 vlan_get_compat(struct ifnet *ifp, struct ifreq *ifr)
1016 {
1017 struct vlan_softc *sc = ifp->if_softc;
1018 struct vlanreq vlr;
1019 struct ifnet *p;
1020
1021 memset(&vlr, 0, sizeof(vlr));
1022 p = if_get(sc->sc_ifidx0);
1023 if (p != NULL)
1024 memcpy(vlr.vlr_parent, p->if_xname, sizeof(vlr.vlr_parent));
1025 if_put(p);
1026
1027 vlr.vlr_tag = sc->sc_tag;
1028
1029 return (copyout(&vlr, ifr->ifr_data, sizeof(vlr)));
1030 }
1031
1032 /*
1033 * do a quick check of up and running vlans for existing configurations.
1034 *
1035 * NOTE: this does allow the same config on down vlans, but vlan_up()
1036 * will catch them.
1037 */
1038 int
vlan_inuse(uint16_t type,unsigned int ifidx,uint16_t tag)1039 vlan_inuse(uint16_t type, unsigned int ifidx, uint16_t tag)
1040 {
1041 int error = 0;
1042
1043 error = rw_enter(&vlan_tagh_lk, RW_READ | RW_INTR);
1044 if (error != 0)
1045 return (error);
1046
1047 error = vlan_inuse_locked(type, ifidx, tag);
1048
1049 rw_exit(&vlan_tagh_lk);
1050
1051 return (error);
1052 }
1053
1054 int
vlan_inuse_locked(uint16_t type,unsigned int ifidx,uint16_t tag)1055 vlan_inuse_locked(uint16_t type, unsigned int ifidx, uint16_t tag)
1056 {
1057 struct vlan_list *tagh, *list;
1058 struct vlan_softc *sc;
1059
1060 tagh = type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
1061 list = &tagh[TAG_HASH(tag)];
1062
1063 SMR_SLIST_FOREACH_LOCKED(sc, list, sc_list) {
1064 if (sc->sc_tag == tag &&
1065 sc->sc_type == type && /* wat */
1066 sc->sc_ifidx0 == ifidx)
1067 return (EADDRINUSE);
1068 }
1069
1070 return (0);
1071 }
1072
1073 int
vlan_multi_add(struct vlan_softc * sc,struct ifreq * ifr)1074 vlan_multi_add(struct vlan_softc *sc, struct ifreq *ifr)
1075 {
1076 struct ifnet *ifp0;
1077 struct vlan_mc_entry *mc;
1078 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1079 int error;
1080
1081 error = ether_addmulti(ifr, &sc->sc_ac);
1082 if (error != ENETRESET)
1083 return (error);
1084
1085 /*
1086 * This is new multicast address. We have to tell parent
1087 * about it. Also, remember this multicast address so that
1088 * we can delete them on unconfigure.
1089 */
1090 if ((mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT)) == NULL) {
1091 error = ENOMEM;
1092 goto alloc_failed;
1093 }
1094
1095 /*
1096 * As ether_addmulti() returns ENETRESET, following two
1097 * statement shouldn't fail.
1098 */
1099 (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
1100 ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, mc->mc_enm);
1101 memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
1102 LIST_INSERT_HEAD(&sc->sc_mc_listhead, mc, mc_entries);
1103
1104 ifp0 = if_get(sc->sc_ifidx0);
1105 error = (ifp0 == NULL) ? 0 :
1106 (*ifp0->if_ioctl)(ifp0, SIOCADDMULTI, (caddr_t)ifr);
1107 if_put(ifp0);
1108
1109 if (error != 0)
1110 goto ioctl_failed;
1111
1112 return (error);
1113
1114 ioctl_failed:
1115 LIST_REMOVE(mc, mc_entries);
1116 free(mc, M_DEVBUF, sizeof(*mc));
1117 alloc_failed:
1118 (void)ether_delmulti(ifr, &sc->sc_ac);
1119
1120 return (error);
1121 }
1122
1123 int
vlan_multi_del(struct vlan_softc * sc,struct ifreq * ifr)1124 vlan_multi_del(struct vlan_softc *sc, struct ifreq *ifr)
1125 {
1126 struct ifnet *ifp0;
1127 struct ether_multi *enm;
1128 struct vlan_mc_entry *mc;
1129 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1130 int error;
1131
1132 /*
1133 * Find a key to lookup vlan_mc_entry. We have to do this
1134 * before calling ether_delmulti for obvious reason.
1135 */
1136 if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
1137 return (error);
1138 ETHER_LOOKUP_MULTI(addrlo, addrhi, &sc->sc_ac, enm);
1139 if (enm == NULL)
1140 return (EINVAL);
1141
1142 LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) {
1143 if (mc->mc_enm == enm)
1144 break;
1145 }
1146
1147 /* We won't delete entries we didn't add */
1148 if (mc == NULL)
1149 return (EINVAL);
1150
1151 error = ether_delmulti(ifr, &sc->sc_ac);
1152 if (error != ENETRESET)
1153 return (error);
1154
1155 if (!ISSET(sc->sc_if.if_flags, IFF_RUNNING))
1156 goto forget;
1157
1158 ifp0 = if_get(sc->sc_ifidx0);
1159 error = (ifp0 == NULL) ? 0 :
1160 (*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr);
1161 if_put(ifp0);
1162
1163 if (error != 0) {
1164 (void)ether_addmulti(ifr, &sc->sc_ac);
1165 return (error);
1166 }
1167
1168 forget:
1169 /* forget about this address */
1170 LIST_REMOVE(mc, mc_entries);
1171 free(mc, M_DEVBUF, sizeof(*mc));
1172
1173 return (0);
1174 }
1175
1176 int
vlan_media_get(struct vlan_softc * sc,struct ifreq * ifr)1177 vlan_media_get(struct vlan_softc *sc, struct ifreq *ifr)
1178 {
1179 struct ifnet *ifp0;
1180 int error;
1181
1182 ifp0 = if_get(sc->sc_ifidx0);
1183 error = (ifp0 == NULL) ? ENOTTY :
1184 (*ifp0->if_ioctl)(ifp0, SIOCGIFMEDIA, (caddr_t)ifr);
1185 if_put(ifp0);
1186
1187 return (error);
1188 }
1189
1190 void
vlan_multi_apply(struct vlan_softc * sc,struct ifnet * ifp0,u_long cmd)1191 vlan_multi_apply(struct vlan_softc *sc, struct ifnet *ifp0, u_long cmd)
1192 {
1193 struct vlan_mc_entry *mc;
1194 union {
1195 struct ifreq ifreq;
1196 struct {
1197 char ifr_name[IFNAMSIZ];
1198 struct sockaddr_storage ifr_ss;
1199 } ifreq_storage;
1200 } ifreq;
1201 struct ifreq *ifr = &ifreq.ifreq;
1202
1203 memcpy(ifr->ifr_name, ifp0->if_xname, IFNAMSIZ);
1204 LIST_FOREACH(mc, &sc->sc_mc_listhead, mc_entries) {
1205 memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
1206
1207 (void)(*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)ifr);
1208 }
1209 }
1210
1211 void
vlan_multi_free(struct vlan_softc * sc)1212 vlan_multi_free(struct vlan_softc *sc)
1213 {
1214 struct vlan_mc_entry *mc;
1215
1216 while ((mc = LIST_FIRST(&sc->sc_mc_listhead)) != NULL) {
1217 LIST_REMOVE(mc, mc_entries);
1218 free(mc, M_DEVBUF, sizeof(*mc));
1219 }
1220 }
1221