net/sfc/base: import filters support
authorAndrew Rybchenko <arybchenko@solarflare.com>
Tue, 29 Nov 2016 16:18:36 +0000 (16:18 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:25 +0000 (19:39 +0100)
Filtering capabilities depend on NIC family and used firmware
variant. Provided API allows to get supported filter types
(in a priority order), add/delete individual filters and
restore entire filter table after, for example, NIC management
CPU reboot.

Rx filters allow to redirect matching flow to specified Rx queue.

Tx filters allow to control generated traffic (e.g. to implement
virtual function anti-spoofing control).

EFSYS_OPT_FILTER should be enabled to use it. It is required
for SFN7xxx and SFN8xxx adapter families support.

From Solarflare Communications Inc.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_check.h
drivers/net/sfc/base/efx_filter.c [new file with mode: 0644]
drivers/net/sfc/base/efx_impl.h

index 572520d..1814aef 100644 (file)
@@ -1044,6 +1044,165 @@ efx_tx_qdestroy(
 
 /* FILTER */
 
+#if EFSYS_OPT_FILTER
+
+#define        EFX_ETHER_TYPE_IPV4 0x0800
+#define        EFX_ETHER_TYPE_IPV6 0x86DD
+
+#define        EFX_IPPROTO_TCP 6
+#define        EFX_IPPROTO_UDP 17
+
+/* Use RSS to spread across multiple queues */
+#define        EFX_FILTER_FLAG_RX_RSS          0x01
+/* Enable RX scatter */
+#define        EFX_FILTER_FLAG_RX_SCATTER      0x02
+/*
+ * Override an automatic filter (priority EFX_FILTER_PRI_AUTO).
+ * May only be set by the filter implementation for each type.
+ * A removal request will restore the automatic filter in its place.
+ */
+#define        EFX_FILTER_FLAG_RX_OVER_AUTO    0x04
+/* Filter is for RX */
+#define        EFX_FILTER_FLAG_RX              0x08
+/* Filter is for TX */
+#define        EFX_FILTER_FLAG_TX              0x10
+
+typedef unsigned int efx_filter_flags_t;
+
+typedef enum efx_filter_match_flags_e {
+       EFX_FILTER_MATCH_REM_HOST = 0x0001,     /* Match by remote IP host
+                                                * address */
+       EFX_FILTER_MATCH_LOC_HOST = 0x0002,     /* Match by local IP host
+                                                * address */
+       EFX_FILTER_MATCH_REM_MAC = 0x0004,      /* Match by remote MAC address */
+       EFX_FILTER_MATCH_REM_PORT = 0x0008,     /* Match by remote TCP/UDP port */
+       EFX_FILTER_MATCH_LOC_MAC = 0x0010,      /* Match by remote TCP/UDP port */
+       EFX_FILTER_MATCH_LOC_PORT = 0x0020,     /* Match by local TCP/UDP port */
+       EFX_FILTER_MATCH_ETHER_TYPE = 0x0040,   /* Match by Ether-type */
+       EFX_FILTER_MATCH_INNER_VID = 0x0080,    /* Match by inner VLAN ID */
+       EFX_FILTER_MATCH_OUTER_VID = 0x0100,    /* Match by outer VLAN ID */
+       EFX_FILTER_MATCH_IP_PROTO = 0x0200,     /* Match by IP transport
+                                                * protocol */
+       EFX_FILTER_MATCH_LOC_MAC_IG = 0x0400,   /* Match by local MAC address
+                                                * I/G bit. Used for RX default
+                                                * unicast and multicast/
+                                                * broadcast filters. */
+} efx_filter_match_flags_t;
+
+typedef enum efx_filter_priority_s {
+       EFX_FILTER_PRI_HINT = 0,        /* Performance hint */
+       EFX_FILTER_PRI_AUTO,            /* Automatic filter based on device
+                                        * address list or hardware
+                                        * requirements. This may only be used
+                                        * by the filter implementation for
+                                        * each NIC type. */
+       EFX_FILTER_PRI_MANUAL,          /* Manually configured filter */
+       EFX_FILTER_PRI_REQUIRED,        /* Required for correct behaviour of the
+                                        * client (e.g. SR-IOV, HyperV VMQ etc.)
+                                        */
+} efx_filter_priority_t;
+
+/*
+ * FIXME: All these fields are assumed to be in little-endian byte order.
+ * It may be better for some to be big-endian. See bug42804.
+ */
+
+typedef struct efx_filter_spec_s {
+       uint32_t        efs_match_flags:12;
+       uint32_t        efs_priority:2;
+       uint32_t        efs_flags:6;
+       uint32_t        efs_dmaq_id:12;
+       uint32_t        efs_rss_context;
+       uint16_t        efs_outer_vid;
+       uint16_t        efs_inner_vid;
+       uint8_t         efs_loc_mac[EFX_MAC_ADDR_LEN];
+       uint8_t         efs_rem_mac[EFX_MAC_ADDR_LEN];
+       uint16_t        efs_ether_type;
+       uint8_t         efs_ip_proto;
+       uint16_t        efs_loc_port;
+       uint16_t        efs_rem_port;
+       efx_oword_t     efs_rem_host;
+       efx_oword_t     efs_loc_host;
+} efx_filter_spec_t;
+
+
+/* Default values for use in filter specifications */
+#define        EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT     0xffffffff
+#define        EFX_FILTER_SPEC_RX_DMAQ_ID_DROP         0xfff
+#define        EFX_FILTER_SPEC_VID_UNSPEC              0xffff
+
+extern __checkReturn   efx_rc_t
+efx_filter_init(
+       __in            efx_nic_t *enp);
+
+extern                 void
+efx_filter_fini(
+       __in            efx_nic_t *enp);
+
+extern __checkReturn   efx_rc_t
+efx_filter_insert(
+       __in            efx_nic_t *enp,
+       __inout         efx_filter_spec_t *spec);
+
+extern __checkReturn   efx_rc_t
+efx_filter_remove(
+       __in            efx_nic_t *enp,
+       __inout         efx_filter_spec_t *spec);
+
+extern __checkReturn   efx_rc_t
+efx_filter_restore(
+       __in            efx_nic_t *enp);
+
+extern __checkReturn   efx_rc_t
+efx_filter_supported_filters(
+       __in            efx_nic_t *enp,
+       __out           uint32_t *list,
+       __out           size_t *length);
+
+extern                 void
+efx_filter_spec_init_rx(
+       __out           efx_filter_spec_t *spec,
+       __in            efx_filter_priority_t priority,
+       __in            efx_filter_flags_t flags,
+       __in            efx_rxq_t *erp);
+
+extern                 void
+efx_filter_spec_init_tx(
+       __out           efx_filter_spec_t *spec,
+       __in            efx_txq_t *etp);
+
+extern __checkReturn   efx_rc_t
+efx_filter_spec_set_ipv4_local(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint8_t proto,
+       __in            uint32_t host,
+       __in            uint16_t port);
+
+extern __checkReturn   efx_rc_t
+efx_filter_spec_set_ipv4_full(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint8_t proto,
+       __in            uint32_t lhost,
+       __in            uint16_t lport,
+       __in            uint32_t rhost,
+       __in            uint16_t rport);
+
+extern __checkReturn   efx_rc_t
+efx_filter_spec_set_eth_local(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint16_t vid,
+       __in            const uint8_t *addr);
+
+extern __checkReturn   efx_rc_t
+efx_filter_spec_set_uc_def(
+       __inout         efx_filter_spec_t *spec);
+
+extern __checkReturn   efx_rc_t
+efx_filter_spec_set_mc_def(
+       __inout         efx_filter_spec_t *spec);
+
+#endif /* EFSYS_OPT_FILTER */
+
 /* HASH */
 
 extern __checkReturn           uint32_t
index 78cfd8e..555c184 100644 (file)
 # error "FALCON_NIC_CFG_OVERRIDE is obsolete and is not supported."
 #endif
 
+#if EFSYS_OPT_FILTER
+/* Support hardware packet filters */
+#  error "FILTER requires SIENA or HUNTINGTON or MEDFORD"
+#endif /* EFSYS_OPT_FILTER */
+
 #ifdef EFSYS_OPT_MAC_FALCON_GMAC
 # error "MAC_FALCON_GMAC is obsolete and is not supported."
 #endif
diff --git a/drivers/net/sfc/base/efx_filter.c b/drivers/net/sfc/base/efx_filter.c
new file mode 100644 (file)
index 0000000..560562d
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2007-2016 Solarflare Communications Inc.
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the FreeBSD Project.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+
+#if EFSYS_OPT_FILTER
+
+       __checkReturn   efx_rc_t
+efx_filter_insert(
+       __in            efx_nic_t *enp,
+       __inout         efx_filter_spec_t *spec)
+{
+       const efx_filter_ops_t *efop = enp->en_efop;
+
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+       EFSYS_ASSERT3P(spec, !=, NULL);
+       EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
+
+       return (efop->efo_add(enp, spec, B_FALSE));
+}
+
+       __checkReturn   efx_rc_t
+efx_filter_remove(
+       __in            efx_nic_t *enp,
+       __inout         efx_filter_spec_t *spec)
+{
+       const efx_filter_ops_t *efop = enp->en_efop;
+
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+       EFSYS_ASSERT3P(spec, !=, NULL);
+       EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
+
+       return (efop->efo_delete(enp, spec));
+}
+
+       __checkReturn   efx_rc_t
+efx_filter_restore(
+       __in            efx_nic_t *enp)
+{
+       efx_rc_t rc;
+
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+       if ((rc = enp->en_efop->efo_restore(enp)) != 0)
+               goto fail1;
+
+       return (0);
+
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+       __checkReturn   efx_rc_t
+efx_filter_init(
+       __in            efx_nic_t *enp)
+{
+       const efx_filter_ops_t *efop;
+       efx_rc_t rc;
+
+       /* Check that efx_filter_spec_t is 64 bytes. */
+       EFX_STATIC_ASSERT(sizeof (efx_filter_spec_t) == 64);
+
+       EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+       EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
+
+       switch (enp->en_family) {
+
+       default:
+               EFSYS_ASSERT(0);
+               rc = ENOTSUP;
+               goto fail1;
+       }
+
+       if ((rc = efop->efo_init(enp)) != 0)
+               goto fail2;
+
+       enp->en_efop = efop;
+       enp->en_mod_flags |= EFX_MOD_FILTER;
+       return (0);
+
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       enp->en_efop = NULL;
+       enp->en_mod_flags &= ~EFX_MOD_FILTER;
+       return (rc);
+}
+
+                       void
+efx_filter_fini(
+       __in            efx_nic_t *enp)
+{
+       EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+       enp->en_efop->efo_fini(enp);
+
+       enp->en_efop = NULL;
+       enp->en_mod_flags &= ~EFX_MOD_FILTER;
+}
+
+       __checkReturn   efx_rc_t
+efx_filter_supported_filters(
+       __in            efx_nic_t *enp,
+       __out           uint32_t *list,
+       __out           size_t *length)
+{
+       efx_rc_t rc;
+
+       EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+       EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
+
+       if ((rc = enp->en_efop->efo_supported_filters(enp, list, length)) != 0)
+               goto fail1;
+
+       return (0);
+
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+       __checkReturn   efx_rc_t
+efx_filter_reconfigure(
+       __in                            efx_nic_t *enp,
+       __in_ecount(6)                  uint8_t const *mac_addr,
+       __in                            boolean_t all_unicst,
+       __in                            boolean_t mulcst,
+       __in                            boolean_t all_mulcst,
+       __in                            boolean_t brdcst,
+       __in_ecount(6*count)            uint8_t const *addrs,
+       __in                            uint32_t count)
+{
+       efx_rc_t rc;
+
+       EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+       EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
+
+       if (enp->en_efop->efo_reconfigure != NULL) {
+               if ((rc = enp->en_efop->efo_reconfigure(enp, mac_addr,
+                                                       all_unicst, mulcst,
+                                                       all_mulcst, brdcst,
+                                                       addrs, count)) != 0)
+                       goto fail1;
+       }
+
+       return (0);
+
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+               void
+efx_filter_spec_init_rx(
+       __out           efx_filter_spec_t *spec,
+       __in            efx_filter_priority_t priority,
+       __in            efx_filter_flags_t flags,
+       __in            efx_rxq_t *erp)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+       EFSYS_ASSERT3P(erp, !=, NULL);
+       EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
+                               EFX_FILTER_FLAG_RX_SCATTER)) == 0);
+
+       memset(spec, 0, sizeof (*spec));
+       spec->efs_priority = priority;
+       spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
+       spec->efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT;
+       spec->efs_dmaq_id = (uint16_t)erp->er_index;
+}
+
+               void
+efx_filter_spec_init_tx(
+       __out           efx_filter_spec_t *spec,
+       __in            efx_txq_t *etp)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+       EFSYS_ASSERT3P(etp, !=, NULL);
+
+       memset(spec, 0, sizeof (*spec));
+       spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
+       spec->efs_flags = EFX_FILTER_FLAG_TX;
+       spec->efs_dmaq_id = (uint16_t)etp->et_index;
+}
+
+
+/*
+ *  Specify IPv4 host, transport protocol and port in a filter specification
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_ipv4_local(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint8_t proto,
+       __in            uint32_t host,
+       __in            uint16_t port)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+
+       spec->efs_match_flags |=
+               EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+               EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
+       spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
+       spec->efs_ip_proto = proto;
+       spec->efs_loc_host.eo_u32[0] = host;
+       spec->efs_loc_port = port;
+       return (0);
+}
+
+/*
+ * Specify IPv4 hosts, transport protocol and ports in a filter specification
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_ipv4_full(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint8_t proto,
+       __in            uint32_t lhost,
+       __in            uint16_t lport,
+       __in            uint32_t rhost,
+       __in            uint16_t rport)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+
+       spec->efs_match_flags |=
+               EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+               EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
+               EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
+       spec->efs_ether_type = EFX_ETHER_TYPE_IPV4;
+       spec->efs_ip_proto = proto;
+       spec->efs_loc_host.eo_u32[0] = lhost;
+       spec->efs_loc_port = lport;
+       spec->efs_rem_host.eo_u32[0] = rhost;
+       spec->efs_rem_port = rport;
+       return (0);
+}
+
+/*
+ * Specify local Ethernet address and/or VID in filter specification
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_eth_local(
+       __inout         efx_filter_spec_t *spec,
+       __in            uint16_t vid,
+       __in            const uint8_t *addr)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+       EFSYS_ASSERT3P(addr, !=, NULL);
+
+       if (vid == EFX_FILTER_SPEC_VID_UNSPEC && addr == NULL)
+               return (EINVAL);
+
+       if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
+               spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
+               spec->efs_outer_vid = vid;
+       }
+       if (addr != NULL) {
+               spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
+               memcpy(spec->efs_loc_mac, addr, EFX_MAC_ADDR_LEN);
+       }
+       return (0);
+}
+
+/*
+ * Specify matching otherwise-unmatched unicast in a filter specification
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_uc_def(
+       __inout         efx_filter_spec_t *spec)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+
+       spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
+       return (0);
+}
+
+/*
+ * Specify matching otherwise-unmatched multicast in a filter specification
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_mc_def(
+       __inout         efx_filter_spec_t *spec)
+{
+       EFSYS_ASSERT3P(spec, !=, NULL);
+
+       spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
+       spec->efs_loc_mac[0] = 1;
+       return (0);
+}
+
+
+
+#endif /* EFSYS_OPT_FILTER */
index 15bca37..47d4819 100644 (file)
@@ -161,6 +161,33 @@ typedef struct efx_phy_ops_s {
        efx_rc_t        (*epo_oui_get)(efx_nic_t *, uint32_t *);
 } efx_phy_ops_t;
 
