Module Name: src Committed By: yamaguchi Date: Mon Nov 15 07:07:06 UTC 2021
Modified Files: src/sys/net: if_ether.h if_ethersubr.c if_vlan.c src/sys/net/lagg: if_lagg.c Log Message: introduced APIs to configure VLAN TAG to ethernet devices To generate a diff of this commit: cvs rdiff -u -r1.87 -r1.88 src/sys/net/if_ether.h cvs rdiff -u -r1.303 -r1.304 src/sys/net/if_ethersubr.c cvs rdiff -u -r1.164 -r1.165 src/sys/net/if_vlan.c cvs rdiff -u -r1.25 -r1.26 src/sys/net/lagg/if_lagg.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_ether.h diff -u src/sys/net/if_ether.h:1.87 src/sys/net/if_ether.h:1.88 --- src/sys/net/if_ether.h:1.87 Thu Sep 30 03:54:04 2021 +++ src/sys/net/if_ether.h Mon Nov 15 07:07:05 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ether.h,v 1.87 2021/09/30 03:54:04 yamaguchi Exp $ */ +/* $NetBSD: if_ether.h,v 1.88 2021/11/15 07:07:05 yamaguchi Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -401,6 +401,8 @@ uint32_t ether_crc32_be(const uint8_t *, int ether_aton_r(u_char *, size_t, const char *); int ether_enable_vlan_mtu(struct ifnet *); int ether_disable_vlan_mtu(struct ifnet *); +int ether_add_vlantag(struct ifnet *, uint16_t, bool *); +int ether_del_vlantag(struct ifnet *, uint16_t); #else /* * Prototype ethers(3) functions. Index: src/sys/net/if_ethersubr.c diff -u src/sys/net/if_ethersubr.c:1.303 src/sys/net/if_ethersubr.c:1.304 --- src/sys/net/if_ethersubr.c:1.303 Mon Nov 8 16:50:05 2021 +++ src/sys/net/if_ethersubr.c Mon Nov 15 07:07:05 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ethersubr.c,v 1.303 2021/11/08 16:50:05 christos Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.304 2021/11/15 07:07:05 yamaguchi Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.303 2021/11/08 16:50:05 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.304 2021/11/15 07:07:05 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1659,6 +1659,104 @@ ether_disable_vlan_mtu(struct ifnet *ifp return error; } +/* + * Add and delete VLAN TAG + */ +int +ether_add_vlantag(struct ifnet *ifp, uint16_t vtag, bool *vlanmtu_status) +{ + struct ethercom *ec = (void *)ifp; + struct vlanid_list *vidp; + bool vlanmtu_enabled; + uint16_t vid = EVL_VLANOFTAG(vtag); + int error; + + vlanmtu_enabled = false; + + /* Add a vid to the list */ + vidp = kmem_alloc(sizeof(*vidp), KM_SLEEP); + vidp->vid = vid; + + ETHER_LOCK(ec); + ec->ec_nvlans++; + SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidp, vid_list); + ETHER_UNLOCK(ec); + + if (ec->ec_nvlans == 1) { + IFNET_LOCK(ifp); + error = ether_enable_vlan_mtu(ifp); + IFNET_UNLOCK(ifp); + + if (error == 0) { + vlanmtu_enabled = true; + } else if (error != -1) { + goto fail; + } + } + + if (ec->ec_vlan_cb != NULL) { + error = (*ec->ec_vlan_cb)(ec, vid, true); + if (error != 0) + goto fail; + } + + if (vlanmtu_status != NULL) + *vlanmtu_status = vlanmtu_enabled; + + return 0; +fail: + ETHER_LOCK(ec); + ec->ec_nvlans--; + SIMPLEQ_REMOVE(&ec->ec_vids, vidp, vlanid_list, vid_list); + ETHER_UNLOCK(ec); + + if (vlanmtu_enabled) { + IFNET_LOCK(ifp); + (void)ether_disable_vlan_mtu(ifp); + IFNET_UNLOCK(ifp); + } + + kmem_free(vidp, sizeof(*vidp)); + + return error; +} + +int +ether_del_vlantag(struct ifnet *ifp, uint16_t vtag) +{ + struct ethercom *ec = (void *)ifp; + struct vlanid_list *vidp; + uint16_t vid = EVL_VLANOFTAG(vtag); + + ETHER_LOCK(ec); + SIMPLEQ_FOREACH(vidp, &ec->ec_vids, vid_list) { + if (vidp->vid == vid) { + SIMPLEQ_REMOVE(&ec->ec_vids, vidp, + vlanid_list, vid_list); + ec->ec_nvlans--; + break; + } + } + ETHER_UNLOCK(ec); + + if (vidp == NULL) + return ENOENT; + + if (ec->ec_vlan_cb != NULL) { + (void)(*ec->ec_vlan_cb)(ec, vidp->vid, false); + } + + if (ec->ec_nvlans == 0) { + IFNET_LOCK(ifp); + (void)ether_disable_vlan_mtu(ifp); + IFNET_UNLOCK(ifp); + } + + kmem_free(vidp, sizeof(*vidp)); + + return 0; +} + static int ether_multicast_sysctl(SYSCTLFN_ARGS) { Index: src/sys/net/if_vlan.c diff -u src/sys/net/if_vlan.c:1.164 src/sys/net/if_vlan.c:1.165 --- src/sys/net/if_vlan.c:1.164 Tue Oct 5 04:09:49 2021 +++ src/sys/net/if_vlan.c Mon Nov 15 07:07:05 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_vlan.c,v 1.164 2021/10/05 04:09:49 yamaguchi Exp $ */ +/* $NetBSD: if_vlan.c,v 1.165 2021/11/15 07:07:05 yamaguchi Exp $ */ /* * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.164 2021/10/05 04:09:49 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.165 2021/11/15 07:07:05 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -434,57 +434,29 @@ vlan_config(struct ifvlan *ifv, struct i case IFT_ETHER: { struct ethercom *ec = (void *)p; - struct vlanid_list *vidmem; + bool vlanmtu_enabled; nmib->ifvm_msw = &vlan_ether_multisw; nmib->ifvm_encaplen = ETHER_VLAN_ENCAP_LEN; nmib->ifvm_mintu = ETHERMIN; - if (ec->ec_nvlans++ == 0) { - IFNET_LOCK(p); - error = ether_enable_vlan_mtu(p); - IFNET_UNLOCK(p); - if (error >= 0) { - if (error) { - ec->ec_nvlans--; - goto done; - } - nmib->ifvm_mtufudge = 0; - } else { - /* - * Fudge the MTU by the encapsulation size. This - * makes us incompatible with strictly compliant - * 802.1Q implementations, but allows us to use - * the feature with other NetBSD - * implementations, which might still be useful. - */ - nmib->ifvm_mtufudge = nmib->ifvm_encaplen; - } - error = 0; - } - /* Add a vid to the list */ - vidmem = kmem_alloc(sizeof(struct vlanid_list), KM_SLEEP); - vidmem->vid = vid; - ETHER_LOCK(ec); - SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); - ETHER_UNLOCK(ec); + error = ether_add_vlantag(p, tag, &vlanmtu_enabled); + if (error != 0) + goto done; - if (ec->ec_vlan_cb != NULL) { + if (vlanmtu_enabled) { + nmib->ifvm_mtufudge = 0; + } else { /* - * Call ec_vlan_cb(). It will setup VLAN HW filter or - * HW tagging function. + * Fudge the MTU by the encapsulation size. This + * makes us incompatible with strictly compliant + * 802.1Q implementations, but allows us to use + * the feature with other NetBSD + * implementations, which might still be useful. */ - error = (*ec->ec_vlan_cb)(ec, vid, true); - if (error) { - ec->ec_nvlans--; - if (ec->ec_nvlans == 0) { - IFNET_LOCK(p); - (void)ether_disable_vlan_mtu(p); - IFNET_UNLOCK(p); - } - goto done; - } + nmib->ifvm_mtufudge = nmib->ifvm_encaplen; } + /* * If the parent interface can do hardware-assisted * VLAN encapsulation, then propagate its hardware- @@ -624,34 +596,7 @@ vlan_unconfig_locked(struct ifvlan *ifv, switch (p->if_type) { case IFT_ETHER: { - struct ethercom *ec = (void *)p; - struct vlanid_list *vlanidp; - uint16_t vid = EVL_VLANOFTAG(nmib->ifvm_tag); - - ETHER_LOCK(ec); - SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { - if (vlanidp->vid == vid) { - SIMPLEQ_REMOVE(&ec->ec_vids, vlanidp, - vlanid_list, vid_list); - break; - } - } - ETHER_UNLOCK(ec); - if (vlanidp != NULL) - kmem_free(vlanidp, sizeof(*vlanidp)); - - if (ec->ec_vlan_cb != NULL) { - /* - * Call ec_vlan_cb(). It will setup VLAN HW filter or - * HW tagging function. - */ - (void)(*ec->ec_vlan_cb)(ec, vid, false); - } - if (--ec->ec_nvlans == 0) { - IFNET_LOCK(p); - (void)ether_disable_vlan_mtu(p); - IFNET_UNLOCK(p); - } + (void)ether_del_vlantag(p, nmib->ifvm_tag); /* XXX ether_ifdetach must not be called with IFNET_LOCK */ ifv->ifv_stopping = true; Index: src/sys/net/lagg/if_lagg.c diff -u src/sys/net/lagg/if_lagg.c:1.25 src/sys/net/lagg/if_lagg.c:1.26 --- src/sys/net/lagg/if_lagg.c:1.25 Fri Nov 12 05:56:54 2021 +++ src/sys/net/lagg/if_lagg.c Mon Nov 15 07:07:05 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.25 2021/11/12 05:56:54 yamaguchi Exp $ */ +/* $NetBSD: if_lagg.c,v 1.26 2021/11/15 07:07:05 yamaguchi Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter <r...@openbsd.org> @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.25 2021/11/12 05:56:54 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.26 2021/11/15 07:07:05 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1198,106 +1198,10 @@ lagg_media_status(struct ifnet *ifp, str } static int -lagg_register_vid(struct ethercom *ec, uint16_t vid) -{ - struct ifnet *ifp; - struct vlanid_list *vidmem; - bool vlanmtu_enabled; - int error; - - ifp = (struct ifnet *)ec; - vlanmtu_enabled = false; - - /* Add a vid to the list */ - vidmem = kmem_alloc(sizeof(*vidmem), KM_SLEEP); - vidmem->vid = vid; - ec->ec_nvlans++; - ETHER_LOCK(ec); - SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); - ETHER_UNLOCK(ec); - - if (ec->ec_nvlans == 1) { - IFNET_LOCK(ifp); - error = ether_enable_vlan_mtu(ifp); - IFNET_UNLOCK(ifp); - - if (error == -1) { - error = 0; - } else if (error != 0) { - goto fail; - } - - vlanmtu_enabled = true; - } - - if (ec->ec_vlan_cb != NULL) { - error = (*ec->ec_vlan_cb)(ec, vid, true); - if (error != 0) { - goto fail; - } - } - - return 0; - -fail: - ETHER_LOCK(ec); - ec->ec_nvlans--; - SIMPLEQ_REMOVE(&ec->ec_vids, vidmem, vlanid_list, vid_list); - ETHER_UNLOCK(ec); - - if (vlanmtu_enabled) { - IFNET_LOCK(ifp); - (void)ether_disable_vlan_mtu(ifp); - IFNET_UNLOCK(ifp); - } - - kmem_free(vidmem, sizeof(*vidmem)); - - return error; -} - -static int -lagg_unregister_vid(struct ethercom *ec, uint16_t vid) -{ - struct ifnet *ifp; - struct vlanid_list *vlanidp; - - ETHER_LOCK(ec); - SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { - if (vlanidp->vid == vid) { - SIMPLEQ_REMOVE(&ec->ec_vids, vlanidp, - vlanid_list, vid_list); - ec->ec_nvlans--; - break; - } - } - ETHER_UNLOCK(ec); - - if (vlanidp == NULL) - return ENOENT; - - if (ec->ec_vlan_cb != NULL) { - (void)(*ec->ec_vlan_cb)(ec, vlanidp->vid, false); - } - - if (ec->ec_nvlans == 0) { - ifp = (struct ifnet *)ec; - IFNET_LOCK(ifp); - (void)ether_disable_vlan_mtu(ifp); - IFNET_UNLOCK(ifp); - } - - kmem_free(vlanidp, sizeof(*vlanidp)); - - return 0; -} - -static int lagg_port_vlan_cb(struct lagg_port *lp, struct lagg_vlantag *lvt, bool set) { struct ifnet *ifp_port; - struct ethercom *ec_port; int error; if (lp->lp_iftype != IFT_ETHER) @@ -1305,12 +1209,13 @@ lagg_port_vlan_cb(struct lagg_port *lp, error = 0; ifp_port = lp->lp_ifp; - ec_port = (struct ethercom *)ifp_port; if (set) { - error = lagg_register_vid(ec_port, lvt->lvt_vtag); + error = ether_add_vlantag(ifp_port, + lvt->lvt_vtag, NULL); } else { - error = lagg_unregister_vid(ec_port, lvt->lvt_vtag); + error = ether_del_vlantag(ifp_port, + lvt->lvt_vtag); } return error;