Author: arybchik
Date: Wed Dec 26 09:42:40 2018
New Revision: 342487
URL: https://svnweb.freebsd.org/changeset/base/342487

Log:
  MFC r340804
  
  sfxge(4): insert filters for encapsulated packets
  
  On Medford, with full-featured firmware running, encapsulated
  packets may not be delivered unless filters are inserted for
  them, as ordinary filters are not applied to encapsulated
  packets. So filters for encapsulated packets need to be
  inserted for each class of encapsulated packet. For simplicity,
  catch-all filters are always inserted. These may match more
  packets than the OS has asked for, but trying to insert more
  precise filters increases complexity for little gain.
  
  Submitted by:   Mark Spender <mspender at solarflare.com>
  Sponsored by:   Solarflare Communications, Inc.
  Differential Revision:  https://reviews.freebsd.org/D18074

Modified:
  stable/10/sys/dev/sfxge/common/ef10_filter.c
  stable/10/sys/dev/sfxge/common/ef10_impl.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/sfxge/common/ef10_filter.c
==============================================================================
--- stable/10/sys/dev/sfxge/common/ef10_filter.c        Wed Dec 26 09:41:04 
2018        (r342486)
+++ stable/10/sys/dev/sfxge/common/ef10_filter.c        Wed Dec 26 09:42:40 
2018        (r342487)
@@ -1234,6 +1234,108 @@ fail1:
        return (rc);
 }
 
+typedef struct ef10_filter_encap_entry_s {
+       uint16_t                ether_type;
+       efx_tunnel_protocol_t   encap_type;
+       uint32_t                inner_frame_match;
+} ef10_filter_encap_entry_t;
+
+#define EF10_ENCAP_FILTER_ENTRY(ipv, encap_type, inner_frame_match)    \
+       { EFX_ETHER_TYPE_##ipv, EFX_TUNNEL_PROTOCOL_##encap_type,               
\
+           EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_##inner_frame_match }
+
+static ef10_filter_encap_entry_t ef10_filter_encap_list[] = {
+       EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, MCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, MCAST_DST),
+
+       EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, MCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, MCAST_DST),
+
+       EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, MCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, UCAST_DST),
+       EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, MCAST_DST),
+};
+
+#undef EF10_ENCAP_FILTER_ENTRY
+
+static __checkReturn   efx_rc_t
+ef10_filter_insert_encap_filters(
+       __in            efx_nic_t *enp,
+       __in            boolean_t mulcst,
+       __in            efx_filter_flags_t filter_flags)
+{
+       ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
+       uint32_t i;
+       efx_rc_t rc;
+
+       EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(ef10_filter_encap_list) <=
+                           EFX_ARRAY_SIZE(table->eft_encap_filter_indexes));
+
+       /*
+        * On Medford, full-featured firmware can identify packets as being
+        * tunnel encapsulated, even if no encapsulated packet offloads are in
+        * use. When packets are identified as such, ordinary filters are not
+        * applied, only ones specific to encapsulated packets. Hence we need to
+        * insert filters for encapsulated packets in order to receive them.
+        *
+        * Separate filters need to be inserted for each ether type,
+        * encapsulation type, and inner frame type (unicast or multicast). To
+        * keep things simple and reduce the number of filters needed, catch-all
+        * filters for all combinations of types are inserted, even if
+        * all_unicst or all_mulcst have not been set. (These catch-all filters
+        * may well, however, fail to insert on unprivileged functions.)
+        */
+       table->eft_encap_filter_count = 0;
+       for (i = 0; i < EFX_ARRAY_SIZE(ef10_filter_encap_list); i++) {
+               efx_filter_spec_t spec;
+               ef10_filter_encap_entry_t *encap_filter =
+                       &ef10_filter_encap_list[i];
+
+               /*
+                * Skip multicast filters if we've not been asked for
+                * any multicast traffic.
+                */
+               if ((mulcst == B_FALSE) &&
+                   (encap_filter->inner_frame_match ==
+                    EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST))
+                               continue;
+
+               efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
+                                       filter_flags,
+                                       table->eft_default_rxq);
+               efx_filter_spec_set_ether_type(&spec, encap_filter->ether_type);
+               rc = efx_filter_spec_set_encap_type(&spec,
+                                           encap_filter->encap_type,
+                                           encap_filter->inner_frame_match);
+               if (rc != 0)
+                       goto fail1;
+
+               rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
+                           &table->eft_encap_filter_indexes[
+                                   table->eft_encap_filter_count]);
+               if (rc != 0) {
+                       if (rc != EACCES)
+                               goto fail2;
+               } else {
+                       table->eft_encap_filter_count++;
+               }
+       }
+
+       return (0);
+
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
 static                 void
 ef10_filter_remove_old(
        __in            efx_nic_t *enp)
