]> git.droids-corp.org - dpdk.git/commitdiff
net/sfc: fix RSS hash offload if queue action is used
authorIgor Romanov <igor.romanov@oktetlabs.ru>
Thu, 24 Sep 2020 12:40:59 +0000 (13:40 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 30 Sep 2020 17:19:15 +0000 (19:19 +0200)
When RSS hash offload is requested, the ingress filters that forward
packets to an RX queue must have an RSS context assigned to them to
calculate RSS hash, which was not always provided.

Fix it by creating a dummy RSS context that forwards packets
to the same queue and assign it to created by flow API filters when
RSS hash offload is enabled. RSS key and hash functions from
default RSS context are used.

Fixes: 5d308972954c ("ethdev: add mbuf RSS update as an offload")
Cc: stable@dpdk.org
Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
drivers/net/sfc/sfc.c
drivers/net/sfc/sfc.h
drivers/net/sfc/sfc_ethdev.c
drivers/net/sfc/sfc_flow.c
drivers/net/sfc/sfc_flow.h
drivers/net/sfc/sfc_rx.c
drivers/net/sfc/sfc_rx.h

index 4be65c15dcf4557ccfa3442968a0412a6649db98..615e15af647eb5ca9df265b9a41682f82bf121a0 100644 (file)
@@ -685,6 +685,7 @@ sfc_rss_attach(struct sfc_adapter *sa)
        efx_intr_fini(sa->nic);
 
        rte_memcpy(rss->key, default_rss_key, sizeof(rss->key));
+       rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT;
 
        return 0;
 
index fa7c79b80bc6e3b1b2e3d41d5d6ca698e278e7d1..5ea29362e19fab76dcd70b32be9c98f219d15236 100644 (file)
@@ -157,6 +157,8 @@ struct sfc_rss {
        efx_rx_hash_type_t              hash_types;
        unsigned int                    tbl[EFX_RSS_TBL_SIZE];
        uint8_t                         key[EFX_RSS_KEY_SIZE];
+
+       uint32_t                        dummy_rss_context;
 };
 
 /* Adapter private data shared by primary and secondary processes */
index 6e6eb16860c7cbb9df78318dd9fe115a0ded2a52..602351bcc47f5d536d83a93bc92daa8e0ac05c1b 100644 (file)
@@ -1544,8 +1544,15 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
        struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
        struct sfc_rss *rss = &sfc_sa2shared(sa)->rss;
        unsigned int efx_hash_types;
+       uint32_t contexts[] = {EFX_RSS_CONTEXT_DEFAULT, rss->dummy_rss_context};
+       unsigned int n_contexts;
+       unsigned int mode_i = 0;
+       unsigned int key_i = 0;
+       unsigned int i = 0;
        int rc = 0;
 
+       n_contexts = rss->dummy_rss_context == EFX_RSS_CONTEXT_DEFAULT ? 1 : 2;
+
        if (sfc_sa2shared(sa)->isolated)
                return -ENOTSUP;
 
@@ -1572,19 +1579,24 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
        if (rc != 0)
                goto fail_rx_hf_rte_to_efx;
 
-       rc = efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT,
-                                  rss->hash_alg, efx_hash_types, B_TRUE);
-       if (rc != 0)
-               goto fail_scale_mode_set;
+       for (mode_i = 0; mode_i < n_contexts; mode_i++) {
+               rc = efx_rx_scale_mode_set(sa->nic, contexts[mode_i],
+                                          rss->hash_alg, efx_hash_types,
+                                          B_TRUE);
+               if (rc != 0)
+                       goto fail_scale_mode_set;
+       }
 
        if (rss_conf->rss_key != NULL) {
                if (sa->state == SFC_ADAPTER_STARTED) {
-                       rc = efx_rx_scale_key_set(sa->nic,
-                                                 EFX_RSS_CONTEXT_DEFAULT,
-                                                 rss_conf->rss_key,
-                                                 sizeof(rss->key));
-                       if (rc != 0)
-                               goto fail_scale_key_set;
+                       for (key_i = 0; key_i < n_contexts; key_i++) {
+                               rc = efx_rx_scale_key_set(sa->nic,
+                                                         contexts[key_i],
+                                                         rss_conf->rss_key,
+                                                         sizeof(rss->key));
+                               if (rc != 0)
+                                       goto fail_scale_key_set;
+                       }
                }
 
                rte_memcpy(rss->key, rss_conf->rss_key, sizeof(rss->key));
@@ -1597,12 +1609,20 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
        return 0;
 
 fail_scale_key_set:
-       if (efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT,
-                                 EFX_RX_HASHALG_TOEPLITZ,
-                                 rss->hash_types, B_TRUE) != 0)
-               sfc_err(sa, "failed to restore RSS mode");
+       for (i = 0; i < key_i; i++) {
+               if (efx_rx_scale_key_set(sa->nic, contexts[i], rss->key,
+                                        sizeof(rss->key)) != 0)
+                       sfc_err(sa, "failed to restore RSS key");
+       }
 
 fail_scale_mode_set:
