if_vlan.c (215726) | if_vlan.c (219819) |
---|---|
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 --- 26 unchanged lines hidden (view full) --- 35 * to make arp work. The way we do this is by telling everyone 36 * that we are an Ethernet, and then catch the packets that 37 * ether_output() left on our output queue when it calls 38 * if_start(), rewrite them for use by the real outgoing interface, 39 * and ask it to send them. 40 */ 41 42#include <sys/cdefs.h> | 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 --- 26 unchanged lines hidden (view full) --- 35 * to make arp work. The way we do this is by telling everyone 36 * that we are an Ethernet, and then catch the packets that 37 * ether_output() left on our output queue when it calls 38 * if_start(), rewrite them for use by the real outgoing interface, 39 * and ask it to send them. 40 */ 41 42#include <sys/cdefs.h> |
43__FBSDID("$FreeBSD: head/sys/net/if_vlan.c 215726 2010-11-22 23:35:29Z zec $"); | 43__FBSDID("$FreeBSD: head/sys/net/if_vlan.c 219819 2011-03-21 09:40:01Z jeff $"); |
44 45#include "opt_vlan.h" 46 47#include <sys/param.h> 48#include <sys/kernel.h> 49#include <sys/lock.h> 50#include <sys/malloc.h> 51#include <sys/mbuf.h> 52#include <sys/module.h> 53#include <sys/rwlock.h> 54#include <sys/queue.h> 55#include <sys/socket.h> 56#include <sys/sockio.h> 57#include <sys/sysctl.h> 58#include <sys/systm.h> | 44 45#include "opt_vlan.h" 46 47#include <sys/param.h> 48#include <sys/kernel.h> 49#include <sys/lock.h> 50#include <sys/malloc.h> 51#include <sys/mbuf.h> 52#include <sys/module.h> 53#include <sys/rwlock.h> 54#include <sys/queue.h> 55#include <sys/socket.h> 56#include <sys/sockio.h> 57#include <sys/sysctl.h> 58#include <sys/systm.h> |
59#include <sys/sx.h> |
|
59 60#include <net/bpf.h> 61#include <net/ethernet.h> 62#include <net/if.h> 63#include <net/if_clone.h> 64#include <net/if_dl.h> 65#include <net/if_types.h> 66#include <net/if_vlan_var.h> --- 18 unchanged lines hidden (view full) --- 85 struct ifvlanhead *hash; /* dynamic hash-list table */ 86 uint16_t hmask; 87 uint16_t hwidth; 88#endif 89 int refcnt; 90}; 91 92struct vlan_mc_entry { | 60 61#include <net/bpf.h> 62#include <net/ethernet.h> 63#include <net/if.h> 64#include <net/if_clone.h> 65#include <net/if_dl.h> 66#include <net/if_types.h> 67#include <net/if_vlan_var.h> --- 18 unchanged lines hidden (view full) --- 86 struct ifvlanhead *hash; /* dynamic hash-list table */ 87 uint16_t hmask; 88 uint16_t hwidth; 89#endif 90 int refcnt; 91}; 92 93struct vlan_mc_entry { |
93 struct ether_addr mc_addr; | 94 struct sockaddr_dl mc_addr; |
94 SLIST_ENTRY(vlan_mc_entry) mc_entries; 95}; 96 97struct ifvlan { 98 struct ifvlantrunk *ifv_trunk; 99 struct ifnet *ifv_ifp; | 95 SLIST_ENTRY(vlan_mc_entry) mc_entries; 96}; 97 98struct ifvlan { 99 struct ifvlantrunk *ifv_trunk; 100 struct ifnet *ifv_ifp; |
101 void *ifv_cookie; |
|
100#define TRUNK(ifv) ((ifv)->ifv_trunk) 101#define PARENT(ifv) ((ifv)->ifv_trunk->parent) 102 int ifv_pflags; /* special flags we have set on parent */ 103 struct ifv_linkmib { 104 int ifvm_encaplen; /* encapsulation length */ 105 int ifvm_mtufudge; /* MTU fudged by this much */ 106 int ifvm_mintu; /* min transmission unit */ 107 uint16_t ifvm_proto; /* encapsulation ethertype */ --- 40 unchanged lines hidden (view full) --- 148 * We also have a per-trunk rwlock, that is locked shared on packet 149 * processing and exclusive when configuration is changed. 150 * 151 * The VLAN_ARRAY substitutes the dynamic hash with a static array 152 * with 4096 entries. In theory this can give a boost in processing, 153 * however on practice it does not. Probably this is because array 154 * is too big to fit into CPU cache. 155 */ | 102#define TRUNK(ifv) ((ifv)->ifv_trunk) 103#define PARENT(ifv) ((ifv)->ifv_trunk->parent) 104 int ifv_pflags; /* special flags we have set on parent */ 105 struct ifv_linkmib { 106 int ifvm_encaplen; /* encapsulation length */ 107 int ifvm_mtufudge; /* MTU fudged by this much */ 108 int ifvm_mintu; /* min transmission unit */ 109 uint16_t ifvm_proto; /* encapsulation ethertype */ --- 40 unchanged lines hidden (view full) --- 150 * We also have a per-trunk rwlock, that is locked shared on packet 151 * processing and exclusive when configuration is changed. 152 * 153 * The VLAN_ARRAY substitutes the dynamic hash with a static array 154 * with 4096 entries. In theory this can give a boost in processing, 155 * however on practice it does not. Probably this is because array 156 * is too big to fit into CPU cache. 157 */ |
156static struct mtx ifv_mtx; 157#define VLAN_LOCK_INIT() mtx_init(&ifv_mtx, "vlan_global", NULL, MTX_DEF) 158#define VLAN_LOCK_DESTROY() mtx_destroy(&ifv_mtx) 159#define VLAN_LOCK_ASSERT() mtx_assert(&ifv_mtx, MA_OWNED) 160#define VLAN_LOCK() mtx_lock(&ifv_mtx) 161#define VLAN_UNLOCK() mtx_unlock(&ifv_mtx) | 158static struct sx ifv_lock; 159#define VLAN_LOCK_INIT() sx_init(&ifv_lock, "vlan_global") 160#define VLAN_LOCK_DESTROY() sx_destroy(&ifv_lock) 161#define VLAN_LOCK_ASSERT() sx_assert(&ifv_lock, SA_LOCKED) 162#define VLAN_LOCK() sx_xlock(&ifv_lock) 163#define VLAN_UNLOCK() sx_xunlock(&ifv_lock) |
162#define TRUNK_LOCK_INIT(trunk) rw_init(&(trunk)->rw, VLANNAME) 163#define TRUNK_LOCK_DESTROY(trunk) rw_destroy(&(trunk)->rw) 164#define TRUNK_LOCK(trunk) rw_wlock(&(trunk)->rw) 165#define TRUNK_UNLOCK(trunk) rw_wunlock(&(trunk)->rw) 166#define TRUNK_LOCK_ASSERT(trunk) rw_assert(&(trunk)->rw, RA_WLOCKED) 167#define TRUNK_RLOCK(trunk) rw_rlock(&(trunk)->rw) 168#define TRUNK_RUNLOCK(trunk) rw_runlock(&(trunk)->rw) 169#define TRUNK_LOCK_RASSERT(trunk) rw_assert(&(trunk)->rw, RA_RLOCKED) --- 211 unchanged lines hidden (view full) --- 381 for (i = 0; i < (1 << trunk->hwidth); i++) { 382 printf("%d: ", i); 383 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list) 384 printf("%s ", ifv->ifv_ifp->if_xname); 385 printf("\n"); 386 } 387} 388#endif /* 0 */ | 164#define TRUNK_LOCK_INIT(trunk) rw_init(&(trunk)->rw, VLANNAME) 165#define TRUNK_LOCK_DESTROY(trunk) rw_destroy(&(trunk)->rw) 166#define TRUNK_LOCK(trunk) rw_wlock(&(trunk)->rw) 167#define TRUNK_UNLOCK(trunk) rw_wunlock(&(trunk)->rw) 168#define TRUNK_LOCK_ASSERT(trunk) rw_assert(&(trunk)->rw, RA_WLOCKED) 169#define TRUNK_RLOCK(trunk) rw_rlock(&(trunk)->rw) 170#define TRUNK_RUNLOCK(trunk) rw_runlock(&(trunk)->rw) 171#define TRUNK_LOCK_RASSERT(trunk) rw_assert(&(trunk)->rw, RA_RLOCKED) --- 211 unchanged lines hidden (view full) --- 383 for (i = 0; i < (1 << trunk->hwidth); i++) { 384 printf("%d: ", i); 385 LIST_FOREACH(ifv, &trunk->hash[i], ifv_list) 386 printf("%s ", ifv->ifv_ifp->if_xname); 387 printf("\n"); 388 } 389} 390#endif /* 0 */ |
391#else 392 393static __inline struct ifvlan * 394vlan_gethash(struct ifvlantrunk *trunk, uint16_t tag) 395{ 396 397 return trunk->vlans[tag]; 398} 399 400static __inline int 401vlan_inshash(struct ifvlantrunk *trunk, struct ifvlan *ifv) 402{ 403 404 if (trunk->vlans[ifv->ifv_tag] != NULL) 405 return EEXIST; 406 trunk->vlans[ifv->ifv_tag] = ifv; 407 trunk->refcnt++; 408 409 return (0); 410} 411 412static __inline int 413vlan_remhash(struct ifvlantrunk *trunk, struct ifvlan *ifv) 414{ 415 416 trunk->vlans[ifv->ifv_tag] = NULL; 417 trunk->refcnt--; 418 419 return (0); 420} 421 422static __inline void 423vlan_freehash(struct ifvlantrunk *trunk) 424{ 425} 426 427static __inline void 428vlan_inithash(struct ifvlantrunk *trunk) 429{ 430} 431 |
|
389#endif /* !VLAN_ARRAY */ 390 391static void 392trunk_destroy(struct ifvlantrunk *trunk) 393{ 394 VLAN_LOCK_ASSERT(); 395 396 TRUNK_LOCK(trunk); | 432#endif /* !VLAN_ARRAY */ 433 434static void 435trunk_destroy(struct ifvlantrunk *trunk) 436{ 437 VLAN_LOCK_ASSERT(); 438 439 TRUNK_LOCK(trunk); |
397#ifndef VLAN_ARRAY | |
398 vlan_freehash(trunk); | 440 vlan_freehash(trunk); |
399#endif | |
400 trunk->parent->if_vlantrunk = NULL; 401 TRUNK_UNLOCK(trunk); 402 TRUNK_LOCK_DESTROY(trunk); 403 free(trunk, M_VLAN); 404} 405 406/* 407 * Program our multicast filter. What we're actually doing is --- 8 unchanged lines hidden (view full) --- 416 */ 417static int 418vlan_setmulti(struct ifnet *ifp) 419{ 420 struct ifnet *ifp_p; 421 struct ifmultiaddr *ifma, *rifma = NULL; 422 struct ifvlan *sc; 423 struct vlan_mc_entry *mc; | 441 trunk->parent->if_vlantrunk = NULL; 442 TRUNK_UNLOCK(trunk); 443 TRUNK_LOCK_DESTROY(trunk); 444 free(trunk, M_VLAN); 445} 446 447/* 448 * Program our multicast filter. What we're actually doing is --- 8 unchanged lines hidden (view full) --- 457 */ 458static int 459vlan_setmulti(struct ifnet *ifp) 460{ 461 struct ifnet *ifp_p; 462 struct ifmultiaddr *ifma, *rifma = NULL; 463 struct ifvlan *sc; 464 struct vlan_mc_entry *mc; |
424 struct sockaddr_dl sdl; | |
425 int error; 426 427 /*VLAN_LOCK_ASSERT();*/ 428 429 /* Find the parent. */ 430 sc = ifp->if_softc; 431 ifp_p = PARENT(sc); 432 433 CURVNET_SET_QUIET(ifp_p->if_vnet); 434 | 465 int error; 466 467 /*VLAN_LOCK_ASSERT();*/ 468 469 /* Find the parent. */ 470 sc = ifp->if_softc; 471 ifp_p = PARENT(sc); 472 473 CURVNET_SET_QUIET(ifp_p->if_vnet); 474 |
435 bzero((char *)&sdl, sizeof(sdl)); 436 sdl.sdl_len = sizeof(sdl); 437 sdl.sdl_family = AF_LINK; 438 sdl.sdl_index = ifp_p->if_index; 439 sdl.sdl_type = IFT_ETHER; 440 sdl.sdl_alen = ETHER_ADDR_LEN; 441 | |
442 /* First, remove any existing filter entries. */ 443 while ((mc = SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) { | 475 /* First, remove any existing filter entries. */ 476 while ((mc = SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) { |
444 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN); 445 error = if_delmulti(ifp_p, (struct sockaddr *)&sdl); | 477 error = if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr); |
446 if (error) 447 return (error); 448 SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); 449 free(mc, M_VLAN); 450 } 451 452 /* Now program new ones. */ 453 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 454 if (ifma->ifma_addr->sa_family != AF_LINK) 455 continue; 456 mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); 457 if (mc == NULL) 458 return (ENOMEM); | 478 if (error) 479 return (error); 480 SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); 481 free(mc, M_VLAN); 482 } 483 484 /* Now program new ones. */ 485 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 486 if (ifma->ifma_addr->sa_family != AF_LINK) 487 continue; 488 mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); 489 if (mc == NULL) 490 return (ENOMEM); |
459 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 460 (char *)&mc->mc_addr, ETHER_ADDR_LEN); | 491 bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len); 492 mc->mc_addr.sdl_index = ifp_p->if_index; |
461 SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); | 493 SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); |
462 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 463 LLADDR(&sdl), ETHER_ADDR_LEN); 464 error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma); | 494 error = if_addmulti(ifp_p, (struct sockaddr *)&mc->mc_addr, 495 &rifma); |
465 if (error) 466 return (error); 467 } 468 469 CURVNET_RESTORE(); 470 return (0); 471} 472 --- 25 unchanged lines hidden (view full) --- 498#ifdef VLAN_ARRAY 499 for (i = 0; i < VLAN_ARRAY_SIZE; i++) 500 if ((ifv = ifp->if_vlantrunk->vlans[i])) { 501#else /* VLAN_ARRAY */ 502 for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++) 503 LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) { 504#endif /* VLAN_ARRAY */ 505 VLAN_UNLOCK(); | 496 if (error) 497 return (error); 498 } 499 500 CURVNET_RESTORE(); 501 return (0); 502} 503 --- 25 unchanged lines hidden (view full) --- 529#ifdef VLAN_ARRAY 530 for (i = 0; i < VLAN_ARRAY_SIZE; i++) 531 if ((ifv = ifp->if_vlantrunk->vlans[i])) { 532#else /* VLAN_ARRAY */ 533 for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++) 534 LIST_FOREACH_SAFE(ifv, &ifp->if_vlantrunk->hash[i], ifv_list, next) { 535#endif /* VLAN_ARRAY */ 536 VLAN_UNLOCK(); |
506 if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), ETHER_ADDR_LEN); | 537 if_setlladdr(ifv->ifv_ifp, IF_LLADDR(ifp), 538 ifp->if_addrlen); |
507 VLAN_LOCK(); 508 } 509 VLAN_UNLOCK(); 510 511} 512 513/* 514 * A handler for network interface departure events. --- 44 unchanged lines hidden (view full) --- 559 } 560#endif /* VLAN_ARRAY */ 561 /* Trunk should have been destroyed in vlan_unconfig(). */ 562 KASSERT(ifp->if_vlantrunk == NULL, ("%s: purge failed", __func__)); 563 VLAN_UNLOCK(); 564} 565 566/* | 539 VLAN_LOCK(); 540 } 541 VLAN_UNLOCK(); 542 543} 544 545/* 546 * A handler for network interface departure events. --- 44 unchanged lines hidden (view full) --- 591 } 592#endif /* VLAN_ARRAY */ 593 /* Trunk should have been destroyed in vlan_unconfig(). */ 594 KASSERT(ifp->if_vlantrunk == NULL, ("%s: purge failed", __func__)); 595 VLAN_UNLOCK(); 596} 597 598/* |
599 * Return the trunk device for a virtual interface. 600 */ 601static struct ifnet * 602vlan_trunkdev(struct ifnet *ifp) 603{ 604 struct ifvlan *ifv; 605 606 if (ifp->if_type != IFT_L2VLAN) 607 return (NULL); 608 ifv = ifp->if_softc; 609 ifp = NULL; 610 VLAN_LOCK(); 611 if (ifv->ifv_trunk) 612 ifp = PARENT(ifv); 613 VLAN_UNLOCK(); 614 return (ifp); 615} 616 617/* 618 * Return the 16bit vlan tag for this interface. 619 */ 620static int 621vlan_tag(struct ifnet *ifp, uint16_t *tagp) 622{ 623 struct ifvlan *ifv; 624 625 if (ifp->if_type != IFT_L2VLAN) 626 return (EINVAL); 627 ifv = ifp->if_softc; 628 *tagp = ifv->ifv_tag; 629 return (0); 630} 631 632/* 633 * Return a driver specific cookie for this interface. Synchronization 634 * with setcookie must be provided by the driver. 635 */ 636static void * 637vlan_cookie(struct ifnet *ifp) 638{ 639 struct ifvlan *ifv; 640 641 if (ifp->if_type != IFT_L2VLAN) 642 return (NULL); 643 ifv = ifp->if_softc; 644 return (ifv->ifv_cookie); 645} 646 647/* 648 * Store a cookie in our softc that drivers can use to store driver 649 * private per-instance data in. 650 */ 651static int 652vlan_setcookie(struct ifnet *ifp, void *cookie) 653{ 654 struct ifvlan *ifv; 655 656 if (ifp->if_type != IFT_L2VLAN) 657 return (EINVAL); 658 ifv = ifp->if_softc; 659 ifv->ifv_cookie = cookie; 660 return (0); 661} 662 663/* 664 * Return the vlan device present at the specific tag. 665 */ 666static struct ifnet * 667vlan_devat(struct ifnet *ifp, uint16_t tag) 668{ 669 struct ifvlantrunk *trunk; 670 struct ifvlan *ifv; 671 672 trunk = ifp->if_vlantrunk; 673 if (trunk == NULL) 674 return (NULL); 675 ifp = NULL; 676 TRUNK_RLOCK(trunk); 677 ifv = vlan_gethash(trunk, tag); 678 if (ifv) 679 ifp = ifv->ifv_ifp; 680 TRUNK_RUNLOCK(trunk); 681 return (ifp); 682} 683 684/* |
|
567 * VLAN support can be loaded as a module. The only place in the 568 * system that's intimately aware of this is ether_input. We hook 569 * into this code through vlan_input_p which is defined there and 570 * set here. Noone else in the system should be aware of this so 571 * we use an explicit reference here. 572 */ 573extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); 574 --- 13 unchanged lines hidden (view full) --- 588 iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, 589 vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); 590 if (iflladdr_tag == NULL) 591 return (ENOMEM); 592 VLAN_LOCK_INIT(); 593 vlan_input_p = vlan_input; 594 vlan_link_state_p = vlan_link_state; 595 vlan_trunk_cap_p = vlan_trunk_capabilities; | 685 * VLAN support can be loaded as a module. The only place in the 686 * system that's intimately aware of this is ether_input. We hook 687 * into this code through vlan_input_p which is defined there and 688 * set here. Noone else in the system should be aware of this so 689 * we use an explicit reference here. 690 */ 691extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); 692 --- 13 unchanged lines hidden (view full) --- 706 iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, 707 vlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); 708 if (iflladdr_tag == NULL) 709 return (ENOMEM); 710 VLAN_LOCK_INIT(); 711 vlan_input_p = vlan_input; 712 vlan_link_state_p = vlan_link_state; 713 vlan_trunk_cap_p = vlan_trunk_capabilities; |
714 vlan_trunkdev_p = vlan_trunkdev; 715 vlan_cookie_p = vlan_cookie; 716 vlan_setcookie_p = vlan_setcookie; 717 vlan_tag_p = vlan_tag; 718 vlan_devat_p = vlan_devat; |
|
596#ifndef VIMAGE 597 if_clone_attach(&vlan_cloner); 598#endif 599 if (bootverbose) 600 printf("vlan: initialized, using " 601#ifdef VLAN_ARRAY 602 "full-size arrays" 603#else --- 6 unchanged lines hidden (view full) --- 610#ifndef VIMAGE 611 if_clone_detach(&vlan_cloner); 612#endif 613 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag); 614 EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag); 615 vlan_input_p = NULL; 616 vlan_link_state_p = NULL; 617 vlan_trunk_cap_p = NULL; | 719#ifndef VIMAGE 720 if_clone_attach(&vlan_cloner); 721#endif 722 if (bootverbose) 723 printf("vlan: initialized, using " 724#ifdef VLAN_ARRAY 725 "full-size arrays" 726#else --- 6 unchanged lines hidden (view full) --- 733#ifndef VIMAGE 734 if_clone_detach(&vlan_cloner); 735#endif 736 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag); 737 EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag); 738 vlan_input_p = NULL; 739 vlan_link_state_p = NULL; 740 vlan_trunk_cap_p = NULL; |
741 vlan_trunkdev_p = NULL; 742 vlan_tag_p = NULL; 743 vlan_cookie_p = vlan_cookie; 744 vlan_setcookie_p = vlan_setcookie; 745 vlan_devat_p = NULL; |
|
618 VLAN_LOCK_DESTROY(); 619 if (bootverbose) 620 printf("vlan: unloaded\n"); 621 break; 622 default: 623 return (EOPNOTSUPP); 624 } 625 return (0); --- 34 unchanged lines hidden (view full) --- 660{ 661 const char *cp; 662 struct ifnet *ifp; 663 int t; 664 665 /* Check for <etherif>.<vlan> style interface names. */ 666 IFNET_RLOCK_NOSLEEP(); 667 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { | 746 VLAN_LOCK_DESTROY(); 747 if (bootverbose) 748 printf("vlan: unloaded\n"); 749 break; 750 default: 751 return (EOPNOTSUPP); 752 } 753 return (0); --- 34 unchanged lines hidden (view full) --- 788{ 789 const char *cp; 790 struct ifnet *ifp; 791 int t; 792 793 /* Check for <etherif>.<vlan> style interface names. */ 794 IFNET_RLOCK_NOSLEEP(); 795 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { |
668 if (ifp->if_type != IFT_ETHER) | 796 /* 797 * We can handle non-ethernet hardware types as long as 798 * they handle the tagging and headers themselves. 799 */ 800 if (ifp->if_type != IFT_ETHER && 801 (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) |
669 continue; 670 if (strncmp(ifp->if_xname, name, strlen(ifp->if_xname)) != 0) 671 continue; 672 cp = name + strlen(ifp->if_xname); 673 if (*cp++ != '.') 674 continue; 675 if (*cp == '\0') 676 continue; --- 234 unchanged lines hidden (view full) --- 911 * bridges that violate paragraph C.4.4.3.a from the same 912 * document, i.e., fail to pad short frames after untagging. 913 * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but 914 * untagging it will produce a 62-byte frame, which is a runt 915 * and requires padding. There are VLAN-enabled network 916 * devices that just discard such runts instead or mishandle 917 * them somehow. 918 */ | 802 continue; 803 if (strncmp(ifp->if_xname, name, strlen(ifp->if_xname)) != 0) 804 continue; 805 cp = name + strlen(ifp->if_xname); 806 if (*cp++ != '.') 807 continue; 808 if (*cp == '\0') 809 continue; --- 234 unchanged lines hidden (view full) --- 1044 * bridges that violate paragraph C.4.4.3.a from the same 1045 * document, i.e., fail to pad short frames after untagging. 1046 * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but 1047 * untagging it will produce a 62-byte frame, which is a runt 1048 * and requires padding. There are VLAN-enabled network 1049 * devices that just discard such runts instead or mishandle 1050 * them somehow. 1051 */ |
919 if (soft_pad) { | 1052 if (soft_pad && p->if_type == IFT_ETHER) { |
920 static char pad[8]; /* just zeros */ 921 int n; 922 923 for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len; 924 n > 0; n -= sizeof(pad)) 925 if (!m_append(m, min(n, sizeof(pad)), pad)) 926 break; 927 --- 87 unchanged lines hidden (view full) --- 1015#endif 1016 m_freem(m); 1017 ifp->if_noproto++; 1018 return; 1019 } 1020 } 1021 1022 TRUNK_RLOCK(trunk); | 1053 static char pad[8]; /* just zeros */ 1054 int n; 1055 1056 for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len; 1057 n > 0; n -= sizeof(pad)) 1058 if (!m_append(m, min(n, sizeof(pad)), pad)) 1059 break; 1060 --- 87 unchanged lines hidden (view full) --- 1148#endif 1149 m_freem(m); 1150 ifp->if_noproto++; 1151 return; 1152 } 1153 } 1154 1155 TRUNK_RLOCK(trunk); |
1023#ifdef VLAN_ARRAY 1024 ifv = trunk->vlans[tag]; 1025#else | |
1026 ifv = vlan_gethash(trunk, tag); | 1156 ifv = vlan_gethash(trunk, tag); |
1027#endif | |
1028 if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) { 1029 TRUNK_RUNLOCK(trunk); 1030 m_freem(m); 1031 ifp->if_noproto++; 1032 return; 1033 } 1034 TRUNK_RUNLOCK(trunk); 1035 --- 9 unchanged lines hidden (view full) --- 1045{ 1046 struct ifvlantrunk *trunk; 1047 struct ifnet *ifp; 1048 int error = 0; 1049 1050 /* VID numbers 0x0 and 0xFFF are reserved */ 1051 if (tag == 0 || tag == 0xFFF) 1052 return (EINVAL); | 1157 if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) { 1158 TRUNK_RUNLOCK(trunk); 1159 m_freem(m); 1160 ifp->if_noproto++; 1161 return; 1162 } 1163 TRUNK_RUNLOCK(trunk); 1164 --- 9 unchanged lines hidden (view full) --- 1174{ 1175 struct ifvlantrunk *trunk; 1176 struct ifnet *ifp; 1177 int error = 0; 1178 1179 /* VID numbers 0x0 and 0xFFF are reserved */ 1180 if (tag == 0 || tag == 0xFFF) 1181 return (EINVAL); |
1053 if (p->if_type != IFT_ETHER) | 1182 if (p->if_type != IFT_ETHER && 1183 (p->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) |
1054 return (EPROTONOSUPPORT); 1055 if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS) 1056 return (EPROTONOSUPPORT); 1057 if (ifv->ifv_trunk) 1058 return (EBUSY); 1059 1060 if (p->if_vlantrunk == NULL) { 1061 trunk = malloc(sizeof(struct ifvlantrunk), 1062 M_VLAN, M_WAITOK | M_ZERO); | 1184 return (EPROTONOSUPPORT); 1185 if ((p->if_flags & VLAN_IFFLAGS) != VLAN_IFFLAGS) 1186 return (EPROTONOSUPPORT); 1187 if (ifv->ifv_trunk) 1188 return (EBUSY); 1189 1190 if (p->if_vlantrunk == NULL) { 1191 trunk = malloc(sizeof(struct ifvlantrunk), 1192 M_VLAN, M_WAITOK | M_ZERO); |
1063#ifndef VLAN_ARRAY | |
1064 vlan_inithash(trunk); | 1193 vlan_inithash(trunk); |
1065#endif | |
1066 VLAN_LOCK(); 1067 if (p->if_vlantrunk != NULL) { 1068 /* A race that that is very unlikely to be hit. */ | 1194 VLAN_LOCK(); 1195 if (p->if_vlantrunk != NULL) { 1196 /* A race that that is very unlikely to be hit. */ |
1069#ifndef VLAN_ARRAY | |
1070 vlan_freehash(trunk); | 1197 vlan_freehash(trunk); |
1071#endif | |
1072 free(trunk, M_VLAN); 1073 goto exists; 1074 } 1075 TRUNK_LOCK_INIT(trunk); 1076 TRUNK_LOCK(trunk); 1077 p->if_vlantrunk = trunk; 1078 trunk->parent = p; 1079 } else { 1080 VLAN_LOCK(); 1081exists: 1082 trunk = p->if_vlantrunk; 1083 TRUNK_LOCK(trunk); 1084 } 1085 1086 ifv->ifv_tag = tag; /* must set this before vlan_inshash() */ | 1198 free(trunk, M_VLAN); 1199 goto exists; 1200 } 1201 TRUNK_LOCK_INIT(trunk); 1202 TRUNK_LOCK(trunk); 1203 p->if_vlantrunk = trunk; 1204 trunk->parent = p; 1205 } else { 1206 VLAN_LOCK(); 1207exists: 1208 trunk = p->if_vlantrunk; 1209 TRUNK_LOCK(trunk); 1210 } 1211 1212 ifv->ifv_tag = tag; /* must set this before vlan_inshash() */ |
1087#ifdef VLAN_ARRAY 1088 if (trunk->vlans[tag] != NULL) { 1089 error = EEXIST; 1090 goto done; 1091 } 1092 trunk->vlans[tag] = ifv; 1093 trunk->refcnt++; 1094#else | |
1095 error = vlan_inshash(trunk, ifv); 1096 if (error) 1097 goto done; | 1213 error = vlan_inshash(trunk, ifv); 1214 if (error) 1215 goto done; |
1098#endif | |
1099 ifv->ifv_proto = ETHERTYPE_VLAN; 1100 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 1101 ifv->ifv_mintu = ETHERMIN; 1102 ifv->ifv_pflags = 0; 1103 1104 /* 1105 * If the parent supports the VLAN_MTU capability, 1106 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, --- 13 unchanged lines hidden (view full) --- 1120 * the feature with other NetBSD implementations, 1121 * which might still be useful. 1122 */ 1123 ifv->ifv_mtufudge = ifv->ifv_encaplen; 1124 } 1125 1126 ifv->ifv_trunk = trunk; 1127 ifp = ifv->ifv_ifp; | 1216 ifv->ifv_proto = ETHERTYPE_VLAN; 1217 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; 1218 ifv->ifv_mintu = ETHERMIN; 1219 ifv->ifv_pflags = 0; 1220 1221 /* 1222 * If the parent supports the VLAN_MTU capability, 1223 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, --- 13 unchanged lines hidden (view full) --- 1237 * the feature with other NetBSD implementations, 1238 * which might still be useful. 1239 */ 1240 ifv->ifv_mtufudge = ifv->ifv_encaplen; 1241 } 1242 1243 ifv->ifv_trunk = trunk; 1244 ifp = ifv->ifv_ifp; |
1245 /* 1246 * Initialize fields from our parent. This duplicates some 1247 * work with ether_ifattach() but allows for non-ethernet 1248 * interfaces to also work. 1249 */ |
|
1128 ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge; 1129 ifp->if_baudrate = p->if_baudrate; | 1250 ifp->if_mtu = p->if_mtu - ifv->ifv_mtufudge; 1251 ifp->if_baudrate = p->if_baudrate; |
1252 ifp->if_output = p->if_output; 1253 ifp->if_input = p->if_input; 1254 ifp->if_resolvemulti = p->if_resolvemulti; 1255 ifp->if_addrlen = p->if_addrlen; 1256 ifp->if_broadcastaddr = p->if_broadcastaddr; 1257 |
|
1130 /* 1131 * Copy only a selected subset of flags from the parent. 1132 * Other flags are none of our business. 1133 */ 1134#define VLAN_COPY_FLAGS (IFF_SIMPLEX) 1135 ifp->if_flags &= ~VLAN_COPY_FLAGS; 1136 ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS; 1137#undef VLAN_COPY_FLAGS 1138 1139 ifp->if_link_state = p->if_link_state; 1140 1141 vlan_capabilities(ifv); 1142 1143 /* | 1258 /* 1259 * Copy only a selected subset of flags from the parent. 1260 * Other flags are none of our business. 1261 */ 1262#define VLAN_COPY_FLAGS (IFF_SIMPLEX) 1263 ifp->if_flags &= ~VLAN_COPY_FLAGS; 1264 ifp->if_flags |= p->if_flags & VLAN_COPY_FLAGS; 1265#undef VLAN_COPY_FLAGS 1266 1267 ifp->if_link_state = p->if_link_state; 1268 1269 vlan_capabilities(ifv); 1270 1271 /* |
1144 * Set up our ``Ethernet address'' to reflect the underlying | 1272 * Set up our interface address to reflect the underlying |
1145 * physical interface's. 1146 */ | 1273 * physical interface's. 1274 */ |
1147 bcopy(IF_LLADDR(p), IF_LLADDR(ifp), ETHER_ADDR_LEN); | 1275 bcopy(IF_LLADDR(p), IF_LLADDR(ifp), p->if_addrlen); 1276 ((struct sockaddr_dl *)ifp->if_addr->ifa_addr)->sdl_alen = 1277 p->if_addrlen; |
1148 1149 /* 1150 * Configure multicast addresses that may already be 1151 * joined on the vlan device. 1152 */ 1153 (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */ 1154 1155 /* We are ready for operation now. */ --- 26 unchanged lines hidden (view full) --- 1182 1183 VLAN_LOCK_ASSERT(); 1184 1185 ifv = ifp->if_softc; 1186 trunk = ifv->ifv_trunk; 1187 parent = NULL; 1188 1189 if (trunk != NULL) { | 1278 1279 /* 1280 * Configure multicast addresses that may already be 1281 * joined on the vlan device. 1282 */ 1283 (void)vlan_setmulti(ifp); /* XXX: VLAN lock held */ 1284 1285 /* We are ready for operation now. */ --- 26 unchanged lines hidden (view full) --- 1312 1313 VLAN_LOCK_ASSERT(); 1314 1315 ifv = ifp->if_softc; 1316 trunk = ifv->ifv_trunk; 1317 parent = NULL; 1318 1319 if (trunk != NULL) { |
1190 struct sockaddr_dl sdl; | |
1191 1192 TRUNK_LOCK(trunk); 1193 parent = trunk->parent; 1194 1195 /* 1196 * Since the interface is being unconfigured, we need to 1197 * empty the list of multicast groups that we may have joined 1198 * while we were alive from the parent's list. 1199 */ | 1320 1321 TRUNK_LOCK(trunk); 1322 parent = trunk->parent; 1323 1324 /* 1325 * Since the interface is being unconfigured, we need to 1326 * empty the list of multicast groups that we may have joined 1327 * while we were alive from the parent's list. 1328 */ |
1200 bzero((char *)&sdl, sizeof(sdl)); 1201 sdl.sdl_len = sizeof(sdl); 1202 sdl.sdl_family = AF_LINK; 1203 sdl.sdl_index = parent->if_index; 1204 sdl.sdl_type = IFT_ETHER; 1205 sdl.sdl_alen = ETHER_ADDR_LEN; 1206 | |
1207 while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) { | 1329 while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) { |
1208 bcopy((char *)&mc->mc_addr, LLADDR(&sdl), 1209 ETHER_ADDR_LEN); 1210 | |
1211 /* 1212 * This may fail if the parent interface is 1213 * being detached. Regardless, we should do a 1214 * best effort to free this interface as much 1215 * as possible as all callers expect vlan 1216 * destruction to succeed. 1217 */ | 1330 /* 1331 * This may fail if the parent interface is 1332 * being detached. Regardless, we should do a 1333 * best effort to free this interface as much 1334 * as possible as all callers expect vlan 1335 * destruction to succeed. 1336 */ |
1218 (void)if_delmulti(parent, (struct sockaddr *)&sdl); | 1337 (void)if_delmulti(parent, 1338 (struct sockaddr *)&mc->mc_addr); |
1219 SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); 1220 free(mc, M_VLAN); 1221 } 1222 1223 vlan_setflags(ifp, 0); /* clear special flags on parent */ | 1339 SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries); 1340 free(mc, M_VLAN); 1341 } 1342 1343 vlan_setflags(ifp, 0); /* clear special flags on parent */ |
1224#ifdef VLAN_ARRAY 1225 trunk->vlans[ifv->ifv_tag] = NULL; 1226 trunk->refcnt--; 1227#else | |
1228 vlan_remhash(trunk, ifv); | 1344 vlan_remhash(trunk, ifv); |
1229#endif | |
1230 ifv->ifv_trunk = NULL; 1231 1232 /* 1233 * Check if we were the last. 1234 */ 1235 if (trunk->refcnt == 0) { 1236 trunk->parent->if_vlantrunk = NULL; 1237 /* --- 164 unchanged lines hidden (view full) --- 1402 TRUNK_UNLOCK(trunk); 1403} 1404 1405static int 1406vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1407{ 1408 struct ifnet *p; 1409 struct ifreq *ifr; | 1345 ifv->ifv_trunk = NULL; 1346 1347 /* 1348 * Check if we were the last. 1349 */ 1350 if (trunk->refcnt == 0) { 1351 trunk->parent->if_vlantrunk = NULL; 1352 /* --- 164 unchanged lines hidden (view full) --- 1517 TRUNK_UNLOCK(trunk); 1518} 1519 1520static int 1521vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1522{ 1523 struct ifnet *p; 1524 struct ifreq *ifr; |
1525 struct ifaddr *ifa; |
|
1410 struct ifvlan *ifv; 1411 struct vlanreq vlr; 1412 int error = 0; 1413 1414 ifr = (struct ifreq *)data; | 1526 struct ifvlan *ifv; 1527 struct vlanreq vlr; 1528 int error = 0; 1529 1530 ifr = (struct ifreq *)data; |
1531 ifa = (struct ifaddr *) data; |
|
1415 ifv = ifp->if_softc; 1416 1417 switch (cmd) { | 1532 ifv = ifp->if_softc; 1533 1534 switch (cmd) { |
1535 case SIOCSIFADDR: 1536 ifp->if_flags |= IFF_UP; 1537#ifdef INET 1538 if (ifa->ifa_addr->sa_family == AF_INET) 1539 arp_ifinit(ifp, ifa); 1540#endif 1541 break; 1542 case SIOCGIFADDR: 1543 { 1544 struct sockaddr *sa; 1545 1546 sa = (struct sockaddr *)&ifr->ifr_data; 1547 bcopy(IF_LLADDR(ifp), sa->sa_data, ifp->if_addrlen); 1548 } 1549 break; |
|
1418 case SIOCGIFMEDIA: 1419 VLAN_LOCK(); 1420 if (TRUNK(ifv) != NULL) { 1421 p = PARENT(ifv); 1422 VLAN_UNLOCK(); 1423 error = (*p->if_ioctl)(p, SIOCGIFMEDIA, data); 1424 /* Limit the result to the parent's current config. */ 1425 if (error == 0) { --- 103 unchanged lines hidden (view full) --- 1529 * If we don't have a parent, just remember the membership for 1530 * when we do. 1531 */ 1532 if (TRUNK(ifv) != NULL) 1533 error = vlan_setmulti(ifp); 1534 break; 1535 1536 default: | 1550 case SIOCGIFMEDIA: 1551 VLAN_LOCK(); 1552 if (TRUNK(ifv) != NULL) { 1553 p = PARENT(ifv); 1554 VLAN_UNLOCK(); 1555 error = (*p->if_ioctl)(p, SIOCGIFMEDIA, data); 1556 /* Limit the result to the parent's current config. */ 1557 if (error == 0) { --- 103 unchanged lines hidden (view full) --- 1661 * If we don't have a parent, just remember the membership for 1662 * when we do. 1663 */ 1664 if (TRUNK(ifv) != NULL) 1665 error = vlan_setmulti(ifp); 1666 break; 1667 1668 default: |
1537 error = ether_ioctl(ifp, cmd, data); | 1669 error = EINVAL; 1670 break; |
1538 } 1539 1540 return (error); 1541} | 1671 } 1672 1673 return (error); 1674} |