From: Dengdui Huang <huangdeng...@huawei.com> The hardware determines the priority of the flow rule based on the position of the rule in the hardware flow director table. Lower index denotes higher priority (it means when a packet matches multiple indexes, the smaller index wins). This patch implements flow priority based on this feature.
To avoid affecting the current use, use runtime config 'fdir_index_config' to select flow director index strategy. The options are as follows: 1. hash: Default config, the rule priority level cannot be set. The driver generates a flow index based on the hash of the rte_flow key. 2. priority: The flow rule priority feature is supported. The driver uses the rte_flow priority field as the flow director index. Signed-off-by: Dengdui Huang <huangdeng...@huawei.com> Signed-off-by: Jie Hai <haij...@huawei.com> --- doc/guides/nics/hns3.rst | 12 +++++++ drivers/net/hns3/hns3_common.c | 25 ++++++++++++++ drivers/net/hns3/hns3_common.h | 1 + drivers/net/hns3/hns3_dump.c | 2 ++ drivers/net/hns3/hns3_ethdev.c | 3 +- drivers/net/hns3/hns3_fdir.c | 62 ++++++++++++++++++++++++---------- drivers/net/hns3/hns3_fdir.h | 10 ++++++ drivers/net/hns3/hns3_flow.c | 45 +++++++++++++++++++++--- 8 files changed, 136 insertions(+), 24 deletions(-) diff --git a/doc/guides/nics/hns3.rst b/doc/guides/nics/hns3.rst index bdc10da1c74f..b8e79c1b575d 100644 --- a/doc/guides/nics/hns3.rst +++ b/doc/guides/nics/hns3.rst @@ -193,6 +193,15 @@ Runtime Configuration ``+outvlan-sctptag``: means disable sctp tag tuple, and enable outer vlan tuple. ``+outvlan-tunvni``: means disable tunnel vni tuple, and enable outer vlan tuple. +- ``fdir_index_config`` (default ``hash``) + + Used to select flow director index strategy, the flow director index is the index + position in the hardware flow director table. Lower index denotes higher priority + (it means when a packet matches multiple indexes, the smaller index wins). + Current supported options are as follows: + ``hash``: The driver generates a flow index based on the hash of the rte_flow key. + ``priority``: the driver uses the rte_flow priority field as the flow director index. + Driver compilation and testing ------------------------------ @@ -322,6 +331,9 @@ Generic flow API configuration for hardware which will affect other rules. The rule just setting input tuple is completely independent. + In addition, if the rule priority level is set, no error is reported, + but the rule priority level does not take effect. + Run ``testpmd``: .. code-block:: console diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c index 99a1d59a8a68..25a45212bed6 100644 --- a/drivers/net/hns3/hns3_common.c +++ b/drivers/net/hns3/hns3_common.c @@ -290,6 +290,27 @@ hns3_parse_fdir_tuple_config(const char *key, const char *value, void *args) return 0; } +static int +hns3_parse_fdir_index_config(const char *key, const char *value, void *args) +{ + enum hns3_fdir_index_config cfg; + + if (strcmp(value, "hash") == 0) { + cfg = HNS3_FDIR_INDEX_CONFIG_HASH; + } else if (strcmp(value, "priority") == 0) { + cfg = HNS3_FDIR_INDEX_CONFIG_PRIORITY; + } else { + PMD_INIT_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\", " + "value must be 'hash' or 'priority'", + value, key); + return -1; + } + + *(enum hns3_fdir_index_config *)args = cfg; + + return 0; +} + void hns3_parse_devargs(struct rte_eth_dev *dev) { @@ -333,6 +354,10 @@ hns3_parse_devargs(struct rte_eth_dev *dev) HNS3_DEVARG_FDIR_TUPLE_CONFIG, &hns3_parse_fdir_tuple_config, &hns->pf.fdir.tuple_cfg); + (void)rte_kvargs_process(kvlist, + HNS3_DEVARG_FDIR_INDEX_CONFIG, + &hns3_parse_fdir_index_config, + &hns->pf.fdir.index_cfg); } rte_kvargs_free(kvlist); diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h index ca909365e420..7b3f96b01a82 100644 --- a/drivers/net/hns3/hns3_common.h +++ b/drivers/net/hns3/hns3_common.h @@ -29,6 +29,7 @@ enum { #define HNS3_DEVARG_FDIR_VLAN_MATCH_MODE "fdir_vlan_match_mode" #define HNS3_DEVARG_FDIR_TUPLE_CONFIG "fdir_tuple_config" +#define HNS3_DEVARG_FDIR_INDEX_CONFIG "fdir_index_config" #define MSEC_PER_SEC 1000L #define USEC_PER_MSEC 1000L diff --git a/drivers/net/hns3/hns3_dump.c b/drivers/net/hns3/hns3_dump.c index 1a50391851b4..738dcb0c42fc 100644 --- a/drivers/net/hns3/hns3_dump.c +++ b/drivers/net/hns3/hns3_dump.c @@ -169,6 +169,7 @@ hns3_get_fdir_basic_info(FILE *file, struct hns3_pf *pf) "\t -- mode=%u max_key_len=%u rule_num:%u cnt_num:%u\n" "\t -- key_sel=%u tuple_active=0x%x meta_data_active=0x%x\n" "\t -- ipv6_word_en: in_s=%u in_d=%u out_s=%u out_d=%u\n" + "\t -- index_cfg: %s\n" "\t -- tuple_config: %s\n" "\t -- active_tuples:\n", fdcfg->fd_mode, fdcfg->max_key_length, @@ -181,6 +182,7 @@ hns3_get_fdir_basic_info(FILE *file, struct hns3_pf *pf) fdcfg->key_cfg[HNS3_FD_STAGE_1].inner_dipv6_word_en, fdcfg->key_cfg[HNS3_FD_STAGE_1].outer_sipv6_word_en, fdcfg->key_cfg[HNS3_FD_STAGE_1].outer_dipv6_word_en, + hns3_fdir_index_config_name(pf->fdir.index_cfg), hns3_tuple_config_name(pf->fdir.tuple_cfg)); for (i = 0; i < MAX_TUPLE; i++) { diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 365b8529698b..0b3df565feb0 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -6674,7 +6674,8 @@ RTE_PMD_REGISTER_PARAM_STRING(net_hns3, HNS3_DEVARG_FDIR_VLAN_MATCH_MODE "=strict|nostrict " HNS3_DEVARG_FDIR_TUPLE_CONFIG "=+outvlan-insmac|+outvlan-indmac|" "+outvlan-insip|+outvlan-indip" - "+outvlan-sctptag|+outvlan-tunvni "); + "+outvlan-sctptag|+outvlan-tunvni " + HNS3_DEVARG_FDIR_INDEX_CONFIG "=hash|priority "); RTE_LOG_REGISTER_SUFFIX(hns3_logtype_init, init, NOTICE); RTE_LOG_REGISTER_SUFFIX(hns3_logtype_driver, driver, NOTICE); #ifdef RTE_ETHDEV_DEBUG_RX diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c index a354d1d32f16..d18d08353565 100644 --- a/drivers/net/hns3/hns3_fdir.c +++ b/drivers/net/hns3/hns3_fdir.c @@ -981,39 +981,44 @@ static int hns3_insert_fdir_filter(struct hns3_hw *hw, { struct hns3_fdir_key_conf *key; hash_sig_t sig; - int ret; + int index; key = &fdir_filter->fdir_conf.key_conf; sig = rte_hash_crc(key, sizeof(*key), 0); - ret = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig); - if (ret < 0) { - hns3_err(hw, "Hash table full? err:%d!", ret); - return ret; + index = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig); + if (index < 0) { + hns3_err(hw, "Hash table full? err:%d!", index); + return index; } - fdir_info->hash_map[ret] = fdir_filter; + if (fdir_info->index_cfg == HNS3_FDIR_INDEX_CONFIG_PRIORITY) + index = fdir_filter->fdir_conf.location; + + fdir_info->hash_map[index] = fdir_filter; TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries); - return ret; + return index; } static int hns3_remove_fdir_filter(struct hns3_hw *hw, struct hns3_fdir_info *fdir_info, - struct hns3_fdir_key_conf *key) + struct hns3_fdir_rule *rule) { struct hns3_fdir_rule_ele *fdir_filter; hash_sig_t sig; - int ret; + int index; - sig = rte_hash_crc(key, sizeof(*key), 0); - ret = rte_hash_del_key_with_hash(fdir_info->hash_handle, key, sig); - if (ret < 0) { - hns3_err(hw, "Delete hash key fail ret=%d", ret); - return ret; + sig = rte_hash_crc(&rule->key_conf, sizeof(rule->key_conf), 0); + index = rte_hash_del_key_with_hash(fdir_info->hash_handle, &rule->key_conf, sig); + if (index < 0) { + hns3_err(hw, "Delete hash key fail ret=%d", index); + return index; } - fdir_filter = fdir_info->hash_map[ret]; - fdir_info->hash_map[ret] = NULL; + if (fdir_info->index_cfg == HNS3_FDIR_INDEX_CONFIG_PRIORITY) + index = rule->location; + fdir_filter = fdir_info->hash_map[index]; + fdir_info->hash_map[index] = NULL; TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries); rte_free(fdir_filter); @@ -1042,7 +1047,7 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns, rule->key_conf.spec.src_port, rule->key_conf.spec.dst_port, ret); else - ret = hns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf); + ret = hns3_remove_fdir_filter(hw, fdir_info, rule); return ret; } @@ -1080,7 +1085,7 @@ int hns3_fdir_filter_program(struct hns3_adapter *hns, rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID], rule->key_conf.spec.src_port, rule->key_conf.spec.dst_port, ret); - (void)hns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf); + (void)hns3_remove_fdir_filter(hw, fdir_info, rule); } return ret; @@ -1231,3 +1236,24 @@ hns3_tuple_config_name(enum hns3_fdir_tuple_config tuple_cfg) return "unknown"; } + +static struct { + enum hns3_fdir_index_config cfg; + const char *name; +} index_cfg_map[] = { + { HNS3_FDIR_INDEX_CONFIG_HASH, "hash"}, + { HNS3_FDIR_INDEX_CONFIG_PRIORITY, "priority"}, +}; + +const char * +hns3_fdir_index_config_name(enum hns3_fdir_index_config cfg) +{ + uint32_t i; + + for (i = 0; i < RTE_DIM(index_cfg_map); i++) { + if (cfg == index_cfg_map[i].cfg) + return index_cfg_map[i].name; + } + + return "unknown"; +} diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h index 2d0c9bf3c8b6..5ba7b5b60d16 100644 --- a/drivers/net/hns3/hns3_fdir.h +++ b/drivers/net/hns3/hns3_fdir.h @@ -228,6 +228,14 @@ enum hns3_fdir_tuple_config { HNS3_FDIR_TUPLE_CONFIG_BUTT }; +enum hns3_fdir_index_config { + /* Generate the hardware flow director index based on rte_hash (Default) */ + HNS3_FDIR_INDEX_CONFIG_HASH, + + /* Use the rte_flow priority field as the hardware flow director index. */ + HNS3_FDIR_INDEX_CONFIG_PRIORITY +}; + /* * A structure used to define fields of a FDIR related info. */ @@ -238,6 +246,7 @@ struct hns3_fdir_info { struct hns3_fd_cfg fd_cfg; uint8_t vlan_match_mode; enum hns3_fdir_tuple_config tuple_cfg; + enum hns3_fdir_index_config index_cfg; }; struct hns3_adapter; @@ -254,5 +263,6 @@ int hns3_restore_all_fdir_filter(struct hns3_adapter *hns); enum hns3_fdir_tuple_config hns3_parse_tuple_config(const char *name); const char *hns3_tuple_config_name(enum hns3_fdir_tuple_config tuple_cfg); +const char *hns3_fdir_index_config_name(enum hns3_fdir_index_config cfg); #endif /* HNS3_FDIR_H */ diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c index 042359c1abf1..192ffc015e14 100644 --- a/drivers/net/hns3/hns3_flow.c +++ b/drivers/net/hns3/hns3_flow.c @@ -597,10 +597,6 @@ hns3_check_attr(const struct rte_flow_attr *attr, struct rte_flow_error *error) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr, "No support for transfer"); - if (attr->priority) - return rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, - attr, "Not support priority"); if (attr->group) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_GROUP, @@ -1441,6 +1437,40 @@ is_tunnel_packet(enum rte_flow_item_type type) return false; } +static int +hns3_handle_attributes(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + struct hns3_fdir_rule *rule, + struct rte_flow_error *error) +{ + struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private); + struct hns3_fdir_info fdir = pf->fdir; + uint32_t rule_num; + + if (fdir.index_cfg != HNS3_FDIR_INDEX_CONFIG_PRIORITY) { + if (attr->priority == 0) + return 0; + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, + attr, "Not support priority"); + } + + rule_num = fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1]; + if (attr->priority >= rule_num) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, + attr, "Priority out of range"); + + if (fdir.hash_map[attr->priority] != NULL) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, + attr, "Priority already exists"); + + rule->location = attr->priority; + + return 0; +} + /* * Parse the flow director rule. * The supported PATTERN: @@ -1468,6 +1498,7 @@ is_tunnel_packet(enum rte_flow_item_type type) */ static int hns3_parse_fdir_filter(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action actions[], struct hns3_fdir_rule *rule, @@ -1484,6 +1515,10 @@ hns3_parse_fdir_filter(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Fdir not supported in VF"); + ret = hns3_handle_attributes(dev, attr, rule, error); + if (ret) + return ret; + step_mngr.items = first_items; step_mngr.count = RTE_DIM(first_items); for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { @@ -2248,7 +2283,7 @@ hns3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, return hns3_parse_rss_filter(dev, pattern, actions, &conf->rss_conf, error); - return hns3_parse_fdir_filter(dev, pattern, actions, + return hns3_parse_fdir_filter(dev, attr, pattern, actions, &conf->fdir_conf, error); } -- 2.22.0