Enable receive side scaling

Signed-off-by: Serhii Iliushyk <sil-...@napatech.com>
---
 doc/guides/nics/features/ntnic.ini            |  3 +
 drivers/net/ntnic/include/create_elements.h   |  1 +
 drivers/net/ntnic/include/flow_api.h          |  2 +
 drivers/net/ntnic/nthw/flow_api/flow_api.c    |  6 ++
 .../profile_inline/flow_api_profile_inline.c  | 43 +++++++++++
 drivers/net/ntnic/ntnic_ethdev.c              | 77 +++++++++++++++++++
 drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 73 ++++++++++++++++++
 drivers/net/ntnic/ntnic_mod_reg.h             |  7 ++
 8 files changed, 212 insertions(+)

diff --git a/doc/guides/nics/features/ntnic.ini 
b/doc/guides/nics/features/ntnic.ini
index 4cb9509742..e5d5abd0ed 100644
--- a/doc/guides/nics/features/ntnic.ini
+++ b/doc/guides/nics/features/ntnic.ini
@@ -10,6 +10,8 @@ Link status          = Y
 Queue start/stop     = Y
 Unicast MAC filter   = Y
 Multicast MAC filter = Y
+RSS hash             = Y
+RSS key update       = Y
 Linux                = Y
 x86-64               = Y
 
@@ -37,3 +39,4 @@ port_id              = Y
 queue                = Y
 raw_decap            = Y
 raw_encap            = Y
