Deleted Added
full compact
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}