+       for (i = 0; i < mode_i; i++) {
+               if (efx_rx_scale_mode_set(sa->nic, contexts[i],
+                                         EFX_RX_HASHALG_TOEPLITZ,
+                                         rss->hash_types, B_TRUE) != 0)
+                       sfc_err(sa, "failed to restore RSS mode");
+       }
+
 fail_rx_hf_rte_to_efx:
        sfc_adapter_unlock(sa);
        return -rc;
index 1a3c0d618b92b070a6fdd2d7e051c929d5ae7c0a..cb802d7991ffec02ad1cbbd704aeba12ab4b7c7d 100644 (file)
@@ -1293,6 +1293,7 @@ sfc_flow_parse_queue(struct sfc_adapter *sa,
        struct sfc_flow_spec *spec = &flow->spec;
        struct sfc_flow_spec_filter *spec_filter = &spec->filter;
        struct sfc_rxq *rxq;
+       struct sfc_rxq_info *rxq_info;
 
        if (queue->index >= sfc_sa2shared(sa)->rxq_count)
                return -EINVAL;
@@ -1300,6 +1301,10 @@ sfc_flow_parse_queue(struct sfc_adapter *sa,
        rxq = &sa->rxq_ctrl[queue->index];
        spec_filter->template.efs_dmaq_id = (uint16_t)rxq->hw_index;
 
+       rxq_info = &sfc_sa2shared(sa)->rxq_info[queue->index];
+       spec_filter->rss_hash_required = !!(rxq_info->rxq_flags &
+                                           SFC_RXQ_FLAG_RSS_HASH);
+
        return 0;
 }
 
@@ -1465,13 +1470,34 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
        struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
        struct sfc_flow_rss *flow_rss = &spec_filter->rss_conf;
        uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
+       boolean_t create_context;
        unsigned int i;
        int rc = 0;
 
-       if (spec_filter->rss) {
-               unsigned int rss_spread = MIN(flow_rss->rxq_hw_index_max -
-                                             flow_rss->rxq_hw_index_min + 1,
-                                             EFX_MAXRSS);
+       create_context = spec_filter->rss || (spec_filter->rss_hash_required &&
+                       rss->dummy_rss_context == EFX_RSS_CONTEXT_DEFAULT);
+
+       if (create_context) {
+               unsigned int rss_spread;
+               unsigned int rss_hash_types;
+               uint8_t *rss_key;
+
+               if (spec_filter->rss) {
+                       rss_spread = MIN(flow_rss->rxq_hw_index_max -
+                                       flow_rss->rxq_hw_index_min + 1,
+                                       EFX_MAXRSS);
+                       rss_hash_types = flow_rss->rss_hash_types;
+                       rss_key = flow_rss->rss_key;
+               } else {
+                       /*
+                        * Initialize dummy RSS context parameters to have
+                        * valid RSS hash. Use default RSS hash function and
+                        * key.
+                        */
+                       rss_spread = 1;
+                       rss_hash_types = rss->hash_types;
+                       rss_key = rss->key;
+               }
 
                rc = efx_rx_scale_context_alloc(sa->nic,
                                                EFX_RX_SCALE_EXCLUSIVE,
@@ -1482,16 +1508,19 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 
                rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context,
                                           rss->hash_alg,
-                                          flow_rss->rss_hash_types, B_TRUE);
+                                          rss_hash_types, B_TRUE);
                if (rc != 0)
                        goto fail_scale_mode_set;
 
                rc = efx_rx_scale_key_set(sa->nic, efs_rss_context,
-                                         flow_rss->rss_key,
-                                         sizeof(rss->key));
+                                         rss_key, sizeof(rss->key));
                if (rc != 0)
                        goto fail_scale_key_set;
+       } else {
+               efs_rss_context = rss->dummy_rss_context;
+       }
 