+rss                  = Y
diff --git a/drivers/net/ntnic/include/create_elements.h 
b/drivers/net/ntnic/include/create_elements.h
index 70e6cad195..eaa578e72a 100644
--- a/drivers/net/ntnic/include/create_elements.h
+++ b/drivers/net/ntnic/include/create_elements.h
@@ -27,6 +27,7 @@ struct cnv_attr_s {
 
 struct cnv_action_s {
        struct rte_flow_action flow_actions[MAX_ACTIONS];
+       struct rte_flow_action_rss flow_rss;
        struct flow_action_raw_encap encap;
        struct flow_action_raw_decap decap;
        struct rte_flow_action_queue queue;
diff --git a/drivers/net/ntnic/include/flow_api.h 
b/drivers/net/ntnic/include/flow_api.h
index 2e96fa5bed..4a1525f237 100644
--- a/drivers/net/ntnic/include/flow_api.h
+++ b/drivers/net/ntnic/include/flow_api.h
@@ -114,6 +114,8 @@ struct flow_nic_dev {
        struct flow_eth_dev *eth_base;
        pthread_mutex_t mtx;
 
+       /* RSS hashing configuration */
+       struct nt_eth_rss_conf rss_conf;
        /* next NIC linked list */
        struct flow_nic_dev *next;
 };
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c 
b/drivers/net/ntnic/nthw/flow_api/flow_api.c
index 34f2cad2cd..d61044402d 100644
--- a/drivers/net/ntnic/nthw/flow_api/flow_api.c
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c
@@ -1061,6 +1061,12 @@ static const struct flow_filter_ops ops = {
        .flow_destroy = flow_destroy,
        .flow_flush = flow_flush,
        .flow_dev_dump = flow_dev_dump,
+
+       /*
+        * Other
+        */
+        .hw_mod_hsh_rcp_flush = hw_mod_hsh_rcp_flush,
+        .flow_nic_set_hasher_fields = flow_nic_set_hasher_fields,
 };
 
 void init_flow_filter(void)
diff --git 
a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c 
b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index 1dfd96eaac..bbf450697c 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -603,6 +603,49 @@ static int interpret_flow_actions(const struct 
flow_eth_dev *dev,
 
                        break;
 
+               case RTE_FLOW_ACTION_TYPE_RSS:
+                       NT_LOG(DBG, FILTER, "Dev:%p: RTE_FLOW_ACTION_TYPE_RSS", 
dev);
+
+                       if (action[aidx].conf) {
+                               struct rte_flow_action_rss rss_tmp;
+                               const struct rte_flow_action_rss *rss =
+                                       memcpy_mask_if(&rss_tmp, 
action[aidx].conf,
+                                       action_mask ? action_mask[aidx].conf : 
NULL,
+                                       sizeof(struct rte_flow_action_rss));
+
+                               if (rss->key_len > MAX_RSS_KEY_LEN) {
+                                       NT_LOG(ERR, FILTER,
+                                               "ERROR: RSS hash key length %u 
exceeds maximum value %u",
+                                               rss->key_len, MAX_RSS_KEY_LEN);
+                                       
flow_nic_set_error(ERR_RSS_TOO_LONG_KEY, error);
+                                       return -1;
+                               }
+
+                               for (uint32_t i = 0; i < rss->queue_num; ++i) {
+                                       int hw_id = rx_queue_idx_to_hw_id(dev, 
rss->queue[i]);
+
+                                       
fd->dst_id[fd->dst_num_avail].owning_port_id = dev->port;
+                                       fd->dst_id[fd->dst_num_avail].id = 
hw_id;
+                                       fd->dst_id[fd->dst_num_avail].type = 
PORT_VIRT;
+                                       fd->dst_id[fd->dst_num_avail].active = 
1;
+                                       fd->dst_num_avail++;
+                               }
+
+                               fd->hsh.func = rss->func;
+                               fd->hsh.types = rss->types;
+                               fd->hsh.key = rss->key;
+                               fd->hsh.key_len = rss->key_len;
+
+                               NT_LOG(DBG, FILTER,
+                                       "Dev:%p: RSS func: %d, types: 0x%" 
PRIX64 ", key_len: %d",
+                                       dev, rss->func, rss->types, 
rss->key_len);
+
+                               fd->full_offload = 0;
+                               *num_queues += rss->queue_num;
+                       }
+
+                       break;
+
                case RTE_FLOW_ACTION_TYPE_MARK:
                        NT_LOG(DBG, FILTER, "Dev:%p: 
RTE_FLOW_ACTION_TYPE_MARK", dev);
 
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index bfca8f28b1..1b25621537 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -214,6 +214,14 @@ eth_dev_infos_get(struct rte_eth_dev *eth_dev, struct 
rte_eth_dev_info *dev_info
        dev_info->max_rx_pktlen = HW_MAX_PKT_LEN;
        dev_info->max_mtu = MAX_MTU;
 
+       if (p_adapter_info->fpga_info.profile == FPGA_INFO_PROFILE_INLINE) {
+               dev_info->flow_type_rss_offloads = NT_ETH_RSS_OFFLOAD_MASK;
+               dev_info->hash_key_size = MAX_RSS_KEY_LEN;
+
+               dev_info->rss_algo_capa = RTE_ETH_HASH_ALGO_CAPA_MASK(DEFAULT) |
+                       RTE_ETH_HASH_ALGO_CAPA_MASK(TOEPLITZ);
+       }
+
        if (internals->p_drv) {
                dev_info->max_rx_queues = internals->nb_rx_queues;
                dev_info->max_tx_queues = internals->nb_tx_queues;
@@ -1372,6 +1380,73 @@ promiscuous_enable(struct rte_eth_dev __rte_unused(*dev))
        return 0;
 }
 
+static int eth_dev_rss_hash_update(struct rte_eth_dev *eth_dev, struct 
rte_eth_rss_conf *rss_conf)
+{
+       const struct flow_filter_ops *flow_filter_ops = get_flow_filter_ops();
+
+       if (flow_filter_ops == NULL) {
+               NT_LOG_DBGX(ERR, NTNIC, "flow_filter module uninitialized");
+               return -1;
+       }
+
+       struct pmd_internals *internals = (struct pmd_internals 
*)eth_dev->data->dev_private;
+
+       struct flow_nic_dev *ndev = internals->flw_dev->ndev;
+       struct nt_eth_rss_conf tmp_rss_conf = { 0 };
+       const int hsh_idx = 0;  /* hsh index 0 means the default receipt in HSH 
module */
+       int res = 0;
+
+       if (rss_conf->rss_key != NULL) {
+               if (rss_conf->rss_key_len > MAX_RSS_KEY_LEN) {
+                       NT_LOG(ERR, NTNIC,
+                               "ERROR: - RSS hash key length %u exceeds 
maximum value %u",
+                               rss_conf->rss_key_len, MAX_RSS_KEY_LEN);
+                       return -1;
+               }
+
+               rte_memcpy(&tmp_rss_conf.rss_key, rss_conf->rss_key, 
rss_conf->rss_key_len);
+       }
+
+       tmp_rss_conf.algorithm = rss_conf->algorithm;
+
+       tmp_rss_conf.rss_hf = rss_conf->rss_hf;
+       res = flow_filter_ops->flow_nic_set_hasher_fields(ndev, hsh_idx, 
tmp_rss_conf);
+
+       if (res == 0) {
+               flow_filter_ops->hw_mod_hsh_rcp_flush(&ndev->be, hsh_idx, 1);
+               rte_memcpy(&ndev->rss_conf, &tmp_rss_conf, sizeof(struct 
nt_eth_rss_conf));
+
+       } else {
+               NT_LOG(ERR, NTNIC, "ERROR: - RSS hash update failed with error 
%i", res);
+       }
+
+       return res;
+}
+
+static int rss_hash_conf_get(struct rte_eth_dev *eth_dev, struct 
rte_eth_rss_conf *rss_conf)
+{
+       struct pmd_internals *internals = (struct pmd_internals 
*)eth_dev->data->dev_private;
+       struct flow_nic_dev *ndev = internals->flw_dev->ndev;
+
+       rss_conf->algorithm = (enum 
rte_eth_hash_function)ndev->rss_conf.algorithm;
+
+       rss_conf->rss_hf = ndev->rss_conf.rss_hf;
+
+       /*
+        * copy full stored key into rss_key and pad it with
+        * zeros up to rss_key_len / MAX_RSS_KEY_LEN
+        */
+       if (rss_conf->rss_key != NULL) {
+               int key_len = rss_conf->rss_key_len < MAX_RSS_KEY_LEN ? 
rss_conf->rss_key_len
+                       : MAX_RSS_KEY_LEN;
+               memset(rss_conf->rss_key, 0, rss_conf->rss_key_len);
+               rte_memcpy(rss_conf->rss_key, &ndev->rss_conf.rss_key, key_len);
+               rss_conf->rss_key_len = key_len;
+       }
+
+       return 0;
+}
+
 static const struct eth_dev_ops nthw_eth_dev_ops = {
        .dev_configure = eth_dev_configure,
        .dev_start = eth_dev_start,
@@ -1395,6 +1470,8 @@ static const struct eth_dev_ops nthw_eth_dev_ops = {
        .set_mc_addr_list = eth_set_mc_addr_list,
        .flow_ops_get = dev_flow_ops_get,
        .promiscuous_enable = promiscuous_enable,
+       .rss_hash_update = eth_dev_rss_hash_update,
+       .rss_hash_conf_get = rss_hash_conf_get,
 };
 
 /*
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c 
b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
index 87b26bd315..4962ab8d5a 100644
--- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -317,6 +317,79 @@ int create_action_elements_inline(struct cnv_action_s 
*action,
                         * Non-compatible actions handled here
                         */
                        switch (type) {
+                       case RTE_FLOW_ACTION_TYPE_RSS: {
+                               const struct rte_flow_action_rss *rss =
+                                       (const struct rte_flow_action_rss 
*)actions[aidx].conf;
+
+                               switch (rss->func) {
+                               case RTE_ETH_HASH_FUNCTION_DEFAULT:
+                                       action->flow_rss.func =
+                                               (enum rte_eth_hash_function)
+                                               RTE_ETH_HASH_FUNCTION_DEFAULT;
+                                       break;
+
+                               case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+                                       action->flow_rss.func =
+                                               (enum rte_eth_hash_function)
+                                               RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+
+                                       if (rte_is_power_of_2(rss->queue_num) 
== 0) {
+                                               NT_LOG(ERR, FILTER,
+                                                       "RTE ACTION RSS - for 
Toeplitz the number of queues must be power of two");
+                                               return -1;
+                                       }
+
+                                       break;
+
+                               case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+                               case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
+                               case 
RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ_SORT:
+                               case RTE_ETH_HASH_FUNCTION_MAX:
+                               default:
+                                       NT_LOG(ERR, FILTER,
+                                               "RTE ACTION RSS - unsupported 
function: %u",
+                                               rss->func);
+                                       return -1;
+                               }
+
+                               uint64_t tmp_rss_types = 0;
+
+                               switch (rss->level) {
+                               case 1:
+                                       /* clear/override level mask specified 
at types */
+                                       tmp_rss_types = rss->types & 
(~RTE_ETH_RSS_LEVEL_MASK);
+                                       action->flow_rss.types =
+                                               tmp_rss_types | 
RTE_ETH_RSS_LEVEL_OUTERMOST;
+                                       break;
+
+                               case 2:
+                                       /* clear/override level mask specified 
at types */
+                                       tmp_rss_types = rss->types & 
(~RTE_ETH_RSS_LEVEL_MASK);
+                                       action->flow_rss.types =
+                                               tmp_rss_types | 
RTE_ETH_RSS_LEVEL_INNERMOST;
+                                       break;
+
+                               case 0:
+                                       /* keep level mask specified at types */
+                                       action->flow_rss.types = rss->types;
+                                       break;
+
+                               default:
+                                       NT_LOG(ERR, FILTER,
+                                               "RTE ACTION RSS - unsupported 
level: %u",
+                                               rss->level);
+                                       return -1;
+                               }
+
+                               action->flow_rss.level = 0;
+                               action->flow_rss.key_len = rss->key_len;
+                               action->flow_rss.queue_num = rss->queue_num;
+                               action->flow_rss.key = rss->key;
+                               action->flow_rss.queue = rss->queue;
+                               action->flow_actions[aidx].conf = 
&action->flow_rss;
+                       }
+                       break;
+
                        case RTE_FLOW_ACTION_TYPE_RAW_DECAP: {
                                const struct rte_flow_action_raw_decap *decap =
                                        (const struct rte_flow_action_raw_decap 
*)actions[aidx]
diff --git a/drivers/net/ntnic/ntnic_mod_reg.h 
b/drivers/net/ntnic/ntnic_mod_reg.h
index 12baa13800..e40ed9b949 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.h
+++ b/drivers/net/ntnic/ntnic_mod_reg.h
@@ -316,6 +316,13 @@ struct flow_filter_ops {
 
        int (*flow_flush)(struct flow_eth_dev *dev, uint16_t caller_id,
                struct rte_flow_error *error);
+
+       /*
+        * Other
+        */
+       int (*flow_nic_set_hasher_fields)(struct flow_nic_dev *ndev, int 
hsh_idx,
+               struct nt_eth_rss_conf rss_conf);
+       int (*hw_mod_hsh_rcp_flush)(struct flow_api_backend_s *be, int 
start_idx, int count);
 };
 
 void register_dev_flow_ops(const struct rte_flow_ops *ops);
-- 
2.45.0

Reply via email to