+#if EFSYS_OPT_FILTER
+typedef struct efx_filter_ops_s {
+       efx_rc_t        (*efo_init)(efx_nic_t *);
+       void            (*efo_fini)(efx_nic_t *);
+       efx_rc_t        (*efo_restore)(efx_nic_t *);
+       efx_rc_t        (*efo_add)(efx_nic_t *, efx_filter_spec_t *,
+                                  boolean_t may_replace);
+       efx_rc_t        (*efo_delete)(efx_nic_t *, efx_filter_spec_t *);
+       efx_rc_t        (*efo_supported_filters)(efx_nic_t *, uint32_t *, size_t *);
+       efx_rc_t        (*efo_reconfigure)(efx_nic_t *, uint8_t const *, boolean_t,
+                                  boolean_t, boolean_t, boolean_t,
+                                  uint8_t const *, uint32_t);
+} efx_filter_ops_t;
+
+extern __checkReturn   efx_rc_t
+efx_filter_reconfigure(
+       __in                            efx_nic_t *enp,
+       __in_ecount(6)                  uint8_t const *mac_addr,
+       __in                            boolean_t all_unicst,
+       __in                            boolean_t mulcst,
+       __in                            boolean_t all_mulcst,
+       __in                            boolean_t brdcst,
+       __in_ecount(6*count)            uint8_t const *addrs,
+       __in                            uint32_t count);
+
+#endif /* EFSYS_OPT_FILTER */
+
 
 typedef struct efx_port_s {
        efx_mac_type_t          ep_mac_type;
@@ -245,6 +272,13 @@ typedef struct efx_nic_ops_s {
 #define        EFX_RXQ_DC_SIZE 3 /* 64 descriptors */
 #endif
 
+#if EFSYS_OPT_FILTER
+
+typedef struct efx_filter_s {
+} efx_filter_t;
+
+#endif /* EFSYS_OPT_FILTER */
+
 typedef struct efx_drv_cfg_s {
        uint32_t                edc_min_vi_count;
        uint32_t                edc_max_vi_count;
@@ -274,6 +308,10 @@ struct efx_nic_s {
        const efx_ev_ops_t      *en_eevop;
        const efx_tx_ops_t      *en_etxop;
        const efx_rx_ops_t      *en_erxop;
+#if EFSYS_OPT_FILTER
+       efx_filter_t            en_filter;
+       const efx_filter_ops_t  *en_efop;
+#endif /* EFSYS_OPT_FILTER */
        uint32_t                en_vport_id;
        union {
                int     enu_unused;