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

Reply via email to