xref: /dragonfly/sys/net/vlan/if_vlan.c (revision 8a7bdfea)
1 /*
2  * Copyright 1998 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose and without fee is hereby
6  * granted, provided that both the above copyright notice and this
7  * permission notice appear in all copies, that both the above
8  * copyright notice and this permission notice appear in all
9  * supporting documentation, and that the name of M.I.T. not be used
10  * in advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.  M.I.T. makes
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/sys/net/if_vlan.c,v 1.15.2.13 2003/02/14 22:25:58 fenner Exp $
30  * $DragonFly: src/sys/net/vlan/if_vlan.c,v 1.31 2008/03/18 14:12:45 sephe Exp $
31  */
32 
33 /*
34  * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
35  * Might be extended some day to also handle IEEE 802.1p priority
36  * tagging.  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 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  *
45  * XXX It's incorrect to assume that we must always kludge up
46  * headers on the physical device's behalf: some devices support
47  * VLAN tag insertion and extraction in firmware. For these cases,
48  * one can change the behavior of the vlan interface by setting
49  * the LINK0 flag on it (that is setting the vlan interface's LINK0
50  * flag, _not_ the parent's LINK0 flag; we try to leave the parent
51  * alone). If the interface has the LINK0 flag set, then it will
52  * not modify the ethernet header on output, because the parent
53  * can do that for itself. On input, the parent can call vlan_input_tag()
54  * directly in order to supply us with an incoming mbuf and the vlan
55  * tag value that goes with it.
56  */
57 
58 #ifndef NVLAN
59 #include "use_vlan.h"
60 #endif
61 #include "opt_inet.h"
62 
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/malloc.h>
67 #include <sys/mbuf.h>
68 #include <sys/module.h>
69 #include <sys/queue.h>
70 #include <sys/socket.h>
71 #include <sys/sockio.h>
72 #include <sys/sysctl.h>
73 #include <sys/bus.h>
74 #include <sys/thread2.h>
75 
76 #include <net/bpf.h>
77 #include <net/ethernet.h>
78 #include <net/if.h>
79 #include <net/if_arp.h>
80 #include <net/if_dl.h>
81 #include <net/if_types.h>
82 #include <net/ifq_var.h>
83 #include <net/if_clone.h>
84 #include <net/netmsg2.h>
85 
86 #ifdef INET
87 #include <netinet/in.h>
88 #include <netinet/if_ether.h>
89 #endif
90 
91 #include <net/vlan/if_vlan_var.h>
92 #include <net/vlan/if_vlan_ether.h>
93 
94 struct ifvlan;
95 
96 struct vlan_mc_entry {
97 	struct ether_addr		mc_addr;
98 	SLIST_ENTRY(vlan_mc_entry)	mc_entries;
99 };
100 
101 struct vlan_entry {
102 	struct ifvlan		*ifv;
103 	LIST_ENTRY(vlan_entry)	ifv_link;
104 };
105 
106 struct	ifvlan {
107 	struct	arpcom ifv_ac;	/* make this an interface */
108 	struct	ifnet *ifv_p;	/* parent inteface of this vlan */
109 	struct	ifv_linkmib {
110 		int	ifvm_parent;
111 		uint16_t ifvm_proto; /* encapsulation ethertype */
112 		uint16_t ifvm_tag; /* tag to apply on packets leaving if */
113 	}	ifv_mib;
114 	SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
115 	LIST_ENTRY(ifvlan) ifv_list;
116 	struct vlan_entry ifv_entries[1];
117 };
118 #define	ifv_if	ifv_ac.ac_if
119 #define	ifv_tag	ifv_mib.ifvm_tag
120 
121 struct vlan_trunk {
122 	LIST_HEAD(, vlan_entry) vlan_list;
123 };
124 
125 struct netmsg_vlan {
126 	struct netmsg	nv_nmsg;
127 	struct ifvlan	*nv_ifv;
128 	struct ifnet	*nv_ifp_p;
129 	const char	*nv_parent_name;
130 	uint16_t	nv_vlantag;
131 };
132 
133 #define VLANNAME	"vlan"
134 
135 SYSCTL_DECL(_net_link);
136 SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN");
137 SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency");
138 
139 static MALLOC_DEFINE(M_VLAN, "vlan", "802.1Q Virtual LAN Interface");
140 static LIST_HEAD(, ifvlan) ifv_list;
141 
142 static int	vlan_clone_create(struct if_clone *, int);
143 static void	vlan_clone_destroy(struct ifnet *);
144 static void	vlan_ifdetach(void *, struct ifnet *);
145 
146 static void	vlan_init(void *);
147 static void	vlan_start(struct ifnet *);
148 static int	vlan_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
149 
150 static int	vlan_input(const struct ether_header *eh, struct mbuf *m);
151 static int	vlan_input_tag(struct mbuf *m, uint16_t t);
152 
153 static void	vlan_clrmulti(struct ifvlan *, struct ifnet *);
154 static int	vlan_setmulti(struct ifvlan *, struct ifnet *);
155 static int	vlan_config_multi(struct ifvlan *);
156 static int	vlan_config(struct ifvlan *, const char *, uint16_t);
157 static int	vlan_unconfig(struct ifvlan *);
158 static void	vlan_link(struct ifvlan *, struct ifnet *);
159 static void	vlan_unlink(struct ifvlan *, struct ifnet *);
160 
161 static void	vlan_config_dispatch(struct netmsg *);
162 static void	vlan_unconfig_dispatch(struct netmsg *);
163 static void	vlan_link_dispatch(struct netmsg *);
164 static void	vlan_unlink_dispatch(struct netmsg *);
165 static void	vlan_multi_dispatch(struct netmsg *);
166 static void	vlan_ifdetach_dispatch(struct netmsg *);
167 
168 static eventhandler_tag vlan_ifdetach_cookie;
169 static struct if_clone vlan_cloner =
170 	IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy,
171 			     NVLAN, IF_MAXUNIT);
172 
173 static __inline void
174 vlan_forwardmsg(struct lwkt_msg *lmsg, int next_cpu)
175 {
176 	if (next_cpu < ncpus)
177 		lwkt_forwardmsg(ifa_portfn(next_cpu), lmsg);
178 	else
179 		lwkt_replymsg(lmsg, 0);
180 }
181 
182 /*
183  * Program our multicast filter. What we're actually doing is
184  * programming the multicast filter of the parent. This has the
185  * side effect of causing the parent interface to receive multicast
186  * traffic that it doesn't really want, which ends up being discarded
187  * later by the upper protocol layers. Unfortunately, there's no way
188  * to avoid this: there really is only one physical interface.
189  */
190 static int
191 vlan_setmulti(struct ifvlan *ifv, struct ifnet *ifp_p)
192 {
193 	struct ifmultiaddr *ifma, *rifma = NULL;
194 	struct vlan_mc_entry *mc = NULL;
195 	struct sockaddr_dl sdl;
196 	struct ifnet *ifp = &ifv->ifv_if;
197 
198 	ASSERT_NOT_SERIALIZED(ifp->if_serializer);
199 
200 	/*
201 	 * First, remove any existing filter entries.
202 	 */
203 	vlan_clrmulti(ifv, ifp_p);
204 
205 	/*
206 	 * Now program new ones.
207 	 */
208 	bzero(&sdl, sizeof(sdl));
209 	sdl.sdl_len = sizeof(sdl);
210 	sdl.sdl_family = AF_LINK;
211 	sdl.sdl_index = ifp_p->if_index;
212 	sdl.sdl_type = IFT_ETHER;
213 	sdl.sdl_alen = ETHER_ADDR_LEN;
214 
215 	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
216 		int error;
217 
218 		if (ifma->ifma_addr->sa_family != AF_LINK)
219 			continue;
220 
221 		/* Save a copy */
222 		mc = kmalloc(sizeof(struct vlan_mc_entry), M_VLAN, M_WAITOK);
223 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
224 		      &mc->mc_addr, ETHER_ADDR_LEN);
225 		SLIST_INSERT_HEAD(&ifv->vlan_mc_listhead, mc, mc_entries);
226 
227 		/* Program the parent multicast filter */
228 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
229 		      LLADDR(&sdl), ETHER_ADDR_LEN);
230 		error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma);
231 		if (error)
232 			return error;
233 	}
234 	return 0;
235 }
236 
237 static void
238 vlan_clrmulti(struct ifvlan *ifv, struct ifnet *ifp_p)
239 {
240 	struct vlan_mc_entry *mc;
241 	struct sockaddr_dl sdl;
242 
243 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
244 
245 	bzero(&sdl, sizeof(sdl));
246 	sdl.sdl_len = sizeof(sdl);
247 	sdl.sdl_family = AF_LINK;
248 	sdl.sdl_index = ifp_p->if_index;
249 	sdl.sdl_type = IFT_ETHER;
250 	sdl.sdl_alen = ETHER_ADDR_LEN;
251 
252 	while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
253 		bcopy(&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN);
254 		if_delmulti(ifp_p, (struct sockaddr *)&sdl); /* ignore error */
255 
256 		SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
257 		kfree(mc, M_VLAN);
258 	}
259 }
260 
261 static int
262 vlan_modevent(module_t mod, int type, void *data)
263 {
264 	switch (type) {
265 	case MOD_LOAD:
266 		LIST_INIT(&ifv_list);
267 		vlan_input_p = vlan_input;
268 		vlan_input_tag_p = vlan_input_tag;
269 		vlan_ifdetach_cookie =
270 		EVENTHANDLER_REGISTER(ifnet_detach_event,
271 				      vlan_ifdetach, NULL,
272 				      EVENTHANDLER_PRI_ANY);
273 		if_clone_attach(&vlan_cloner);
274 		break;
275 
276 	case MOD_UNLOAD:
277 		if_clone_detach(&vlan_cloner);
278 		vlan_input_p = NULL;
279 		vlan_input_tag_p = NULL;
280 		EVENTHANDLER_DEREGISTER(ifnet_detach_event,
281 					vlan_ifdetach_cookie);
282 		while (!LIST_EMPTY(&ifv_list))
283 			vlan_clone_destroy(&LIST_FIRST(&ifv_list)->ifv_if);
284 		break;
285 	}
286 	return 0;
287 }
288 
289 static moduledata_t vlan_mod = {
290 	"if_vlan",
291 	vlan_modevent,
292 	0
293 };
294 
295 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
296 
297 static void
298 vlan_ifdetach_dispatch(struct netmsg *nmsg)
299 {
300 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
301 	struct ifnet *ifp_p = vmsg->nv_ifp_p;
302 	struct vlan_trunk *vlantrunks, *trunk;
303 	struct vlan_entry *ifve;
304 
305 	vlantrunks = ifp_p->if_vlantrunks;
306 	if (vlantrunks == NULL)
307 		goto reply;
308 	trunk = &vlantrunks[mycpuid];
309 
310 	while (ifp_p->if_vlantrunks &&
311 	       (ifve = LIST_FIRST(&trunk->vlan_list)) != NULL)
312 		vlan_unconfig(ifve->ifv);
313 reply:
314 	lwkt_replymsg(&nmsg->nm_lmsg, 0);
315 }
316 
317 static void
318 vlan_ifdetach(void *arg __unused, struct ifnet *ifp)
319 {
320 	struct netmsg_vlan vmsg;
321 	struct netmsg *nmsg;
322 
323 	ASSERT_NOT_SERIALIZED(ifp->if_serializer);
324 
325 	bzero(&vmsg, sizeof(vmsg));
326 	nmsg = &vmsg.nv_nmsg;
327 
328 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_ifdetach_dispatch);
329 	vmsg.nv_ifp_p = ifp;
330 
331 	lwkt_domsg(cpu_portfn(0), &nmsg->nm_lmsg, 0);
332 }
333 
334 static int
335 vlan_clone_create(struct if_clone *ifc, int unit)
336 {
337 	struct ifvlan *ifv;
338 	struct ifnet *ifp;
339 	int vlan_size, i;
340 
341 	vlan_size = sizeof(struct ifvlan)
342 		  + ((ncpus - 1) * sizeof(struct vlan_entry));
343 	ifv = kmalloc(vlan_size, M_VLAN, M_WAITOK | M_ZERO);
344 	SLIST_INIT(&ifv->vlan_mc_listhead);
345 	for (i = 0; i < ncpus; ++i)
346 		ifv->ifv_entries[i].ifv = ifv;
347 
348 	crit_enter();	/* XXX not MP safe */
349 	LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list);
350 	crit_exit();
351 
352 	ifp = &ifv->ifv_if;
353 	ifp->if_softc = ifv;
354 	if_initname(ifp, "vlan", unit);
355 	/* NB: flags are not set here */
356 	ifp->if_linkmib = &ifv->ifv_mib;
357 	ifp->if_linkmiblen = sizeof ifv->ifv_mib;
358 	/* NB: mtu is not set here */
359 
360 	ifp->if_init = vlan_init;
361 	ifp->if_start = vlan_start;
362 	ifp->if_ioctl = vlan_ioctl;
363 	ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
364 	ifq_set_ready(&ifp->if_snd);
365 	ether_ifattach(ifp, ifv->ifv_ac.ac_enaddr, NULL);
366 	/* Now undo some of the damage... */
367 	ifp->if_data.ifi_type = IFT_L2VLAN;
368 	ifp->if_data.ifi_hdrlen = EVL_ENCAPLEN;
369 
370 	return (0);
371 }
372 
373 static void
374 vlan_clone_destroy(struct ifnet *ifp)
375 {
376 	struct ifvlan *ifv = ifp->if_softc;
377 
378 	crit_enter();	/* XXX not MP safe */
379 	LIST_REMOVE(ifv, ifv_list);
380 	crit_exit();
381 
382 	vlan_unconfig(ifv);
383 	ether_ifdetach(ifp);
384 
385 	kfree(ifv, M_VLAN);
386 }
387 
388 static void
389 vlan_init(void *xsc)
390 {
391 	struct ifvlan *ifv = xsc;
392 	struct ifnet *ifp = &ifv->ifv_if;
393 
394 	ASSERT_SERIALIZED(ifp->if_serializer);
395 
396 	if (ifv->ifv_p != NULL)
397 		ifp->if_flags |= IFF_RUNNING;
398 }
399 
400 static void
401 vlan_start(struct ifnet *ifp)
402 {
403 	struct ifvlan *ifv = ifp->if_softc;
404 	struct ifnet *ifp_p = ifv->ifv_p;
405 	struct mbuf *m;
406 
407 	ASSERT_SERIALIZED(ifp->if_serializer);
408 
409 	if ((ifp->if_flags & IFF_RUNNING) == 0 || ifp_p == NULL)
410 		return;
411 
412 	ifp->if_flags |= IFF_OACTIVE;
413 	for (;;) {
414 		struct netmsg_packet *nmp;
415 		struct netmsg *nmsg;
416 		struct lwkt_port *port;
417 
418 		m = ifq_dequeue(&ifp->if_snd, NULL);
419 		if (m == NULL)
420 			break;
421 		BPF_MTAP(ifp, m);
422 
423 		/*
424 		 * Do not run parent's if_start() if the parent is not up,
425 		 * or parent's driver will cause a system crash.
426 		 */
427 		if ((ifp_p->if_flags & (IFF_UP | IFF_RUNNING)) !=
428 		    (IFF_UP | IFF_RUNNING)) {
429 			m_freem(m);
430 			ifp->if_data.ifi_collisions++;
431 			continue;
432 		}
433 
434 		/*
435 		 * We need some way to tell the interface where the packet
436 		 * came from so that it knows how to find the VLAN tag to
437 		 * use, so we set the ether_vlantag in the mbuf packet header
438 		 * to our vlan tag.  We also set the M_VLANTAG flag in the
439 		 * mbuf to let the parent driver know that the ether_vlantag
440 		 * is really valid.
441 		 */
442 		m->m_pkthdr.ether_vlantag = ifv->ifv_tag;
443 		m->m_flags |= M_VLANTAG;
444 
445 		nmp = &m->m_hdr.mh_netmsg;
446 		nmsg = &nmp->nm_netmsg;
447 
448 		netmsg_init(nmsg, &netisr_apanic_rport, 0, vlan_start_dispatch);
449 		nmp->nm_packet = m;
450 		nmsg->nm_lmsg.u.ms_resultp = ifp_p;
451 
452 		port = cpu_portfn(ifp_p->if_index % ncpus /* XXX */);
453 		lwkt_sendmsg(port, &nmp->nm_netmsg.nm_lmsg);
454 		ifp->if_opackets++;
455 	}
456 	ifp->if_flags &= ~IFF_OACTIVE;
457 }
458 
459 static int
460 vlan_input_tag(struct mbuf *m, uint16_t t)
461 {
462 	struct bpf_if *bif;
463 	struct ifvlan *ifv;
464 	struct ifnet *rcvif;
465 
466 	rcvif = m->m_pkthdr.rcvif;
467 
468 	ASSERT_SERIALIZED(rcvif->if_serializer);
469 
470 	/*
471 	 * Fake up a header and send the packet to the physical interface's
472 	 * bpf tap if active.
473 	 */
474 	if ((bif = rcvif->if_bpf) != NULL)
475 		vlan_ether_ptap(bif, m, t);
476 
477 	for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
478 	    ifv = LIST_NEXT(ifv, ifv_list)) {
479 		if (rcvif == ifv->ifv_p && ifv->ifv_tag == t)
480 			break;
481 	}
482 
483 	if (ifv == NULL || (ifv->ifv_if.if_flags & IFF_UP) == 0) {
484 		m_freem(m);
485 		return -1;	/* So the parent can take note */
486 	}
487 
488 	/*
489 	 * Having found a valid vlan interface corresponding to
490 	 * the given source interface and vlan tag, run the
491 	 * the real packet through ether_input().
492 	 */
493 	m->m_pkthdr.rcvif = &ifv->ifv_if;
494 
495 	ifv->ifv_if.if_ipackets++;
496 	lwkt_serialize_exit(rcvif->if_serializer);
497 	lwkt_serialize_enter(ifv->ifv_if.if_serializer);
498 	ether_input(&ifv->ifv_if, m);
499 	lwkt_serialize_exit(ifv->ifv_if.if_serializer);
500 	lwkt_serialize_enter(rcvif->if_serializer);
501 	return 0;
502 }
503 
504 static int
505 vlan_input(const struct ether_header *eh, struct mbuf *m)
506 {
507 	struct ifvlan *ifv;
508 	struct ifnet *rcvif;
509 	struct ether_header eh_copy;
510 
511 	rcvif = m->m_pkthdr.rcvif;
512 	ASSERT_SERIALIZED(rcvif->if_serializer);
513 
514 	for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
515 	    ifv = LIST_NEXT(ifv, ifv_list)) {
516 		if (rcvif == ifv->ifv_p
517 		    && (EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *)))
518 			== ifv->ifv_tag))
519 			break;
520 	}
521 
522 	if (ifv == NULL || (ifv->ifv_if.if_flags & IFF_UP) == 0) {
523 		rcvif->if_noproto++;
524 		m_freem(m);
525 		return -1;	/* so ether_input can take note */
526 	}
527 
528 	/*
529 	 * Having found a valid vlan interface corresponding to
530 	 * the given source interface and vlan tag, remove the
531 	 * remaining encapsulation (ether_vlan_header minus the ether_header
532 	 * that had already been removed) and run the real packet
533 	 * through ether_input() a second time (it had better be
534 	 * reentrant!).
535 	 */
536 	eh_copy = *eh;
537 	eh_copy.ether_type = mtod(m, u_int16_t *)[1];	/* evl_proto */
538 	m->m_pkthdr.rcvif = &ifv->ifv_if;
539 	m_adj(m, EVL_ENCAPLEN);
540 	M_PREPEND(m, ETHER_HDR_LEN, MB_WAIT);
541 	*(struct ether_header *)mtod(m, void *) = eh_copy;
542 
543 	ifv->ifv_if.if_ipackets++;
544 	lwkt_serialize_exit(rcvif->if_serializer);
545 	lwkt_serialize_enter(ifv->ifv_if.if_serializer);
546 	ether_input(&ifv->ifv_if, m);
547 	lwkt_serialize_exit(ifv->ifv_if.if_serializer);
548 	lwkt_serialize_enter(rcvif->if_serializer);
549 	return 0;
550 }
551 
552 static void
553 vlan_link_dispatch(struct netmsg *nmsg)
554 {
555 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
556 	struct ifvlan *ifv = vmsg->nv_ifv;
557 	struct ifnet *ifp_p = vmsg->nv_ifp_p;
558 	struct vlan_entry *entry;
559 	struct vlan_trunk *vlantrunks, *trunk;
560 	int cpu = mycpuid;
561 
562 	vlantrunks = ifp_p->if_vlantrunks;
563 	KASSERT(vlantrunks != NULL,
564 		("vlan trunk has not been initialized yet\n"));
565 
566 	entry = &ifv->ifv_entries[cpu];
567 	trunk = &vlantrunks[cpu];
568 
569 	crit_enter();
570 	LIST_INSERT_HEAD(&trunk->vlan_list, entry, ifv_link);
571 	crit_exit();
572 
573 	vlan_forwardmsg(&nmsg->nm_lmsg, cpu + 1);
574 }
575 
576 static void
577 vlan_link(struct ifvlan *ifv, struct ifnet *ifp_p)
578 {
579 	struct netmsg_vlan vmsg;
580 	struct netmsg *nmsg;
581 
582 	/* Assert in netisr0 */
583 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
584 
585 	if (ifp_p->if_vlantrunks == NULL) {
586 		struct vlan_trunk *vlantrunks;
587 		int i;
588 
589 		vlantrunks = kmalloc(sizeof(*vlantrunks) * ncpus, M_VLAN,
590 				     M_WAITOK | M_ZERO);
591 		for (i = 0; i < ncpus; ++i)
592 			LIST_INIT(&vlantrunks[i].vlan_list);
593 
594 		ifp_p->if_vlantrunks = vlantrunks;
595 	}
596 
597 	bzero(&vmsg, sizeof(vmsg));
598 	nmsg = &vmsg.nv_nmsg;
599 
600 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_link_dispatch);
601 	vmsg.nv_ifv = ifv;
602 	vmsg.nv_ifp_p = ifp_p;
603 
604 	lwkt_domsg(ifa_portfn(0), &nmsg->nm_lmsg, 0);
605 }
606 
607 static void
608 vlan_config_dispatch(struct netmsg *nmsg)
609 {
610 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
611 	struct ifvlan *ifv;
612 	struct ifnet *ifp_p, *ifp;
613 	struct sockaddr_dl *sdl1, *sdl2;
614 	int error;
615 
616 	/* Assert in netisr0 */
617 
618 	ifp_p = ifunit(vmsg->nv_parent_name);
619 	if (ifp_p == NULL) {
620 		error = ENOENT;
621 		goto reply;
622 	}
623 
624 	if (ifp_p->if_data.ifi_type != IFT_ETHER) {
625 		error = EPROTONOSUPPORT;
626 		goto reply;
627 	}
628 
629 	ifv = vmsg->nv_ifv;
630 	ifp = &ifv->ifv_if;
631 
632 	if (ifv->ifv_p) {
633 		error = EBUSY;
634 		goto reply;
635 	}
636 
637 	/* Link vlan into parent's vlantrunk */
638 	vlan_link(ifv, ifp_p);
639 
640 	lwkt_serialize_enter(ifp->if_serializer);
641 
642 	ifv->ifv_tag = vmsg->nv_vlantag;
643 	if (ifp_p->if_capenable & IFCAP_VLAN_MTU)
644 		ifp->if_mtu = ifp_p->if_mtu;
645 	else
646 		ifp->if_mtu = ifp_p->if_data.ifi_mtu - EVL_ENCAPLEN;
647 
648 	/*
649 	 * Copy only a selected subset of flags from the parent.
650 	 * Other flags are none of our business.
651 	 */
652 	ifp->if_flags = (ifp_p->if_flags &
653 	    (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT));
654 
655 	/*
656 	 * Set up our ``Ethernet address'' to reflect the underlying
657 	 * physical interface's.
658 	 */
659 	sdl1 = IF_LLSOCKADDR(ifp);
660 	sdl2 = IF_LLSOCKADDR(ifp_p);
661 	sdl1->sdl_type = IFT_ETHER;
662 	sdl1->sdl_alen = ETHER_ADDR_LEN;
663 	bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
664 	bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
665 
666 	/*
667 	 * Release vlan's serializer before reprogramming parent's
668 	 * multicast filter to avoid possible dead lock.
669 	 */
670 	lwkt_serialize_exit(ifp->if_serializer);
671 
672 	/*
673 	 * Configure multicast addresses that may already be
674 	 * joined on the vlan device.
675 	 */
676 	vlan_setmulti(ifv, ifp_p);
677 
678 	/*
679 	 * Connect to parent after everything have been set up,
680 	 * so input/output could know that vlan is ready to go
681 	 */
682 	ifv->ifv_p = ifp_p;
683 	error = 0;
684 reply:
685 	lwkt_replymsg(&nmsg->nm_lmsg, error);
686 }
687 
688 static int
689 vlan_config(struct ifvlan *ifv, const char *parent_name, uint16_t vlantag)
690 {
691 	struct netmsg_vlan vmsg;
692 	struct netmsg *nmsg;
693 
694 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
695 
696 	bzero(&vmsg, sizeof(vmsg));
697 	nmsg = &vmsg.nv_nmsg;
698 
699 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_config_dispatch);
700 	vmsg.nv_ifv = ifv;
701 	vmsg.nv_parent_name = parent_name;
702 	vmsg.nv_vlantag = vlantag;
703 
704 	return lwkt_domsg(cpu_portfn(0), &nmsg->nm_lmsg, 0);
705 }
706 
707 static void
708 vlan_unlink_dispatch(struct netmsg *nmsg)
709 {
710 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
711 	struct ifvlan *ifv = vmsg->nv_ifv;
712 	struct vlan_entry *entry;
713 	int cpu = mycpuid;
714 
715 	KASSERT(vmsg->nv_ifp_p->if_vlantrunks != NULL,
716 		("vlan trunk has not been initialized yet\n"));
717 	entry = &ifv->ifv_entries[cpu];
718 
719 	crit_enter();
720 	LIST_REMOVE(entry, ifv_link);
721 	crit_exit();
722 
723 	vlan_forwardmsg(&nmsg->nm_lmsg, cpu + 1);
724 }
725 
726 static void
727 vlan_unlink(struct ifvlan *ifv, struct ifnet *ifp_p)
728 {
729 	struct vlan_trunk *vlantrunks = ifp_p->if_vlantrunks;
730 	struct netmsg_vlan vmsg;
731 	struct netmsg *nmsg;
732 
733 	/* Assert in netisr0 */
734 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
735 
736 	KASSERT(ifp_p->if_vlantrunks != NULL,
737 		("vlan trunk has not been initialized yet\n"));
738 
739 	bzero(&vmsg, sizeof(vmsg));
740 	nmsg = &vmsg.nv_nmsg;
741 
742 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_unlink_dispatch);
743 	vmsg.nv_ifv = ifv;
744 	vmsg.nv_ifp_p = ifp_p;
745 
746 	lwkt_domsg(ifa_portfn(0), &nmsg->nm_lmsg, 0);
747 
748 	crit_enter();
749 	if (LIST_EMPTY(&vlantrunks[mycpuid].vlan_list)) {
750 #ifdef notyet
751 		ifp_p->if_vlantrunks = NULL;
752 		netmsg_service_sync();
753 		kfree(vlantrunks, M_VLAN);
754 #else
755 		lwkt_serialize_enter(ifp_p->if_serializer);
756 		kfree(ifp_p->if_vlantrunks, M_VLAN);
757 		ifp_p->if_vlantrunks = NULL;
758 		lwkt_serialize_exit(ifp_p->if_serializer);
759 #endif
760 	}
761 	crit_exit();
762 }
763 
764 static void
765 vlan_unconfig_dispatch(struct netmsg *nmsg)
766 {
767 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
768 	struct sockaddr_dl *sdl;
769 	struct ifvlan *ifv;
770 	struct ifnet *ifp_p, *ifp;
771 	int error;
772 
773 	/* Assert in netisr0 */
774 
775 	ifv = vmsg->nv_ifv;
776 	ifp = &ifv->ifv_if;
777 
778 	if (ifp->if_flags & IFF_UP)
779 		if_down(ifp);
780 
781 	lwkt_serialize_enter(ifp->if_serializer);
782 
783 	ifp->if_flags &= ~IFF_RUNNING;
784 
785 	/*
786 	 * Save parent ifnet pointer and disconnect from parent.
787 	 *
788 	 * This is done early in this function, so input/output could
789 	 * know that we are disconnecting.
790 	 */
791 	ifp_p = ifv->ifv_p;
792 	ifv->ifv_p = NULL;
793 
794 	/*
795 	 * Release vlan's serializer before reprogramming parent's
796 	 * multicast filter to avoid possible dead lock.
797 	 */
798 	lwkt_serialize_exit(ifp->if_serializer);
799 
800 	if (ifp_p) {
801 		/*
802 		 * Since the interface is being unconfigured, we need to
803 		 * empty the list of multicast groups that we may have joined
804 		 * while we were alive from the parent's list.
805 		 */
806 		vlan_clrmulti(ifv, ifp_p);
807 	}
808 
809 	lwkt_serialize_enter(ifp->if_serializer);
810 
811 	ifp->if_mtu = ETHERMTU;
812 
813 	/* Clear our MAC address. */
814 	sdl = IF_LLSOCKADDR(ifp);
815 	sdl->sdl_type = IFT_ETHER;
816 	sdl->sdl_alen = ETHER_ADDR_LEN;
817 	bzero(LLADDR(sdl), ETHER_ADDR_LEN);
818 	bzero(ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
819 
820 	lwkt_serialize_exit(ifp->if_serializer);
821 
822 	/* Unlink vlan from parent's vlantrunk */
823 	if (ifp_p != NULL && ifp_p->if_vlantrunks != NULL)
824 		vlan_unlink(ifv, ifp_p);
825 
826 	error = 0;
827 	lwkt_replymsg(&nmsg->nm_lmsg, error);
828 }
829 
830 static int
831 vlan_unconfig(struct ifvlan *ifv)
832 {
833 	struct netmsg_vlan vmsg;
834 	struct netmsg *nmsg;
835 
836 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
837 
838 	bzero(&vmsg, sizeof(vmsg));
839 	nmsg = &vmsg.nv_nmsg;
840 
841 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_unconfig_dispatch);
842 	vmsg.nv_ifv = ifv;
843 
844 	return lwkt_domsg(cpu_portfn(0), &nmsg->nm_lmsg, 0);
845 }
846 
847 static int
848 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
849 {
850 	struct ifvlan *ifv = ifp->if_softc;
851 	struct ifreq *ifr = (struct ifreq *)data;
852 	struct ifnet *ifp_p;
853 	struct vlanreq vlr;
854 	int error = 0;
855 
856 	ASSERT_SERIALIZED(ifp->if_serializer);
857 
858 	switch (cmd) {
859 	case SIOCGIFMEDIA:
860 		ifp_p = ifv->ifv_p;
861 		if (ifp_p != NULL) {
862 			lwkt_serialize_exit(ifp->if_serializer);
863 
864 			lwkt_serialize_enter(ifp_p->if_serializer);
865 			error = ifp_p->if_ioctl(ifp_p, SIOCGIFMEDIA, data, cr);
866 			lwkt_serialize_exit(ifp_p->if_serializer);
867 
868 			lwkt_serialize_enter(ifp->if_serializer);
869 			/* Limit the result to the parent's current config. */
870 			if (error == 0) {
871 				struct ifmediareq *ifmr;
872 
873 				ifmr = (struct ifmediareq *) data;
874 				if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) {
875 					ifmr->ifm_count = 1;
876 					error = copyout(&ifmr->ifm_current,
877 						ifmr->ifm_ulist,
878 						sizeof(int));
879 				}
880 			}
881 		} else {
882 			error = EINVAL;
883 		}
884 		break;
885 
886 	case SIOCSIFMEDIA:
887 		error = EINVAL;
888 		break;
889 
890 	case SIOCSETVLAN:
891 		error = copyin(ifr->ifr_data, &vlr, sizeof vlr);
892 		if (error)
893 			break;
894 
895 		lwkt_serialize_exit(ifp->if_serializer);
896 		if (vlr.vlr_parent[0] == '\0')
897 			error = vlan_unconfig(ifv);
898 		else
899 			error = vlan_config(ifv, vlr.vlr_parent, vlr.vlr_tag);
900 		lwkt_serialize_enter(ifp->if_serializer);
901 		break;
902 
903 	case SIOCGETVLAN:
904 		bzero(&vlr, sizeof(vlr));
905 		if (ifv->ifv_p) {
906 			strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname,
907 			    sizeof(vlr.vlr_parent));
908 			vlr.vlr_tag = ifv->ifv_tag;
909 		}
910 		error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
911 		break;
912 
913 	case SIOCSIFFLAGS:
914 		if (ifp->if_flags & IFF_UP)
915 			ifp->if_init(ifp);
916 		else
917 			ifp->if_flags &= ~IFF_RUNNING;
918 
919 		/*
920 		 * We don't support promiscuous mode
921 		 * right now because it would require help from the
922 		 * underlying drivers, which hasn't been implemented.
923 		 */
924 		if (ifr->ifr_flags & IFF_PROMISC) {
925 			ifp->if_flags &= ~IFF_PROMISC;
926 			error = EINVAL;
927 		}
928 		break;
929 
930 	case SIOCADDMULTI:
931 	case SIOCDELMULTI:
932 		lwkt_serialize_exit(ifp->if_serializer);
933 		error = vlan_config_multi(ifv);
934 		lwkt_serialize_enter(ifp->if_serializer);
935 		break;
936 
937 	default:
938 		error = ether_ioctl(ifp, cmd, data);
939 		break;
940 	}
941 	return error;
942 }
943 
944 static void
945 vlan_multi_dispatch(struct netmsg *nmsg)
946 {
947 	struct netmsg_vlan *vmsg = (struct netmsg_vlan *)nmsg;
948 	struct ifvlan *ifv = vmsg->nv_ifv;
949 	int error = 0;
950 
951 	/*
952 	 * If we don't have a parent, just remember the membership for
953 	 * when we do.
954 	 */
955 	if (ifv->ifv_p != NULL)
956 		error = vlan_setmulti(ifv, ifv->ifv_p);
957 	lwkt_replymsg(&nmsg->nm_lmsg, error);
958 }
959 
960 static int
961 vlan_config_multi(struct ifvlan *ifv)
962 {
963 	struct netmsg_vlan vmsg;
964 	struct netmsg *nmsg;
965 
966 	ASSERT_NOT_SERIALIZED(ifv->ifv_if.if_serializer);
967 
968 	bzero(&vmsg, sizeof(vmsg));
969 	nmsg = &vmsg.nv_nmsg;
970 
971 	netmsg_init(nmsg, &curthread->td_msgport, 0, vlan_multi_dispatch);
972 	vmsg.nv_ifv = ifv;
973 
974 	return lwkt_domsg(cpu_portfn(0), &nmsg->nm_lmsg, 0);
975 }
976