Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Implement VLAN hardware filter function(ETHERCAP_VLAN_HWFILT...



details:   https://anonhg.NetBSD.org/src/rev/6af6877b7c85
branches:  trunk
changeset: 457750:6af6877b7c85
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Wed Jul 17 03:26:24 2019 +0000

description:
Implement VLAN hardware filter function(ETHERCAP_VLAN_HWFILTER).
First proposed by jmcneill in 2017 and modified by me.

How to use:

 - Set callback function:

        ether_set_vlan_cb(struct ethercom *, ether_vlancb_t)

 - Callback. This function is called when a vlan is attached/detached to the
   parent interface:

        int (*ether_vlancb_t)(struct ethercom *ec, uint16_t vlanid, bool set);

 - ifconfig(8)

        ifconfig ixg0 [-]vlan-hwfilter

 Note that ETHERCAP_VLAN_HWFILTER is set by default on ixg(4) because
the PF driver usually enable "all block" filter by default.

diffstat:

 sbin/ifconfig/ether.c     |    6 +-
 sys/dev/pci/ixgbe/ixgbe.c |   97 +++++++++++++++++++++++-------
 sys/dev/pci/ixgbe/ixgbe.h |    5 +-
 sys/dev/pci/ixgbe/ixv.c   |  142 ++++++++++++++++++++++++++++++++-------------
 sys/net/if_ether.h        |   17 +++++-
 sys/net/if_ethersubr.c    |   13 +++-
 sys/net/if_vlan.c         |   65 ++++++++++++++++----
 7 files changed, 256 insertions(+), 89 deletions(-)

diffs (truncated from 758 to 300 lines):

diff -r 670fc0b5e8bd -r 6af6877b7c85 sbin/ifconfig/ether.c
--- a/sbin/ifconfig/ether.c     Wed Jul 17 03:09:16 2019 +0000
+++ b/sbin/ifconfig/ether.c     Wed Jul 17 03:26:24 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ether.c,v 1.5 2019/07/17 03:09:16 msaitoh Exp $        */
+/*     $NetBSD: ether.c,v 1.6 2019/07/17 03:26:24 msaitoh Exp $        */
 
 /*
  * Copyright (c) 1983, 1993
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ether.c,v 1.5 2019/07/17 03:09:16 msaitoh Exp $");
+__RCSID("$NetBSD: ether.c,v 1.6 2019/07/17 03:26:24 msaitoh Exp $");
 #endif /* not lint */
 
 #include <sys/param.h> 
@@ -64,9 +64,7 @@
 #define MAX_PRINT_LEN 55
 
 static const struct kwinst ethercapskw[] = {
-#if 0 /* notyet */
        IFKW("vlan-hwfilter",   ETHERCAP_VLAN_HWFILTER),
-#endif
        IFKW("vlan-hwtagging",  ETHERCAP_VLAN_HWTAGGING),
        IFKW("eee",             ETHERCAP_EEE)
 };
diff -r 670fc0b5e8bd -r 6af6877b7c85 sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Wed Jul 17 03:09:16 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Wed Jul 17 03:26:24 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.192 2019/07/04 09:02:24 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.193 2019/07/17 03:26:24 msaitoh Exp $ */
 
 /******************************************************************************
 
@@ -220,10 +220,9 @@
 static void    ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t);
 
 static void    ixgbe_setup_vlan_hw_support(struct adapter *);
-#if 0
-static void    ixgbe_register_vlan(void *, struct ifnet *, u16);
-static void    ixgbe_unregister_vlan(void *, struct ifnet *, u16);
-#endif
+static int     ixgbe_vlan_cb(struct ethercom *, uint16_t, bool);
+static int     ixgbe_register_vlan(void *, struct ifnet *, u16);
+static int     ixgbe_unregister_vlan(void *, struct ifnet *, u16);
 
 static void    ixgbe_add_device_sysctls(struct adapter *);
 static void    ixgbe_add_hw_stats(struct adapter *);
@@ -905,6 +904,9 @@
        /* Enable WoL (if supported) */
        ixgbe_check_wol_support(adapter);
 
+       /* Register for VLAN events */
+       ether_set_vlan_cb(&adapter->osdep.ec, ixgbe_vlan_cb);
+
        /* Verify adapter fan is still functional (if applicable) */
        if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
                u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -2299,7 +2301,20 @@
        return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_rdt_handler */
 
-#if 0  /* XXX Badly need to overhaul vlan(4) on NetBSD. */
+static int
+ixgbe_vlan_cb(struct ethercom *ec, uint16_t vid, bool set)
+{
+       struct ifnet *ifp = &ec->ec_if;
+       int rv;
+
+       if (set)
+               rv = ixgbe_register_vlan(ifp->if_softc, ifp, vid);
+       else
+               rv = ixgbe_unregister_vlan(ifp->if_softc, ifp, vid);
+
+       return rv;
+}
+
 /************************************************************************
  * ixgbe_register_vlan
  *
@@ -2308,24 +2323,30 @@
  *   just creates the entry in the soft version of the
  *   VFTA, init will repopulate the real table.
  ************************************************************************/
-static void
+static int
 ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
 {
        struct adapter  *adapter = ifp->if_softc;
        u16             index, bit;
+       int             error;
 
        if (ifp->if_softc != arg)   /* Not our event */
-               return;
+               return EINVAL;
 
        if ((vtag == 0) || (vtag > 4095))       /* Invalid */
-               return;
+               return EINVAL;
 
        IXGBE_CORE_LOCK(adapter);
        index = (vtag >> 5) & 0x7F;
        bit = vtag & 0x1F;
        adapter->shadow_vfta[index] |= (1 << bit);
-       ixgbe_setup_vlan_hw_support(adapter);
+       error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, true,
+           true);
        IXGBE_CORE_UNLOCK(adapter);
+       if (error != 0)
+               error = EACCES;
+
+       return error;
 } /* ixgbe_register_vlan */
 
 /************************************************************************
@@ -2333,27 +2354,31 @@
  *
  *   Run via vlan unconfig EVENT, remove our entry in the soft vfta.
  ************************************************************************/