+       if (spec_filter->rss || spec_filter->rss_hash_required) {
                /*
                 * At this point, fully elaborated filter specifications
                 * have been produced from the template. To make sure that
@@ -1502,8 +1531,9 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
                        efx_filter_spec_t *spec = &spec_filter->filters[i];
 
                        spec->efs_rss_context = efs_rss_context;
-                       spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
                        spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
+                       if (spec_filter->rss)
+                               spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
                }
        }
 
@@ -1511,7 +1541,12 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
        if (rc != 0)
                goto fail_filter_insert;
 
-       if (spec_filter->rss) {
+       if (create_context) {
+               unsigned int dummy_tbl[RTE_DIM(flow_rss->rss_tbl)] = {0};
+               unsigned int *tbl;
+
+               tbl = spec_filter->rss ? flow_rss->rss_tbl : dummy_tbl;
+
                /*
                 * Scale table is set after filter insertion because
                 * the table entries are relative to the base RxQ ID
@@ -1521,10 +1556,13 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
                 * the table entries, and the operation will succeed
                 */
                rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context,
-                                         flow_rss->rss_tbl,
-                                         RTE_DIM(flow_rss->rss_tbl));
+                                         tbl, RTE_DIM(flow_rss->rss_tbl));
                if (rc != 0)
                        goto fail_scale_tbl_set;
+
+               /* Remember created dummy RSS context */
+               if (!spec_filter->rss)
+                       rss->dummy_rss_context = efs_rss_context;
        }
 
        return 0;
@@ -1535,7 +1573,7 @@ fail_scale_tbl_set:
 fail_filter_insert:
 fail_scale_key_set:
 fail_scale_mode_set:
-       if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT)
+       if (create_context)
                efx_rx_scale_context_free(sa->nic, efs_rss_context);
 
 fail_scale_context_alloc:
@@ -2634,12 +2672,19 @@ sfc_flow_fini(struct sfc_adapter *sa)
 void
 sfc_flow_stop(struct sfc_adapter *sa)
 {
+       struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+       struct sfc_rss *rss = &sas->rss;
        struct rte_flow *flow;
 
        SFC_ASSERT(sfc_adapter_is_locked(sa));
 
        TAILQ_FOREACH(flow, &sa->flow_list, entries)
                sfc_flow_remove(sa, flow, NULL);
+
+       if (rss->dummy_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
+               efx_rx_scale_context_free(sa->nic, rss->dummy_rss_context);
+               rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT;
+       }
 }
 
 int
index 5a7dad8f09751b75c5de0054259c7c1dc81bf177..433c7a31e9f118ca125767c5320c4e7d21f5c8d9 100644 (file)
@@ -52,6 +52,8 @@ struct sfc_flow_spec_filter {
        unsigned int count;
        /* RSS toggle */
        boolean_t rss;
+       /* RSS hash toggle */
+       boolean_t rss_hash_required;
        /* RSS configuration */
        struct sfc_flow_rss rss_conf;
 };
index dccafb163a840f330299ca92434eeb2c79742267..3e5c8e42da6bf484b84bffe0d08d4fcdbe62d5f0 100644 (file)
@@ -1139,6 +1139,13 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index,
        rxq_info->refill_threshold =
                RTE_MAX(rx_free_thresh, SFC_RX_REFILL_BULK);
        rxq_info->refill_mb_pool = mb_pool;
+
+       if (rss->hash_support == EFX_RX_HASH_AVAILABLE && rss->channels > 0 &&
+           (offloads & DEV_RX_OFFLOAD_RSS_HASH))
+               rxq_info->rxq_flags = SFC_RXQ_FLAG_RSS_HASH;
+       else
+               rxq_info->rxq_flags = 0;
+
        rxq->buf_size = buf_size;
 
        rc = sfc_dma_alloc(sa, "rxq", sw_index,
@@ -1154,11 +1161,7 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index,
        info.buf_size = buf_size;
        info.batch_max = encp->enc_rx_batch_max;
        info.prefix_size = encp->enc_rx_prefix_size;
-
-       if (rss->hash_support == EFX_RX_HASH_AVAILABLE && rss->channels > 0 &&
-           (offloads & DEV_RX_OFFLOAD_RSS_HASH))
-               info.flags |= SFC_RXQ_FLAG_RSS_HASH;
-
+       info.flags = rxq_info->rxq_flags;
        info.rxq_entries = rxq_info->entries;
        info.rxq_hw_ring = rxq->mem.esm_base;
        info.evq_hw_index = sfc_evq_index_by_rxq_sw_index(sa, sw_index);
index 697ea29d625cf26af1ff5221376adef9402ecc2b..b0b5327a4963649a7ea4e6d3ac3ac1def9cdd9aa 100644 (file)
@@ -115,6 +115,7 @@ struct sfc_rxq_info {
        boolean_t               deferred_started;
        unsigned int            refill_threshold;
        struct rte_mempool      *refill_mb_pool;
+       unsigned int            rxq_flags;
 };
 
 struct sfc_rxq_info *sfc_rxq_info_by_dp_rxq(const struct sfc_dp_rxq *dp_rxq);