1698 lines
54 KiB
Diff
1698 lines
54 KiB
Diff
|
|
From d5ee6b81de99a8699a6d4adb620ecc88103eb6e2 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Huisong Li <lihuisong@huawei.com>
|
||
|
|
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 <lihuisong@huawei.com>
|
||
|
|
Signed-off-by: Dongdong Liu <liudongdong3@huawei.com>
|
||
|
|
---
|
||
|
|
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 <ethdev_driver.h>
|
||
|
|
|
||
|
|
#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 <rte_ethdev.h>
|
||
|
|
#include <rte_flow.h>
|
||
|
|
|
||
|
|
-#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
|
||
|
|
|