-static void
+static int
 ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
 {
        struct adapter  *adapter = ifp->if_softc;
        u16             index, bit;
+       int             error;
 
        if (ifp->if_softc != arg)
-               return;
+               return EINVAL;
 
        if ((vtag == 0) || (vtag > 4095))       /* Invalid */
-               return;
+               return EINVAL;
 
        IXGBE_CORE_LOCK(adapter);
        index = (vtag >> 5) & 0x7F;
        bit = vtag & 0x1F;
        adapter->shadow_vfta[index] &= ~(1 << bit);
-       /* Re-init to load the changes */
-       ixgbe_setup_vlan_hw_support(adapter);
+       error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, false,
+           true);
        IXGBE_CORE_UNLOCK(adapter);
+       if (error != 0)
+               error = EACCES;
+
+       return error;
 } /* ixgbe_unregister_vlan */
-#endif
 
 static void
 ixgbe_setup_vlan_hw_support(struct adapter *adapter)
@@ -2363,6 +2388,7 @@
        struct rx_ring  *rxr;
        int             i;
        u32             ctrl;
+       struct vlanid_list *vlanidp;
        bool            hwtagging;
 
        /*
@@ -2391,14 +2417,21 @@
                rxr->vtag_strip = hwtagging ? TRUE : FALSE;
        }
 
-       /*
-        * A soft reset zero's out the VFTA, so
-        * we need to repopulate it now.
-        */
+       /* Cleanup shadow_vfta */
        for (i = 0; i < IXGBE_VFTA_SIZE; i++)
-               if (adapter->shadow_vfta[i] != 0)
-                       IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
-                           adapter->shadow_vfta[i]);
+               adapter->shadow_vfta[i] = 0;
+       /* Generate shadow_vfta from ec_vids */
+       mutex_enter(ec->ec_lock);
+       SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) {
+               uint32_t idx;
+
+               idx = vlanidp->vid / 32;
+               KASSERT(idx < IXGBE_VFTA_SIZE);
+               adapter->shadow_vfta[idx] |= 1 << vlanidp->vid % 32;
+       }
+       mutex_exit(ec->ec_lock);
+       for (i = 0; i < IXGBE_VFTA_SIZE; i++)
+               IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), adapter->shadow_vfta[i]);
 
        ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
        /* Enable the Filter Table if enabled */
@@ -4107,6 +4140,7 @@
 
        /* Update saved flags. See ixgbe_ifflags_cb() */
        adapter->if_flags = ifp->if_flags;
+       adapter->ec_capenable = adapter->osdep.ec.ec_capenable;
 
        /* Now inform the stack we're ready */
        ifp->if_flags |= IFF_RUNNING;