@@ -1329,6 +1431,12 @@ ef10_filter_reconfigure(
                }
                table->eft_mulcst_filter_count = 0;
 
+               for (i = 0; i < table->eft_encap_filter_count; i++) {
+                       (void) ef10_filter_delete_internal(enp,
+                                       table->eft_encap_filter_indexes[i]);
+               }
+               table->eft_encap_filter_count = 0;
+
                return (0);
        }
 
@@ -1346,6 +1454,10 @@ ef10_filter_reconfigure(
                ef10_filter_set_entry_auto_old(table,
                                        table->eft_mulcst_filter_indexes[i]);
        }
+       for (i = 0; i < table->eft_encap_filter_count; i++) {
+               ef10_filter_set_entry_auto_old(table,
+                                       table->eft_encap_filter_indexes[i]);
+       }
 
        /*
         * Insert or renew unicast filters.
@@ -1461,6 +1573,13 @@ ef10_filter_reconfigure(
                                        goto fail4;
                        }
                }
+       }
+
+       if (encp->enc_tunnel_encapsulations_supported != 0) {
+               /* Try to insert filters for encapsulated packets. */
+               (void) ef10_filter_insert_encap_filters(enp,
+                                           mulcst || all_mulcst || brdcst,
+                                           filter_flags);
        }
 
        /* Remove old filters which were not renewed */

Modified: stable/10/sys/dev/sfxge/common/ef10_impl.h
==============================================================================
--- stable/10/sys/dev/sfxge/common/ef10_impl.h  Wed Dec 26 09:41:04 2018        
(r342486)
+++ stable/10/sys/dev/sfxge/common/ef10_impl.h  Wed Dec 26 09:42:40 2018        
(r342487)
@@ -990,6 +990,13 @@ typedef struct ef10_filter_entry_s {
 /* Allow for the broadcast address to be added to the multicast list */
 #define        EFX_EF10_FILTER_MULTICAST_FILTERS_MAX   
(EFX_MAC_MULTICAST_LIST_MAX + 1)
 
+/*
+ * For encapsulated packets, there is one filter each for each combination of
+ * IPv4 or IPv6 outer frame, VXLAN, GENEVE or NVGRE packet type, and unicast or
+ * multicast inner frames.
+ */
+#define EFX_EF10_FILTER_ENCAP_FILTERS_MAX      12
+
 typedef struct ef10_filter_table_s {
        ef10_filter_entry_t     eft_entry[EFX_EF10_FILTER_TBL_ROWS];
        efx_rxq_t               *eft_default_rxq;
@@ -1001,6 +1008,9 @@ typedef struct ef10_filter_table_s {
            EFX_EF10_FILTER_MULTICAST_FILTERS_MAX];
        uint32_t                eft_mulcst_filter_count;
        boolean_t               eft_using_all_mulcst;
+       uint32_t                eft_encap_filter_indexes[
+           EFX_EF10_FILTER_ENCAP_FILTERS_MAX];
+       uint32_t                eft_encap_filter_count;
 } ef10_filter_table_t;
 
        __checkReturn   efx_rc_t
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to