commit 28e90f6d67c89336c84c33cd6156f0368cfd2a9b Author: Andrey V. Elsukov Date: Thu Aug 10 20:03:11 2017 +0300 Add new experimental direct vlan handling implementation. diff --git a/sys/conf/files b/sys/conf/files index 0dba49f8dc2..f8f1fa0b5b4 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3978,6 +3978,7 @@ net/slcompress.c optional netgraph_vjc | sppp | \ netgraph_sppp net/toeplitz.c optional inet rss | inet6 rss net/vnet.c optional vimage +net/yandex.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" net80211/ieee80211.c optional wlan net80211/ieee80211_acl.c optional wlan wlan_acl net80211/ieee80211_action.c optional wlan diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 92662f5afe2..c874eeab2a8 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -772,6 +772,12 @@ ixgbe_attach(device_t dev) /* Enable WoL (if supported) */ ixgbe_check_wol_support(adapter); + adapter->vlans = malloc(sizeof(*adapter->vlans), M_IXGBE, M_NOWAIT | M_ZERO); + if (adapter->vlans == NULL) { + device_printf(dev, "Can not allocate VLANs table\n"); + error = ENOMEM; + goto err_out; + } /* Register for VLAN events */ adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST); @@ -953,6 +959,7 @@ err_out: IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); ixgbe_free_pci_resources(adapter); free(adapter->mta, M_IXGBE); + free(adapter->vlans, M_IXGBE); IXGBE_CORE_LOCK_DESTROY(adapter); return (error); @@ -1054,20 +1061,12 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter) | IFCAP_VLAN_MTU | IFCAP_HWSTATS; + ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; + /* Enable the above capabilities by default */ ifp->if_capenable = ifp->if_capabilities; /* - * Don't turn this on by default, if vlans are - * created on another pseudo device (eg. lagg) - * then vlan events are not passed thru, breaking - * operation, but with HW FILTER off it works. If - * using vlans directly on the ixgbe driver you can - * enable this and get full hardware tag filtering. - */ - ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; - - /* * Specify the media types supported by this adapter and register * callbacks to update media and link information */ @@ -1707,6 +1706,8 @@ ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + yndx_vlan_set(adapter->vlans, vtag, yndx_vlan_devat(ifp, vtag)); + IXGBE_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; @@ -1733,6 +1734,8 @@ ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + yndx_vlan_set(adapter->vlans, vtag, NULL); + IXGBE_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; @@ -1765,6 +1768,9 @@ ixgbe_setup_vlan_hw_support(struct adapter *adapter) if (adapter->num_vlans == 0) return; + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) + return; + /* Setup the queues for vlans */ for (i = 0; i < adapter->num_queues; i++) { rxr = &adapter->rx_rings[i]; @@ -2658,6 +2664,7 @@ ixgbe_detach(device_t dev) EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach); if (adapter->vlan_detach != NULL) EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach); + free(adapter->vlans, M_IXGBE); callout_drain(&adapter->timer); diff --git a/sys/dev/ixgbe/ix_txrx.c b/sys/dev/ixgbe/ix_txrx.c index 0f2d61df95a..398196e8f4c 100644 --- a/sys/dev/ixgbe/ix_txrx.c +++ b/sys/dev/ixgbe/ix_txrx.c @@ -1594,7 +1594,7 @@ ixgbe_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, if (tcp_lro_rx(&rxr->lro, m, 0) == 0) return; } - (*ifp->if_input)(ifp, m); + (*ifp->if_input)(m->m_pkthdr.rcvif, m); } /* ixgbe_rx_input */ /************************************************************************ @@ -1647,7 +1647,7 @@ ixgbe_rxeof(struct ix_queue *que) { struct adapter *adapter = que->adapter; struct rx_ring *rxr = que->rxr; - struct ifnet *ifp = adapter->ifp; + struct ifnet *ifp = adapter->ifp, *rcvif; struct lro_ctrl *lro = &rxr->lro; union ixgbe_adv_rx_desc *cur; struct ixgbe_rx_buf *rbuf, *nbuf; @@ -1806,8 +1806,20 @@ ixgbe_rxeof(struct ix_queue *que) if ((rxr->vtag_strip) && (staterr & IXGBE_RXD_STAT_VP)) vtag = le16toh(cur->wb.upper.vlan); if (vtag) { - sendmp->m_pkthdr.ether_vtag = vtag; - sendmp->m_flags |= M_VLANTAG; + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + rcvif = yndx_vlan_get(adapter->vlans, + EVL_VLANOFTAG(vtag)); + else + rcvif = NULL; + + if (rcvif == NULL) { + sendmp->m_pkthdr.ether_vtag = vtag; + sendmp->m_flags |= M_VLANTAG; + } else { + sendmp->m_pkthdr.rcvif = rcvif; + if_inc_counter(rcvif, + IFCOUNTER_IPACKETS, 1); + } } if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) ixgbe_rx_checksum(staterr, sendmp, ptype); diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index 454313cb7c8..27573cbb100 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -444,6 +445,8 @@ struct adapter { struct mtx core_mtx; + struct vlans_table *vlans; + eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; diff --git a/sys/net/yandex.c b/sys/net/yandex.c new file mode 100644 index 00000000000..94fb1b2ad84 --- /dev/null +++ b/sys/net/yandex.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2017 Yandex LLC + * Copyright (c) 2017 Andrey V. Elsukov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct ifnet * +yndx_vlan_get(struct vlans_table *table, uint16_t vid) +{ + + return (ck_pr_load_ptr(&table->vifp[vid])); +} + +void +yndx_vlan_set(struct vlans_table *table, uint16_t vid, struct ifnet *ifp) +{ + + ck_pr_fence_store(); + ck_pr_store_ptr(&table->vifp[vid], ifp); +} + +/* + * VLAN_DEVAT() that allows handle vlans on the if_lagg(4) + */ +struct ifnet * +yndx_vlan_devat(struct ifnet *ifp, uint16_t vid) +{ + struct lagg_port *lp; + struct lagg_softc *sc; + + /* Skip lagg nesting */ + while (ifp->if_type == IFT_IEEE8023ADLAG) { + lp = ifp->if_lagg; + sc = lp->lp_softc; + ifp = sc->sc_ifp; + } + /* Get vlan interface based on tag */ + return (VLAN_DEVAT(ifp, vid)); +} + diff --git a/sys/net/yandex.h b/sys/net/yandex.h new file mode 100644 index 00000000000..a47ce4dddd9 --- /dev/null +++ b/sys/net/yandex.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2017 Yandex LLC + * Copyright (c) 2017 Andrey V. Elsukov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NET_YANDEX_H_ +#define _NET_YANDEX_H_ + +struct vlans_table { + struct ifnet *vifp[4096]; +}; + +struct ifnet *yndx_vlan_devat(struct ifnet *ifp, uint16_t vid); +struct ifnet *yndx_vlan_get(struct vlans_table *table, uint16_t vid); +void yndx_vlan_set(struct vlans_table *table, uint16_t vid, struct ifnet *ifp); + +#endif /* _NET_YANDEX_H_ */