@@ -6151,8 +6185,23 @@
        } else if ((change & IFF_PROMISC) != 0)
                ixgbe_set_promisc(adapter);
 
+       /* Check for ec_capenable. */
+       change = ec->ec_capenable ^ adapter->ec_capenable;
+       adapter->ec_capenable = ec->ec_capenable;
+       if ((change & ~(ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING
+           | ETHERCAP_VLAN_HWFILTER)) != 0) {
+               rv = ENETRESET;
+               goto out;
+       }
+
+       /*
+        * Special handling is not required for ETHERCAP_VLAN_MTU.
+        * MAXFRS(MHADD) does not include the 4bytes of the VLAN header.
+        */
+
        /* Set up VLAN support and filter */
-       ixgbe_setup_vlan_hw_support(adapter);
+       if ((change & (ETHERCAP_VLAN_HWTAGGING | ETHERCAP_VLAN_HWFILTER)) != 0)
+               ixgbe_setup_vlan_hw_support(adapter);
 
 out:
        IXGBE_CORE_UNLOCK(adapter);
diff -r 670fc0b5e8bd -r 6af6877b7c85 sys/dev/pci/ixgbe/ixgbe.h
--- a/sys/dev/pci/ixgbe/ixgbe.h Wed Jul 17 03:09:16 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.h Wed Jul 17 03:26:24 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.h,v 1.55 2019/06/27 05:55:40 msaitoh Exp $ */
+/* $NetBSD: ixgbe.h,v 1.56 2019/07/17 03:26:24 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -475,7 +475,8 @@
 
        struct ifmedia          media;
        callout_t               timer;
-       int                     if_flags;
+       int                     if_flags;       /* saved ifp->if_flags */
+       int                     ec_capenable;   /* saved ec->ec_capenable */
 
        kmutex_t                core_mtx;
 
diff -r 670fc0b5e8bd -r 6af6877b7c85 sys/dev/pci/ixgbe/ixv.c
--- a/sys/dev/pci/ixgbe/ixv.c   Wed Jul 17 03:09:16 2019 +0000
+++ b/sys/dev/pci/ixgbe/ixv.c   Wed Jul 17 03:26:24 2019 +0000
@@ -1,4 +1,4 @@
-/*$NetBSD: ixv.c,v 1.119 2019/07/17 03:09:16 msaitoh Exp $*/
+/*$NetBSD: ixv.c,v 1.120 2019/07/17 03:26:24 msaitoh Exp $*/
 
 /******************************************************************************
 
@@ -120,11 +120,10 @@
 static u8 *    ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
 static void    ixv_eitr_write(struct adapter *, uint32_t, uint32_t);
 
-static void    ixv_setup_vlan_support(struct adapter *);
-#if 0
-static void    ixv_register_vlan(void *, struct ifnet *, u16);
-static void    ixv_unregister_vlan(void *, struct ifnet *, u16);
-#endif
+static int     ixv_setup_vlan_support(struct adapter *);
+static int     ixv_vlan_cb(struct ethercom *, uint16_t, bool);
+static int     ixv_register_vlan(void *, struct ifnet *, u16);
+static int     ixv_unregister_vlan(void *, struct ifnet *, u16);
 
 static void    ixv_add_device_sysctls(struct adapter *);
 static void    ixv_save_stats(struct adapter *);
@@ -471,12 +470,7 @@
        }
 
        /* Register for VLAN events */
-#if 0 /* XXX delete after write? */
-       adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
-           ixv_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-       adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
-           ixv_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-#endif
+       ether_set_vlan_cb(&adapter->osdep.ec, ixv_vlan_cb);
 
        /* Sysctls for limiting the amount of work done in the taskqueues */
        ixv_set_sysctl_value(adapter, "rx_processing_limit",
@@ -618,14 +612,6 @@
        /* Drain the Mailbox(link) queue */
        softint_disestablish(adapter->link_si);
 
-       /* Unregister VLAN events */
-#if 0 /* XXX msaitoh delete after write? */
-       if (adapter->vlan_attach != NULL)
-               EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
-       if (adapter->vlan_detach != NULL)
-               EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
-#endif
-
        ether_ifdetach(adapter->ifp);
        callout_halt(&adapter->timer, NULL);
 
@@ -823,6 +809,7 @@



Home | Main Index | Thread Index | Old Index