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