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
77struct 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
86struct 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
105SMR_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)
114struct vlan_list *vlan_tagh, *svlan_tagh;
115struct rwlock vlan_tagh_lk = RWLOCK_INITIALIZER("vlantag");
116
117void	vlanattach(int count);
118int	vlan_clone_create(struct if_clone *, int);
119int	vlan_clone_destroy(struct ifnet *);
120
121int	vlan_enqueue(struct ifnet *, struct mbuf *);
122void	vlan_start(struct ifqueue *ifq);
123int	vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
124
125int	vlan_up(struct vlan_softc *);
126int	vlan_down(struct vlan_softc *);
127
128void	vlan_ifdetach(void *);
129void	vlan_link_hook(void *);
130void	vlan_link_state(struct vlan_softc *, u_char, uint64_t);
131
132int	vlan_set_vnetid(struct vlan_softc *, uint16_t);
133int	vlan_set_parent(struct vlan_softc *, const char *);
134int	vlan_del_parent(struct vlan_softc *);
135int	vlan_inuse(uint16_t, unsigned int, uint16_t);
136int	vlan_inuse_locked(uint16_t, unsigned int, uint16_t);
137
138int	vlan_multi_add(struct vlan_softc *, struct ifreq *);
139int	vlan_multi_del(struct vlan_softc *, struct ifreq *);
140void	vlan_multi_apply(struct vlan_softc *, struct ifnet *, u_long);
141void	vlan_multi_free(struct vlan_softc *);
142
143int	vlan_media_get(struct vlan_softc *, struct ifreq *);
144
145int	vlan_iff(struct vlan_softc *);
146int	vlan_setlladdr(struct vlan_softc *, struct ifreq *);
147
148int	vlan_set_compat(struct ifnet *, struct ifreq *);
149int	vlan_get_compat(struct ifnet *, struct ifreq *);
150
151struct if_clone vlan_cloner =
152    IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
153struct if_clone svlan_cloner =
154    IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy);
155
156void
157vlanattach(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
182int
183vlan_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
226int
227vlan_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
248void
249vlan_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
289int
290vlan_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
316void
317vlan_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
333leave:
334	if_put(ifp0);
335}
336
337struct mbuf *
338vlan_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
354struct mbuf *
355vlan_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
376struct mbuf *
377vlan_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);
475leave:
476	refcnt_rele_wake(&sc->sc_refcnt);
477	return (NULL);
478}
479
480int
481vlan_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
576leave:
577	rw_exit(&vlan_tagh_lk);
578unpromisc:
579	if (ISSET(sc->sc_flags, IFVF_PROMISC))
580		(void)ifpromisc(ifp0, 0); /* XXX */
581scrub:
582	ifp->if_capabilities = 0;
583	CLR(ifp->if_flags, IFF_SIMPLEX);
584	ifp->if_hardmtu = 0xffff;
585put:
586	if_put(ifp0);
587
588	return (error);
589}
590
591int
592vlan_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
629void
630vlan_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
643void
644vlan_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
662void
663vlan_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
674int
675vlan_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
808int
809vlan_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
837int
838vlan_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
872int
873vlan_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
905unlock:
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
914int
915vlan_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
952put:
953	if_put(ifp0);
954	return (error);
955}
956
957int
958vlan_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
973int
974vlan_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
1014int
1015vlan_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 */
1038int
1039vlan_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
1054int
1055vlan_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
1073int
1074vlan_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
1123int
1124vlan_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
1168forget:
1169	/* forget about this address */
1170	LIST_REMOVE(mc, mc_entries);
1171	free(mc, M_DEVBUF, sizeof(*mc));
1172
1173	return (0);
1174}
1175
1176int
1177vlan_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
1190void
1191vlan_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
1211void
1212vlan_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