diff --git a/0239-net-hns3-fix-possible-truncation-of-hash-key-when-co.patch b/0239-net-hns3-fix-possible-truncation-of-hash-key-when-co.patch new file mode 100644 index 0000000..cf636b6 --- /dev/null +++ b/0239-net-hns3-fix-possible-truncation-of-hash-key-when-co.patch @@ -0,0 +1,37 @@ +From eeeacb6170dabebbfb5fcbcb3fa240db11cdd362 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:03 +0800 +Subject: net/hns3: fix possible truncation of hash key when config + +[ upstream commit bb38316e738ad6009b3f20b3abfaf27ea8cb0202 ] + +The hash key length of hns3 driver is obtained from firmware. If the +length is a multiple of HNS3_RSS_HASH_KEY_NUM (16), the last part +of hash key will be truncated. + +Fixes: 88347111eb53 ("net/hns3: refactor set RSS hash algorithm and key interface") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index d6e0754273..2011c18b9b 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -301,7 +301,8 @@ hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + req->hash_config |= (hash_algo & HNS3_RSS_HASH_ALGO_MASK); + req->hash_config |= (idx << HNS3_RSS_HASH_KEY_OFFSET_B); + +- if (idx == max_bd_num - 1) ++ if (idx == max_bd_num - 1 && ++ (key_len % HNS3_RSS_HASH_KEY_NUM) != 0) + cur_key_size = key_len % HNS3_RSS_HASH_KEY_NUM; + else + cur_key_size = HNS3_RSS_HASH_KEY_NUM; +-- +2.23.0 + diff --git a/0240-net-hns3-fix-possible-truncation-of-redirection-tabl.patch b/0240-net-hns3-fix-possible-truncation-of-redirection-tabl.patch new file mode 100644 index 0000000..01b8996 --- /dev/null +++ b/0240-net-hns3-fix-possible-truncation-of-redirection-tabl.patch @@ -0,0 +1,59 @@ +From 81cda32ef08ef6b179a36fcfe5b04b0a702dfa33 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:04 +0800 +Subject: net/hns3: fix possible truncation of redirection table + +[ upstream commit 4729376e555b58a739e6e231d403ca3b029ad92c ] + +The size of the redirection table is obtained from firmware. If the size +isn't a multiple of HNS3_RSS_CFG_TBL_SIZE, the redirection table from +user will be truncated. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index 2011c18b9b..ed397587b5 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -329,6 +329,7 @@ int + hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size) + { + struct hns3_rss_indirection_table_cmd *req; ++ uint16_t max_bd_num, cfg_tbl_size; + struct hns3_cmd_desc desc; + uint8_t qid_msb_off; + uint8_t qid_msb_val; +@@ -337,14 +338,20 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size) + int ret; + + req = (struct hns3_rss_indirection_table_cmd *)desc.data; +- +- for (i = 0; i < size / HNS3_RSS_CFG_TBL_SIZE; i++) { ++ max_bd_num = DIV_ROUND_UP(size, HNS3_RSS_CFG_TBL_SIZE); ++ for (i = 0; i < max_bd_num; i++) { + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INDIR_TABLE, + false); + req->start_table_index = + rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE); + req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK); +- for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) { ++ ++ if (i == max_bd_num - 1 && (size % HNS3_RSS_CFG_TBL_SIZE) != 0) ++ cfg_tbl_size = size % HNS3_RSS_CFG_TBL_SIZE; ++ else ++ cfg_tbl_size = HNS3_RSS_CFG_TBL_SIZE; ++ ++ for (j = 0; j < cfg_tbl_size; j++) { + q_id = indir[i * HNS3_RSS_CFG_TBL_SIZE + j]; + req->rss_result_l[j] = q_id & 0xff; + +-- +2.23.0 + diff --git a/0241-net-hns3-use-hardware-config-to-report-hash-key.patch b/0241-net-hns3-use-hardware-config-to-report-hash-key.patch new file mode 100644 index 0000000..0175113 --- /dev/null +++ b/0241-net-hns3-use-hardware-config-to-report-hash-key.patch @@ -0,0 +1,114 @@ +From da66262ce661cba4454a7e00971822791a5e1305 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:05 +0800 +Subject: net/hns3: use hardware config to report hash key + +[ upstream commit 7da415d27d8872a45a2d0cf9b5e66a8027c8f53c ] + +Currently, hns3_dev_rss_hash_conf_get() interface reports RSS key from +the key maintained by driver. It's better to report the key from +hardware, which is more realistic. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.c | 53 ++++++++++++++++++++++++++++++++++++- + drivers/net/hns3/hns3_rss.h | 3 ++- + 2 files changed, 54 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index ed397587b5..a8ea5150ab 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -321,6 +321,48 @@ hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + return 0; + } + ++int ++hns3_rss_get_algo_key(struct hns3_hw *hw, uint8_t *hash_algo, ++ uint8_t *key, uint8_t key_len) ++{ ++ struct hns3_rss_generic_config_cmd *req; ++ struct hns3_cmd_desc desc; ++ uint16_t cur_key_size; ++ uint16_t max_bd_num; ++ uint8_t *cur_key; ++ uint16_t idx; ++ int ret; ++ ++ req = (struct hns3_rss_generic_config_cmd *)desc.data; ++ max_bd_num = DIV_ROUND_UP(key_len, HNS3_RSS_HASH_KEY_NUM); ++ for (idx = 0; idx < max_bd_num; idx++) { ++ hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_GENERIC_CONFIG, ++ true); ++ ++ req->hash_config |= (idx << HNS3_RSS_HASH_KEY_OFFSET_B); ++ ret = hns3_cmd_send(hw, &desc, 1); ++ if (ret) { ++ hns3_err(hw, "fail to obtain RSS algo and key from firmware, ret = %d", ++ ret); ++ return ret; ++ } ++ ++ if (idx == 0) ++ *hash_algo = req->hash_config & HNS3_RSS_HASH_ALGO_MASK; ++ ++ if (idx == max_bd_num - 1 && ++ (key_len % HNS3_RSS_HASH_KEY_NUM) != 0) ++ cur_key_size = key_len % HNS3_RSS_HASH_KEY_NUM; ++ else ++ cur_key_size = HNS3_RSS_HASH_KEY_NUM; ++ ++ cur_key = key + idx * HNS3_RSS_HASH_KEY_NUM; ++ memcpy(cur_key, req->hash_key, cur_key_size); ++ } ++ ++ return 0; ++} ++ + /* + * rss_indirection_table command function, opcode:0x0D07. + * Used to configure the indirection table of rss. +@@ -550,13 +592,22 @@ hns3_dev_rss_hash_conf_get(struct rte_eth_dev *dev, + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_rss_conf *rss_cfg = &hw->rss_info; ++ uint8_t hash_algo; ++ int ret; + + rte_spinlock_lock(&hw->lock); + rss_conf->rss_hf = rss_cfg->conf.types; + + /* Get the RSS Key required by the user */ + if (rss_conf->rss_key && rss_conf->rss_key_len >= hw->rss_key_size) { +- memcpy(rss_conf->rss_key, rss_cfg->key, hw->rss_key_size); ++ ret = hns3_rss_get_algo_key(hw, &hash_algo, rss_conf->rss_key, ++ hw->rss_key_size); ++ if (ret != 0) { ++ rte_spinlock_unlock(&hw->lock); ++ hns3_err(hw, "obtain hash algo and key failed, ret = %d", ++ ret); ++ return ret; ++ } + rss_conf->rss_key_len = hw->rss_key_size; + } + rte_spinlock_unlock(&hw->lock); +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index d6f81996f4..be0141f602 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -112,6 +112,7 @@ void hns3_rss_uninit(struct hns3_adapter *hns); + int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf); + int hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + const uint8_t *key, uint8_t key_len); +- ++int hns3_rss_get_algo_key(struct hns3_hw *hw, uint8_t *hash_algo, ++ uint8_t *key, uint8_t key_len); + + #endif /* HNS3_RSS_H */ +-- +2.23.0 + diff --git a/0242-net-hns3-use-hardware-config-to-report-hash-types.patch b/0242-net-hns3-use-hardware-config-to-report-hash-types.patch new file mode 100644 index 0000000..ef63558 --- /dev/null +++ b/0242-net-hns3-use-hardware-config-to-report-hash-types.patch @@ -0,0 +1,490 @@ +From b36d99962a7ef0c2ae408e4edbabb95f00554d58 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:06 +0800 +Subject: net/hns3: use hardware config to report hash types + +[ upstream commit 406b25c7ffd2d84b1e09665872f69755c75e7d89 ] + +Use the configuration in hardware to report hash types instead +of data maintained in software. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.c | 260 ++++++++++++++++++++++++++++-------- + drivers/net/hns3/hns3_rss.h | 1 + + 2 files changed, 208 insertions(+), 53 deletions(-) + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index a8ea5150ab..9addc00a67 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -70,6 +70,17 @@ enum hns3_tuple_field { + HNS3_RSS_FIELD_IPV6_FRAG_IP_S + }; + ++#define HNS3_RSS_TUPLE_IPV4_TCP_M GENMASK(3, 0) ++#define HNS3_RSS_TUPLE_IPV4_UDP_M GENMASK(11, 8) ++#define HNS3_RSS_TUPLE_IPV4_SCTP_M GENMASK(20, 16) ++#define HNS3_RSS_TUPLE_IPV4_NONF_M GENMASK(25, 24) ++#define HNS3_RSS_TUPLE_IPV4_FLAG_M GENMASK(27, 26) ++#define HNS3_RSS_TUPLE_IPV6_TCP_M GENMASK(35, 32) ++#define HNS3_RSS_TUPLE_IPV6_UDP_M GENMASK(43, 40) ++#define HNS3_RSS_TUPLE_IPV6_SCTP_M GENMASK(52, 48) ++#define HNS3_RSS_TUPLE_IPV6_NONF_M GENMASK(57, 56) ++#define HNS3_RSS_TUPLE_IPV6_FLAG_M GENMASK(59, 58) ++ + enum hns3_rss_tuple_type { + HNS3_RSS_IP_TUPLE, + HNS3_RSS_IP_L4_TUPLE, +@@ -79,200 +90,249 @@ static const struct { + uint64_t rss_types; + uint16_t tuple_type; + uint64_t rss_field; ++ uint64_t tuple_mask; + } hns3_set_tuple_table[] = { + /* IPV4-FRAG */ + { RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV4_FLAG_M }, + { RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_FLAG_M }, + { RTE_ETH_RSS_FRAG_IPV4, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_FLAG_M }, + + /* IPV4 */ + { RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + { RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + { RTE_ETH_RSS_IPV4, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + + /* IPV4-OTHER */ + { RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_OTHER, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV4_NONF_M }, + + /* IPV4-TCP */ + { RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV4_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV4_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S), ++ HNS3_RSS_TUPLE_IPV4_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D), ++ HNS3_RSS_TUPLE_IPV4_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_TCP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D), ++ HNS3_RSS_TUPLE_IPV4_TCP_M }, + + /* IPV4-UDP */ + { RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV4_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV4_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S), ++ HNS3_RSS_TUPLE_IPV4_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D), ++ HNS3_RSS_TUPLE_IPV4_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_UDP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D), ++ HNS3_RSS_TUPLE_IPV4_UDP_M }, + + /* IPV4-SCTP */ + { RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV4_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV4_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S), ++ HNS3_RSS_TUPLE_IPV4_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D), ++ HNS3_RSS_TUPLE_IPV4_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV4_SCTP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D) | +- BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER), ++ HNS3_RSS_TUPLE_IPV4_SCTP_M }, + + /* IPV6-FRAG */ + { RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV6_FLAG_M }, + { RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_FLAG_M }, + { RTE_ETH_RSS_FRAG_IPV6, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_FLAG_M }, + + /* IPV6 */ + { RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + { RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + { RTE_ETH_RSS_IPV6, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + + /* IPV6-OTHER */ + { RTE_ETH_RSS_NONFRAG_IPV6_OTHER | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_OTHER | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_OTHER, + HNS3_RSS_IP_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D), ++ HNS3_RSS_TUPLE_IPV6_NONF_M }, + + /* IPV6-TCP */ + { RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV6_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV6_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S), ++ HNS3_RSS_TUPLE_IPV6_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D), ++ HNS3_RSS_TUPLE_IPV6_TCP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_TCP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D), ++ HNS3_RSS_TUPLE_IPV6_TCP_M }, + + /* IPV6-UDP */ + { RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV6_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV6_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S), ++ HNS3_RSS_TUPLE_IPV6_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D), ++ HNS3_RSS_TUPLE_IPV6_UDP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_UDP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D), ++ HNS3_RSS_TUPLE_IPV6_UDP_M }, + + /* IPV6-SCTP */ + { RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L3_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S), ++ HNS3_RSS_TUPLE_IPV6_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L3_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D), ++ HNS3_RSS_TUPLE_IPV6_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L4_SRC_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S), ++ HNS3_RSS_TUPLE_IPV6_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L4_DST_ONLY, + HNS3_RSS_IP_L4_TUPLE, +- BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D), ++ HNS3_RSS_TUPLE_IPV6_SCTP_M }, + { RTE_ETH_RSS_NONFRAG_IPV6_SCTP, + HNS3_RSS_IP_L4_TUPLE, + BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D) | + BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S) | +- BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER) }, ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER), ++ HNS3_RSS_TUPLE_IPV6_SCTP_M }, + }; + + /* +@@ -576,6 +636,96 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev, + return ret; + } + ++int ++hns3_get_rss_tuple_field(struct hns3_hw *hw, uint64_t *tuple_fields) ++{ ++ struct hns3_rss_input_tuple_cmd *req; ++ struct hns3_cmd_desc desc; ++ int ret; ++ ++ hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, true); ++ req = (struct hns3_rss_input_tuple_cmd *)desc.data; ++ ret = hns3_cmd_send(hw, &desc, 1); ++ if (ret != 0) { ++ hns3_err(hw, "fail to get RSS hash tuple fields from firmware, ret = %d", ++ ret); ++ return ret; ++ } ++ ++ *tuple_fields = rte_le_to_cpu_64(req->tuple_field); ++ ++ return 0; ++} ++ ++static uint64_t ++hns3_rss_tuple_fields_to_rss_hf(struct hns3_hw *hw, uint64_t tuple_fields) ++{ ++ uint64_t ipv6_sctp_l4_mask = ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D) | ++ BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S); ++ uint64_t rss_hf = 0; ++ uint64_t tuple_mask; ++ uint32_t i; ++ ++ for (i = 0; i < RTE_DIM(hns3_set_tuple_table); i++) { ++ tuple_mask = hns3_set_tuple_table[i].tuple_mask; ++ /* ++ * The RSS hash of the packet type is disabled if its tuples is ++ * zero. ++ */ ++ if ((tuple_fields & tuple_mask) == 0) ++ continue; ++ ++ /* ++ * Some hardware don't support to use src/dst port fields to ++ * hash for IPV6-SCTP packet. ++ */ ++ if ((hns3_set_tuple_table[i].rss_types & ++ RTE_ETH_RSS_NONFRAG_IPV6_SCTP) && ++ !hw->rss_info.ipv6_sctp_offload_supported) ++ tuple_mask &= ~ipv6_sctp_l4_mask; ++ ++ /* ++ * The framework (ethdev ops) or driver (rte flow API) ensure ++ * that both L3_SRC/DST_ONLY and L4_SRC/DST_ONLY cannot be set ++ * to driver at the same time. But if user doesn't specify ++ * anything L3/L4_SRC/DST_ONLY, driver enables all tuple fields. ++ * In this case, driver should not report L3/L4_SRC/DST_ONLY. ++ */ ++ if ((tuple_fields & tuple_mask) == tuple_mask) { ++ /* Skip the item enabled part tuples. */ ++ if ((tuple_fields & hns3_set_tuple_table[i].rss_field) != ++ tuple_mask) ++ continue; ++ ++ rss_hf |= hns3_set_tuple_table[i].rss_types; ++ continue; ++ } ++ ++ /* Match the item enabled part tuples.*/ ++ if ((tuple_fields & hns3_set_tuple_table[i].rss_field) == ++ hns3_set_tuple_table[i].rss_field) ++ rss_hf |= hns3_set_tuple_table[i].rss_types; ++ } ++ ++ return rss_hf; ++} ++ ++static int ++hns3_rss_hash_get_rss_hf(struct hns3_hw *hw, uint64_t *rss_hf) ++{ ++ uint64_t tuple_fields; ++ int ret; ++ ++ ret = hns3_get_rss_tuple_field(hw, &tuple_fields); ++ if (ret != 0) ++ return ret; ++ ++ *rss_hf = hns3_rss_tuple_fields_to_rss_hf(hw, tuple_fields); ++ ++ return 0; ++} ++ + /* + * Get rss key and rss_hf types set of RSS hash configuration. + * @param dev +@@ -591,28 +741,32 @@ hns3_dev_rss_hash_conf_get(struct rte_eth_dev *dev, + { + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; +- struct hns3_rss_conf *rss_cfg = &hw->rss_info; + uint8_t hash_algo; + int ret; + + rte_spinlock_lock(&hw->lock); +- rss_conf->rss_hf = rss_cfg->conf.types; ++ ret = hns3_rss_hash_get_rss_hf(hw, &rss_conf->rss_hf); ++ if (ret != 0) { ++ hns3_err(hw, "obtain hash tuples failed, ret = %d", ret); ++ goto out; ++ } + + /* Get the RSS Key required by the user */ + if (rss_conf->rss_key && rss_conf->rss_key_len >= hw->rss_key_size) { + ret = hns3_rss_get_algo_key(hw, &hash_algo, rss_conf->rss_key, + hw->rss_key_size); + if (ret != 0) { +- rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "obtain hash algo and key failed, ret = %d", + ret); +- return ret; ++ goto out; + } + rss_conf->rss_key_len = hw->rss_key_size; + } ++ ++out: + rte_spinlock_unlock(&hw->lock); + +- return 0; ++ return ret; + } + + /* +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index be0141f602..17473e70e2 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -110,6 +110,7 @@ int hns3_rss_reset_indir_table(struct hns3_hw *hw); + int hns3_config_rss(struct hns3_adapter *hns); + void hns3_rss_uninit(struct hns3_adapter *hns); + int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf); ++int hns3_get_rss_tuple_field(struct hns3_hw *hw, uint64_t *tuple_fields); + int hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + const uint8_t *key, uint8_t key_len); + int hns3_rss_get_algo_key(struct hns3_hw *hw, uint8_t *hash_algo, +-- +2.23.0 + diff --git a/0243-net-hns3-use-hardware-config-to-report-redirection-t.patch b/0243-net-hns3-use-hardware-config-to-report-redirection-t.patch new file mode 100644 index 0000000..df64168 --- /dev/null +++ b/0243-net-hns3-use-hardware-config-to-report-redirection-t.patch @@ -0,0 +1,133 @@ +From 866a61065fb67ec7e8cf34f5919ca93633d09cf7 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:07 +0800 +Subject: net/hns3: use hardware config to report redirection table + +[ upstream commit d1e37d1c6916858314a2c67e6317b0bb6c691b36 ] + +Currently, reta_query() API reports the redirection table from software. +This patch uses the one in hardware to report. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_cmd.h | 1 + + drivers/net/hns3/hns3_rss.c | 65 ++++++++++++++++++++++++++++++++++--- + 2 files changed, 62 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h +index 994dfc48cc..eb394c9dec 100644 +--- a/drivers/net/hns3/hns3_cmd.h ++++ b/drivers/net/hns3/hns3_cmd.h +@@ -606,6 +606,7 @@ struct hns3_rss_input_tuple_cmd { + #define HNS3_RSS_CFG_TBL_SIZE_H 4 + #define HNS3_RSS_CFG_TBL_BW_H 2 + #define HNS3_RSS_CFG_TBL_BW_L 8 ++#define HNS3_RSS_CFG_TBL_BW_H_M 0x3 + + /* Configure the indirection table, opcode:0x0D07 */ + struct hns3_rss_indirection_table_cmd { +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index 9addc00a67..7dc4e03d83 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -481,6 +481,54 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size) + return 0; + } + ++static int ++hns3_get_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size) ++{ ++ struct hns3_rss_indirection_table_cmd *req; ++ uint16_t max_bd_num, cfg_tbl_size; ++ uint8_t qid_msb_off, qid_msb_idx; ++ struct hns3_cmd_desc desc; ++ uint16_t q_id, q_hi, q_lo; ++ uint8_t rss_result_h; ++ uint16_t i, j; ++ int ret; ++ ++ req = (struct hns3_rss_indirection_table_cmd *)desc.data; ++ max_bd_num = DIV_ROUND_UP(size, HNS3_RSS_CFG_TBL_SIZE); ++ for (i = 0; i < max_bd_num; i++) { ++ hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INDIR_TABLE, ++ true); ++ req->start_table_index = ++ rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE); ++ ret = hns3_cmd_send(hw, &desc, 1); ++ if (ret) { ++ hns3_err(hw, "fail to get RSS indirection table from firmware, ret = %d", ++ ret); ++ return ret; ++ } ++ ++ if (i == max_bd_num - 1 && (size % HNS3_RSS_CFG_TBL_SIZE) != 0) ++ cfg_tbl_size = size % HNS3_RSS_CFG_TBL_SIZE; ++ else ++ cfg_tbl_size = HNS3_RSS_CFG_TBL_SIZE; ++ ++ for (j = 0; j < cfg_tbl_size; j++) { ++ qid_msb_idx = ++ j * HNS3_RSS_CFG_TBL_BW_H / HNS3_BITS_PER_BYTE; ++ rss_result_h = req->rss_result_h[qid_msb_idx]; ++ qid_msb_off = ++ j * HNS3_RSS_CFG_TBL_BW_H % HNS3_BITS_PER_BYTE; ++ q_hi = (rss_result_h >> qid_msb_off) & ++ HNS3_RSS_CFG_TBL_BW_H_M; ++ q_lo = req->rss_result_l[j]; ++ q_id = (q_hi << HNS3_RSS_CFG_TBL_BW_L) | q_lo; ++ indir[i * HNS3_RSS_CFG_TBL_SIZE + j] = q_id; ++ } ++ } ++ ++ return 0; ++} ++ + int + hns3_rss_reset_indir_table(struct hns3_hw *hw) + { +@@ -842,10 +890,11 @@ hns3_dev_rss_reta_query(struct rte_eth_dev *dev, + uint16_t reta_size) + { + struct hns3_adapter *hns = dev->data->dev_private; ++ uint16_t reta_table[HNS3_RSS_IND_TBL_SIZE_MAX]; + struct hns3_hw *hw = &hns->hw; +- struct hns3_rss_conf *rss_cfg = &hw->rss_info; + uint16_t idx, shift; + uint16_t i; ++ int ret; + + if (reta_size != hw->rss_ind_tbl_size) { + hns3_err(hw, "The size of hash lookup table configured (%u)" +@@ -854,14 +903,22 @@ hns3_dev_rss_reta_query(struct rte_eth_dev *dev, + return -EINVAL; + } + rte_spinlock_lock(&hw->lock); ++ ret = hns3_get_rss_indir_table(hw, reta_table, reta_size); ++ if (ret != 0) { ++ rte_spinlock_unlock(&hw->lock); ++ hns3_err(hw, "query RSS redirection table failed, ret = %d.", ++ ret); ++ return ret; ++ } ++ rte_spinlock_unlock(&hw->lock); ++ + for (i = 0; i < reta_size; i++) { + idx = i / RTE_ETH_RETA_GROUP_SIZE; + shift = i % RTE_ETH_RETA_GROUP_SIZE; + if (reta_conf[idx].mask & (1ULL << shift)) +- reta_conf[idx].reta[shift] = +- rss_cfg->rss_indirection_tbl[i]; ++ reta_conf[idx].reta[shift] = reta_table[i]; + } +- rte_spinlock_unlock(&hw->lock); ++ + return 0; + } + +-- +2.23.0 + diff --git a/0244-net-hns3-separate-setting-hash-algorithm.patch b/0244-net-hns3-separate-setting-hash-algorithm.patch new file mode 100644 index 0000000..0526a23 --- /dev/null +++ b/0244-net-hns3-separate-setting-hash-algorithm.patch @@ -0,0 +1,186 @@ +From e9ff78f09278b62f184277357777ebec6b7ac0f2 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:08 +0800 +Subject: net/hns3: separate setting hash algorithm + +[ upstream commit 1fcbef5ccb993b6028a3f8a68a7b01f9b8c67413 ] + +Currently, the setting of hash algorithm comes from the +default configuration in driver and the rte_flow interface. +The hash algorithm that is set to hardware in both ways is +saved in hw->rss_info.conf.func. + +But the 'func' in struct rte_flow_action_rss is usually used +in rte flow interface. And the ethdev ops interface may also +set hash algorithm in the future. It is not appropriate and +is a little messy for ethdev ops interface and driver default +configuration to use struct rte_flow_action_rss. So we have +to separate the RSS configuration from ethdev ops and rte +flow interface to make codes more easier to maintain. + +This patch separates hash algorithm by following ways: +1) 'hash_algo' in struct hns3_rss_conf is used for ethdev ops + interface or default configuration in driver. +2) Add a 'rte_flow_hash_algo' field in struct hns3_rss_conf + to save algorithm from rte flow interface. The main reasons + are as follows: + Currently, only the last rule is used to restore the rte + flow rule. If 'func' in RSS action is 'DEFAULT', it means + that this rule doesn't modify algorithm and driver need to + save current algorithm for restoring algorithm during reset + phase. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 60 +++++++++++++++++++++--------------- + drivers/net/hns3/hns3_rss.c | 14 +-------- + drivers/net/hns3/hns3_rss.h | 1 + + 3 files changed, 37 insertions(+), 38 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index e80ec0f053..0cb6914982 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1438,30 +1438,40 @@ hns3_disable_rss(struct hns3_hw *hw) + } + + static int +-hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function *func, ++hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function func, + uint8_t *hash_algo) + { +- enum rte_eth_hash_function algo_func = *func; +- switch (algo_func) { +- case RTE_ETH_HASH_FUNCTION_DEFAULT: +- /* Keep *hash_algo as what it used to be */ +- algo_func = hw->rss_info.conf.func; +- break; +- case RTE_ETH_HASH_FUNCTION_TOEPLITZ: +- *hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ; +- break; +- case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR: +- *hash_algo = HNS3_RSS_HASH_ALGO_SIMPLE; +- break; +- case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ: +- *hash_algo = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP; +- break; +- default: +- hns3_err(hw, "Invalid RSS algorithm configuration(%d)", +- algo_func); +- return -EINVAL; ++ const uint8_t hash_func_map[] = { ++ [RTE_ETH_HASH_FUNCTION_DEFAULT] = HNS3_RSS_HASH_ALGO_TOEPLITZ, ++ [RTE_ETH_HASH_FUNCTION_TOEPLITZ] = HNS3_RSS_HASH_ALGO_TOEPLITZ, ++ [RTE_ETH_HASH_FUNCTION_SIMPLE_XOR] = HNS3_RSS_HASH_ALGO_SIMPLE, ++ [RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ] = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP, ++ }; ++ uint8_t key[HNS3_RSS_KEY_SIZE_MAX] = {0}; ++ int ret; ++ ++ if (func == RTE_ETH_HASH_FUNCTION_DEFAULT) { ++ ret = hns3_rss_get_algo_key(hw, hash_algo, key, ++ hw->rss_key_size); ++ if (ret != 0) { ++ hns3_err(hw, "fail to get current RSS hash algorithm, ret = %d", ++ ret); ++ return ret; ++ } ++ ++ /* ++ * During the phase of reset recovery, the hash algorithm ++ * obtained from hardware may not be the one used(saved in ++ * rte_flow_hash_algo) when this rule is delivered. ++ */ ++ if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) && ++ *hash_algo != hw->rss_info.rte_flow_hash_algo) ++ *hash_algo = hw->rss_info.rte_flow_hash_algo; ++ ++ return 0; + } +- *func = algo_func; ++ ++ *hash_algo = hash_func_map[func]; + + return 0; + } +@@ -1471,6 +1481,7 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + { + uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; + bool use_default_key = false; ++ uint8_t hash_algo; + int ret; + + if (rss_config->key == NULL || rss_config->key_len != hw->rss_key_size) { +@@ -1480,18 +1491,17 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + use_default_key = true; + } + +- ret = hns3_parse_rss_algorithm(hw, &rss_config->func, +- &hw->rss_info.hash_algo); ++ ret = hns3_parse_rss_algorithm(hw, rss_config->func, &hash_algo); + if (ret) + return ret; + +- ret = hns3_rss_set_algo_key(hw, hw->rss_info.hash_algo, ++ ret = hns3_rss_set_algo_key(hw, hash_algo, + use_default_key ? rss_key : rss_config->key, + hw->rss_key_size); + if (ret) + return ret; + +- hw->rss_info.conf.func = rss_config->func; ++ hw->rss_info.rte_flow_hash_algo = hash_algo; + + ret = hns3_set_rss_tuple_by_rss_hf(hw, rss_config->types); + if (ret) +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index 7dc4e03d83..dcd42b554a 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -1022,7 +1022,7 @@ hns3_rss_set_default_args(struct hns3_hw *hw) + uint16_t i; + + /* Default hash algorithm */ +- rss_cfg->conf.func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; ++ rss_cfg->hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ; + + memcpy(rss_cfg->key, hns3_hash_key, + RTE_MIN(sizeof(hns3_hash_key), hw->rss_key_size)); +@@ -1046,18 +1046,6 @@ hns3_config_rss(struct hns3_adapter *hns) + + enum rte_eth_rx_mq_mode mq_mode = hw->data->dev_conf.rxmode.mq_mode; + +- switch (hw->rss_info.conf.func) { +- case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR: +- hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SIMPLE; +- break; +- case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ: +- hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP; +- break; +- default: +- hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ; +- break; +- } +- + ret = hns3_rss_set_algo_key(hw, rss_cfg->hash_algo, + hash_key, hw->rss_key_size); + if (ret) +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index 17473e70e2..6e679b709b 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -42,6 +42,7 @@ struct hns3_rss_conf { + /* RSS parameters :algorithm, flow_types, key, queue */ + struct rte_flow_action_rss conf; + uint8_t hash_algo; /* hash function type defined by hardware */ ++ uint8_t rte_flow_hash_algo; + uint8_t key[HNS3_RSS_KEY_SIZE_MAX]; /* Hash key */ + uint16_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE_MAX]; + uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */ +-- +2.23.0 + diff --git a/0245-net-hns3-separate-setting-hash-key.patch b/0245-net-hns3-separate-setting-hash-key.patch new file mode 100644 index 0000000..85b75f4 --- /dev/null +++ b/0245-net-hns3-separate-setting-hash-key.patch @@ -0,0 +1,49 @@ +From 8ca08cd0671207b57d934b439d7b245966fbbfe8 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:09 +0800 +Subject: net/hns3: separate setting hash key + +[ upstream commit fe9cc8b88babd0911d91dc194b35c7c352e2bf7b ] + +The settings of hash key comes from the ethdev ops (like, dev_configure +and rss_hash_update) and rte_flow API. For the ethdev ops, driver has +to save it to rss_info::key in hns3_hw structure so as to it can be +restored when reset is triggered. While rte_flow API no need to use +this field to save, they has a global flow_rss_list to maintain all +rules which save hash key. And hash key can be restored by this rule +information during the reset phase. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index dcd42b554a..401e3adfdf 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -376,8 +376,7 @@ hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + return ret; + } + } +- /* Update the shadow RSS key with user specified */ +- memcpy(hw->rss_info.key, key, hw->rss_key_size); ++ + return 0; + } + +@@ -672,6 +671,8 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev, + key, hw->rss_key_size); + if (ret) + goto set_algo_key_fail; ++ /* Update the shadow RSS key with user specified */ ++ memcpy(hw->rss_info.key, key, hw->rss_key_size); + } + rte_spinlock_unlock(&hw->lock); + +-- +2.23.0 + diff --git a/0246-net-hns3-separate-setting-redirection-table.patch b/0246-net-hns3-separate-setting-redirection-table.patch new file mode 100644 index 0000000..4e71a61 --- /dev/null +++ b/0246-net-hns3-separate-setting-redirection-table.patch @@ -0,0 +1,98 @@ +From 5a9f2de85e9f9185165c7fe82247ef6125ef4115 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:10 +0800 +Subject: net/hns3: separate setting redirection table + +[ upstream commit a421cb93462932717f23c5d8342381726e547ba6 ] + +The settings of redirection table comes from the ethdev ops (like, +dev_configure and rss_hash_update) and rte_flow API. For the ethdev +ops, driver has to save it to rss_info::rss_indirection_tbl in hns3_hw +structure so as to it can be restored when reset is triggered. +While rte_flow API no need to use this field to save, they has a global +RSS flow list to maintain all rules which can be used to restore the +table during the reset phase. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 2 -- + drivers/net/hns3/hns3_rss.c | 21 +++++++++++++-------- + 2 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index 0cb6914982..875c0eec11 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1519,8 +1519,6 @@ hns3_update_indir_table(struct hns3_hw *hw, + uint32_t i; + + /* Fill in redirection table */ +- memcpy(indir_tbl, hw->rss_info.rss_indirection_tbl, +- sizeof(hw->rss_info.rss_indirection_tbl)); + for (i = 0, j = 0; i < hw->rss_ind_tbl_size; i++, j++) { + j %= num; + if (conf->queue[j] >= hw->alloc_rss_size) { +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index 401e3adfdf..751033d98f 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -473,10 +473,6 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size) + } + } + +- /* Update redirection table of hw */ +- memcpy(hw->rss_info.rss_indirection_tbl, indir, +- sizeof(uint16_t) * size); +- + return 0; + } + +@@ -542,8 +538,11 @@ hns3_rss_reset_indir_table(struct hns3_hw *hw) + } + + ret = hns3_set_rss_indir_table(hw, lut, hw->rss_ind_tbl_size); +- if (ret) +- hns3_err(hw, "RSS uninit indir table failed: %d", ret); ++ if (ret != 0) ++ hns3_err(hw, "RSS uninit indir table failed, ret = %d.", ret); ++ else ++ memcpy(hw->rss_info.rss_indirection_tbl, lut, ++ sizeof(uint16_t) * hw->rss_ind_tbl_size); + rte_free(lut); + + return ret; +@@ -855,12 +854,12 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev, + idx = i / RTE_ETH_RETA_GROUP_SIZE; + shift = i % RTE_ETH_RETA_GROUP_SIZE; + if (reta_conf[idx].reta[shift] >= hw->alloc_rss_size) { +- rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "queue id(%u) set to redirection table " + "exceeds queue number(%u) allocated to a TC", + reta_conf[idx].reta[shift], + hw->alloc_rss_size); +- return -EINVAL; ++ ret = -EINVAL; ++ goto out; + } + + if (reta_conf[idx].mask & (1ULL << shift)) +@@ -869,7 +868,13 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev, + + ret = hns3_set_rss_indir_table(hw, indirection_tbl, + hw->rss_ind_tbl_size); ++ if (ret != 0) ++ goto out; + ++ memcpy(rss_cfg->rss_indirection_tbl, indirection_tbl, ++ sizeof(uint16_t) * hw->rss_ind_tbl_size); ++ ++out: + rte_spinlock_unlock(&hw->lock); + return ret; + } +-- +2.23.0 + diff --git a/0247-net-hns3-separate-setting-RSS-types.patch b/0247-net-hns3-separate-setting-RSS-types.patch new file mode 100644 index 0000000..457d326 --- /dev/null +++ b/0247-net-hns3-separate-setting-RSS-types.patch @@ -0,0 +1,131 @@ +From b99379a51ab920cbd8d4ee51122efff2f1af57db Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:11 +0800 +Subject: net/hns3: separate setting RSS types + +[ upstream commit 791e56935e488b8154a83daaf3952e1901ed7552 ] + +The settings of RSS types comes from the ethdev ops (like, dev_configure +and rss_hash_update) and rte_flow API. For the ethdev ops, driver has to +save it so as to it can be restored when reset is triggered. +While rte_flow API no need to maintain this field, it can be restored by +the saved rule. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 3 ++- + drivers/net/hns3/hns3_rss.c | 22 ++++++++++++++-------- + drivers/net/hns3/hns3_rss.h | 1 + + 3 files changed, 17 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index 875c0eec11..9e51891bd9 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1433,6 +1433,7 @@ hns3_disable_rss(struct hns3_hw *hw) + ret = hns3_set_rss_tuple_by_rss_hf(hw, 0); + if (ret) + return ret; ++ hw->rss_info.rss_hf = 0; + + return 0; + } +@@ -1580,7 +1581,7 @@ hns3_config_rss_filter(struct hns3_hw *hw, + /* Filter the unsupported flow types */ + flow_types = conf->conf.types ? + rss_flow_conf.types & HNS3_ETH_RSS_SUPPORT : +- hw->rss_info.conf.types; ++ hw->rss_info.rss_hf; + if (flow_types != rss_flow_conf.types) + hns3_warn(hw, "modified RSS types based on hardware support," + " requested:0x%" PRIx64 " configured:0x%" PRIx64, +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index 751033d98f..f51d70a8e5 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -628,9 +628,6 @@ hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf) + return ret; + } + +- /* Update supported flow types when set tuple success */ +- hw->rss_info.conf.types = rss_hf; +- + return 0; + } + +@@ -648,7 +645,7 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev, + struct rte_eth_rss_conf *rss_conf) + { + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); +- uint64_t rss_hf_bk = hw->rss_info.conf.types; ++ uint64_t rss_hf_bk = hw->rss_info.rss_hf; + uint8_t key_len = rss_conf->rss_key_len; + uint64_t rss_hf = rss_conf->rss_hf; + uint8_t *key = rss_conf->rss_key; +@@ -673,6 +670,7 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev, + /* Update the shadow RSS key with user specified */ + memcpy(hw->rss_info.key, key, hw->rss_key_size); + } ++ hw->rss_info.rss_hf = rss_hf; + rte_spinlock_unlock(&hw->lock); + + return 0; +@@ -1030,6 +1028,7 @@ hns3_rss_set_default_args(struct hns3_hw *hw) + /* Default hash algorithm */ + rss_cfg->hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ; + ++ hw->rss_info.rss_hf = 0; + memcpy(rss_cfg->key, hns3_hash_key, + RTE_MIN(sizeof(hns3_hash_key), hw->rss_key_size)); + +@@ -1067,15 +1066,22 @@ hns3_config_rss(struct hns3_adapter *hns) + return ret; + + /* +- * When muli-queue RSS mode flag is not set or unsupported tuples are ++ * When multi-queue RSS mode flag is not set or unsupported tuples are + * set, disable all tuples. + */ +- rss_hf = hw->rss_info.conf.types; ++ rss_hf = hw->rss_info.rss_hf; + if (!((uint32_t)mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) || + !(rss_hf & HNS3_ETH_RSS_SUPPORT)) + rss_hf = 0; + +- return hns3_set_rss_tuple_by_rss_hf(hw, rss_hf); ++ ret = hns3_set_rss_tuple_by_rss_hf(hw, rss_hf); ++ if (ret != 0) { ++ hns3_err(hw, "set RSS tuples failed, ret = %d.", ret); ++ return ret; ++ } ++ hw->rss_info.rss_hf = rss_hf; ++ ++ return 0; + } + + /* +@@ -1093,5 +1099,5 @@ hns3_rss_uninit(struct hns3_adapter *hns) + return; + + /* Disable RSS */ +- hw->rss_info.conf.types = 0; ++ hw->rss_info.rss_hf = 0; + } +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index 6e679b709b..21b90789d0 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -41,6 +41,7 @@ + struct hns3_rss_conf { + /* RSS parameters :algorithm, flow_types, key, queue */ + struct rte_flow_action_rss conf; ++ uint64_t rss_hf; + uint8_t hash_algo; /* hash function type defined by hardware */ + uint8_t rte_flow_hash_algo; + uint8_t key[HNS3_RSS_KEY_SIZE_MAX]; /* Hash key */ +-- +2.23.0 + diff --git a/0248-net-hns3-separate-setting-and-clearing-RSS-rule.patch b/0248-net-hns3-separate-setting-and-clearing-RSS-rule.patch new file mode 100644 index 0000000..85d77c6 --- /dev/null +++ b/0248-net-hns3-separate-setting-and-clearing-RSS-rule.patch @@ -0,0 +1,126 @@ +From 0667045e83f2ed2769e1e71947ce6530108739ed Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:12 +0800 +Subject: net/hns3: separate setting and clearing RSS rule + +[ upstream commit 1c3aeb2be4b8ef8b18846883ebbb9320f62cf097 ] + +Separate the setting and clearing of RSS rule. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 46 +++++++++++++++++------------------- + 1 file changed, 22 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index 9e51891bd9..80dda63afe 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1535,8 +1535,22 @@ hns3_update_indir_table(struct hns3_hw *hw, + } + + static int +-hns3_config_rss_filter(struct hns3_hw *hw, +- const struct hns3_rss_conf *conf, bool add) ++hns3_reset_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) ++{ ++ int ret; ++ ++ if (!conf->valid) ++ return 0; ++ ++ ret = hns3_disable_rss(hw); ++ if (ret) ++ hns3_err(hw, "RSS disable failed(%d)", ret); ++ ++ return ret; ++} ++ ++static int ++hns3_config_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) + { + uint64_t flow_types; + uint16_t num; +@@ -1553,19 +1567,6 @@ hns3_config_rss_filter(struct hns3_hw *hw, + .queue = conf->conf.queue, + }; + +- if (!add) { +- if (!conf->valid) +- return 0; +- +- ret = hns3_disable_rss(hw); +- if (ret) { +- hns3_err(hw, "RSS disable failed(%d)", ret); +- return ret; +- } +- +- return 0; +- } +- + /* Set rx queues to use */ + num = RTE_MIN(hw->data->nb_rx_queues, rss_flow_conf.queue_num); + if (rss_flow_conf.queue_num > num) +@@ -1606,8 +1607,7 @@ hns3_clear_rss_filter(struct rte_eth_dev *dev) + rss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list); + while (rss_filter_ptr) { + TAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries); +- ret = hns3_config_rss_filter(hw, &rss_filter_ptr->filter_info, +- false); ++ ret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info); + if (ret) + rss_rule_fail_cnt++; + else +@@ -1636,7 +1636,7 @@ hns3_restore_rss_filter(struct hns3_hw *hw) + if (!filter->filter_info.valid) + continue; + +- ret = hns3_config_rss_filter(hw, &filter->filter_info, true); ++ ret = hns3_config_rss_filter(hw, &filter->filter_info); + if (ret != 0) { + hns3_err(hw, "restore RSS filter failed, ret=%d", ret); + goto out; +@@ -1680,8 +1680,7 @@ hns3_rss_action_is_dup(struct hns3_hw *hw, + } + + static int +-hns3_flow_parse_rss(struct rte_eth_dev *dev, +- const struct hns3_rss_conf *conf, bool add) ++hns3_flow_parse_rss(struct rte_eth_dev *dev, const struct hns3_rss_conf *conf) + { + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; +@@ -1691,7 +1690,7 @@ hns3_flow_parse_rss(struct rte_eth_dev *dev, + return -EINVAL; + } + +- return hns3_config_rss_filter(hw, conf, add); ++ return hns3_config_rss_filter(hw, conf); + } + + static int +@@ -1778,7 +1777,7 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev, + } + } + +- ret = hns3_flow_parse_rss(dev, new_conf, true); ++ ret = hns3_flow_parse_rss(dev, new_conf); + if (ret != 0) { + rte_free(rss_filter_ptr); + return ret; +@@ -1961,8 +1960,7 @@ hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, + break; + case RTE_ETH_FILTER_HASH: + rss_filter_ptr = (struct hns3_rss_conf_ele *)flow->rule; +- ret = hns3_config_rss_filter(hw, &rss_filter_ptr->filter_info, +- false); ++ ret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info); + if (ret) + return rte_flow_error_set(error, EIO, + RTE_FLOW_ERROR_TYPE_HANDLE, +-- +2.23.0 + diff --git a/0249-net-hns3-use-new-RSS-rule-to-configure-hardware.patch b/0249-net-hns3-use-new-RSS-rule-to-configure-hardware.patch new file mode 100644 index 0000000..82de7a0 --- /dev/null +++ b/0249-net-hns3-use-new-RSS-rule-to-configure-hardware.patch @@ -0,0 +1,121 @@ +From 08730d02d9f5cb532ea3953c2ae1920aaa123358 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:13 +0800 +Subject: net/hns3: use new RSS rule to configure hardware + +[ upstream commit 218a119a08e01f203f92b46334b6b2f03ff9765d ] + +Remove redundant assignment and directly use new RSS rule to configure +hardware. Additionally, considering that the new rule configuration may +need to be modified, the 'const' of input parameter about it is removed. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 52 ++++++++++++++---------------------- + 1 file changed, 20 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index 80dda63afe..3ac5279538 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1482,6 +1482,7 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + { + uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; + bool use_default_key = false; ++ uint64_t flow_types; + uint8_t hash_algo; + int ret; + +@@ -1501,10 +1502,18 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + hw->rss_key_size); + if (ret) + return ret; +- + hw->rss_info.rte_flow_hash_algo = hash_algo; + +- ret = hns3_set_rss_tuple_by_rss_hf(hw, rss_config->types); ++ /* Filter the unsupported flow types */ ++ flow_types = rss_config->types ? ++ rss_config->types & HNS3_ETH_RSS_SUPPORT : ++ hw->rss_info.rss_hf; ++ if (flow_types != rss_config->types) ++ hns3_warn(hw, "modified RSS types based on hardware support," ++ " requested:0x%" PRIx64 " configured:0x%" PRIx64, ++ rss_config->types, flow_types); ++ ++ ret = hns3_set_rss_tuple_by_rss_hf(hw, flow_types); + if (ret) + hns3_err(hw, "Update RSS tuples by rss hf failed %d", ret); + +@@ -1550,48 +1559,27 @@ hns3_reset_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) + } + + static int +-hns3_config_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) ++hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_rss_conf *conf) + { +- uint64_t flow_types; ++ struct rte_flow_action_rss *rss_act; + uint16_t num; + int ret; + +- struct rte_flow_action_rss rss_flow_conf = { +- .func = conf->conf.func, +- .level = conf->conf.level, +- .types = conf->conf.types, +- .key_len = conf->conf.key_len, +- .queue_num = conf->conf.queue_num, +- .key = conf->conf.key_len ? +- (void *)(uintptr_t)conf->conf.key : NULL, +- .queue = conf->conf.queue, +- }; +- ++ rss_act = &conf->conf; + /* Set rx queues to use */ +- num = RTE_MIN(hw->data->nb_rx_queues, rss_flow_conf.queue_num); +- if (rss_flow_conf.queue_num > num) ++ num = RTE_MIN(hw->data->nb_rx_queues, rss_act->queue_num); ++ if (rss_act->queue_num > num) + hns3_warn(hw, "Config queue numbers %u are beyond the scope of truncated", +- rss_flow_conf.queue_num); ++ rss_act->queue_num); + hns3_info(hw, "Max of contiguous %u PF queues are configured", num); + if (num) { +- ret = hns3_update_indir_table(hw, &rss_flow_conf, num); ++ ret = hns3_update_indir_table(hw, rss_act, num); + if (ret) + return ret; + } + +- /* Filter the unsupported flow types */ +- flow_types = conf->conf.types ? +- rss_flow_conf.types & HNS3_ETH_RSS_SUPPORT : +- hw->rss_info.rss_hf; +- if (flow_types != rss_flow_conf.types) +- hns3_warn(hw, "modified RSS types based on hardware support," +- " requested:0x%" PRIx64 " configured:0x%" PRIx64, +- rss_flow_conf.types, flow_types); +- /* Update the useful flow types */ +- rss_flow_conf.types = flow_types; +- + /* Set hash algorithm and flow types by the user's config */ +- return hns3_hw_rss_hash_set(hw, &rss_flow_conf); ++ return hns3_hw_rss_hash_set(hw, rss_act); + } + + static int +@@ -1680,7 +1668,7 @@ hns3_rss_action_is_dup(struct hns3_hw *hw, + } + + static int +-hns3_flow_parse_rss(struct rte_eth_dev *dev, const struct hns3_rss_conf *conf) ++hns3_flow_parse_rss(struct rte_eth_dev *dev, struct hns3_rss_conf *conf) + { + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; +-- +2.23.0 + diff --git a/0250-net-hns3-save-hash-algo-to-RSS-filter-list-node.patch b/0250-net-hns3-save-hash-algo-to-RSS-filter-list-node.patch new file mode 100644 index 0000000..77d24d8 --- /dev/null +++ b/0250-net-hns3-save-hash-algo-to-RSS-filter-list-node.patch @@ -0,0 +1,96 @@ +From e439b6f69b496ab010cff1b87f7a8cd83e258faf Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:14 +0800 +Subject: net/hns3: save hash algo to RSS filter list node + +[ upstream commit 9d34b8a181bf022fe3a3a3ae8511f3d921fc5c67 ] + +Save hash algo from rte flow RSS rule to RSS filter list node +instead of struct hns3_rss_conf. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index 3ac5279538..f073adebb6 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1439,7 +1439,7 @@ hns3_disable_rss(struct hns3_hw *hw) + } + + static int +-hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function func, ++hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_rss_conf *rss_conf, + uint8_t *hash_algo) + { + const uint8_t hash_func_map[] = { +@@ -1451,7 +1451,7 @@ hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function func, + uint8_t key[HNS3_RSS_KEY_SIZE_MAX] = {0}; + int ret; + +- if (func == RTE_ETH_HASH_FUNCTION_DEFAULT) { ++ if (rss_conf->conf.func == RTE_ETH_HASH_FUNCTION_DEFAULT) { + ret = hns3_rss_get_algo_key(hw, hash_algo, key, + hw->rss_key_size); + if (ret != 0) { +@@ -1466,20 +1466,21 @@ hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function func, + * rte_flow_hash_algo) when this rule is delivered. + */ + if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) && +- *hash_algo != hw->rss_info.rte_flow_hash_algo) +- *hash_algo = hw->rss_info.rte_flow_hash_algo; ++ *hash_algo != rss_conf->rte_flow_hash_algo) ++ *hash_algo = rss_conf->rte_flow_hash_algo; + + return 0; + } + +- *hash_algo = hash_func_map[func]; ++ *hash_algo = hash_func_map[rss_conf->conf.func]; + + return 0; + } + + static int +-hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) ++hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_rss_conf *conf) + { ++ struct rte_flow_action_rss *rss_config = &conf->conf; + uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; + bool use_default_key = false; + uint64_t flow_types; +@@ -1493,7 +1494,7 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + use_default_key = true; + } + +- ret = hns3_parse_rss_algorithm(hw, rss_config->func, &hash_algo); ++ ret = hns3_parse_rss_algorithm(hw, conf, &hash_algo); + if (ret) + return ret; + +@@ -1502,7 +1503,7 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config) + hw->rss_key_size); + if (ret) + return ret; +- hw->rss_info.rte_flow_hash_algo = hash_algo; ++ conf->rte_flow_hash_algo = hash_algo; + + /* Filter the unsupported flow types */ + flow_types = rss_config->types ? +@@ -1579,7 +1580,7 @@ hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_rss_conf *conf) + } + + /* Set hash algorithm and flow types by the user's config */ +- return hns3_hw_rss_hash_set(hw, rss_act); ++ return hns3_hw_rss_hash_set(hw, conf); + } + + static int +-- +2.23.0 + diff --git a/0251-net-hns3-allow-adding-queue-buffer-size-hash-rule.patch b/0251-net-hns3-allow-adding-queue-buffer-size-hash-rule.patch new file mode 100644 index 0000000..31542c5 --- /dev/null +++ b/0251-net-hns3-allow-adding-queue-buffer-size-hash-rule.patch @@ -0,0 +1,37 @@ +From 9810ccb9266f09bef6f0d8cfcab6ac0d203d8e23 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:15 +0800 +Subject: net/hns3: allow adding queue buffer size hash rule + +[ upstream commit 8095bf3e6d8ca7349e0a15f95407acd2063e7be0 ] + +The maximum queue number from RSS flow rule allowed depends on +the maximum queue number (512) under one TC instead of the one +of Rx/Tx queue so as to eliminate restrictions on user usage. + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_rss.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index 21b90789d0..cc0bb8431d 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -37,7 +37,8 @@ + #define HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP 2 + #define HNS3_RSS_HASH_ALGO_MASK 0xf + +-#define HNS3_RSS_QUEUES_BUFFER_NUM 64 /* Same as the Max rx/tx queue num */ ++/* Same as the Max queue num under TC */ ++#define HNS3_RSS_QUEUES_BUFFER_NUM 512 + struct hns3_rss_conf { + /* RSS parameters :algorithm, flow_types, key, queue */ + struct rte_flow_action_rss conf; +-- +2.23.0 + diff --git a/0252-net-hns3-separate-flow-RSS-config-from-RSS-conf.patch b/0252-net-hns3-separate-flow-RSS-config-from-RSS-conf.patch new file mode 100644 index 0000000..22b7646 --- /dev/null +++ b/0252-net-hns3-separate-flow-RSS-config-from-RSS-conf.patch @@ -0,0 +1,169 @@ +From bfbcc4acf9a007f4774e54febda3eac275b9c747 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:16 +0800 +Subject: net/hns3: separate flow RSS config from RSS conf + +[ upstream commit b93ad0cc7677881911e5fc3baa89e0a0bbd73c48 ] + +Some RSS fields in struct hns3_rss_conf (e.g. conf, queue, +valid) are only used when create RSS flow rule, which is +unnecessary for RSS configuration information from ethdev +ops. This patch removes these fields from hns3_rss_conf +and add a new struct hns3_flow_rss_conf as rte flow +RSS filter list node element. + +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 23 ++++++++++++----------- + drivers/net/hns3/hns3_flow.h | 10 +++++++++- + drivers/net/hns3/hns3_rss.h | 5 ----- + 3 files changed, 21 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index f073adebb6..b1189455ec 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1359,7 +1359,6 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev, + { + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; +- struct hns3_rss_conf *rss_conf = &hw->rss_info; + const struct rte_flow_action_rss *rss; + const struct rte_flow_action *act; + uint32_t act_index = 0; +@@ -1374,7 +1373,7 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev, + act, "no valid queues"); + } + +- if (rss->queue_num > RTE_DIM(rss_conf->queue)) ++ if (rss->queue_num > HNS3_RSS_QUEUES_BUFFER_NUM) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, + "queue number configured exceeds " +@@ -1439,7 +1438,7 @@ hns3_disable_rss(struct hns3_hw *hw) + } + + static int +-hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_rss_conf *rss_conf, ++hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_flow_rss_conf *rss_conf, + uint8_t *hash_algo) + { + const uint8_t hash_func_map[] = { +@@ -1466,8 +1465,8 @@ hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_rss_conf *rss_conf, + * rte_flow_hash_algo) when this rule is delivered. + */ + if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) && +- *hash_algo != rss_conf->rte_flow_hash_algo) +- *hash_algo = rss_conf->rte_flow_hash_algo; ++ *hash_algo != rss_conf->hash_algo) ++ *hash_algo = rss_conf->hash_algo; + + return 0; + } +@@ -1478,7 +1477,7 @@ hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_rss_conf *rss_conf, + } + + static int +-hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_rss_conf *conf) ++hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf) + { + struct rte_flow_action_rss *rss_config = &conf->conf; + uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; +@@ -1503,7 +1502,7 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_rss_conf *conf) + hw->rss_key_size); + if (ret) + return ret; +- conf->rte_flow_hash_algo = hash_algo; ++ conf->hash_algo = hash_algo; + + /* Filter the unsupported flow types */ + flow_types = rss_config->types ? +@@ -1545,7 +1544,8 @@ hns3_update_indir_table(struct hns3_hw *hw, + } + + static int +-hns3_reset_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) ++hns3_reset_rss_filter(struct hns3_hw *hw, ++ const struct hns3_flow_rss_conf *conf) + { + int ret; + +@@ -1560,7 +1560,7 @@ hns3_reset_rss_filter(struct hns3_hw *hw, const struct hns3_rss_conf *conf) + } + + static int +-hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_rss_conf *conf) ++hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf) + { + struct rte_flow_action_rss *rss_act; + uint16_t num; +@@ -1669,7 +1669,8 @@ hns3_rss_action_is_dup(struct hns3_hw *hw, + } + + static int +-hns3_flow_parse_rss(struct rte_eth_dev *dev, struct hns3_rss_conf *conf) ++hns3_flow_parse_rss(struct rte_eth_dev *dev, ++ struct hns3_flow_rss_conf *conf) + { + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; +@@ -1739,8 +1740,8 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev, + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + const struct rte_flow_action_rss *rss_act; + struct hns3_rss_conf_ele *rss_filter_ptr; ++ struct hns3_flow_rss_conf *new_conf; + struct hns3_rss_conf_ele *filter_ptr; +- struct hns3_rss_conf *new_conf; + int ret; + + rss_filter_ptr = rte_zmalloc("hns3 rss filter", +diff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h +index e4b2fdf2e6..90126f2b6e 100644 +--- a/drivers/net/hns3/hns3_flow.h ++++ b/drivers/net/hns3/hns3_flow.h +@@ -24,10 +24,18 @@ struct rte_flow { + uint32_t counter_id; + }; + ++struct hns3_flow_rss_conf { ++ struct rte_flow_action_rss conf; ++ uint8_t hash_algo; ++ uint8_t key[HNS3_RSS_KEY_SIZE_MAX]; /* Hash key */ ++ uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */ ++ bool valid; /* check if RSS rule is valid */ ++}; ++ + /* rss filter list structure */ + struct hns3_rss_conf_ele { + TAILQ_ENTRY(hns3_rss_conf_ele) entries; +- struct hns3_rss_conf filter_info; ++ struct hns3_flow_rss_conf filter_info; + }; + + /* hns3_flow memory list structure */ +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index cc0bb8431d..d19730c69c 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -40,15 +40,10 @@ + /* Same as the Max queue num under TC */ + #define HNS3_RSS_QUEUES_BUFFER_NUM 512 + struct hns3_rss_conf { +- /* RSS parameters :algorithm, flow_types, key, queue */ +- struct rte_flow_action_rss conf; + uint64_t rss_hf; + uint8_t hash_algo; /* hash function type defined by hardware */ +- uint8_t rte_flow_hash_algo; + uint8_t key[HNS3_RSS_KEY_SIZE_MAX]; /* Hash key */ + uint16_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE_MAX]; +- uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */ +- bool valid; /* check if RSS rule is valid */ + /* + * For IPv6 SCTP packets type, check whether the NIC hardware support + * RSS hash using the src/dst port as the input tuple. For Kunpeng920 +-- +2.23.0 + diff --git a/0253-net-hns3-reimplement-hash-flow-function.patch b/0253-net-hns3-reimplement-hash-flow-function.patch new file mode 100644 index 0000000..ea37f42 --- /dev/null +++ b/0253-net-hns3-reimplement-hash-flow-function.patch @@ -0,0 +1,1697 @@ +From d5ee6b81de99a8699a6d4adb620ecc88103eb6e2 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:17 +0800 +Subject: net/hns3: reimplement hash flow function + +[ upstream commit e3069658da9ffb6f83a0d972ff2776c405eb6a8f ] + +Currently, hns3 driver supports setting multiple rte flow RSS rule, +but only the last is valid. This implementation is different from +the mainstream usage of rte flow hash in the community. Please see +the discussion threads [1] and [2]. + +This patch sets RSS hash feature completely based on the request of +the flow rule so that multiple hash rules can take effect at the same +time. Please notice that: +1. For hns3, 'func' has only one hardware. 'key' and 'queue' have only + one entry in hardware. +2. the overlapping part of the old rule will be overridden if the + configuration items of a new rule overlap with those of an old rule. + +The hns3_flow_validate() verifies and parses RSS or Fdir rules from +user, and saves them to a local variable at the same time. The local +variable is directly used to create RSS or Fdir rules. In this way, +we save one parsing and saving process. + +[1] https://lore.kernel.org/all/DM5PR12MB46648085D7CABF1AFF2D75CDD60A9@DM5PR12MB4664.namprd12.prod.outlook.com/ +[2] https://lore.kernel.org/all/f7de4db4-1b88-622f-4e03-acd3eee8a72c@oktetlabs.ru/ + +Fixes: c37ca66f2b27 ("net/hns3: support RSS") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_ethdev.h | 9 - + drivers/net/hns3/hns3_flow.c | 966 +++++++++++++++++++++++---------- + drivers/net/hns3/hns3_flow.h | 15 +- + drivers/net/hns3/hns3_rss.c | 144 ++--- + drivers/net/hns3/hns3_rss.h | 117 +++- + 5 files changed, 855 insertions(+), 396 deletions(-) + +diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h +index 2457754b3d..9acc5a3d7e 100644 +--- a/drivers/net/hns3/hns3_ethdev.h ++++ b/drivers/net/hns3/hns3_ethdev.h +@@ -996,15 +996,6 @@ static inline uint32_t hns3_read_reg(void *base, uint32_t reg) + #define hns3_read_dev(a, reg) \ + hns3_read_reg((a)->io_base, (reg)) + +-#define NEXT_ITEM_OF_ACTION(act, actions, index) \ +- do { \ +- (act) = (actions) + (index); \ +- while ((act)->type == RTE_FLOW_ACTION_TYPE_VOID) { \ +- (index)++; \ +- (act) = (actions) + (index); \ +- } \ +- } while (0) +- + static inline uint64_t + hns3_atomic_test_bit(unsigned int nr, volatile uint64_t *addr) + { +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index b1189455ec..c38bd9dd8b 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -10,6 +10,125 @@ + #include "hns3_logs.h" + #include "hns3_flow.h" + ++#define NEXT_ITEM_OF_ACTION(act, actions, index) \ ++ do { \ ++ (act) = (actions) + (index); \ ++ while ((act)->type == RTE_FLOW_ACTION_TYPE_VOID) { \ ++ (index)++; \ ++ (act) = (actions) + (index); \ ++ } \ ++ } while (0) ++ ++#define NEXT_ITEM_OF_PATTERN(item, pattern, index) \ ++ do { \ ++ (item) = (pattern) + (index); \ ++ while ((item)->type == RTE_FLOW_ITEM_TYPE_VOID) { \ ++ (index)++; \ ++ (item) = (pattern) + (index); \ ++ } \ ++ } while (0) ++ ++#define HNS3_HASH_HDR_ETH RTE_BIT64(0) ++#define HNS3_HASH_HDR_IPV4 RTE_BIT64(1) ++#define HNS3_HASH_HDR_IPV6 RTE_BIT64(2) ++#define HNS3_HASH_HDR_TCP RTE_BIT64(3) ++#define HNS3_HASH_HDR_UDP RTE_BIT64(4) ++#define HNS3_HASH_HDR_SCTP RTE_BIT64(5) ++ ++#define HNS3_HASH_VOID_NEXT_ALLOW BIT_ULL(RTE_FLOW_ITEM_TYPE_ETH) ++ ++#define HNS3_HASH_ETH_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \ ++ BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6)) ++ ++#define HNS3_HASH_IP_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_TCP) | \ ++ BIT_ULL(RTE_FLOW_ITEM_TYPE_UDP) | \ ++ BIT_ULL(RTE_FLOW_ITEM_TYPE_SCTP)) ++ ++static const uint64_t hash_pattern_next_allow_items[] = { ++ [RTE_FLOW_ITEM_TYPE_VOID] = HNS3_HASH_VOID_NEXT_ALLOW, ++ [RTE_FLOW_ITEM_TYPE_ETH] = HNS3_HASH_ETH_NEXT_ALLOW, ++ [RTE_FLOW_ITEM_TYPE_IPV4] = HNS3_HASH_IP_NEXT_ALLOW, ++ [RTE_FLOW_ITEM_TYPE_IPV6] = HNS3_HASH_IP_NEXT_ALLOW, ++}; ++ ++static const uint64_t hash_pattern_item_header[] = { ++ [RTE_FLOW_ITEM_TYPE_ETH] = HNS3_HASH_HDR_ETH, ++ [RTE_FLOW_ITEM_TYPE_IPV4] = HNS3_HASH_HDR_IPV4, ++ [RTE_FLOW_ITEM_TYPE_IPV6] = HNS3_HASH_HDR_IPV6, ++ [RTE_FLOW_ITEM_TYPE_TCP] = HNS3_HASH_HDR_TCP, ++ [RTE_FLOW_ITEM_TYPE_UDP] = HNS3_HASH_HDR_UDP, ++ [RTE_FLOW_ITEM_TYPE_SCTP] = HNS3_HASH_HDR_SCTP, ++}; ++ ++#define HNS3_HASH_IPV4 (HNS3_HASH_HDR_ETH | HNS3_HASH_HDR_IPV4) ++#define HNS3_HASH_IPV4_TCP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV4 | \ ++ HNS3_HASH_HDR_TCP) ++#define HNS3_HASH_IPV4_UDP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV4 | \ ++ HNS3_HASH_HDR_UDP) ++#define HNS3_HASH_IPV4_SCTP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV4 | \ ++ HNS3_HASH_HDR_SCTP) ++#define HNS3_HASH_IPV6 (HNS3_HASH_HDR_ETH | HNS3_HASH_HDR_IPV6) ++#define HNS3_HASH_IPV6_TCP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV6 | \ ++ HNS3_HASH_HDR_TCP) ++#define HNS3_HASH_IPV6_UDP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV6 | \ ++ HNS3_HASH_HDR_UDP) ++#define HNS3_HASH_IPV6_SCTP (HNS3_HASH_HDR_ETH | \ ++ HNS3_HASH_HDR_IPV6 | \ ++ HNS3_HASH_HDR_SCTP) ++ ++static const struct hns3_hash_map_info { ++ /* flow type specified, zero means action works for all flow types. */ ++ uint64_t pattern_type; ++ uint64_t rss_pctype; /* packet type with prefix RTE_ETH_RSS_xxx */ ++ uint64_t l3l4_types; /* Supported L3/L4 RSS types for this packet type */ ++ uint64_t hw_pctype; /* packet type in driver */ ++ uint64_t tuple_mask; /* full tuples of the hw_pctype */ ++} hash_map_table[] = { ++ /* IPV4 */ ++ { HNS3_HASH_IPV4, ++ RTE_ETH_RSS_IPV4, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV4_NONF, HNS3_RSS_TUPLE_IPV4_NONF_M }, ++ { HNS3_HASH_IPV4, ++ RTE_ETH_RSS_NONFRAG_IPV4_OTHER, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV4_NONF, HNS3_RSS_TUPLE_IPV4_NONF_M }, ++ { HNS3_HASH_IPV4, ++ RTE_ETH_RSS_FRAG_IPV4, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV4_FLAG, HNS3_RSS_TUPLE_IPV4_FLAG_M }, ++ { HNS3_HASH_IPV4_TCP, ++ RTE_ETH_RSS_NONFRAG_IPV4_TCP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV4_TCP, HNS3_RSS_TUPLE_IPV4_TCP_M }, ++ { HNS3_HASH_IPV4_UDP, ++ RTE_ETH_RSS_NONFRAG_IPV4_UDP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV4_UDP, HNS3_RSS_TUPLE_IPV4_UDP_M }, ++ { HNS3_HASH_IPV4_SCTP, ++ RTE_ETH_RSS_NONFRAG_IPV4_SCTP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV4_SCTP, HNS3_RSS_TUPLE_IPV4_SCTP_M }, ++ /* IPV6 */ ++ { HNS3_HASH_IPV6, ++ RTE_ETH_RSS_IPV6, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV6_NONF, HNS3_RSS_TUPLE_IPV6_NONF_M }, ++ { HNS3_HASH_IPV6, ++ RTE_ETH_RSS_NONFRAG_IPV6_OTHER, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV6_NONF, HNS3_RSS_TUPLE_IPV6_NONF_M }, ++ { HNS3_HASH_IPV6, ++ RTE_ETH_RSS_FRAG_IPV6, HNS3_RSS_SUPPORT_L3_SRC_DST, ++ HNS3_RSS_PCTYPE_IPV6_FLAG, HNS3_RSS_TUPLE_IPV6_FLAG_M }, ++ { HNS3_HASH_IPV6_TCP, ++ RTE_ETH_RSS_NONFRAG_IPV6_TCP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV6_TCP, HNS3_RSS_TUPLE_IPV6_TCP_M }, ++ { HNS3_HASH_IPV6_UDP, ++ RTE_ETH_RSS_NONFRAG_IPV6_UDP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV6_UDP, HNS3_RSS_TUPLE_IPV6_UDP_M }, ++ { HNS3_HASH_IPV6_SCTP, ++ RTE_ETH_RSS_NONFRAG_IPV6_SCTP, HNS3_RSS_SUPPORT_L3L4, ++ HNS3_RSS_PCTYPE_IPV6_SCTP, HNS3_RSS_TUPLE_IPV6_SCTP_M }, ++}; ++ + static const uint8_t full_mask[VNI_OR_TNI_LEN] = { 0xFF, 0xFF, 0xFF }; + static const uint8_t zero_mask[VNI_OR_TNI_LEN] = { 0x00, 0x00, 0x00 }; + +@@ -79,7 +198,7 @@ net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len) + } + + /* +- * This function is used to find rss general action. ++ * This function is used to parse filter type. + * 1. As we know RSS is used to spread packets among several queues, the flow + * API provide the struct rte_flow_action_rss, user could config its field + * sush as: func/level/types/key/queue to control RSS function. +@@ -87,16 +206,18 @@ net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len) + * implemented by FDIR + RSS in hns3 hardware, user can create one FDIR rule + * which action is RSS queues region. + * 3. When action is RSS, we use the following rule to distinguish: +- * Case 1: pattern have ETH and action's queue_num > 0, indicate it is queue +- * region configuration. ++ * Case 1: pattern has ETH and all fields in RSS action except 'queues' are ++ * zero or default, indicate it is queue region configuration. + * Case other: an rss general action. + */ +-static const struct rte_flow_action * +-hns3_find_rss_general_action(const struct rte_flow_item pattern[], +- const struct rte_flow_action actions[]) ++static void ++hns3_parse_filter_type(const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct hns3_filter_info *filter_info) + { + const struct rte_flow_action_rss *rss_act; + const struct rte_flow_action *act = NULL; ++ bool only_has_queues = false; + bool have_eth = false; + + for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { +@@ -105,8 +226,10 @@ hns3_find_rss_general_action(const struct rte_flow_item pattern[], + break; + } + } +- if (!act) +- return NULL; ++ if (act == NULL) { ++ filter_info->type = RTE_ETH_FILTER_FDIR; ++ return; ++ } + + for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { + if (pattern->type == RTE_FLOW_ITEM_TYPE_ETH) { +@@ -116,18 +239,20 @@ hns3_find_rss_general_action(const struct rte_flow_item pattern[], + } + + rss_act = act->conf; +- if (have_eth && rss_act->queue_num) { ++ only_has_queues = (rss_act->queue_num > 0) && ++ (rss_act->func == RTE_ETH_HASH_FUNCTION_DEFAULT && ++ rss_act->types == 0 && rss_act->key_len == 0); ++ if (have_eth && only_has_queues) { + /* +- * Pattern have ETH and action's queue_num > 0, indicate this is +- * queue region configuration. +- * Because queue region is implemented by FDIR + RSS in hns3 +- * hardware, it needs to enter FDIR process, so here return NULL +- * to avoid enter RSS process. ++ * Pattern has ETH and all fields in RSS action except 'queues' ++ * are zero or default, which indicates this is queue region ++ * configuration. + */ +- return NULL; ++ filter_info->type = RTE_ETH_FILTER_FDIR; ++ return; + } + +- return act; ++ filter_info->type = RTE_ETH_FILTER_HASH; + } + + static inline struct hns3_flow_counter * +@@ -1246,7 +1371,6 @@ hns3_filterlist_flush(struct rte_eth_dev *dev) + { + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct hns3_fdir_rule_ele *fdir_rule_ptr; +- struct hns3_rss_conf_ele *rss_filter_ptr; + struct hns3_flow_mem *flow_node; + + fdir_rule_ptr = TAILQ_FIRST(&hw->flow_fdir_list); +@@ -1256,13 +1380,6 @@ hns3_filterlist_flush(struct rte_eth_dev *dev) + fdir_rule_ptr = TAILQ_FIRST(&hw->flow_fdir_list); + } + +- rss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list); +- while (rss_filter_ptr) { +- TAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries); +- rte_free(rss_filter_ptr); +- rss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list); +- } +- + flow_node = TAILQ_FIRST(&hw->flow_list); + while (flow_node) { + TAILQ_REMOVE(&hw->flow_list, flow_node, entries); +@@ -1328,196 +1445,422 @@ hns3_action_rss_same(const struct rte_flow_action_rss *comp, + } + + static bool +-hns3_rss_input_tuple_supported(struct hns3_hw *hw, +- const struct rte_flow_action_rss *rss) ++hns3_valid_ipv6_sctp_rss_types(struct hns3_hw *hw, uint64_t types) + { + /* +- * For IP packet, it is not supported to use src/dst port fields to RSS +- * hash for the following packet types. +- * - IPV4 FRAG | IPV4 NONFRAG | IPV6 FRAG | IPV6 NONFRAG +- * Besides, for Kunpeng920, the NIC HW is not supported to use src/dst +- * port fields to RSS hash for IPV6 SCTP packet type. However, the +- * Kunpeng930 and future kunpeng series support to use src/dst port +- * fields to RSS hash for IPv6 SCTP packet type. ++ * Some hardware don't support to use src/dst port fields to hash ++ * for IPV6 SCTP packet type. + */ +- if (rss->types & (RTE_ETH_RSS_L4_DST_ONLY | RTE_ETH_RSS_L4_SRC_ONLY) && +- (rss->types & RTE_ETH_RSS_IP || +- (!hw->rss_info.ipv6_sctp_offload_supported && +- rss->types & RTE_ETH_RSS_NONFRAG_IPV6_SCTP))) ++ if (types & RTE_ETH_RSS_NONFRAG_IPV6_SCTP && ++ types & HNS3_RSS_SUPPORT_L4_SRC_DST && ++ !hw->rss_info.ipv6_sctp_offload_supported) + return false; + + return true; + } + +-/* +- * This function is used to parse rss action validation. +- */ + static int +-hns3_parse_rss_filter(struct rte_eth_dev *dev, +- const struct rte_flow_action *actions, +- struct rte_flow_error *error) ++hns3_flow_parse_hash_func(const struct rte_flow_action_rss *rss_act, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) + { +- struct hns3_adapter *hns = dev->data->dev_private; +- struct hns3_hw *hw = &hns->hw; +- const struct rte_flow_action_rss *rss; +- const struct rte_flow_action *act; +- uint32_t act_index = 0; +- uint16_t n; ++ if (rss_act->func >= RTE_ETH_HASH_FUNCTION_MAX) ++ return rte_flow_error_set(error, ENOTSUP, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, "RSS hash func are not supported"); + +- NEXT_ITEM_OF_ACTION(act, actions, act_index); +- rss = act->conf; ++ rss_conf->conf.func = rss_act->func; ++ return 0; ++} + +- if (rss == NULL) { ++static int ++hns3_flow_parse_hash_key(struct hns3_hw *hw, ++ const struct rte_flow_action_rss *rss_act, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ if (rss_act->key_len != hw->rss_key_size) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, +- act, "no valid queues"); +- } ++ NULL, "invalid RSS key length"); ++ ++ if (rss_act->key != NULL) ++ memcpy(rss_conf->key, rss_act->key, rss_act->key_len); ++ else ++ memcpy(rss_conf->key, hns3_hash_key, ++ RTE_MIN(sizeof(hns3_hash_key), rss_act->key_len)); ++ /* Need to record if user sets hash key. */ ++ rss_conf->conf.key = rss_act->key; ++ rss_conf->conf.key_len = rss_act->key_len; + +- if (rss->queue_num > HNS3_RSS_QUEUES_BUFFER_NUM) ++ return 0; ++} ++ ++static int ++hns3_flow_parse_queues(struct hns3_hw *hw, ++ const struct rte_flow_action_rss *rss_act, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ uint16_t i; ++ ++ if (rss_act->queue_num > hw->rss_ind_tbl_size) + return rte_flow_error_set(error, ENOTSUP, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, +- "queue number configured exceeds " +- "queue buffer size driver supported"); ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, ++ "queue number can not exceed RSS indirection table."); + +- for (n = 0; n < rss->queue_num; n++) { +- if (rss->queue[n] < hw->alloc_rss_size) +- continue; +- return rte_flow_error_set(error, EINVAL, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, +- "queue id must be less than queue number allocated to a TC"); ++ if (rss_act->queue_num > HNS3_RSS_QUEUES_BUFFER_NUM) ++ return rte_flow_error_set(error, ENOTSUP, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, ++ "queue number configured exceeds queue buffer size driver supported"); ++ ++ for (i = 0; i < rss_act->queue_num; i++) { ++ if (rss_act->queue[i] >= hw->alloc_rss_size) ++ return rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, ++ "queue id must be less than queue number allocated to a TC"); + } + +- if (!(rss->types & HNS3_ETH_RSS_SUPPORT) && rss->types) ++ memcpy(rss_conf->queue, rss_act->queue, ++ rss_act->queue_num * sizeof(rss_conf->queue[0])); ++ rss_conf->conf.queue = rss_conf->queue; ++ rss_conf->conf.queue_num = rss_act->queue_num; ++ ++ return 0; ++} ++ ++static int ++hns3_flow_get_hw_pctype(struct hns3_hw *hw, ++ const struct rte_flow_action_rss *rss_act, ++ const struct hns3_hash_map_info *map, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ uint64_t l3l4_src_dst, l3l4_refine, left_types; ++ ++ if (rss_act->types == 0) { ++ /* Disable RSS hash of this packet type if types is zero. */ ++ rss_conf->hw_pctypes |= map->hw_pctype; ++ return 0; ++ } ++ ++ /* ++ * Can not have extra types except rss_pctype and l3l4_type in this map. ++ */ ++ left_types = ~map->rss_pctype & rss_act->types; ++ if (left_types & ~map->l3l4_types) + return rte_flow_error_set(error, EINVAL, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, +- act, +- "Flow types is unsupported by " +- "hns3's RSS"); +- if (rss->func >= RTE_ETH_HASH_FUNCTION_MAX) +- return rte_flow_error_set(error, ENOTSUP, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, +- "RSS hash func are not supported"); +- if (rss->level) ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, ++ "cannot set extra types."); ++ ++ l3l4_src_dst = left_types; ++ /* L3/L4 SRC and DST shouldn't be specified at the same time. */ ++ l3l4_refine = rte_eth_rss_hf_refine(l3l4_src_dst); ++ if (l3l4_refine != l3l4_src_dst) + return rte_flow_error_set(error, ENOTSUP, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, +- "a nonzero RSS encapsulation level is not supported"); +- if (rss->key_len && rss->key_len != hw->rss_key_size) ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, ++ "cannot specify L3_SRC/DST_ONLY or L4_SRC/DST_ONLY at the same."); ++ ++ if (!hns3_valid_ipv6_sctp_rss_types(hw, rss_act->types)) + return rte_flow_error_set(error, ENOTSUP, +- RTE_FLOW_ERROR_TYPE_ACTION_CONF, act, +- "invalid RSS key length"); ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, ++ "hardware doesn't support to use L4 src/dst to hash for IPV6-SCTP."); + +- if (!hns3_rss_input_tuple_supported(hw, rss)) +- return rte_flow_error_set(error, EINVAL, ++ rss_conf->hw_pctypes |= map->hw_pctype; ++ ++ return 0; ++} ++ ++static int ++hns3_flow_parse_rss_types_by_ptype(struct hns3_hw *hw, ++ const struct rte_flow_action_rss *rss_act, ++ uint64_t pattern_type, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ const struct hns3_hash_map_info *map; ++ bool matched = false; ++ uint16_t i; ++ int ret; ++ ++ for (i = 0; i < RTE_DIM(hash_map_table); i++) { ++ map = &hash_map_table[i]; ++ if (map->pattern_type != pattern_type) { ++ /* ++ * If the target pattern type is already matched with ++ * the one before this pattern in the hash map table, ++ * no need to continue walk. ++ */ ++ if (matched) ++ break; ++ continue; ++ } ++ matched = true; ++ ++ /* ++ * If pattern type is matched and the 'types' is zero, all packet flow ++ * types related to this pattern type disable RSS hash. ++ * Otherwise, RSS types must match the pattern type and cannot have no ++ * extra or unsupported types. ++ */ ++ if (rss_act->types != 0 && !(map->rss_pctype & rss_act->types)) ++ continue; ++ ++ ret = hns3_flow_get_hw_pctype(hw, rss_act, map, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ } ++ ++ if (rss_conf->hw_pctypes != 0) ++ return 0; ++ ++ if (matched) ++ return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, +- &rss->types, +- "input RSS types are not supported"); ++ NULL, "RSS types are unsupported"); + +- act_index++; ++ return rte_flow_error_set(error, ENOTSUP, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, "Pattern specified is unsupported"); ++} + +- /* Check if the next not void action is END */ +- NEXT_ITEM_OF_ACTION(act, actions, act_index); +- if (act->type != RTE_FLOW_ACTION_TYPE_END) +- return rte_flow_error_set(error, EINVAL, +- RTE_FLOW_ERROR_TYPE_ACTION, +- act, "Not supported action."); ++static uint64_t ++hns3_flow_get_all_hw_pctypes(uint64_t types) ++{ ++ uint64_t hw_pctypes = 0; ++ uint16_t i; + +- return 0; ++ for (i = 0; i < RTE_DIM(hash_map_table); i++) { ++ if (types & hash_map_table[i].rss_pctype) ++ hw_pctypes |= hash_map_table[i].hw_pctype; ++ } ++ ++ return hw_pctypes; + } + + static int +-hns3_disable_rss(struct hns3_hw *hw) ++hns3_flow_parse_rss_types(struct hns3_hw *hw, ++ const struct rte_flow_action_rss *rss_act, ++ uint64_t pattern_type, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ rss_conf->conf.types = rss_act->types; ++ ++ /* no pattern specified to set global RSS types. */ ++ if (pattern_type == 0) { ++ if (rss_act->types & ~HNS3_ETH_RSS_SUPPORT) ++ hns3_warn(hw, "some types in the requested RSS types (0x%" PRIx64 ") aren't supported, they are ignored.", ++ rss_act->types); ++ rss_conf->hw_pctypes = ++ hns3_flow_get_all_hw_pctypes(rss_act->types); ++ return 0; ++ } ++ ++ return hns3_flow_parse_rss_types_by_ptype(hw, rss_act, pattern_type, ++ rss_conf, error); ++} ++ ++static int ++hns3_flow_parse_hash_global_conf(struct rte_eth_dev *dev, ++ const struct rte_flow_action_rss *rss_act, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) + { ++ struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + +- ret = hns3_set_rss_tuple_by_rss_hf(hw, 0); +- if (ret) ++ ret = hns3_flow_parse_hash_func(rss_act, rss_conf, error); ++ if (ret != 0) + return ret; +- hw->rss_info.rss_hf = 0; + +- return 0; ++ if (rss_act->queue_num > 0) { ++ ret = hns3_flow_parse_queues(hw, rss_act, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ } ++ ++ if (rss_act->key_len > 0) { ++ ret = hns3_flow_parse_hash_key(hw, rss_act, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ } ++ ++ return hns3_flow_parse_rss_types(hw, rss_act, rss_conf->pattern_type, ++ rss_conf, error); + } + + static int +-hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_flow_rss_conf *rss_conf, +- uint8_t *hash_algo) +-{ +- const uint8_t hash_func_map[] = { +- [RTE_ETH_HASH_FUNCTION_DEFAULT] = HNS3_RSS_HASH_ALGO_TOEPLITZ, +- [RTE_ETH_HASH_FUNCTION_TOEPLITZ] = HNS3_RSS_HASH_ALGO_TOEPLITZ, +- [RTE_ETH_HASH_FUNCTION_SIMPLE_XOR] = HNS3_RSS_HASH_ALGO_SIMPLE, +- [RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ] = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP, +- }; +- uint8_t key[HNS3_RSS_KEY_SIZE_MAX] = {0}; +- int ret; ++hns3_flow_parse_pattern_type(const struct rte_flow_item pattern[], ++ uint64_t *ptype, struct rte_flow_error *error) ++{ ++ enum rte_flow_item_type pre_type = RTE_FLOW_ITEM_TYPE_VOID; ++ const char *message = "Pattern specified isn't supported"; ++ uint64_t item_hdr, pattern_hdrs = 0; ++ enum rte_flow_item_type cur_type; + +- if (rss_conf->conf.func == RTE_ETH_HASH_FUNCTION_DEFAULT) { +- ret = hns3_rss_get_algo_key(hw, hash_algo, key, +- hw->rss_key_size); +- if (ret != 0) { +- hns3_err(hw, "fail to get current RSS hash algorithm, ret = %d", +- ret); +- return ret; ++ for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { ++ if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) ++ continue; ++ if (pattern->mask || pattern->spec || pattern->last) { ++ message = "Header info shouldn't be specified"; ++ goto unsup; + } + +- /* +- * During the phase of reset recovery, the hash algorithm +- * obtained from hardware may not be the one used(saved in +- * rte_flow_hash_algo) when this rule is delivered. +- */ +- if (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) && +- *hash_algo != rss_conf->hash_algo) +- *hash_algo = rss_conf->hash_algo; ++ /* Check the sub-item allowed by the previous item . */ ++ if (pre_type >= RTE_DIM(hash_pattern_next_allow_items) || ++ !(hash_pattern_next_allow_items[pre_type] & ++ BIT_ULL(pattern->type))) ++ goto unsup; ++ ++ cur_type = pattern->type; ++ /* Unsupported for current type being greater than array size. */ ++ if (cur_type >= RTE_DIM(hash_pattern_item_header)) ++ goto unsup; ++ ++ /* The value is zero, which means unsupported current header. */ ++ item_hdr = hash_pattern_item_header[cur_type]; ++ if (item_hdr == 0) ++ goto unsup; ++ ++ /* Have duplicate pattern header. */ ++ if (item_hdr & pattern_hdrs) ++ goto unsup; ++ pre_type = cur_type; ++ pattern_hdrs |= item_hdr; ++ } + ++ if (pattern_hdrs != 0) { ++ *ptype = pattern_hdrs; + return 0; + } + +- *hash_algo = hash_func_map[rss_conf->conf.func]; ++unsup: ++ return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, ++ pattern, message); ++} ++ ++static int ++hns3_flow_parse_pattern_act(struct rte_eth_dev *dev, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action_rss *rss_act, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) ++{ ++ struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); ++ int ret; ++ ++ ret = hns3_flow_parse_hash_func(rss_act, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ ++ if (rss_act->key_len > 0) { ++ ret = hns3_flow_parse_hash_key(hw, rss_act, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ } ++ ++ if (rss_act->queue_num > 0) { ++ ret = hns3_flow_parse_queues(hw, rss_act, rss_conf, error); ++ if (ret != 0) ++ return ret; ++ } ++ ++ ret = hns3_flow_parse_pattern_type(pattern, &rss_conf->pattern_type, ++ error); ++ if (ret != 0) ++ return ret; ++ ++ ret = hns3_flow_parse_rss_types(hw, rss_act, rss_conf->pattern_type, ++ rss_conf, error); ++ if (ret != 0) ++ return ret; ++ ++ if (rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT || ++ rss_act->key_len > 0 || rss_act->queue_num > 0) ++ hns3_warn(hw, "hash func, key and queues are global config, which work for all flow types. " ++ "Recommend: don't set them together with pattern."); + + return 0; + } + ++static bool ++hns3_rss_action_is_dup(struct hns3_hw *hw, ++ const struct hns3_flow_rss_conf *conf) ++{ ++ struct hns3_rss_conf_ele *filter; ++ ++ TAILQ_FOREACH(filter, &hw->flow_rss_list, entries) { ++ if (conf->pattern_type != filter->filter_info.pattern_type) ++ continue; ++ ++ if (hns3_action_rss_same(&filter->filter_info.conf, &conf->conf)) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * This function is used to parse rss action validation. ++ */ + static int +-hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf) ++hns3_parse_rss_filter(struct rte_eth_dev *dev, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action *actions, ++ struct hns3_flow_rss_conf *rss_conf, ++ struct rte_flow_error *error) + { +- struct rte_flow_action_rss *rss_config = &conf->conf; +- uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; +- bool use_default_key = false; +- uint64_t flow_types; +- uint8_t hash_algo; ++ struct hns3_adapter *hns = dev->data->dev_private; ++ const struct rte_flow_action_rss *rss_act; ++ const struct rte_flow_action *act; ++ const struct rte_flow_item *pat; ++ struct hns3_hw *hw = &hns->hw; ++ uint32_t index = 0; + int ret; + +- if (rss_config->key == NULL || rss_config->key_len != hw->rss_key_size) { +- hns3_warn(hw, "Default RSS hash key to be set"); +- memcpy(rss_key, hns3_hash_key, +- RTE_MIN(sizeof(hns3_hash_key), hw->rss_key_size)); +- use_default_key = true; ++ NEXT_ITEM_OF_ACTION(act, actions, index); ++ if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) ++ return rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION, ++ &actions[1], ++ "Only support one action for RSS."); ++ ++ rss_act = (const struct rte_flow_action_rss *)act->conf; ++ if (rss_act == NULL) { ++ return rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ act, "lost RSS action configuration"); + } + +- ret = hns3_parse_rss_algorithm(hw, conf, &hash_algo); +- if (ret) ++ if (rss_act->level != 0) ++ return rte_flow_error_set(error, ENOTSUP, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ act, ++ "RSS level is not supported"); ++ ++ index = 0; ++ NEXT_ITEM_OF_PATTERN(pat, pattern, index); ++ if (pat[0].type == RTE_FLOW_ITEM_TYPE_END) { ++ rss_conf->pattern_type = 0; ++ ret = hns3_flow_parse_hash_global_conf(dev, rss_act, ++ rss_conf, error); ++ } else { ++ ret = hns3_flow_parse_pattern_act(dev, pat, rss_act, ++ rss_conf, error); ++ } ++ if (ret != 0) + return ret; + +- ret = hns3_rss_set_algo_key(hw, hash_algo, +- use_default_key ? rss_key : rss_config->key, +- hw->rss_key_size); +- if (ret) +- return ret; +- conf->hash_algo = hash_algo; +- +- /* Filter the unsupported flow types */ +- flow_types = rss_config->types ? +- rss_config->types & HNS3_ETH_RSS_SUPPORT : +- hw->rss_info.rss_hf; +- if (flow_types != rss_config->types) +- hns3_warn(hw, "modified RSS types based on hardware support," +- " requested:0x%" PRIx64 " configured:0x%" PRIx64, +- rss_config->types, flow_types); +- +- ret = hns3_set_rss_tuple_by_rss_hf(hw, flow_types); +- if (ret) +- hns3_err(hw, "Update RSS tuples by rss hf failed %d", ret); ++ if (hns3_rss_action_is_dup(hw, rss_conf)) ++ return rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ act, "duplicate RSS rule"); + +- return ret; ++ return 0; + } + + static int +@@ -1543,44 +1886,106 @@ hns3_update_indir_table(struct hns3_hw *hw, + return hns3_set_rss_indir_table(hw, indir_tbl, hw->rss_ind_tbl_size); + } + ++static uint64_t ++hns3_flow_get_pctype_tuple_mask(uint64_t hw_pctype) ++{ ++ uint64_t tuple_mask = 0; ++ uint16_t i; ++ ++ for (i = 0; i < RTE_DIM(hash_map_table); i++) { ++ if (hw_pctype == hash_map_table[i].hw_pctype) { ++ tuple_mask = hash_map_table[i].tuple_mask; ++ break; ++ } ++ } ++ ++ return tuple_mask; ++} ++ + static int +-hns3_reset_rss_filter(struct hns3_hw *hw, +- const struct hns3_flow_rss_conf *conf) ++hns3_flow_set_rss_ptype_tuple(struct hns3_hw *hw, ++ struct hns3_flow_rss_conf *rss_conf) + { ++ uint64_t old_tuple_fields, new_tuple_fields; ++ uint64_t hw_pctypes, tuples, tuple_mask = 0; ++ bool cfg_global_tuple; + int ret; + +- if (!conf->valid) +- return 0; ++ cfg_global_tuple = (rss_conf->pattern_type == 0); ++ if (!cfg_global_tuple) { ++ /* ++ * To ensure that different packets do not affect each other, ++ * we have to first read all tuple fields, and then only modify ++ * the tuples for the specified packet type. ++ */ ++ ret = hns3_get_rss_tuple_field(hw, &old_tuple_fields); ++ if (ret != 0) ++ return ret; + +- ret = hns3_disable_rss(hw); +- if (ret) +- hns3_err(hw, "RSS disable failed(%d)", ret); ++ new_tuple_fields = old_tuple_fields; ++ hw_pctypes = rss_conf->hw_pctypes; ++ while (hw_pctypes > 0) { ++ uint32_t idx = rte_bsf64(hw_pctypes); ++ uint64_t pctype = BIT_ULL(idx); ++ ++ tuple_mask = hns3_flow_get_pctype_tuple_mask(pctype); ++ tuples = hns3_rss_calc_tuple_filed(hw, ++ rss_conf->conf.types); ++ new_tuple_fields &= ~tuple_mask; ++ new_tuple_fields |= tuples; ++ hw_pctypes &= ~pctype; ++ } ++ } else { ++ new_tuple_fields = ++ hns3_rss_calc_tuple_filed(hw, rss_conf->conf.types); ++ } + +- return ret; ++ ret = hns3_set_rss_tuple_field(hw, new_tuple_fields); ++ if (ret != 0) ++ return ret; ++ ++ hns3_info(hw, "RSS tuple fields changed from 0x%" PRIx64 " to 0x%" PRIx64, ++ old_tuple_fields, new_tuple_fields); ++ ++ return 0; + } + + static int +-hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf) ++hns3_config_rss_filter(struct hns3_hw *hw, ++ struct hns3_flow_rss_conf *rss_conf) + { + struct rte_flow_action_rss *rss_act; +- uint16_t num; + int ret; + +- rss_act = &conf->conf; +- /* Set rx queues to use */ +- num = RTE_MIN(hw->data->nb_rx_queues, rss_act->queue_num); +- if (rss_act->queue_num > num) +- hns3_warn(hw, "Config queue numbers %u are beyond the scope of truncated", +- rss_act->queue_num); +- hns3_info(hw, "Max of contiguous %u PF queues are configured", num); +- if (num) { +- ret = hns3_update_indir_table(hw, rss_act, num); +- if (ret) ++ rss_act = &rss_conf->conf; ++ if (rss_act->queue_num > 0) { ++ ret = hns3_update_indir_table(hw, rss_act, rss_act->queue_num); ++ if (ret) { ++ hns3_err(hw, "set queues action failed, ret = %d", ret); ++ return ret; ++ } ++ } ++ ++ if (rss_act->key_len > 0 || ++ rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT) { ++ ret = hns3_update_rss_algo_key(hw, rss_act->func, rss_conf->key, ++ rss_act->key_len); ++ if (ret != 0) { ++ hns3_err(hw, "set func or hash key action failed, ret = %d", ++ ret); + return ret; ++ } ++ } ++ ++ if (rss_conf->hw_pctypes > 0) { ++ ret = hns3_flow_set_rss_ptype_tuple(hw, rss_conf); ++ if (ret != 0) { ++ hns3_err(hw, "set types action failed, ret = %d", ret); ++ return ret; ++ } + } + +- /* Set hash algorithm and flow types by the user's config */ +- return hns3_hw_rss_hash_set(hw, conf); ++ return 0; + } + + static int +@@ -1589,50 +1994,44 @@ hns3_clear_rss_filter(struct rte_eth_dev *dev) + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_rss_conf_ele *rss_filter_ptr; + struct hns3_hw *hw = &hns->hw; +- int rss_rule_succ_cnt = 0; /* count for success of clearing RSS rules */ +- int rss_rule_fail_cnt = 0; /* count for failure of clearing RSS rules */ +- int ret = 0; + + rss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list); + while (rss_filter_ptr) { + TAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries); +- ret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info); +- if (ret) +- rss_rule_fail_cnt++; +- else +- rss_rule_succ_cnt++; + rte_free(rss_filter_ptr); + rss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list); + } + +- if (rss_rule_fail_cnt) { +- hns3_err(hw, "fail to delete all RSS filters, success num = %d fail num = %d", +- rss_rule_succ_cnt, rss_rule_fail_cnt); +- ret = -EIO; +- } +- +- return ret; ++ return hns3_config_rss(hns); + } + + static int +-hns3_restore_rss_filter(struct hns3_hw *hw) ++hns3_reconfig_all_rss_filter(struct hns3_hw *hw) + { + struct hns3_rss_conf_ele *filter; +- int ret = 0; ++ uint32_t rule_no = 0; ++ int ret; + +- pthread_mutex_lock(&hw->flows_lock); + TAILQ_FOREACH(filter, &hw->flow_rss_list, entries) { +- if (!filter->filter_info.valid) +- continue; +- + ret = hns3_config_rss_filter(hw, &filter->filter_info); + if (ret != 0) { +- hns3_err(hw, "restore RSS filter failed, ret=%d", ret); +- goto out; ++ hns3_err(hw, "config %uth RSS filter failed, ret = %d", ++ rule_no, ret); ++ return ret; + } ++ rule_no++; + } + +-out: ++ return 0; ++} ++ ++static int ++hns3_restore_rss_filter(struct hns3_hw *hw) ++{ ++ int ret; ++ ++ pthread_mutex_lock(&hw->flows_lock); ++ ret = hns3_reconfig_all_rss_filter(hw); + pthread_mutex_unlock(&hw->flows_lock); + + return ret; +@@ -1651,38 +2050,6 @@ hns3_restore_filter(struct hns3_adapter *hns) + return hns3_restore_rss_filter(hw); + } + +-static bool +-hns3_rss_action_is_dup(struct hns3_hw *hw, +- const struct rte_flow_action_rss *act) +-{ +- struct hns3_rss_conf_ele *filter; +- +- TAILQ_FOREACH(filter, &hw->flow_rss_list, entries) { +- if (!filter->filter_info.valid) +- continue; +- +- if (hns3_action_rss_same(&filter->filter_info.conf, act)) +- return true; +- } +- +- return false; +-} +- +-static int +-hns3_flow_parse_rss(struct rte_eth_dev *dev, +- struct hns3_flow_rss_conf *conf) +-{ +- struct hns3_adapter *hns = dev->data->dev_private; +- struct hns3_hw *hw = &hns->hw; +- +- if (hns3_rss_action_is_dup(hw, &conf->conf)) { +- hns3_err(hw, "duplicate RSS configuration"); +- return -EINVAL; +- } +- +- return hns3_config_rss_filter(hw, conf); +-} +- + static int + hns3_flow_args_check(const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], +@@ -1716,32 +2083,55 @@ static int + hns3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], +- struct rte_flow_error *error) ++ struct rte_flow_error *error, ++ struct hns3_filter_info *filter_info) + { +- struct hns3_fdir_rule fdir_rule; ++ union hns3_filter_conf *conf; + int ret; + + ret = hns3_flow_args_check(attr, pattern, actions, error); + if (ret) + return ret; + +- if (hns3_find_rss_general_action(pattern, actions)) +- return hns3_parse_rss_filter(dev, actions, error); ++ hns3_parse_filter_type(pattern, actions, filter_info); ++ conf = &filter_info->conf; ++ if (filter_info->type == RTE_ETH_FILTER_HASH) ++ return hns3_parse_rss_filter(dev, pattern, actions, ++ &conf->rss_conf, error); + +- memset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule)); +- return hns3_parse_fdir_filter(dev, pattern, actions, &fdir_rule, error); ++ return hns3_parse_fdir_filter(dev, pattern, actions, ++ &conf->fdir_conf, error); ++} ++ ++static int ++hns3_flow_rebuild_all_rss_filter(struct hns3_adapter *hns) ++{ ++ struct hns3_hw *hw = &hns->hw; ++ int ret; ++ ++ ret = hns3_config_rss(hns); ++ if (ret != 0) { ++ hns3_err(hw, "restore original RSS configuration failed, ret = %d.", ++ ret); ++ return ret; ++ } ++ ret = hns3_reconfig_all_rss_filter(hw); ++ if (ret != 0) ++ hns3_err(hw, "rebuild all RSS filter failed, ret = %d.", ret); ++ ++ return ret; + } + + static int + hns3_flow_create_rss_rule(struct rte_eth_dev *dev, +- const struct rte_flow_action *act, ++ struct hns3_flow_rss_conf *rss_conf, + struct rte_flow *flow) + { + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); +- const struct rte_flow_action_rss *rss_act; ++ struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + struct hns3_rss_conf_ele *rss_filter_ptr; + struct hns3_flow_rss_conf *new_conf; +- struct hns3_rss_conf_ele *filter_ptr; ++ struct rte_flow_action_rss *rss_act; + int ret; + + rss_filter_ptr = rte_zmalloc("hns3 rss filter", +@@ -1751,35 +2141,28 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev, + return -ENOMEM; + } + +- rss_act = (const struct rte_flow_action_rss *)act->conf; + new_conf = &rss_filter_ptr->filter_info; +- memcpy(&new_conf->conf, rss_act, sizeof(*rss_act)); +- if (rss_act->queue_num > 0) { +- memcpy(new_conf->queue, rss_act->queue, +- rss_act->queue_num * sizeof(new_conf->queue[0])); ++ memcpy(new_conf, rss_conf, sizeof(*new_conf)); ++ rss_act = &new_conf->conf; ++ if (rss_act->queue_num > 0) + new_conf->conf.queue = new_conf->queue; +- } +- if (rss_act->key_len > 0) { +- if (rss_act->key != NULL) { +- memcpy(new_conf->key, rss_act->key, +- rss_act->key_len * sizeof(new_conf->key[0])); +- new_conf->conf.key = new_conf->key; +- } +- } ++ /* ++ * There are two ways to deliver hash key action: ++ * 1> 'key_len' is greater than zero and 'key' isn't NULL. ++ * 2> 'key_len' is greater than zero, but 'key' is NULL. ++ * For case 2, we need to keep 'key' of the new_conf is NULL so as to ++ * inherit the configuration from user in case of failing to verify ++ * duplicate rule later. ++ */ ++ if (rss_act->key_len > 0 && rss_act->key != NULL) ++ new_conf->conf.key = new_conf->key; + +- ret = hns3_flow_parse_rss(dev, new_conf); ++ ret = hns3_config_rss_filter(hw, new_conf); + if (ret != 0) { + rte_free(rss_filter_ptr); ++ (void)hns3_flow_rebuild_all_rss_filter(hns); + return ret; + } +- rss_filter_ptr->filter_info.valid = true; +- +- /* +- * When create a new RSS rule, the old rule will be overlaid and set +- * invalid. +- */ +- TAILQ_FOREACH(filter_ptr, &hw->flow_rss_list, entries) +- filter_ptr->filter_info.valid = false; + + TAILQ_INSERT_TAIL(&hw->flow_rss_list, rss_filter_ptr, entries); + flow->rule = rss_filter_ptr; +@@ -1790,31 +2173,24 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev, + + static int + hns3_flow_create_fdir_rule(struct rte_eth_dev *dev, +- const struct rte_flow_item pattern[], +- const struct rte_flow_action actions[], ++ struct hns3_fdir_rule *fdir_rule, + struct rte_flow_error *error, + struct rte_flow *flow) + { + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + struct hns3_fdir_rule_ele *fdir_rule_ptr; +- struct hns3_fdir_rule fdir_rule; + bool indir; + int ret; + +- memset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule)); +- ret = hns3_parse_fdir_filter(dev, pattern, actions, &fdir_rule, error); +- if (ret != 0) +- return ret; +- +- indir = !!(fdir_rule.flags & HNS3_RULE_FLAG_COUNTER_INDIR); +- if (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER) { +- ret = hns3_counter_new(dev, indir, fdir_rule.act_cnt.id, ++ indir = !!(fdir_rule->flags & HNS3_RULE_FLAG_COUNTER_INDIR); ++ if (fdir_rule->flags & HNS3_RULE_FLAG_COUNTER) { ++ ret = hns3_counter_new(dev, indir, fdir_rule->act_cnt.id, + error); + if (ret != 0) + return ret; + +- flow->counter_id = fdir_rule.act_cnt.id; ++ flow->counter_id = fdir_rule->act_cnt.id; + } + + fdir_rule_ptr = rte_zmalloc("hns3 fdir rule", +@@ -1830,11 +2206,11 @@ hns3_flow_create_fdir_rule(struct rte_eth_dev *dev, + * rules to the hardware to simplify the rollback of rules in the + * hardware. + */ +- ret = hns3_fdir_filter_program(hns, &fdir_rule, false); ++ ret = hns3_fdir_filter_program(hns, fdir_rule, false); + if (ret != 0) + goto err_fdir_filter; + +- memcpy(&fdir_rule_ptr->fdir_conf, &fdir_rule, ++ memcpy(&fdir_rule_ptr->fdir_conf, fdir_rule, + sizeof(struct hns3_fdir_rule)); + TAILQ_INSERT_TAIL(&hw->flow_fdir_list, fdir_rule_ptr, entries); + flow->rule = fdir_rule_ptr; +@@ -1845,8 +2221,8 @@ hns3_flow_create_fdir_rule(struct rte_eth_dev *dev, + err_fdir_filter: + rte_free(fdir_rule_ptr); + err_malloc: +- if (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER) +- hns3_counter_release(dev, fdir_rule.act_cnt.id); ++ if (fdir_rule->flags & HNS3_RULE_FLAG_COUNTER) ++ hns3_counter_release(dev, fdir_rule->act_cnt.id); + + return ret; + } +@@ -1864,13 +2240,15 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, + struct rte_flow_error *error) + { + struct hns3_adapter *hns = dev->data->dev_private; +- struct hns3_hw *hw = &hns->hw; ++ struct hns3_filter_info filter_info = {0}; + struct hns3_flow_mem *flow_node; +- const struct rte_flow_action *act; ++ struct hns3_hw *hw = &hns->hw; ++ union hns3_filter_conf *conf; + struct rte_flow *flow; + int ret; + +- ret = hns3_flow_validate(dev, attr, pattern, actions, error); ++ ret = hns3_flow_validate(dev, attr, pattern, actions, error, ++ &filter_info); + if (ret) + return NULL; + +@@ -1890,13 +2268,12 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, + } + + flow_node->flow = flow; ++ conf = &filter_info.conf; + TAILQ_INSERT_TAIL(&hw->flow_list, flow_node, entries); +- +- act = hns3_find_rss_general_action(pattern, actions); +- if (act) +- ret = hns3_flow_create_rss_rule(dev, act, flow); ++ if (filter_info.type == RTE_ETH_FILTER_HASH) ++ ret = hns3_flow_create_rss_rule(dev, &conf->rss_conf, flow); + else +- ret = hns3_flow_create_fdir_rule(dev, pattern, actions, ++ ret = hns3_flow_create_fdir_rule(dev, &conf->fdir_conf, + error, flow); + if (ret == 0) + return flow; +@@ -1950,15 +2327,10 @@ hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, + break; + case RTE_ETH_FILTER_HASH: + rss_filter_ptr = (struct hns3_rss_conf_ele *)flow->rule; +- ret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info); +- if (ret) +- return rte_flow_error_set(error, EIO, +- RTE_FLOW_ERROR_TYPE_HANDLE, +- flow, +- "Destroy RSS fail.Try again"); + TAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries); + rte_free(rss_filter_ptr); + rss_filter_ptr = NULL; ++ (void)hns3_flow_rebuild_all_rss_filter(hns); + break; + default: + return rte_flow_error_set(error, EINVAL, +@@ -2064,10 +2436,12 @@ hns3_flow_validate_wrap(struct rte_eth_dev *dev, + struct rte_flow_error *error) + { + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); ++ struct hns3_filter_info filter_info = {0}; + int ret; + + pthread_mutex_lock(&hw->flows_lock); +- ret = hns3_flow_validate(dev, attr, pattern, actions, error); ++ ret = hns3_flow_validate(dev, attr, pattern, actions, error, ++ &filter_info); + pthread_mutex_unlock(&hw->flows_lock); + + return ret; +diff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h +index 90126f2b6e..1b49673f11 100644 +--- a/drivers/net/hns3/hns3_flow.h ++++ b/drivers/net/hns3/hns3_flow.h +@@ -9,6 +9,7 @@ + #include + + #include "hns3_rss.h" ++#include "hns3_fdir.h" + + struct hns3_flow_counter { + LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */ +@@ -26,10 +27,10 @@ struct rte_flow { + + struct hns3_flow_rss_conf { + struct rte_flow_action_rss conf; +- uint8_t hash_algo; + uint8_t key[HNS3_RSS_KEY_SIZE_MAX]; /* Hash key */ + uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */ +- bool valid; /* check if RSS rule is valid */ ++ uint64_t pattern_type; ++ uint64_t hw_pctypes; /* packet types in driver */ + }; + + /* rss filter list structure */ +@@ -53,6 +54,16 @@ struct rte_flow_action_handle { + uint32_t counter_id; + }; + ++union hns3_filter_conf { ++ struct hns3_fdir_rule fdir_conf; ++ struct hns3_flow_rss_conf rss_conf; ++}; ++ ++struct hns3_filter_info { ++ enum rte_filter_type type; ++ union hns3_filter_conf conf; ++}; ++ + TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele); + TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem); + +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index f51d70a8e5..dfa2901ae3 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -18,69 +18,13 @@ const uint8_t hns3_hash_key[HNS3_RSS_KEY_SIZE] = { + 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA + }; + +-enum hns3_tuple_field { +- /* IPV4_TCP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D = 0, +- HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S, +- HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D, +- HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S, +- +- /* IPV4_UDP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D = 8, +- HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S, +- HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D, +- HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S, +- +- /* IPV4_SCTP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D = 16, +- HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S, +- HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D, +- HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S, +- HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER, +- +- /* IPV4 ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D = 24, +- HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S, +- HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D, +- HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S, +- +- /* IPV6_TCP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D = 32, +- HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S, +- HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D, +- HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S, +- +- /* IPV6_UDP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D = 40, +- HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S, +- HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D, +- HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S, +- +- /* IPV6_SCTP ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D = 48, +- HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S, +- HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D, +- HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S, +- HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER, +- +- /* IPV6 ENABLE FIELD */ +- HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D = 56, +- HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S, +- HNS3_RSS_FIELD_IPV6_FRAG_IP_D, +- HNS3_RSS_FIELD_IPV6_FRAG_IP_S ++const uint8_t hns3_hash_func_map[] = { ++ [RTE_ETH_HASH_FUNCTION_DEFAULT] = HNS3_RSS_HASH_ALGO_TOEPLITZ, ++ [RTE_ETH_HASH_FUNCTION_TOEPLITZ] = HNS3_RSS_HASH_ALGO_TOEPLITZ, ++ [RTE_ETH_HASH_FUNCTION_SIMPLE_XOR] = HNS3_RSS_HASH_ALGO_SIMPLE, ++ [RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ] = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP, + }; + +-#define HNS3_RSS_TUPLE_IPV4_TCP_M GENMASK(3, 0) +-#define HNS3_RSS_TUPLE_IPV4_UDP_M GENMASK(11, 8) +-#define HNS3_RSS_TUPLE_IPV4_SCTP_M GENMASK(20, 16) +-#define HNS3_RSS_TUPLE_IPV4_NONF_M GENMASK(25, 24) +-#define HNS3_RSS_TUPLE_IPV4_FLAG_M GENMASK(27, 26) +-#define HNS3_RSS_TUPLE_IPV6_TCP_M GENMASK(35, 32) +-#define HNS3_RSS_TUPLE_IPV6_UDP_M GENMASK(43, 40) +-#define HNS3_RSS_TUPLE_IPV6_SCTP_M GENMASK(52, 48) +-#define HNS3_RSS_TUPLE_IPV6_NONF_M GENMASK(57, 56) +-#define HNS3_RSS_TUPLE_IPV6_FLAG_M GENMASK(59, 58) +- + enum hns3_rss_tuple_type { + HNS3_RSS_IP_TUPLE, + HNS3_RSS_IP_L4_TUPLE, +@@ -574,7 +518,7 @@ hns3_rss_check_l3l4_types(struct hns3_hw *hw, uint64_t rss_hf) + hns3_warn(hw, "packet type isn't specified, L4_SRC/DST_ONLY is ignored."); + } + +-static uint64_t ++uint64_t + hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf) + { + uint64_t l3_only_mask = RTE_ETH_RSS_L3_SRC_ONLY | +@@ -610,25 +554,35 @@ hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf) + } + + int +-hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf) ++hns3_set_rss_tuple_field(struct hns3_hw *hw, uint64_t tuple_fields) + { + struct hns3_rss_input_tuple_cmd *req; + struct hns3_cmd_desc desc; +- uint64_t tuple_field; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false); + req = (struct hns3_rss_input_tuple_cmd *)desc.data; +- +- tuple_field = hns3_rss_calc_tuple_filed(hw, rss_hf); +- req->tuple_field = rte_cpu_to_le_64(tuple_field); ++ req->tuple_field = rte_cpu_to_le_64(tuple_fields); + ret = hns3_cmd_send(hw, &desc, 1); +- if (ret) { +- hns3_err(hw, "Update RSS flow types tuples failed %d", ret); +- return ret; +- } ++ if (ret != 0) ++ hns3_err(hw, "set RSS hash tuple fields failed ret = %d", ret); + +- return 0; ++ return ret; ++} ++ ++int ++hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf) ++{ ++ uint64_t tuple_fields; ++ int ret; ++ ++ tuple_fields = hns3_rss_calc_tuple_filed(hw, rss_hf); ++ ret = hns3_set_rss_tuple_field(hw, tuple_fields); ++ if (ret != 0) ++ hns3_err(hw, "Update RSS flow types tuples failed, ret = %d", ++ ret); ++ ++ return ret; + } + + /* +@@ -1000,6 +954,52 @@ hns3_set_rss_tc_mode(struct hns3_hw *hw) + return ret; + } + ++/* ++ * Note: the 'hash_algo' is defined by enum rte_eth_hash_function. ++ */ ++int ++hns3_update_rss_algo_key(struct hns3_hw *hw, uint8_t hash_func, ++ uint8_t *key, uint8_t key_len) ++{ ++ uint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0}; ++ bool modify_key, modify_algo; ++ uint8_t hash_algo; ++ int ret; ++ ++ modify_key = (key != NULL && key_len > 0); ++ modify_algo = hash_func != RTE_ETH_HASH_FUNCTION_DEFAULT; ++ if (!modify_key && !modify_algo) ++ return 0; ++ ++ if (modify_algo && hash_func >= RTE_DIM(hns3_hash_func_map)) { ++ hns3_err(hw, "hash func (%u) is unsupported.", hash_func); ++ return -ENOTSUP; ++ } ++ if (modify_key && key_len != hw->rss_key_size) { ++ hns3_err(hw, "hash key length (%u) is invalid.", key_len); ++ return -EINVAL; ++ } ++ ++ ret = hns3_rss_get_algo_key(hw, &hash_algo, rss_key, hw->rss_key_size); ++ if (ret != 0) { ++ hns3_err(hw, "fail to get RSS hash algorithm and key, ret = %d", ++ ret); ++ return ret; ++ } ++ ++ if (modify_algo) ++ hash_algo = hns3_hash_func_map[hash_func]; ++ if (modify_key) ++ memcpy(rss_key, key, key_len); ++ ++ ret = hns3_rss_set_algo_key(hw, hash_algo, rss_key, hw->rss_key_size); ++ if (ret != 0) ++ hns3_err(hw, "fail to set RSS hash algorithm and key, ret = %d", ++ ret); ++ ++ return ret; ++} ++ + static void + hns3_rss_tuple_uninit(struct hns3_hw *hw) + { +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index d19730c69c..d672481a14 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -8,23 +8,102 @@ + #include + #include + +-#define HNS3_ETH_RSS_SUPPORT ( \ +- RTE_ETH_RSS_IPV4 | \ +- RTE_ETH_RSS_FRAG_IPV4 | \ +- RTE_ETH_RSS_NONFRAG_IPV4_TCP | \ +- RTE_ETH_RSS_NONFRAG_IPV4_UDP | \ +- RTE_ETH_RSS_NONFRAG_IPV4_SCTP | \ +- RTE_ETH_RSS_NONFRAG_IPV4_OTHER | \ +- RTE_ETH_RSS_IPV6 | \ +- RTE_ETH_RSS_FRAG_IPV6 | \ +- RTE_ETH_RSS_NONFRAG_IPV6_TCP | \ +- RTE_ETH_RSS_NONFRAG_IPV6_UDP | \ +- RTE_ETH_RSS_NONFRAG_IPV6_SCTP | \ +- RTE_ETH_RSS_NONFRAG_IPV6_OTHER | \ +- RTE_ETH_RSS_L3_SRC_ONLY | \ +- RTE_ETH_RSS_L3_DST_ONLY | \ +- RTE_ETH_RSS_L4_SRC_ONLY | \ +- RTE_ETH_RSS_L4_DST_ONLY) ++#define HNS3_RSS_SUPPORT_L3_SRC_DST (RTE_ETH_RSS_L3_SRC_ONLY | \ ++ RTE_ETH_RSS_L3_DST_ONLY) ++#define HNS3_RSS_SUPPORT_L4_SRC_DST (RTE_ETH_RSS_L4_SRC_ONLY | \ ++ RTE_ETH_RSS_L4_DST_ONLY) ++#define HNS3_RSS_SUPPORT_L3L4 (HNS3_RSS_SUPPORT_L3_SRC_DST | \ ++ HNS3_RSS_SUPPORT_L4_SRC_DST) ++ ++#define HNS3_RSS_SUPPORT_FLOW_TYPE (RTE_ETH_RSS_IPV4 | \ ++ RTE_ETH_RSS_FRAG_IPV4 | \ ++ RTE_ETH_RSS_NONFRAG_IPV4_TCP | \ ++ RTE_ETH_RSS_NONFRAG_IPV4_UDP | \ ++ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | \ ++ RTE_ETH_RSS_NONFRAG_IPV4_OTHER | \ ++ RTE_ETH_RSS_IPV6 | \ ++ RTE_ETH_RSS_FRAG_IPV6 | \ ++ RTE_ETH_RSS_NONFRAG_IPV6_TCP | \ ++ RTE_ETH_RSS_NONFRAG_IPV6_UDP | \ ++ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | \ ++ RTE_ETH_RSS_NONFRAG_IPV6_OTHER) ++ ++#define HNS3_ETH_RSS_SUPPORT (HNS3_RSS_SUPPORT_FLOW_TYPE | \ ++ HNS3_RSS_SUPPORT_L3L4) ++ ++enum hns3_tuple_field { ++ /* IPV4_TCP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D = 0, ++ HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S, ++ HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S, ++ ++ /* IPV4_UDP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D = 8, ++ HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S, ++ HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S, ++ ++ /* IPV4_SCTP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D = 16, ++ HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S, ++ HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S, ++ HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER, ++ ++ /* IPV4 ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D = 24, ++ HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S, ++ HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D, ++ HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S, ++ ++ /* IPV6_TCP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D = 32, ++ HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S, ++ HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S, ++ ++ /* IPV6_UDP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D = 40, ++ HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S, ++ HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S, ++ ++ /* IPV6_SCTP ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D = 48, ++ HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S, ++ HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D, ++ HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S, ++ HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER, ++ ++ /* IPV6 ENABLE FIELD */ ++ HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D = 56, ++ HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S, ++ HNS3_RSS_FIELD_IPV6_FRAG_IP_D, ++ HNS3_RSS_FIELD_IPV6_FRAG_IP_S ++}; ++ ++#define HNS3_RSS_PCTYPE_IPV4_TCP BIT_ULL(0) ++#define HNS3_RSS_PCTYPE_IPV4_UDP BIT_ULL(8) ++#define HNS3_RSS_PCTYPE_IPV4_SCTP BIT_ULL(16) ++#define HNS3_RSS_PCTYPE_IPV4_NONF BIT_ULL(24) ++#define HNS3_RSS_PCTYPE_IPV4_FLAG BIT_ULL(26) ++#define HNS3_RSS_PCTYPE_IPV6_TCP BIT_ULL(32) ++#define HNS3_RSS_PCTYPE_IPV6_UDP BIT_ULL(40) ++#define HNS3_RSS_PCTYPE_IPV6_SCTP BIT_ULL(48) ++#define HNS3_RSS_PCTYPE_IPV6_NONF BIT_ULL(56) ++#define HNS3_RSS_PCTYPE_IPV6_FLAG BIT_ULL(58) ++ ++#define HNS3_RSS_TUPLE_IPV4_TCP_M GENMASK(3, 0) ++#define HNS3_RSS_TUPLE_IPV4_UDP_M GENMASK(11, 8) ++#define HNS3_RSS_TUPLE_IPV4_SCTP_M GENMASK(20, 16) ++#define HNS3_RSS_TUPLE_IPV4_NONF_M GENMASK(25, 24) ++#define HNS3_RSS_TUPLE_IPV4_FLAG_M GENMASK(27, 26) ++#define HNS3_RSS_TUPLE_IPV6_TCP_M GENMASK(35, 32) ++#define HNS3_RSS_TUPLE_IPV6_UDP_M GENMASK(43, 40) ++#define HNS3_RSS_TUPLE_IPV6_SCTP_M GENMASK(52, 48) ++#define HNS3_RSS_TUPLE_IPV6_NONF_M GENMASK(57, 56) ++#define HNS3_RSS_TUPLE_IPV6_FLAG_M GENMASK(59, 58) + + #define HNS3_RSS_IND_TBL_SIZE 512 /* The size of hash lookup table */ + #define HNS3_RSS_IND_TBL_SIZE_MAX 2048 +@@ -108,10 +187,14 @@ int hns3_rss_reset_indir_table(struct hns3_hw *hw); + int hns3_config_rss(struct hns3_adapter *hns); + void hns3_rss_uninit(struct hns3_adapter *hns); + int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf); ++int hns3_set_rss_tuple_field(struct hns3_hw *hw, uint64_t tuple_fields); + int hns3_get_rss_tuple_field(struct hns3_hw *hw, uint64_t *tuple_fields); + int hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + const uint8_t *key, uint8_t key_len); + int hns3_rss_get_algo_key(struct hns3_hw *hw, uint8_t *hash_algo, + uint8_t *key, uint8_t key_len); ++uint64_t hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf); ++int hns3_update_rss_algo_key(struct hns3_hw *hw, uint8_t hash_algo, ++ uint8_t *key, uint8_t key_len); + + #endif /* HNS3_RSS_H */ +-- +2.23.0 + diff --git a/0254-net-hns3-add-verification-of-RSS-types.patch b/0254-net-hns3-add-verification-of-RSS-types.patch new file mode 100644 index 0000000..302bf4a --- /dev/null +++ b/0254-net-hns3-add-verification-of-RSS-types.patch @@ -0,0 +1,199 @@ +From 190de70e4c72d4abb356c8f8a24fec9ec17ce6c1 Mon Sep 17 00:00:00 2001 +From: Huisong Li +Date: Fri, 10 Mar 2023 17:35:18 +0800 +Subject: net/hns3: add verification of RSS types + +[ upstream commit eb3ef9e0d7eb54b47ab58d3d14f9f5fff3f4120b ] + +Add the verification of RSS types from ethdev ops and rte flow without +pattern attribute. The following cases are invalid: +1. types contains unsupported RSS type but hasn't type driver support. +2. types has L3 src/dst but hasn't supported packet type. +3. types has L4 src/dst but hasn't supported packet type and hasn't IP + packet type. + +Fixes: 13c3993240c8 ("net/hns3: add L3 and L4 RSS types") +Cc: stable@dpdk.org + +Signed-off-by: Huisong Li +Signed-off-by: Dongdong Liu +--- + drivers/net/hns3/hns3_flow.c | 12 +++--- + drivers/net/hns3/hns3_rss.c | 74 +++++++++++++++++++++++++----------- + drivers/net/hns3/hns3_rss.h | 3 +- + 3 files changed, 60 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c +index c38bd9dd8b..c1f4f5cb0b 100644 +--- a/drivers/net/hns3/hns3_flow.c ++++ b/drivers/net/hns3/hns3_flow.c +@@ -1652,9 +1652,10 @@ hns3_flow_parse_rss_types(struct hns3_hw *hw, + + /* no pattern specified to set global RSS types. */ + if (pattern_type == 0) { +- if (rss_act->types & ~HNS3_ETH_RSS_SUPPORT) +- hns3_warn(hw, "some types in the requested RSS types (0x%" PRIx64 ") aren't supported, they are ignored.", +- rss_act->types); ++ if (!hns3_check_rss_types_valid(hw, rss_act->types)) ++ return rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION_CONF, ++ NULL, "RSS types is invalid."); + rss_conf->hw_pctypes = + hns3_flow_get_all_hw_pctypes(rss_act->types); + return 0; +@@ -1929,15 +1930,14 @@ hns3_flow_set_rss_ptype_tuple(struct hns3_hw *hw, + uint64_t pctype = BIT_ULL(idx); + + tuple_mask = hns3_flow_get_pctype_tuple_mask(pctype); +- tuples = hns3_rss_calc_tuple_filed(hw, +- rss_conf->conf.types); ++ tuples = hns3_rss_calc_tuple_filed(rss_conf->conf.types); + new_tuple_fields &= ~tuple_mask; + new_tuple_fields |= tuples; + hw_pctypes &= ~pctype; + } + } else { + new_tuple_fields = +- hns3_rss_calc_tuple_filed(hw, rss_conf->conf.types); ++ hns3_rss_calc_tuple_filed(rss_conf->conf.types); + } + + ret = hns3_set_rss_tuple_field(hw, new_tuple_fields); +diff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c +index dfa2901ae3..6126512bd7 100644 +--- a/drivers/net/hns3/hns3_rss.c ++++ b/drivers/net/hns3/hns3_rss.c +@@ -492,34 +492,62 @@ hns3_rss_reset_indir_table(struct hns3_hw *hw) + return ret; + } + +-static void +-hns3_rss_check_l3l4_types(struct hns3_hw *hw, uint64_t rss_hf) ++bool ++hns3_check_rss_types_valid(struct hns3_hw *hw, uint64_t types) + { + uint64_t ip_mask = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | + RTE_ETH_RSS_NONFRAG_IPV4_OTHER | + RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | + RTE_ETH_RSS_NONFRAG_IPV6_OTHER; +- uint64_t l4_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP | +- RTE_ETH_RSS_NONFRAG_IPV4_UDP | +- RTE_ETH_RSS_NONFRAG_IPV4_SCTP | +- RTE_ETH_RSS_NONFRAG_IPV6_TCP | +- RTE_ETH_RSS_NONFRAG_IPV6_UDP | +- RTE_ETH_RSS_NONFRAG_IPV6_SCTP; +- uint64_t l3_src_dst_mask = RTE_ETH_RSS_L3_SRC_ONLY | +- RTE_ETH_RSS_L3_DST_ONLY; +- uint64_t l4_src_dst_mask = RTE_ETH_RSS_L4_SRC_ONLY | +- RTE_ETH_RSS_L4_DST_ONLY; +- +- if (rss_hf & l3_src_dst_mask && +- !(rss_hf & ip_mask || rss_hf & l4_mask)) +- hns3_warn(hw, "packet type isn't specified, L3_SRC/DST_ONLY is ignored."); +- +- if (rss_hf & l4_src_dst_mask && !(rss_hf & l4_mask)) +- hns3_warn(hw, "packet type isn't specified, L4_SRC/DST_ONLY is ignored."); ++ uint64_t ip_l4_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP | ++ RTE_ETH_RSS_NONFRAG_IPV4_UDP | ++ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | ++ RTE_ETH_RSS_NONFRAG_IPV6_TCP | ++ RTE_ETH_RSS_NONFRAG_IPV6_UDP | ++ RTE_ETH_RSS_NONFRAG_IPV6_SCTP; ++ bool has_l4_src_dst = !!(types & HNS3_RSS_SUPPORT_L4_SRC_DST); ++ bool has_ip_pkt = !!(types & ip_mask); ++ uint64_t final_types; ++ ++ if (types == 0) ++ return true; ++ ++ if ((types & HNS3_ETH_RSS_SUPPORT) == 0) { ++ hns3_err(hw, "specified types(0x%" PRIx64 ") are unsupported.", ++ types); ++ return false; ++ } ++ ++ if ((types & HNS3_RSS_SUPPORT_L3_SRC_DST) != 0 && ++ (types & HNS3_RSS_SUPPORT_FLOW_TYPE) == 0) { ++ hns3_err(hw, "IP or IP-TCP/UDP/SCTP packet type isn't specified, L3_SRC/DST_ONLY cannot be set."); ++ return false; ++ } ++ ++ if (has_l4_src_dst && (types & ip_l4_mask) == 0) { ++ if (!has_ip_pkt) { ++ hns3_err(hw, "IP-TCP/UDP/SCTP packet type isn't specified, L4_SRC/DST_ONLY cannot be set."); ++ return false; ++ } ++ /* ++ * For the case that the types has L4_SRC/DST_ONLY but hasn't ++ * IP-TCP/UDP/SCTP packet type, this types is considered valid ++ * if it also has IP packet type. ++ */ ++ hns3_warn(hw, "L4_SRC/DST_ONLY is ignored because of no including L4 packet."); ++ } ++ ++ if ((types & ~HNS3_ETH_RSS_SUPPORT) != 0) { ++ final_types = types & HNS3_ETH_RSS_SUPPORT; ++ hns3_warn(hw, "set RSS types based on hardware support, requested:0x%" PRIx64 " configured:0x%" PRIx64 "", ++ types, final_types); ++ } ++ ++ return true; + } + + uint64_t +-hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf) ++hns3_rss_calc_tuple_filed(uint64_t rss_hf) + { + uint64_t l3_only_mask = RTE_ETH_RSS_L3_SRC_ONLY | + RTE_ETH_RSS_L3_DST_ONLY; +@@ -548,7 +576,6 @@ hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf) + !has_l3_l4_only) + tuple |= hns3_set_tuple_table[i].rss_field; + } +- hns3_rss_check_l3l4_types(hw, rss_hf); + + return tuple; + } +@@ -576,7 +603,7 @@ hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf) + uint64_t tuple_fields; + int ret; + +- tuple_fields = hns3_rss_calc_tuple_filed(hw, rss_hf); ++ tuple_fields = hns3_rss_calc_tuple_filed(rss_hf); + ret = hns3_set_rss_tuple_field(hw, tuple_fields); + if (ret != 0) + hns3_err(hw, "Update RSS flow types tuples failed, ret = %d", +@@ -611,6 +638,9 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev, + return -EINVAL; + } + ++ if (!hns3_check_rss_types_valid(hw, rss_hf)) ++ return -EINVAL; ++ + rte_spinlock_lock(&hw->lock); + ret = hns3_set_rss_tuple_by_rss_hf(hw, rss_hf); + if (ret) +diff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h +index d672481a14..415430a399 100644 +--- a/drivers/net/hns3/hns3_rss.h ++++ b/drivers/net/hns3/hns3_rss.h +@@ -186,6 +186,7 @@ int hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, + int hns3_rss_reset_indir_table(struct hns3_hw *hw); + int hns3_config_rss(struct hns3_adapter *hns); + void hns3_rss_uninit(struct hns3_adapter *hns); ++bool hns3_check_rss_types_valid(struct hns3_hw *hw, uint64_t types); + int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf); + int hns3_set_rss_tuple_field(struct hns3_hw *hw, uint64_t tuple_fields); + int hns3_get_rss_tuple_field(struct hns3_hw *hw, uint64_t *tuple_fields); +@@ -193,7 +194,7 @@ int hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + const uint8_t *key, uint8_t key_len); + int hns3_rss_get_algo_key(struct hns3_hw *hw, uint8_t *hash_algo, + uint8_t *key, uint8_t key_len); +-uint64_t hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf); ++uint64_t hns3_rss_calc_tuple_filed(uint64_t rss_hf); + int hns3_update_rss_algo_key(struct hns3_hw *hw, uint8_t hash_algo, + uint8_t *key, uint8_t key_len); + +-- +2.23.0 + diff --git a/dpdk.spec b/dpdk.spec index 38a5f93..8b74745 100644 --- a/dpdk.spec +++ b/dpdk.spec @@ -1,6 +1,6 @@ Name: dpdk Version: 21.11 -Release: 34 +Release: 35 Packager: packaging@6wind.com URL: http://dpdk.org %global source_version 21.11 @@ -257,6 +257,22 @@ Patch9235: 0235-net-hns3-make-getting-Tx-function-static.patch Patch9236: 0236-net-hns3-extract-common-functions-to-set-Rx-Tx.patch Patch9237: 0237-net-hns3-declare-flow-rule-keeping-capability.patch Patch9238: 0238-app-testpmd-add-disable-flow-flush-option.patch +Patch9239: 0239-net-hns3-fix-possible-truncation-of-hash-key-when-co.patch +Patch9240: 0240-net-hns3-fix-possible-truncation-of-redirection-tabl.patch +Patch9241: 0241-net-hns3-use-hardware-config-to-report-hash-key.patch +Patch9242: 0242-net-hns3-use-hardware-config-to-report-hash-types.patch +Patch9243: 0243-net-hns3-use-hardware-config-to-report-redirection-t.patch +Patch9244: 0244-net-hns3-separate-setting-hash-algorithm.patch +Patch9245: 0245-net-hns3-separate-setting-hash-key.patch +Patch9246: 0246-net-hns3-separate-setting-redirection-table.patch +Patch9247: 0247-net-hns3-separate-setting-RSS-types.patch +Patch9248: 0248-net-hns3-separate-setting-and-clearing-RSS-rule.patch +Patch9249: 0249-net-hns3-use-new-RSS-rule-to-configure-hardware.patch +Patch9250: 0250-net-hns3-save-hash-algo-to-RSS-filter-list-node.patch +Patch9251: 0251-net-hns3-allow-adding-queue-buffer-size-hash-rule.patch +Patch9252: 0252-net-hns3-separate-flow-RSS-config-from-RSS-conf.patch +Patch9253: 0253-net-hns3-reimplement-hash-flow-function.patch +Patch9254: 0254-net-hns3-add-verification-of-RSS-types.patch Summary: Data Plane Development Kit core Group: System Environment/Libraries @@ -399,6 +415,12 @@ strip -g $RPM_BUILD_ROOT/lib/modules/%{kern_devel_ver}/extra/dpdk/igb_uio.ko /usr/sbin/depmod %changelog +* Wed Mar 15 2023 chenjiji - 21.11-35 + Fix some RSS bugs and reimplement hash flow function for hns3: + - fix some RSS bugs and optimize RSS codes for hns3 + - reimplement hash flow function for hns3 to satisfy the + mainstream usage of rte flow hash in the community + * Fri Mar 03 2023 chenjiji - 21.11-34 Support flow rule keeping capability for hns3 PMD and testpmd. Patchs are as follow: