diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2020-10-21 21:28:20 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2020-10-21 21:28:20 +0000 |
commit | c7cffd65c5d858425e90b847d2e8e583e3b13bf7 (patch) | |
tree | 43a36ae6b443b446902f50162ee514f2429996e8 /sbin/ifconfig/ifclone.c | |
parent | 37d411338e9de344d53ea7d55c4f886978bd8171 (diff) |
Add support for stacked VLANs (IEEE 802.1ad, AKA Q-in-Q).
802.1ad interfaces are created with ifconfig using the "vlanproto" parameter.
Eg., the following creates a 802.1Q VLAN (id #42) over a 802.1ad S-VLAN
(id #5) over a physical Ethernet interface (em0).
ifconfig vlan5 create vlandev em0 vlan 5 vlanproto 802.1ad up
ifconfig vlan42 create vlandev vlan5 vlan 42 inet 10.5.42.1/24
VLAN_MTU, VLAN_HWCSUM and VLAN_TSO capabilities should be properly
supported. VLAN_HWTAGGING is only partially supported, as there is
currently no IFCAP_VLAN_* denoting the possibility to set the VLAN
EtherType to anything else than 0x8100 (802.1ad uses 0x88A8).
Submitted by: Olivier Piras
Sponsored by: RG Nets
Differential Revision: https://reviews.freebsd.org/D26436
Notes
Notes:
svn path=/head/; revision=366917
Diffstat (limited to 'sbin/ifconfig/ifclone.c')
-rw-r--r-- | sbin/ifconfig/ifclone.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c index 134bb0af3efa..58bc3b3103ee 100644 --- a/sbin/ifconfig/ifclone.c +++ b/sbin/ifconfig/ifclone.c @@ -49,6 +49,11 @@ static const char rcsid[] = #include "ifconfig.h" +typedef enum { + MT_PREFIX, + MT_FILTER, +} clone_match_type; + static void list_cloners(void) { @@ -76,7 +81,11 @@ list_cloners(void) } struct clone_defcb { - char ifprefix[IFNAMSIZ]; + union { + char ifprefix[IFNAMSIZ]; + clone_match_func *ifmatch; + }; + clone_match_type clone_mt; clone_callback_func *clone_cb; SLIST_ENTRY(clone_defcb) next; }; @@ -85,12 +94,25 @@ static SLIST_HEAD(, clone_defcb) clone_defcbh = SLIST_HEAD_INITIALIZER(clone_defcbh); void -clone_setdefcallback(const char *ifprefix, clone_callback_func *p) +clone_setdefcallback_prefix(const char *ifprefix, clone_callback_func *p) { struct clone_defcb *dcp; dcp = malloc(sizeof(*dcp)); strlcpy(dcp->ifprefix, ifprefix, IFNAMSIZ-1); + dcp->clone_mt = MT_PREFIX; + dcp->clone_cb = p; + SLIST_INSERT_HEAD(&clone_defcbh, dcp, next); +} + +void +clone_setdefcallback_filter(clone_match_func *filter, clone_callback_func *p) +{ + struct clone_defcb *dcp; + + dcp = malloc(sizeof(*dcp)); + dcp->ifmatch = filter; + dcp->clone_mt = MT_FILTER; dcp->clone_cb = p; SLIST_INSERT_HEAD(&clone_defcbh, dcp, next); } @@ -114,8 +136,14 @@ ifclonecreate(int s, void *arg) if (clone_cb == NULL) { /* Try to find a default callback */ SLIST_FOREACH(dcp, &clone_defcbh, next) { - if (strncmp(dcp->ifprefix, ifr.ifr_name, - strlen(dcp->ifprefix)) == 0) { + if ((dcp->clone_mt == MT_PREFIX) && + (strncmp(dcp->ifprefix, ifr.ifr_name, + strlen(dcp->ifprefix)) == 0)) { + clone_cb = dcp->clone_cb; + break; + } + if ((dcp->clone_mt == MT_FILTER) && + dcp->ifmatch(ifr.ifr_name)) { clone_cb = dcp->clone_cb; break; } |