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