get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/125005/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 125005,
    "url": "http://patches.dpdk.org/api/patches/125005/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230310093518.5198-16-liudongdong3@huawei.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230310093518.5198-16-liudongdong3@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230310093518.5198-16-liudongdong3@huawei.com",
    "date": "2023-03-10T09:35:17",
    "name": "[15/16] net/hns3: reimplement hash flow function",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "5088db3f2daee5f517b3d8c7feb8502203342c0b",
    "submitter": {
        "id": 2718,
        "url": "http://patches.dpdk.org/api/people/2718/?format=api",
        "name": "Dongdong Liu",
        "email": "liudongdong3@huawei.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230310093518.5198-16-liudongdong3@huawei.com/mbox/",
    "series": [
        {
            "id": 27329,
            "url": "http://patches.dpdk.org/api/series/27329/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=27329",
            "date": "2023-03-10T09:35:02",
            "name": "net/hns3: some code refactor for hns3 RSS",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/27329/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/125005/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/125005/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 6740C41E3A;\n\tFri, 10 Mar 2023 10:38:10 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9CFAC42DA2;\n\tFri, 10 Mar 2023 10:36:50 +0100 (CET)",
            "from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187])\n by mails.dpdk.org (Postfix) with ESMTP id 4766342D67;\n Fri, 10 Mar 2023 10:36:46 +0100 (CET)",
            "from kwepemi500017.china.huawei.com (unknown [172.30.72.55])\n by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4PY1Bh37B7zrSSM;\n Fri, 10 Mar 2023 17:35:56 +0800 (CST)",
            "from localhost.localdomain (10.28.79.22) by\n kwepemi500017.china.huawei.com (7.221.188.110) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id\n 15.1.2507.21; Fri, 10 Mar 2023 17:36:44 +0800"
        ],
        "From": "Dongdong Liu <liudongdong3@huawei.com>",
        "To": "<dev@dpdk.org>, <ferruh.yigit@amd.com>, <thomas@monjalon.net>,\n <andrew.rybchenko@oktetlabs.ru>",
        "CC": "<stable@dpdk.org>, <yisen.zhuang@huawei.com>, <liudongdong3@huawei.com>,\n <lihuisong@huawei.com>",
        "Subject": "[PATCH 15/16] net/hns3: reimplement hash flow function",
        "Date": "Fri, 10 Mar 2023 17:35:17 +0800",
        "Message-ID": "<20230310093518.5198-16-liudongdong3@huawei.com>",
        "X-Mailer": "git-send-email 2.22.0",
        "In-Reply-To": "<20230310093518.5198-1-liudongdong3@huawei.com>",
        "References": "<20230310093518.5198-1-liudongdong3@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.28.79.22]",
        "X-ClientProxiedBy": "dggems703-chm.china.huawei.com (10.3.19.180) To\n kwepemi500017.china.huawei.com (7.221.188.110)",
        "X-CFilter-Loop": "Reflected",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "From: Huisong Li <lihuisong@huawei.com>\n\nCurrently, hns3 driver supports setting mulitiple rte flow RSS rule,\nbut only the last is valid. This implementation is different from\nthe mainstream usage of rte flow hash in the community. Please see\nthe discussion threads [1] and [2].\n\nThis patch sets RSS hash feature completely based on the request of\nthe flow rule so that multiple hash rules can take effect at the same\ntime. Please notice that:\n1. For hns3, 'func' has only one hardware. 'key' and 'queue' have only\n   one entry in hardware.\n2. the overlapping part of the old rule will be overridden if the\n   configuration items of a new rule overlap with those of an old rule.\n\nThe hns3_flow_validate() verifies and parses RSS or Fdir rules from\nuser, and saves them to a local variable at the same time. The local\nvariable is directly used to create RSS or Fdir rules. In this way,\nwe save one parsing and saving process.\n\n[1] https://lore.kernel.org/all/DM5PR12MB46648085D7CABF1AFF2D75CDD60A9@DM5PR12MB4664.namprd12.prod.outlook.com/\n[2] https://lore.kernel.org/all/f7de4db4-1b88-622f-4e03-acd3eee8a72c@oktetlabs.ru/\n\nFixes: c37ca66f2b27 (\"net/hns3: support RSS\")\nCc: stable@dpdk.org\n\nSigned-off-by: Huisong Li <lihuisong@huawei.com>\nSigned-off-by: Dongdong Liu <liudongdong3@huawei.com>\n---\n drivers/net/hns3/hns3_ethdev.h |   9 -\n drivers/net/hns3/hns3_flow.c   | 966 +++++++++++++++++++++++----------\n drivers/net/hns3/hns3_flow.h   |  15 +-\n drivers/net/hns3/hns3_rss.c    | 144 ++---\n drivers/net/hns3/hns3_rss.h    | 117 +++-\n 5 files changed, 855 insertions(+), 396 deletions(-)",
    "diff": "diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h\nindex 2457754b3d..9acc5a3d7e 100644\n--- a/drivers/net/hns3/hns3_ethdev.h\n+++ b/drivers/net/hns3/hns3_ethdev.h\n@@ -996,15 +996,6 @@ static inline uint32_t hns3_read_reg(void *base, uint32_t reg)\n #define hns3_read_dev(a, reg) \\\n \thns3_read_reg((a)->io_base, (reg))\n \n-#define NEXT_ITEM_OF_ACTION(act, actions, index)                        \\\n-\tdo {\t\t\t\t\t\t\t\t\\\n-\t\t(act) = (actions) + (index);\t\t\t\t\\\n-\t\twhile ((act)->type == RTE_FLOW_ACTION_TYPE_VOID) {\t\\\n-\t\t\t(index)++;\t\t\t\t\t\\\n-\t\t\t(act) = (actions) + (index);\t\t\t\t\\\n-\t\t}\t\t\t\t\t\t\t\\\n-\t} while (0)\n-\n static inline uint64_t\n hns3_atomic_test_bit(unsigned int nr, volatile uint64_t *addr)\n {\ndiff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c\nindex 89374816aa..6ac623bea9 100644\n--- a/drivers/net/hns3/hns3_flow.c\n+++ b/drivers/net/hns3/hns3_flow.c\n@@ -10,6 +10,125 @@\n #include \"hns3_logs.h\"\n #include \"hns3_flow.h\"\n \n+#define NEXT_ITEM_OF_ACTION(act, actions, index) \\\n+\tdo { \\\n+\t\t(act) = (actions) + (index); \\\n+\t\twhile ((act)->type == RTE_FLOW_ACTION_TYPE_VOID) { \\\n+\t\t\t(index)++; \\\n+\t\t\t(act) = (actions) + (index); \\\n+\t\t} \\\n+\t} while (0)\n+\n+#define NEXT_ITEM_OF_PATTERN(item, pattern, index) \\\n+\tdo { \\\n+\t\t(item) = (pattern) + (index); \\\n+\t\twhile ((item)->type == RTE_FLOW_ITEM_TYPE_VOID) { \\\n+\t\t\t(index)++; \\\n+\t\t\t(item) = (pattern) + (index); \\\n+\t\t} \\\n+\t} while (0)\n+\n+#define HNS3_HASH_HDR_ETH\tRTE_BIT64(0)\n+#define HNS3_HASH_HDR_IPV4\tRTE_BIT64(1)\n+#define HNS3_HASH_HDR_IPV6\tRTE_BIT64(2)\n+#define HNS3_HASH_HDR_TCP\tRTE_BIT64(3)\n+#define HNS3_HASH_HDR_UDP\tRTE_BIT64(4)\n+#define HNS3_HASH_HDR_SCTP\tRTE_BIT64(5)\n+\n+#define HNS3_HASH_VOID_NEXT_ALLOW\tBIT_ULL(RTE_FLOW_ITEM_TYPE_ETH)\n+\n+#define HNS3_HASH_ETH_NEXT_ALLOW\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \\\n+\t\t\t\t\t BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6))\n+\n+#define HNS3_HASH_IP_NEXT_ALLOW\t\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_TCP) | \\\n+\t\t\t\t\t BIT_ULL(RTE_FLOW_ITEM_TYPE_UDP) | \\\n+\t\t\t\t\t BIT_ULL(RTE_FLOW_ITEM_TYPE_SCTP))\n+\n+static const uint64_t hash_pattern_next_allow_items[] = {\n+\t[RTE_FLOW_ITEM_TYPE_VOID] = HNS3_HASH_VOID_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_ETH]  = HNS3_HASH_ETH_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_IPV4] = HNS3_HASH_IP_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_IPV6] = HNS3_HASH_IP_NEXT_ALLOW,\n+};\n+\n+static const uint64_t hash_pattern_item_header[] = {\n+\t[RTE_FLOW_ITEM_TYPE_ETH]  = HNS3_HASH_HDR_ETH,\n+\t[RTE_FLOW_ITEM_TYPE_IPV4] = HNS3_HASH_HDR_IPV4,\n+\t[RTE_FLOW_ITEM_TYPE_IPV6] = HNS3_HASH_HDR_IPV6,\n+\t[RTE_FLOW_ITEM_TYPE_TCP]  = HNS3_HASH_HDR_TCP,\n+\t[RTE_FLOW_ITEM_TYPE_UDP]  = HNS3_HASH_HDR_UDP,\n+\t[RTE_FLOW_ITEM_TYPE_SCTP] = HNS3_HASH_HDR_SCTP,\n+};\n+\n+#define HNS3_HASH_IPV4\t\t(HNS3_HASH_HDR_ETH | HNS3_HASH_HDR_IPV4)\n+#define HNS3_HASH_IPV4_TCP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV4 | \\\n+\t\t\t\t HNS3_HASH_HDR_TCP)\n+#define HNS3_HASH_IPV4_UDP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV4 | \\\n+\t\t\t\t HNS3_HASH_HDR_UDP)\n+#define HNS3_HASH_IPV4_SCTP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV4 | \\\n+\t\t\t\t HNS3_HASH_HDR_SCTP)\n+#define HNS3_HASH_IPV6\t\t(HNS3_HASH_HDR_ETH | HNS3_HASH_HDR_IPV6)\n+#define HNS3_HASH_IPV6_TCP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV6 | \\\n+\t\t\t\t HNS3_HASH_HDR_TCP)\n+#define HNS3_HASH_IPV6_UDP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV6 | \\\n+\t\t\t\t HNS3_HASH_HDR_UDP)\n+#define HNS3_HASH_IPV6_SCTP\t(HNS3_HASH_HDR_ETH | \\\n+\t\t\t\t HNS3_HASH_HDR_IPV6 | \\\n+\t\t\t\t HNS3_HASH_HDR_SCTP)\n+\n+static const struct hns3_hash_map_info {\n+\t/* flow type specified, zero means action works for all flow types. */\n+\tuint64_t pattern_type;\n+\tuint64_t rss_pctype; /* packet type with prefix RTE_ETH_RSS_xxx */\n+\tuint64_t l3l4_types; /* Supported L3/L4 RSS types for this packet type */\n+\tuint64_t hw_pctype; /* packet type in driver */\n+\tuint64_t tuple_mask; /* full tuples of the hw_pctype */\n+} hash_map_table[] = {\n+\t/* IPV4 */\n+\t{ HNS3_HASH_IPV4,\n+\t  RTE_ETH_RSS_IPV4, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV4_NONF, HNS3_RSS_TUPLE_IPV4_NONF_M },\n+\t{ HNS3_HASH_IPV4,\n+\t  RTE_ETH_RSS_NONFRAG_IPV4_OTHER, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV4_NONF, HNS3_RSS_TUPLE_IPV4_NONF_M },\n+\t{ HNS3_HASH_IPV4,\n+\t  RTE_ETH_RSS_FRAG_IPV4, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV4_FLAG, HNS3_RSS_TUPLE_IPV4_FLAG_M },\n+\t{ HNS3_HASH_IPV4_TCP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV4_TCP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV4_TCP, HNS3_RSS_TUPLE_IPV4_TCP_M },\n+\t{ HNS3_HASH_IPV4_UDP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV4_UDP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV4_UDP, HNS3_RSS_TUPLE_IPV4_UDP_M },\n+\t{ HNS3_HASH_IPV4_SCTP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV4_SCTP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV4_SCTP, HNS3_RSS_TUPLE_IPV4_SCTP_M },\n+\t/* IPV6 */\n+\t{ HNS3_HASH_IPV6,\n+\t  RTE_ETH_RSS_IPV6, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV6_NONF, HNS3_RSS_TUPLE_IPV6_NONF_M },\n+\t{ HNS3_HASH_IPV6,\n+\t  RTE_ETH_RSS_NONFRAG_IPV6_OTHER, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV6_NONF, HNS3_RSS_TUPLE_IPV6_NONF_M },\n+\t{ HNS3_HASH_IPV6,\n+\t  RTE_ETH_RSS_FRAG_IPV6, HNS3_RSS_SUPPORT_L3_SRC_DST,\n+\t  HNS3_RSS_PCTYPE_IPV6_FLAG, HNS3_RSS_TUPLE_IPV6_FLAG_M },\n+\t{ HNS3_HASH_IPV6_TCP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV6_TCP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV6_TCP, HNS3_RSS_TUPLE_IPV6_TCP_M },\n+\t{ HNS3_HASH_IPV6_UDP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV6_UDP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV6_UDP, HNS3_RSS_TUPLE_IPV6_UDP_M },\n+\t{ HNS3_HASH_IPV6_SCTP,\n+\t  RTE_ETH_RSS_NONFRAG_IPV6_SCTP, HNS3_RSS_SUPPORT_L3L4,\n+\t  HNS3_RSS_PCTYPE_IPV6_SCTP, HNS3_RSS_TUPLE_IPV6_SCTP_M },\n+};\n+\n static const uint8_t full_mask[VNI_OR_TNI_LEN] = { 0xFF, 0xFF, 0xFF };\n static const uint8_t zero_mask[VNI_OR_TNI_LEN] = { 0x00, 0x00, 0x00 };\n \n@@ -79,7 +198,7 @@ net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len)\n }\n \n /*\n- * This function is used to find rss general action.\n+ * This function is used to parse filter type.\n  * 1. As we know RSS is used to spread packets among several queues, the flow\n  *    API provide the struct rte_flow_action_rss, user could config its field\n  *    sush as: func/level/types/key/queue to control RSS function.\n@@ -87,16 +206,18 @@ net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len)\n  *    implemented by FDIR + RSS in hns3 hardware, user can create one FDIR rule\n  *    which action is RSS queues region.\n  * 3. When action is RSS, we use the following rule to distinguish:\n- *    Case 1: pattern have ETH and action's queue_num > 0, indicate it is queue\n- *            region configuration.\n+ *    Case 1: pattern has ETH and all fields in RSS action except 'queues' are\n+ *            zero or default, indicate it is queue region configuration.\n  *    Case other: an rss general action.\n  */\n-static const struct rte_flow_action *\n-hns3_find_rss_general_action(const struct rte_flow_item pattern[],\n-\t\t\t     const struct rte_flow_action actions[])\n+static void\n+hns3_parse_filter_type(const struct rte_flow_item pattern[],\n+\t\t       const struct rte_flow_action actions[],\n+\t\t       struct hns3_filter_info *filter_info)\n {\n \tconst struct rte_flow_action_rss *rss_act;\n \tconst struct rte_flow_action *act = NULL;\n+\tbool only_has_queues = false;\n \tbool have_eth = false;\n \n \tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n@@ -105,8 +226,10 @@ hns3_find_rss_general_action(const struct rte_flow_item pattern[],\n \t\t\tbreak;\n \t\t}\n \t}\n-\tif (!act)\n-\t\treturn NULL;\n+\tif (act == NULL) {\n+\t\tfilter_info->type = RTE_ETH_FILTER_FDIR;\n+\t\treturn;\n+\t}\n \n \tfor (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {\n \t\tif (pattern->type == RTE_FLOW_ITEM_TYPE_ETH) {\n@@ -116,18 +239,20 @@ hns3_find_rss_general_action(const struct rte_flow_item pattern[],\n \t}\n \n \trss_act = act->conf;\n-\tif (have_eth && rss_act->queue_num) {\n+\tonly_has_queues = (rss_act->queue_num > 0) &&\n+\t\t\t  (rss_act->func == RTE_ETH_HASH_FUNCTION_DEFAULT &&\n+\t\t\t   rss_act->types == 0 && rss_act->key_len == 0);\n+\tif (have_eth && only_has_queues) {\n \t\t/*\n-\t\t * Pattern have ETH and action's queue_num > 0, indicate this is\n-\t\t * queue region configuration.\n-\t\t * Because queue region is implemented by FDIR + RSS in hns3\n-\t\t * hardware, it needs to enter FDIR process, so here return NULL\n-\t\t * to avoid enter RSS process.\n+\t\t * Pattern has ETH and all fields in RSS action except 'queues'\n+\t\t * are zero or default, which indicates this is queue region\n+\t\t * configuration.\n \t\t */\n-\t\treturn NULL;\n+\t\tfilter_info->type = RTE_ETH_FILTER_FDIR;\n+\t\treturn;\n \t}\n \n-\treturn act;\n+\tfilter_info->type = RTE_ETH_FILTER_HASH;\n }\n \n static inline struct hns3_flow_counter *\n@@ -1246,7 +1371,6 @@ hns3_filterlist_flush(struct rte_eth_dev *dev)\n {\n \tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n \tstruct hns3_fdir_rule_ele *fdir_rule_ptr;\n-\tstruct hns3_rss_conf_ele *rss_filter_ptr;\n \tstruct hns3_flow_mem *flow_node;\n \n \tfdir_rule_ptr = TAILQ_FIRST(&hw->flow_fdir_list);\n@@ -1256,13 +1380,6 @@ hns3_filterlist_flush(struct rte_eth_dev *dev)\n \t\tfdir_rule_ptr = TAILQ_FIRST(&hw->flow_fdir_list);\n \t}\n \n-\trss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list);\n-\twhile (rss_filter_ptr) {\n-\t\tTAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries);\n-\t\trte_free(rss_filter_ptr);\n-\t\trss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list);\n-\t}\n-\n \tflow_node = TAILQ_FIRST(&hw->flow_list);\n \twhile (flow_node) {\n \t\tTAILQ_REMOVE(&hw->flow_list, flow_node, entries);\n@@ -1328,196 +1445,422 @@ hns3_action_rss_same(const struct rte_flow_action_rss *comp,\n }\n \n static bool\n-hns3_rss_input_tuple_supported(struct hns3_hw *hw,\n-\t\t\t       const struct rte_flow_action_rss *rss)\n+hns3_valid_ipv6_sctp_rss_types(struct hns3_hw *hw, uint64_t types)\n {\n \t/*\n-\t * For IP packet, it is not supported to use src/dst port fields to RSS\n-\t * hash for the following packet types.\n-\t * - IPV4 FRAG | IPV4 NONFRAG | IPV6 FRAG | IPV6 NONFRAG\n-\t * Besides, for Kunpeng920, the NIC HW is not supported to use src/dst\n-\t * port fields to RSS hash for IPV6 SCTP packet type. However, the\n-\t * Kunpeng930 and future kunpeng series support to use src/dst port\n-\t * fields to RSS hash for IPv6 SCTP packet type.\n+\t * Some hardware don't support to use src/dst port fields to hash\n+\t * for IPV6 SCTP packet type.\n \t */\n-\tif (rss->types & (RTE_ETH_RSS_L4_DST_ONLY | RTE_ETH_RSS_L4_SRC_ONLY) &&\n-\t    (rss->types & RTE_ETH_RSS_IP ||\n-\t    (!hw->rss_info.ipv6_sctp_offload_supported &&\n-\t    rss->types & RTE_ETH_RSS_NONFRAG_IPV6_SCTP)))\n+\tif (types & RTE_ETH_RSS_NONFRAG_IPV6_SCTP &&\n+\t    types & HNS3_RSS_SUPPORT_L4_SRC_DST &&\n+\t    !hw->rss_info.ipv6_sctp_offload_supported)\n \t\treturn false;\n \n \treturn true;\n }\n \n-/*\n- * This function is used to parse rss action validation.\n- */\n static int\n-hns3_parse_rss_filter(struct rte_eth_dev *dev,\n-\t\t      const struct rte_flow_action *actions,\n-\t\t      struct rte_flow_error *error)\n+hns3_flow_parse_hash_func(const struct rte_flow_action_rss *rss_act,\n+\t\t\t  struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t  struct rte_flow_error *error)\n {\n-\tstruct hns3_adapter *hns = dev->data->dev_private;\n-\tstruct hns3_hw *hw = &hns->hw;\n-\tconst struct rte_flow_action_rss *rss;\n-\tconst struct rte_flow_action *act;\n-\tuint32_t act_index = 0;\n-\tuint16_t n;\n+\tif (rss_act->func >= RTE_ETH_HASH_FUNCTION_MAX)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"RSS hash func are not supported\");\n \n-\tNEXT_ITEM_OF_ACTION(act, actions, act_index);\n-\trss = act->conf;\n+\trss_conf->conf.func = rss_act->func;\n+\treturn 0;\n+}\n \n-\tif (rss == NULL) {\n+static int\n+hns3_flow_parse_hash_key(struct hns3_hw *hw,\n+\t\t\t const struct rte_flow_action_rss *rss_act,\n+\t\t\t struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tif (rss_act->key_len != hw->rss_key_size)\n \t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\t  act, \"no valid queues\");\n-\t}\n+\t\t\t\t\t  NULL, \"invalid RSS key length\");\n+\n+\tif (rss_act->key != NULL)\n+\t\tmemcpy(rss_conf->key, rss_act->key, rss_act->key_len);\n+\telse\n+\t\tmemcpy(rss_conf->key, hns3_hash_key,\n+\t\t\tRTE_MIN(sizeof(hns3_hash_key), rss_act->key_len));\n+\t/* Need to record if user sets hash key. */\n+\trss_conf->conf.key = rss_act->key;\n+\trss_conf->conf.key_len = rss_act->key_len;\n \n-\tif (rss->queue_num > HNS3_RSS_QUEUES_BUFFER_NUM)\n+\treturn 0;\n+}\n+\n+static int\n+hns3_flow_parse_queues(struct hns3_hw *hw,\n+\t\t       const struct rte_flow_action_rss *rss_act,\n+\t\t       struct hns3_flow_rss_conf *rss_conf,\n+\t\t       struct rte_flow_error *error)\n+{\n+\tuint16_t i;\n+\n+\tif (rss_act->queue_num > hw->rss_ind_tbl_size)\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,\n-\t\t\t\t\t  \"queue number configured exceeds \"\n-\t\t\t\t\t  \"queue buffer size driver supported\");\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"queue number can not exceed RSS indirection table.\");\n \n-\tfor (n = 0; n < rss->queue_num; n++) {\n-\t\tif (rss->queue[n] < hw->alloc_rss_size)\n-\t\t\tcontinue;\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,\n-\t\t\t\t\t  \"queue id must be less than queue number allocated to a TC\");\n+\tif (rss_act->queue_num > HNS3_RSS_QUEUES_BUFFER_NUM)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"queue number configured exceeds queue buffer size driver supported\");\n+\n+\tfor (i = 0; i < rss_act->queue_num; i++) {\n+\t\tif (rss_act->queue[i] >= hw->alloc_rss_size)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t\tNULL,\n+\t\t\t\t\t\t\"queue id must be less than queue number allocated to a TC\");\n \t}\n \n-\tif (!(rss->types & HNS3_ETH_RSS_SUPPORT) && rss->types)\n+\tmemcpy(rss_conf->queue, rss_act->queue,\n+\t       rss_act->queue_num * sizeof(rss_conf->queue[0]));\n+\trss_conf->conf.queue = rss_conf->queue;\n+\trss_conf->conf.queue_num = rss_act->queue_num;\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_flow_get_hw_pctype(struct hns3_hw *hw,\n+\t\t\tconst struct rte_flow_action_rss *rss_act,\n+\t\t\tconst struct hns3_hash_map_info *map,\n+\t\t\tstruct hns3_flow_rss_conf *rss_conf,\n+\t\t\tstruct rte_flow_error *error)\n+{\n+\tuint64_t l3l4_src_dst, l3l4_refine, left_types;\n+\n+\tif (rss_act->types == 0) {\n+\t\t/* Disable RSS hash of this packet type if types is zero. */\n+\t\trss_conf->hw_pctypes |= map->hw_pctype;\n+\t\treturn 0;\n+\t}\n+\n+\t/*\n+\t * Can not have extra types except rss_pctype and l3l4_type in this map.\n+\t */\n+\tleft_types = ~map->rss_pctype & rss_act->types;\n+\tif (left_types & ~map->l3l4_types)\n \t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\t  act,\n-\t\t\t\t\t  \"Flow types is unsupported by \"\n-\t\t\t\t\t  \"hns3's RSS\");\n-\tif (rss->func >= RTE_ETH_HASH_FUNCTION_MAX)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,\n-\t\t\t\t\t  \"RSS hash func are not supported\");\n-\tif (rss->level)\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,\n+\t\t\t\t\t  \"cannot set extra types.\");\n+\n+\tl3l4_src_dst = left_types;\n+\t/* L3/L4 SRC and DST shouldn't be specified at the same time. */\n+\tl3l4_refine = rte_eth_rss_hf_refine(l3l4_src_dst);\n+\tif (l3l4_refine != l3l4_src_dst)\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,\n-\t\t\t\t\t  \"a nonzero RSS encapsulation level is not supported\");\n-\tif (rss->key_len && rss->key_len != hw->rss_key_size)\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,\n+\t\t\t\t\t  \"cannot specify L3_SRC/DST_ONLY or L4_SRC/DST_ONLY at the same.\");\n+\n+\tif (!hns3_valid_ipv6_sctp_rss_types(hw, rss_act->types))\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,\n-\t\t\t\t\t  \"invalid RSS key length\");\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,\n+\t\t\t\t\t  \"hardware doesn't support to use L4 src/dst to hash for IPV6-SCTP.\");\n \n-\tif (!hns3_rss_input_tuple_supported(hw, rss))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n+\trss_conf->hw_pctypes |= map->hw_pctype;\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_flow_parse_rss_types_by_ptype(struct hns3_hw *hw,\n+\t\t\t\t   const struct rte_flow_action_rss *rss_act,\n+\t\t\t\t   uint64_t pattern_type,\n+\t\t\t\t   struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t\t   struct rte_flow_error *error)\n+{\n+\tconst struct hns3_hash_map_info *map;\n+\tbool matched = false;\n+\tuint16_t i;\n+\tint ret;\n+\n+\tfor (i = 0; i < RTE_DIM(hash_map_table); i++) {\n+\t\tmap = &hash_map_table[i];\n+\t\tif (map->pattern_type != pattern_type) {\n+\t\t\t/*\n+\t\t\t * If the target pattern type is already matched with\n+\t\t\t * the one before this pattern in the hash map table,\n+\t\t\t * no need to continue walk.\n+\t\t\t */\n+\t\t\tif (matched)\n+\t\t\t\tbreak;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tmatched = true;\n+\n+\t\t/*\n+\t\t * If pattern type is matched and the 'types' is zero, all packet flow\n+\t\t * types related to this pattern type disable RSS hash.\n+\t\t * Otherwise, RSS types must match the pattern type and cannot have no\n+\t\t * extra or unsupported types.\n+\t\t */\n+\t\tif (rss_act->types != 0 && !(map->rss_pctype & rss_act->types))\n+\t\t\tcontinue;\n+\n+\t\tret = hns3_flow_get_hw_pctype(hw, rss_act, map, rss_conf, error);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (rss_conf->hw_pctypes != 0)\n+\t\treturn 0;\n+\n+\tif (matched)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\t  &rss->types,\n-\t\t\t\t\t  \"input RSS types are not supported\");\n+\t\t\t\t\t  NULL, \"RSS types are unsupported\");\n \n-\tact_index++;\n+\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t  NULL, \"Pattern specified is unsupported\");\n+}\n \n-\t/* Check if the next not void action is END */\n-\tNEXT_ITEM_OF_ACTION(act, actions, act_index);\n-\tif (act->type != RTE_FLOW_ACTION_TYPE_END)\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t  act, \"Not supported action.\");\n+static uint64_t\n+hns3_flow_get_all_hw_pctypes(uint64_t types)\n+{\n+\tuint64_t hw_pctypes = 0;\n+\tuint16_t i;\n \n-\treturn 0;\n+\tfor (i = 0; i < RTE_DIM(hash_map_table); i++) {\n+\t\tif (types & hash_map_table[i].rss_pctype)\n+\t\t\thw_pctypes |= hash_map_table[i].hw_pctype;\n+\t}\n+\n+\treturn hw_pctypes;\n }\n \n static int\n-hns3_disable_rss(struct hns3_hw *hw)\n+hns3_flow_parse_rss_types(struct hns3_hw *hw,\n+\t\t\t  const struct rte_flow_action_rss *rss_act,\n+\t\t\t  uint64_t pattern_type,\n+\t\t\t  struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t  struct rte_flow_error *error)\n+{\n+\trss_conf->conf.types = rss_act->types;\n+\n+\t/* no pattern specified to set global RSS types. */\n+\tif (pattern_type == 0) {\n+\t\tif (rss_act->types & ~HNS3_ETH_RSS_SUPPORT)\n+\t\t\thns3_warn(hw, \"some types in the requested RSS types (0x%\" PRIx64 \") aren't supported, they are ignored.\",\n+\t\t\t\t  rss_act->types);\n+\t\trss_conf->hw_pctypes =\n+\t\t\t\thns3_flow_get_all_hw_pctypes(rss_act->types);\n+\t\treturn 0;\n+\t}\n+\n+\treturn hns3_flow_parse_rss_types_by_ptype(hw, rss_act, pattern_type,\n+\t\t\t\t\t\t  rss_conf, error);\n+}\n+\n+static int\n+hns3_flow_parse_hash_global_conf(struct rte_eth_dev *dev,\n+\t\t\t\t const struct rte_flow_action_rss *rss_act,\n+\t\t\t\t struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t\t struct rte_flow_error *error)\n {\n+\tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n \tint ret;\n \n-\tret = hns3_set_rss_tuple_by_rss_hf(hw, 0);\n-\tif (ret)\n+\tret = hns3_flow_parse_hash_func(rss_act, rss_conf, error);\n+\tif (ret != 0)\n \t\treturn ret;\n-\thw->rss_info.rss_hf = 0;\n \n-\treturn 0;\n+\tif (rss_act->queue_num > 0) {\n+\t\tret = hns3_flow_parse_queues(hw, rss_act, rss_conf, error);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (rss_act->key_len > 0) {\n+\t\tret = hns3_flow_parse_hash_key(hw, rss_act, rss_conf, error);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn hns3_flow_parse_rss_types(hw, rss_act, rss_conf->pattern_type,\n+\t\t\t\t\t rss_conf, error);\n }\n \n static int\n-hns3_parse_rss_algorithm(struct hns3_hw *hw, struct hns3_flow_rss_conf *rss_conf,\n-\t\t\t uint8_t *hash_algo)\n-{\n-\tconst uint8_t hash_func_map[] = {\n-\t\t[RTE_ETH_HASH_FUNCTION_DEFAULT] = HNS3_RSS_HASH_ALGO_TOEPLITZ,\n-\t\t[RTE_ETH_HASH_FUNCTION_TOEPLITZ] = HNS3_RSS_HASH_ALGO_TOEPLITZ,\n-\t\t[RTE_ETH_HASH_FUNCTION_SIMPLE_XOR] = HNS3_RSS_HASH_ALGO_SIMPLE,\n-\t\t[RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ] = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP,\n-\t};\n-\tuint8_t key[HNS3_RSS_KEY_SIZE_MAX] = {0};\n-\tint ret;\n+hns3_flow_parse_pattern_type(const struct rte_flow_item pattern[],\n+\t\t\t     uint64_t *ptype, struct rte_flow_error *error)\n+{\n+\tenum rte_flow_item_type pre_type = RTE_FLOW_ITEM_TYPE_VOID;\n+\tconst char *message = \"Pattern specified isn't supported\";\n+\tuint64_t item_hdr, pattern_hdrs = 0;\n+\tenum rte_flow_item_type cur_type;\n \n-\tif (rss_conf->conf.func == RTE_ETH_HASH_FUNCTION_DEFAULT) {\n-\t\tret = hns3_rss_get_algo_key(hw, hash_algo, key,\n-\t\t\t\t\t    hw->rss_key_size);\n-\t\tif (ret != 0) {\n-\t\t\thns3_err(hw, \"fail to get current RSS hash algorithm, ret = %d\",\n-\t\t\t\t ret);\n-\t\t\treturn ret;\n+\tfor (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {\n+\t\tif (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\t\tcontinue;\n+\t\tif (pattern->mask || pattern->spec || pattern->last) {\n+\t\t\tmessage = \"Header info shouldn't be specified\";\n+\t\t\tgoto unsup;\n \t\t}\n \n-\t\t/*\n-\t\t * During the phase of reset recovery, the hash algorithm\n-\t\t * obtained from hardware may not be the one used(saved in\n-\t\t * rte_flow_hash_algo) when this rule is delivered.\n-\t\t */\n-\t\tif (__atomic_load_n(&hw->reset.resetting, __ATOMIC_RELAXED) &&\n-\t\t    *hash_algo != rss_conf->hash_algo)\n-\t\t\t*hash_algo = rss_conf->hash_algo;\n+\t\t/* Check the sub-item allowed by the previous item . */\n+\t\tif (pre_type >= RTE_DIM(hash_pattern_next_allow_items) ||\n+\t\t    !(hash_pattern_next_allow_items[pre_type] &\n+\t\t\t\tBIT_ULL(pattern->type)))\n+\t\t\tgoto unsup;\n+\n+\t\tcur_type = pattern->type;\n+\t\t/* Unsupported for current type being greater than array size. */\n+\t\tif (cur_type >= RTE_DIM(hash_pattern_item_header))\n+\t\t\tgoto unsup;\n+\n+\t\t/* The value is zero, which means unsupported current header. */\n+\t\titem_hdr = hash_pattern_item_header[cur_type];\n+\t\tif (item_hdr == 0)\n+\t\t\tgoto unsup;\n+\n+\t\t/* Have duplicate pattern header. */\n+\t\tif (item_hdr & pattern_hdrs)\n+\t\t\tgoto unsup;\n+\t\tpre_type = cur_type;\n+\t\tpattern_hdrs |= item_hdr;\n+\t}\n \n+\tif (pattern_hdrs != 0) {\n+\t\t*ptype = pattern_hdrs;\n \t\treturn 0;\n \t}\n \n-\t*hash_algo = hash_func_map[rss_conf->conf.func];\n+unsup:\n+\treturn rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t  pattern, message);\n+}\n+\n+static int\n+hns3_flow_parse_pattern_act(struct rte_eth_dev *dev,\n+\t\t\t    const struct rte_flow_item pattern[],\n+\t\t\t    const struct rte_flow_action_rss *rss_act,\n+\t\t\t    struct hns3_flow_rss_conf *rss_conf,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint ret;\n+\n+\tret = hns3_flow_parse_hash_func(rss_act, rss_conf, error);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\tif (rss_act->key_len > 0) {\n+\t\tret = hns3_flow_parse_hash_key(hw, rss_act, rss_conf, error);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (rss_act->queue_num > 0) {\n+\t\tret = hns3_flow_parse_queues(hw, rss_act, rss_conf, error);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = hns3_flow_parse_pattern_type(pattern, &rss_conf->pattern_type,\n+\t\t\t\t\t   error);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\tret = hns3_flow_parse_rss_types(hw, rss_act, rss_conf->pattern_type,\n+\t\t\t\t\trss_conf, error);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\tif (rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT ||\n+\t    rss_act->key_len > 0 || rss_act->queue_num > 0)\n+\t\thns3_warn(hw, \"hash func, key and queues are global config, which work for all flow types. \"\n+\t\t\t  \"Recommend: don't set them together with pattern.\");\n \n \treturn 0;\n }\n \n+static bool\n+hns3_rss_action_is_dup(struct hns3_hw *hw,\n+\t\t       const struct hns3_flow_rss_conf *conf)\n+{\n+\tstruct hns3_rss_conf_ele *filter;\n+\n+\tTAILQ_FOREACH(filter, &hw->flow_rss_list, entries) {\n+\t\tif (conf->pattern_type != filter->filter_info.pattern_type)\n+\t\t\tcontinue;\n+\n+\t\tif (hns3_action_rss_same(&filter->filter_info.conf, &conf->conf))\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+/*\n+ * This function is used to parse rss action validation.\n+ */\n static int\n-hns3_hw_rss_hash_set(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf)\n+hns3_parse_rss_filter(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_item pattern[],\n+\t\t      const struct rte_flow_action *actions,\n+\t\t      struct hns3_flow_rss_conf *rss_conf,\n+\t\t      struct rte_flow_error *error)\n {\n-\tstruct rte_flow_action_rss *rss_config = &conf->conf;\n-\tuint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0};\n-\tbool use_default_key = false;\n-\tuint64_t flow_types;\n-\tuint8_t hash_algo;\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tconst struct rte_flow_action_rss *rss_act;\n+\tconst struct rte_flow_action *act;\n+\tconst struct rte_flow_item *pat;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tuint32_t index = 0;\n \tint ret;\n \n-\tif (rss_config->key == NULL || rss_config->key_len != hw->rss_key_size) {\n-\t\thns3_warn(hw, \"Default RSS hash key to be set\");\n-\t\tmemcpy(rss_key, hns3_hash_key,\n-\t\t\tRTE_MIN(sizeof(hns3_hash_key), hw->rss_key_size));\n-\t\tuse_default_key = true;\n+\tNEXT_ITEM_OF_ACTION(act, actions, index);\n+\tif (actions[1].type != RTE_FLOW_ACTION_TYPE_END)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  &actions[1],\n+\t\t\t\t\t  \"Only support one action for RSS.\");\n+\n+\trss_act = (const struct rte_flow_action_rss *)act->conf;\n+\tif (rss_act == NULL) {\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  act, \"lost RSS action configuration\");\n \t}\n \n-\tret = hns3_parse_rss_algorithm(hw, conf, &hash_algo);\n-\tif (ret)\n+\tif (rss_act->level != 0)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  act,\n+\t\t\t\t\t  \"RSS level is not supported\");\n+\n+\tindex = 0;\n+\tNEXT_ITEM_OF_PATTERN(pat, pattern, index);\n+\tif (pat[0].type == RTE_FLOW_ITEM_TYPE_END) {\n+\t\trss_conf->pattern_type = 0;\n+\t\tret = hns3_flow_parse_hash_global_conf(dev, rss_act,\n+\t\t\t\t\t\t       rss_conf, error);\n+\t} else {\n+\t\tret = hns3_flow_parse_pattern_act(dev, pat, rss_act,\n+\t\t\t\t\t\t  rss_conf, error);\n+\t}\n+\tif (ret != 0)\n \t\treturn ret;\n \n-\tret = hns3_rss_set_algo_key(hw, hash_algo,\n-\t\t\t\t    use_default_key ? rss_key : rss_config->key,\n-\t\t\t\t    hw->rss_key_size);\n-\tif (ret)\n-\t\treturn ret;\n-\tconf->hash_algo = hash_algo;\n-\n-\t/* Filter the unsupported flow types */\n-\tflow_types = rss_config->types ?\n-\t\t     rss_config->types & HNS3_ETH_RSS_SUPPORT :\n-\t\t     hw->rss_info.rss_hf;\n-\tif (flow_types != rss_config->types)\n-\t\thns3_warn(hw, \"modified RSS types based on hardware support,\"\n-\t\t\t  \" requested:0x%\" PRIx64 \" configured:0x%\" PRIx64,\n-\t\t\t  rss_config->types, flow_types);\n-\n-\tret = hns3_set_rss_tuple_by_rss_hf(hw, flow_types);\n-\tif (ret)\n-\t\thns3_err(hw, \"Update RSS tuples by rss hf failed %d\", ret);\n+\tif (hns3_rss_action_is_dup(hw, rss_conf))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  act, \"duplicate RSS rule\");\n \n-\treturn ret;\n+\treturn 0;\n }\n \n static int\n@@ -1543,44 +1886,106 @@ hns3_update_indir_table(struct hns3_hw *hw,\n \treturn hns3_set_rss_indir_table(hw, indir_tbl, hw->rss_ind_tbl_size);\n }\n \n+static uint64_t\n+hns3_flow_get_pctype_tuple_mask(uint64_t hw_pctype)\n+{\n+\tuint64_t tuple_mask = 0;\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < RTE_DIM(hash_map_table); i++) {\n+\t\tif (hw_pctype == hash_map_table[i].hw_pctype) {\n+\t\t\ttuple_mask = hash_map_table[i].tuple_mask;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn tuple_mask;\n+}\n+\n static int\n-hns3_reset_rss_filter(struct hns3_hw *hw,\n-\t\t      const struct hns3_flow_rss_conf *conf)\n+hns3_flow_set_rss_ptype_tuple(struct hns3_hw *hw,\n+\t\t\t      struct hns3_flow_rss_conf *rss_conf)\n {\n+\tuint64_t old_tuple_fields, new_tuple_fields;\n+\tuint64_t hw_pctypes, tuples, tuple_mask = 0;\n+\tbool cfg_global_tuple;\n \tint ret;\n \n-\tif (!conf->valid)\n-\t\treturn 0;\n+\tcfg_global_tuple = (rss_conf->pattern_type == 0);\n+\tif (!cfg_global_tuple) {\n+\t\t/*\n+\t\t * To ensure that different packets do not affect each other,\n+\t\t * we have to first read all tuple fields, and then only modify\n+\t\t * the tuples for the specified packet type.\n+\t\t */\n+\t\tret = hns3_get_rss_tuple_field(hw, &old_tuple_fields);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n \n-\tret = hns3_disable_rss(hw);\n-\tif (ret)\n-\t\thns3_err(hw, \"RSS disable failed(%d)\", ret);\n+\t\tnew_tuple_fields = old_tuple_fields;\n+\t\thw_pctypes = rss_conf->hw_pctypes;\n+\t\twhile (hw_pctypes > 0) {\n+\t\t\tuint32_t idx = rte_bsf64(hw_pctypes);\n+\t\t\tuint64_t pctype = BIT_ULL(idx);\n+\n+\t\t\ttuple_mask = hns3_flow_get_pctype_tuple_mask(pctype);\n+\t\t\ttuples = hns3_rss_calc_tuple_filed(hw,\n+\t\t\t\t\t\t\trss_conf->conf.types);\n+\t\t\tnew_tuple_fields &= ~tuple_mask;\n+\t\t\tnew_tuple_fields |= tuples;\n+\t\t\thw_pctypes &= ~pctype;\n+\t\t}\n+\t} else {\n+\t\tnew_tuple_fields =\n+\t\t\thns3_rss_calc_tuple_filed(hw, rss_conf->conf.types);\n+\t}\n \n-\treturn ret;\n+\tret = hns3_set_rss_tuple_field(hw, new_tuple_fields);\n+\tif (ret != 0)\n+\t\treturn ret;\n+\n+\thns3_info(hw, \"RSS tuple fields changed from 0x%\" PRIx64 \" to 0x%\" PRIx64,\n+\t\t  old_tuple_fields, new_tuple_fields);\n+\n+\treturn 0;\n }\n \n static int\n-hns3_config_rss_filter(struct hns3_hw *hw, struct hns3_flow_rss_conf *conf)\n+hns3_config_rss_filter(struct hns3_hw *hw,\n+\t\t       struct hns3_flow_rss_conf *rss_conf)\n {\n \tstruct rte_flow_action_rss *rss_act;\n-\tuint16_t num;\n \tint ret;\n \n-\trss_act = &conf->conf;\n-\t/* Set rx queues to use */\n-\tnum = RTE_MIN(hw->data->nb_rx_queues, rss_act->queue_num);\n-\tif (rss_act->queue_num > num)\n-\t\thns3_warn(hw, \"Config queue numbers %u are beyond the scope of truncated\",\n-\t\t\t  rss_act->queue_num);\n-\thns3_info(hw, \"Max of contiguous %u PF queues are configured\", num);\n-\tif (num) {\n-\t\tret = hns3_update_indir_table(hw, rss_act, num);\n-\t\tif (ret)\n+\trss_act = &rss_conf->conf;\n+\tif (rss_act->queue_num > 0) {\n+\t\tret = hns3_update_indir_table(hw, rss_act, rss_act->queue_num);\n+\t\tif (ret) {\n+\t\t\thns3_err(hw, \"set queues action failed, ret = %d\", ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (rss_act->key_len > 0 ||\n+\t    rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {\n+\t\tret = hns3_update_rss_algo_key(hw, rss_act->func, rss_conf->key,\n+\t\t\t\t\t       rss_act->key_len);\n+\t\tif (ret != 0) {\n+\t\t\thns3_err(hw, \"set func or hash key action failed, ret = %d\",\n+\t\t\t\t ret);\n \t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (rss_conf->hw_pctypes > 0) {\n+\t\tret = hns3_flow_set_rss_ptype_tuple(hw, rss_conf);\n+\t\tif (ret != 0) {\n+\t\t\thns3_err(hw, \"set types action failed, ret = %d\", ret);\n+\t\t\treturn ret;\n+\t\t}\n \t}\n \n-\t/* Set hash algorithm and flow types by the user's config */\n-\treturn hns3_hw_rss_hash_set(hw, conf);\n+\treturn 0;\n }\n \n static int\n@@ -1589,50 +1994,44 @@ hns3_clear_rss_filter(struct rte_eth_dev *dev)\n \tstruct hns3_adapter *hns = dev->data->dev_private;\n \tstruct hns3_rss_conf_ele *rss_filter_ptr;\n \tstruct hns3_hw *hw = &hns->hw;\n-\tint rss_rule_succ_cnt = 0; /* count for success of clearing RSS rules */\n-\tint rss_rule_fail_cnt = 0; /* count for failure of clearing RSS rules */\n-\tint ret = 0;\n \n \trss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list);\n \twhile (rss_filter_ptr) {\n \t\tTAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries);\n-\t\tret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info);\n-\t\tif (ret)\n-\t\t\trss_rule_fail_cnt++;\n-\t\telse\n-\t\t\trss_rule_succ_cnt++;\n \t\trte_free(rss_filter_ptr);\n \t\trss_filter_ptr = TAILQ_FIRST(&hw->flow_rss_list);\n \t}\n \n-\tif (rss_rule_fail_cnt) {\n-\t\thns3_err(hw, \"fail to delete all RSS filters, success num = %d fail num = %d\",\n-\t\t\t rss_rule_succ_cnt, rss_rule_fail_cnt);\n-\t\tret = -EIO;\n-\t}\n-\n-\treturn ret;\n+\treturn hns3_config_rss(hns);\n }\n \n static int\n-hns3_restore_rss_filter(struct hns3_hw *hw)\n+hns3_reconfig_all_rss_filter(struct hns3_hw *hw)\n {\n \tstruct hns3_rss_conf_ele *filter;\n-\tint ret = 0;\n+\tuint32_t rule_no = 0;\n+\tint ret;\n \n-\tpthread_mutex_lock(&hw->flows_lock);\n \tTAILQ_FOREACH(filter, &hw->flow_rss_list, entries) {\n-\t\tif (!filter->filter_info.valid)\n-\t\t\tcontinue;\n-\n \t\tret = hns3_config_rss_filter(hw, &filter->filter_info);\n \t\tif (ret != 0) {\n-\t\t\thns3_err(hw, \"restore RSS filter failed, ret=%d\", ret);\n-\t\t\tgoto out;\n+\t\t\thns3_err(hw, \"config %uth RSS filter failed, ret = %d\",\n+\t\t\t\t rule_no, ret);\n+\t\t\treturn ret;\n \t\t}\n+\t\trule_no++;\n \t}\n \n-out:\n+\treturn 0;\n+}\n+\n+static int\n+hns3_restore_rss_filter(struct hns3_hw *hw)\n+{\n+\tint ret;\n+\n+\tpthread_mutex_lock(&hw->flows_lock);\n+\tret = hns3_reconfig_all_rss_filter(hw);\n \tpthread_mutex_unlock(&hw->flows_lock);\n \n \treturn ret;\n@@ -1651,38 +2050,6 @@ hns3_restore_filter(struct hns3_adapter *hns)\n \treturn hns3_restore_rss_filter(hw);\n }\n \n-static bool\n-hns3_rss_action_is_dup(struct hns3_hw *hw,\n-\t\t       const struct rte_flow_action_rss *act)\n-{\n-\tstruct hns3_rss_conf_ele *filter;\n-\n-\tTAILQ_FOREACH(filter, &hw->flow_rss_list, entries) {\n-\t\tif (!filter->filter_info.valid)\n-\t\t\tcontinue;\n-\n-\t\tif (hns3_action_rss_same(&filter->filter_info.conf, act))\n-\t\t\treturn true;\n-\t}\n-\n-\treturn false;\n-}\n-\n-static int\n-hns3_flow_parse_rss(struct rte_eth_dev *dev,\n-\t\t    struct hns3_flow_rss_conf *conf)\n-{\n-\tstruct hns3_adapter *hns = dev->data->dev_private;\n-\tstruct hns3_hw *hw = &hns->hw;\n-\n-\tif (hns3_rss_action_is_dup(hw, &conf->conf)) {\n-\t\thns3_err(hw, \"duplicate RSS configuration\");\n-\t\treturn -EINVAL;\n-\t}\n-\n-\treturn hns3_config_rss_filter(hw, conf);\n-}\n-\n static int\n hns3_flow_args_check(const struct rte_flow_attr *attr,\n \t\t     const struct rte_flow_item pattern[],\n@@ -1716,32 +2083,55 @@ static int\n hns3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t   const struct rte_flow_item pattern[],\n \t\t   const struct rte_flow_action actions[],\n-\t\t   struct rte_flow_error *error)\n+\t\t   struct rte_flow_error *error,\n+\t\t   struct hns3_filter_info *filter_info)\n {\n-\tstruct hns3_fdir_rule fdir_rule;\n+\tunion hns3_filter_conf *conf;\n \tint ret;\n \n \tret = hns3_flow_args_check(attr, pattern, actions, error);\n \tif (ret)\n \t\treturn ret;\n \n-\tif (hns3_find_rss_general_action(pattern, actions))\n-\t\treturn hns3_parse_rss_filter(dev, actions, error);\n+\thns3_parse_filter_type(pattern, actions, filter_info);\n+\tconf = &filter_info->conf;\n+\tif (filter_info->type == RTE_ETH_FILTER_HASH)\n+\t\treturn hns3_parse_rss_filter(dev, pattern, actions,\n+\t\t\t\t\t     &conf->rss_conf, error);\n \n-\tmemset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule));\n-\treturn hns3_parse_fdir_filter(dev, pattern, actions, &fdir_rule, error);\n+\treturn hns3_parse_fdir_filter(dev, pattern, actions,\n+\t\t\t\t      &conf->fdir_conf, error);\n+}\n+\n+static int\n+hns3_flow_rebuild_all_rss_filter(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tint ret;\n+\n+\tret = hns3_config_rss(hns);\n+\tif (ret != 0) {\n+\t\thns3_err(hw, \"restore original RSS configuration failed, ret = %d.\",\n+\t\t\t ret);\n+\t\treturn ret;\n+\t}\n+\tret = hns3_reconfig_all_rss_filter(hw);\n+\tif (ret != 0)\n+\t\thns3_err(hw, \"rebuild all RSS filter failed, ret = %d.\", ret);\n+\n+\treturn ret;\n }\n \n static int\n hns3_flow_create_rss_rule(struct rte_eth_dev *dev,\n-\t\t\t  const struct rte_flow_action *act,\n+\t\t\t  struct hns3_flow_rss_conf *rss_conf,\n \t\t\t  struct rte_flow *flow)\n {\n \tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tconst struct rte_flow_action_rss *rss_act;\n+\tstruct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);\n \tstruct hns3_rss_conf_ele *rss_filter_ptr;\n \tstruct hns3_flow_rss_conf *new_conf;\n-\tstruct hns3_rss_conf_ele *filter_ptr;\n+\tstruct rte_flow_action_rss *rss_act;\n \tint ret;\n \n \trss_filter_ptr = rte_zmalloc(\"hns3 rss filter\",\n@@ -1751,35 +2141,28 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev,\n \t\treturn -ENOMEM;\n \t}\n \n-\trss_act = (const struct rte_flow_action_rss *)act->conf;\n \tnew_conf = &rss_filter_ptr->filter_info;\n-\tmemcpy(&new_conf->conf, rss_act, sizeof(*rss_act));\n-\tif (rss_act->queue_num > 0) {\n-\t\tmemcpy(new_conf->queue, rss_act->queue,\n-\t\t       rss_act->queue_num * sizeof(new_conf->queue[0]));\n+\tmemcpy(new_conf, rss_conf, sizeof(*new_conf));\n+\trss_act = &new_conf->conf;\n+\tif (rss_act->queue_num > 0)\n \t\tnew_conf->conf.queue = new_conf->queue;\n-\t}\n-\tif (rss_act->key_len > 0) {\n-\t\tif (rss_act->key != NULL) {\n-\t\t\tmemcpy(new_conf->key, rss_act->key,\n-\t\t\t       rss_act->key_len * sizeof(new_conf->key[0]));\n-\t\t\tnew_conf->conf.key = new_conf->key;\n-\t\t}\n-\t}\n+\t/*\n+\t * There are two ways to deliver hash key action:\n+\t * 1> 'key_len' is greater than zero and 'key' isn't NULL.\n+\t * 2> 'key_len' is greater than zero, but 'key' is NULL.\n+\t * For case 2, we need to keep 'key' of the new_conf is NULL so as to\n+\t * inherit the configuration from user in case of failing to verify\n+\t * duplicate rule later.\n+\t */\n+\tif (rss_act->key_len > 0 && rss_act->key != NULL)\n+\t\tnew_conf->conf.key = new_conf->key;\n \n-\tret = hns3_flow_parse_rss(dev, new_conf);\n+\tret = hns3_config_rss_filter(hw, new_conf);\n \tif (ret != 0) {\n \t\trte_free(rss_filter_ptr);\n+\t\t(void)hns3_flow_rebuild_all_rss_filter(hns);\n \t\treturn ret;\n \t}\n-\trss_filter_ptr->filter_info.valid = true;\n-\n-\t/*\n-\t * When create a new RSS rule, the old rule will be overlaid and set\n-\t * invalid.\n-\t */\n-\tTAILQ_FOREACH(filter_ptr, &hw->flow_rss_list, entries)\n-\t\tfilter_ptr->filter_info.valid = false;\n \n \tTAILQ_INSERT_TAIL(&hw->flow_rss_list, rss_filter_ptr, entries);\n \tflow->rule = rss_filter_ptr;\n@@ -1790,31 +2173,24 @@ hns3_flow_create_rss_rule(struct rte_eth_dev *dev,\n \n static int\n hns3_flow_create_fdir_rule(struct rte_eth_dev *dev,\n-\t\t\t   const struct rte_flow_item pattern[],\n-\t\t\t   const struct rte_flow_action actions[],\n+\t\t\t   struct hns3_fdir_rule *fdir_rule,\n \t\t\t   struct rte_flow_error *error,\n \t\t\t   struct rte_flow *flow)\n {\n \tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n \tstruct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);\n \tstruct hns3_fdir_rule_ele *fdir_rule_ptr;\n-\tstruct hns3_fdir_rule fdir_rule;\n \tbool indir;\n \tint ret;\n \n-\tmemset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule));\n-\tret = hns3_parse_fdir_filter(dev, pattern, actions, &fdir_rule, error);\n-\tif (ret != 0)\n-\t\treturn ret;\n-\n-\tindir = !!(fdir_rule.flags & HNS3_RULE_FLAG_COUNTER_INDIR);\n-\tif (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER) {\n-\t\tret = hns3_counter_new(dev, indir, fdir_rule.act_cnt.id,\n+\tindir = !!(fdir_rule->flags & HNS3_RULE_FLAG_COUNTER_INDIR);\n+\tif (fdir_rule->flags & HNS3_RULE_FLAG_COUNTER) {\n+\t\tret = hns3_counter_new(dev, indir, fdir_rule->act_cnt.id,\n \t\t\t\t       error);\n \t\tif (ret != 0)\n \t\t\treturn ret;\n \n-\t\tflow->counter_id = fdir_rule.act_cnt.id;\n+\t\tflow->counter_id = fdir_rule->act_cnt.id;\n \t}\n \n \tfdir_rule_ptr = rte_zmalloc(\"hns3 fdir rule\",\n@@ -1830,11 +2206,11 @@ hns3_flow_create_fdir_rule(struct rte_eth_dev *dev,\n \t * rules to the hardware to simplify the rollback of rules in the\n \t * hardware.\n \t */\n-\tret = hns3_fdir_filter_program(hns, &fdir_rule, false);\n+\tret = hns3_fdir_filter_program(hns, fdir_rule, false);\n \tif (ret != 0)\n \t\tgoto err_fdir_filter;\n \n-\tmemcpy(&fdir_rule_ptr->fdir_conf, &fdir_rule,\n+\tmemcpy(&fdir_rule_ptr->fdir_conf, fdir_rule,\n \t\tsizeof(struct hns3_fdir_rule));\n \tTAILQ_INSERT_TAIL(&hw->flow_fdir_list, fdir_rule_ptr, entries);\n \tflow->rule = fdir_rule_ptr;\n@@ -1845,8 +2221,8 @@ hns3_flow_create_fdir_rule(struct rte_eth_dev *dev,\n err_fdir_filter:\n \trte_free(fdir_rule_ptr);\n err_malloc:\n-\tif (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER)\n-\t\thns3_counter_release(dev, fdir_rule.act_cnt.id);\n+\tif (fdir_rule->flags & HNS3_RULE_FLAG_COUNTER)\n+\t\thns3_counter_release(dev, fdir_rule->act_cnt.id);\n \n \treturn ret;\n }\n@@ -1864,13 +2240,15 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t\t struct rte_flow_error *error)\n {\n \tstruct hns3_adapter *hns = dev->data->dev_private;\n-\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_filter_info filter_info = {0};\n \tstruct hns3_flow_mem *flow_node;\n-\tconst struct rte_flow_action *act;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tunion hns3_filter_conf *conf;\n \tstruct rte_flow *flow;\n \tint ret;\n \n-\tret = hns3_flow_validate(dev, attr, pattern, actions, error);\n+\tret = hns3_flow_validate(dev, attr, pattern, actions, error,\n+\t\t\t\t &filter_info);\n \tif (ret)\n \t\treturn NULL;\n \n@@ -1890,13 +2268,12 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,\n \t}\n \n \tflow_node->flow = flow;\n+\tconf = &filter_info.conf;\n \tTAILQ_INSERT_TAIL(&hw->flow_list, flow_node, entries);\n-\n-\tact = hns3_find_rss_general_action(pattern, actions);\n-\tif (act)\n-\t\tret = hns3_flow_create_rss_rule(dev, act, flow);\n+\tif (filter_info.type == RTE_ETH_FILTER_HASH)\n+\t\tret = hns3_flow_create_rss_rule(dev, &conf->rss_conf, flow);\n \telse\n-\t\tret = hns3_flow_create_fdir_rule(dev, pattern, actions,\n+\t\tret = hns3_flow_create_fdir_rule(dev, &conf->fdir_conf,\n \t\t\t\t\t\t error, flow);\n \tif (ret == 0)\n \t\treturn flow;\n@@ -1950,15 +2327,10 @@ hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,\n \t\tbreak;\n \tcase RTE_ETH_FILTER_HASH:\n \t\trss_filter_ptr = (struct hns3_rss_conf_ele *)flow->rule;\n-\t\tret = hns3_reset_rss_filter(hw, &rss_filter_ptr->filter_info);\n-\t\tif (ret)\n-\t\t\treturn rte_flow_error_set(error, EIO,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\t\t\t\t  flow,\n-\t\t\t\t\t\t  \"Destroy RSS fail.Try again\");\n \t\tTAILQ_REMOVE(&hw->flow_rss_list, rss_filter_ptr, entries);\n \t\trte_free(rss_filter_ptr);\n \t\trss_filter_ptr = NULL;\n+\t\t(void)hns3_flow_rebuild_all_rss_filter(hns);\n \t\tbreak;\n \tdefault:\n \t\treturn rte_flow_error_set(error, EINVAL,\n@@ -2064,10 +2436,12 @@ hns3_flow_validate_wrap(struct rte_eth_dev *dev,\n \t\t\tstruct rte_flow_error *error)\n {\n \tstruct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct hns3_filter_info filter_info = {0};\n \tint ret;\n \n \tpthread_mutex_lock(&hw->flows_lock);\n-\tret = hns3_flow_validate(dev, attr, pattern, actions, error);\n+\tret = hns3_flow_validate(dev, attr, pattern, actions, error,\n+\t\t\t\t &filter_info);\n \tpthread_mutex_unlock(&hw->flows_lock);\n \n \treturn ret;\ndiff --git a/drivers/net/hns3/hns3_flow.h b/drivers/net/hns3/hns3_flow.h\nindex 90126f2b6e..1b49673f11 100644\n--- a/drivers/net/hns3/hns3_flow.h\n+++ b/drivers/net/hns3/hns3_flow.h\n@@ -9,6 +9,7 @@\n #include <ethdev_driver.h>\n \n #include \"hns3_rss.h\"\n+#include \"hns3_fdir.h\"\n \n struct hns3_flow_counter {\n \tLIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */\n@@ -26,10 +27,10 @@ struct rte_flow {\n \n struct hns3_flow_rss_conf {\n \tstruct rte_flow_action_rss conf;\n-\tuint8_t hash_algo;\n \tuint8_t key[HNS3_RSS_KEY_SIZE_MAX];  /* Hash key */\n \tuint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */\n-\tbool valid; /* check if RSS rule is valid */\n+\tuint64_t pattern_type;\n+\tuint64_t hw_pctypes; /* packet types in driver */\n };\n \n /* rss filter list structure */\n@@ -53,6 +54,16 @@ struct rte_flow_action_handle {\n \tuint32_t counter_id;\n };\n \n+union hns3_filter_conf {\n+\tstruct hns3_fdir_rule fdir_conf;\n+\tstruct hns3_flow_rss_conf rss_conf;\n+};\n+\n+struct hns3_filter_info {\n+\tenum rte_filter_type type;\n+\tunion hns3_filter_conf conf;\n+};\n+\n TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);\n TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);\n \ndiff --git a/drivers/net/hns3/hns3_rss.c b/drivers/net/hns3/hns3_rss.c\nindex 2ef267aac6..370565a841 100644\n--- a/drivers/net/hns3/hns3_rss.c\n+++ b/drivers/net/hns3/hns3_rss.c\n@@ -18,69 +18,13 @@ const uint8_t hns3_hash_key[HNS3_RSS_KEY_SIZE] = {\n \t0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA\n };\n \n-enum hns3_tuple_field {\n-\t/* IPV4_TCP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D = 0,\n-\tHNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S,\n-\tHNS3_RSS_FIELD_IPV4_TCP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV4_TCP_EN_IP_S,\n-\n-\t/* IPV4_UDP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D = 8,\n-\tHNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S,\n-\tHNS3_RSS_FIELD_IPV4_UDP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV4_UDP_EN_IP_S,\n-\n-\t/* IPV4_SCTP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D = 16,\n-\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S,\n-\tHNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S,\n-\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER,\n-\n-\t/* IPV4 ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D = 24,\n-\tHNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S,\n-\tHNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D,\n-\tHNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S,\n-\n-\t/* IPV6_TCP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D = 32,\n-\tHNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S,\n-\tHNS3_RSS_FIELD_IPV6_TCP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV6_TCP_EN_IP_S,\n-\n-\t/* IPV6_UDP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D = 40,\n-\tHNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S,\n-\tHNS3_RSS_FIELD_IPV6_UDP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV6_UDP_EN_IP_S,\n-\n-\t/* IPV6_SCTP ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D = 48,\n-\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S,\n-\tHNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D,\n-\tHNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S,\n-\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER,\n-\n-\t/* IPV6 ENABLE FIELD */\n-\tHNS3_RSS_FIELD_IPV6_NONFRAG_IP_D = 56,\n-\tHNS3_RSS_FIELD_IPV6_NONFRAG_IP_S,\n-\tHNS3_RSS_FIELD_IPV6_FRAG_IP_D,\n-\tHNS3_RSS_FIELD_IPV6_FRAG_IP_S\n+const uint8_t hns3_hash_func_map[] = {\n+\t[RTE_ETH_HASH_FUNCTION_DEFAULT] = HNS3_RSS_HASH_ALGO_TOEPLITZ,\n+\t[RTE_ETH_HASH_FUNCTION_TOEPLITZ] = HNS3_RSS_HASH_ALGO_TOEPLITZ,\n+\t[RTE_ETH_HASH_FUNCTION_SIMPLE_XOR] = HNS3_RSS_HASH_ALGO_SIMPLE,\n+\t[RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ] = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP,\n };\n \n-#define HNS3_RSS_TUPLE_IPV4_TCP_M\tGENMASK(3, 0)\n-#define HNS3_RSS_TUPLE_IPV4_UDP_M\tGENMASK(11, 8)\n-#define HNS3_RSS_TUPLE_IPV4_SCTP_M\tGENMASK(20, 16)\n-#define HNS3_RSS_TUPLE_IPV4_NONF_M\tGENMASK(25, 24)\n-#define HNS3_RSS_TUPLE_IPV4_FLAG_M\tGENMASK(27, 26)\n-#define HNS3_RSS_TUPLE_IPV6_TCP_M\tGENMASK(35, 32)\n-#define HNS3_RSS_TUPLE_IPV6_UDP_M\tGENMASK(43, 40)\n-#define HNS3_RSS_TUPLE_IPV6_SCTP_M\tGENMASK(52, 48)\n-#define HNS3_RSS_TUPLE_IPV6_NONF_M\tGENMASK(57, 56)\n-#define HNS3_RSS_TUPLE_IPV6_FLAG_M\tGENMASK(59, 58)\n-\n enum hns3_rss_tuple_type {\n \tHNS3_RSS_IP_TUPLE,\n \tHNS3_RSS_IP_L4_TUPLE,\n@@ -573,7 +517,7 @@ hns3_rss_check_l3l4_types(struct hns3_hw *hw, uint64_t rss_hf)\n \t\thns3_warn(hw, \"packet type isn't specified, L4_SRC/DST_ONLY is ignored.\");\n }\n \n-static uint64_t\n+uint64_t\n hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf)\n {\n \tuint64_t l3_only_mask = RTE_ETH_RSS_L3_SRC_ONLY |\n@@ -609,25 +553,35 @@ hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf)\n }\n \n int\n-hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf)\n+hns3_set_rss_tuple_field(struct hns3_hw *hw, uint64_t tuple_fields)\n {\n \tstruct hns3_rss_input_tuple_cmd *req;\n \tstruct hns3_cmd_desc desc;\n-\tuint64_t tuple_field;\n \tint ret;\n \n \thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false);\n \treq = (struct hns3_rss_input_tuple_cmd *)desc.data;\n-\n-\ttuple_field = hns3_rss_calc_tuple_filed(hw, rss_hf);\n-\treq->tuple_field = rte_cpu_to_le_64(tuple_field);\n+\treq->tuple_field = rte_cpu_to_le_64(tuple_fields);\n \tret = hns3_cmd_send(hw, &desc, 1);\n-\tif (ret) {\n-\t\thns3_err(hw, \"Update RSS flow types tuples failed %d\", ret);\n-\t\treturn ret;\n-\t}\n+\tif (ret != 0)\n+\t\thns3_err(hw, \"set RSS hash tuple fields failed ret = %d\", ret);\n \n-\treturn 0;\n+\treturn ret;\n+}\n+\n+int\n+hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf)\n+{\n+\tuint64_t tuple_fields;\n+\tint ret;\n+\n+\ttuple_fields = hns3_rss_calc_tuple_filed(hw, rss_hf);\n+\tret = hns3_set_rss_tuple_field(hw, tuple_fields);\n+\tif (ret != 0)\n+\t\thns3_err(hw, \"Update RSS flow types tuples failed, ret = %d\",\n+\t\t\t ret);\n+\n+\treturn ret;\n }\n \n /*\n@@ -999,6 +953,52 @@ hns3_set_rss_tc_mode(struct hns3_hw *hw)\n \treturn ret;\n }\n \n+/*\n+ * Note: the 'hash_algo' is defined by enum rte_eth_hash_function.\n+ */\n+int\n+hns3_update_rss_algo_key(struct hns3_hw *hw, uint8_t hash_func,\n+\t\t\t uint8_t *key, uint8_t key_len)\n+{\n+\tuint8_t rss_key[HNS3_RSS_KEY_SIZE_MAX] = {0};\n+\tbool modify_key, modify_algo;\n+\tuint8_t hash_algo;\n+\tint ret;\n+\n+\tmodify_key = (key != NULL && key_len > 0);\n+\tmodify_algo = hash_func != RTE_ETH_HASH_FUNCTION_DEFAULT;\n+\tif (!modify_key && !modify_algo)\n+\t\treturn 0;\n+\n+\tif (modify_algo && hash_func >= RTE_DIM(hns3_hash_func_map)) {\n+\t\thns3_err(hw, \"hash func (%u) is unsupported.\", hash_func);\n+\t\treturn -ENOTSUP;\n+\t}\n+\tif (modify_key && key_len != hw->rss_key_size) {\n+\t\thns3_err(hw, \"hash key length (%u) is invalid.\", key_len);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = hns3_rss_get_algo_key(hw, &hash_algo, rss_key, hw->rss_key_size);\n+\tif (ret != 0) {\n+\t\thns3_err(hw, \"fail to get RSS hash algorithm and key, ret = %d\",\n+\t\t\t ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (modify_algo)\n+\t\thash_algo = hns3_hash_func_map[hash_func];\n+\tif (modify_key)\n+\t\tmemcpy(rss_key, key, key_len);\n+\n+\tret = hns3_rss_set_algo_key(hw, hash_algo, rss_key, hw->rss_key_size);\n+\tif (ret != 0)\n+\t\thns3_err(hw, \"fail to set RSS hash algorithm and key, ret = %d\",\n+\t\t\t ret);\n+\n+\treturn ret;\n+}\n+\n static void\n hns3_rss_tuple_uninit(struct hns3_hw *hw)\n {\ndiff --git a/drivers/net/hns3/hns3_rss.h b/drivers/net/hns3/hns3_rss.h\nindex d19730c69c..d672481a14 100644\n--- a/drivers/net/hns3/hns3_rss.h\n+++ b/drivers/net/hns3/hns3_rss.h\n@@ -8,23 +8,102 @@\n #include <rte_ethdev.h>\n #include <rte_flow.h>\n \n-#define HNS3_ETH_RSS_SUPPORT ( \\\n-\tRTE_ETH_RSS_IPV4 | \\\n-\tRTE_ETH_RSS_FRAG_IPV4 | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV4_TCP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV4_UDP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV4_SCTP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV4_OTHER | \\\n-\tRTE_ETH_RSS_IPV6 | \\\n-\tRTE_ETH_RSS_FRAG_IPV6 | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV6_TCP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV6_UDP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV6_SCTP | \\\n-\tRTE_ETH_RSS_NONFRAG_IPV6_OTHER | \\\n-\tRTE_ETH_RSS_L3_SRC_ONLY | \\\n-\tRTE_ETH_RSS_L3_DST_ONLY | \\\n-\tRTE_ETH_RSS_L4_SRC_ONLY | \\\n-\tRTE_ETH_RSS_L4_DST_ONLY)\n+#define HNS3_RSS_SUPPORT_L3_SRC_DST\t(RTE_ETH_RSS_L3_SRC_ONLY | \\\n+\t\t\t\t\t RTE_ETH_RSS_L3_DST_ONLY)\n+#define HNS3_RSS_SUPPORT_L4_SRC_DST\t(RTE_ETH_RSS_L4_SRC_ONLY | \\\n+\t\t\t\t\t RTE_ETH_RSS_L4_DST_ONLY)\n+#define HNS3_RSS_SUPPORT_L3L4\t\t(HNS3_RSS_SUPPORT_L3_SRC_DST | \\\n+\t\t\t\t\t HNS3_RSS_SUPPORT_L4_SRC_DST)\n+\n+#define HNS3_RSS_SUPPORT_FLOW_TYPE\t(RTE_ETH_RSS_IPV4 | \\\n+\t\t\t\t\t RTE_ETH_RSS_FRAG_IPV4 | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV4_TCP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV4_UDP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV4_SCTP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV4_OTHER | \\\n+\t\t\t\t\t RTE_ETH_RSS_IPV6 | \\\n+\t\t\t\t\t RTE_ETH_RSS_FRAG_IPV6 | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV6_TCP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV6_UDP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV6_SCTP | \\\n+\t\t\t\t\t RTE_ETH_RSS_NONFRAG_IPV6_OTHER)\n+\n+#define HNS3_ETH_RSS_SUPPORT\t\t(HNS3_RSS_SUPPORT_FLOW_TYPE | \\\n+\t\t\t\t\t HNS3_RSS_SUPPORT_L3L4)\n+\n+enum hns3_tuple_field {\n+\t/* IPV4_TCP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D = 0,\n+\tHNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S,\n+\tHNS3_RSS_FIELD_IPV4_TCP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV4_TCP_EN_IP_S,\n+\n+\t/* IPV4_UDP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D = 8,\n+\tHNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S,\n+\tHNS3_RSS_FIELD_IPV4_UDP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV4_UDP_EN_IP_S,\n+\n+\t/* IPV4_SCTP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D = 16,\n+\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S,\n+\tHNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S,\n+\tHNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER,\n+\n+\t/* IPV4 ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D = 24,\n+\tHNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S,\n+\tHNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D,\n+\tHNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S,\n+\n+\t/* IPV6_TCP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D = 32,\n+\tHNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S,\n+\tHNS3_RSS_FIELD_IPV6_TCP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV6_TCP_EN_IP_S,\n+\n+\t/* IPV6_UDP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D = 40,\n+\tHNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S,\n+\tHNS3_RSS_FIELD_IPV6_UDP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV6_UDP_EN_IP_S,\n+\n+\t/* IPV6_SCTP ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_D = 48,\n+\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_S,\n+\tHNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D,\n+\tHNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S,\n+\tHNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER,\n+\n+\t/* IPV6 ENABLE FIELD */\n+\tHNS3_RSS_FIELD_IPV6_NONFRAG_IP_D = 56,\n+\tHNS3_RSS_FIELD_IPV6_NONFRAG_IP_S,\n+\tHNS3_RSS_FIELD_IPV6_FRAG_IP_D,\n+\tHNS3_RSS_FIELD_IPV6_FRAG_IP_S\n+};\n+\n+#define HNS3_RSS_PCTYPE_IPV4_TCP\tBIT_ULL(0)\n+#define HNS3_RSS_PCTYPE_IPV4_UDP\tBIT_ULL(8)\n+#define HNS3_RSS_PCTYPE_IPV4_SCTP\tBIT_ULL(16)\n+#define HNS3_RSS_PCTYPE_IPV4_NONF\tBIT_ULL(24)\n+#define HNS3_RSS_PCTYPE_IPV4_FLAG\tBIT_ULL(26)\n+#define HNS3_RSS_PCTYPE_IPV6_TCP\tBIT_ULL(32)\n+#define HNS3_RSS_PCTYPE_IPV6_UDP\tBIT_ULL(40)\n+#define HNS3_RSS_PCTYPE_IPV6_SCTP\tBIT_ULL(48)\n+#define HNS3_RSS_PCTYPE_IPV6_NONF\tBIT_ULL(56)\n+#define HNS3_RSS_PCTYPE_IPV6_FLAG\tBIT_ULL(58)\n+\n+#define HNS3_RSS_TUPLE_IPV4_TCP_M\tGENMASK(3, 0)\n+#define HNS3_RSS_TUPLE_IPV4_UDP_M\tGENMASK(11, 8)\n+#define HNS3_RSS_TUPLE_IPV4_SCTP_M\tGENMASK(20, 16)\n+#define HNS3_RSS_TUPLE_IPV4_NONF_M\tGENMASK(25, 24)\n+#define HNS3_RSS_TUPLE_IPV4_FLAG_M\tGENMASK(27, 26)\n+#define HNS3_RSS_TUPLE_IPV6_TCP_M\tGENMASK(35, 32)\n+#define HNS3_RSS_TUPLE_IPV6_UDP_M\tGENMASK(43, 40)\n+#define HNS3_RSS_TUPLE_IPV6_SCTP_M\tGENMASK(52, 48)\n+#define HNS3_RSS_TUPLE_IPV6_NONF_M\tGENMASK(57, 56)\n+#define HNS3_RSS_TUPLE_IPV6_FLAG_M\tGENMASK(59, 58)\n \n #define HNS3_RSS_IND_TBL_SIZE\t512 /* The size of hash lookup table */\n #define HNS3_RSS_IND_TBL_SIZE_MAX 2048\n@@ -108,10 +187,14 @@ int hns3_rss_reset_indir_table(struct hns3_hw *hw);\n int hns3_config_rss(struct hns3_adapter *hns);\n void hns3_rss_uninit(struct hns3_adapter *hns);\n int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf);\n+int hns3_set_rss_tuple_field(struct hns3_hw *hw, uint64_t tuple_fields);\n int hns3_get_rss_tuple_field(struct hns3_hw *hw, uint64_t *tuple_fields);\n int hns3_rss_set_algo_key(struct hns3_hw *hw, uint8_t hash_algo,\n \t\t\t  const uint8_t *key, uint8_t key_len);\n int hns3_rss_get_algo_key(struct hns3_hw *hw,  uint8_t *hash_algo,\n \t\t\t  uint8_t *key, uint8_t key_len);\n+uint64_t hns3_rss_calc_tuple_filed(struct hns3_hw *hw, uint64_t rss_hf);\n+int hns3_update_rss_algo_key(struct hns3_hw *hw, uint8_t hash_algo,\n+\t\t\t     uint8_t *key, uint8_t key_len);\n \n #endif /* HNS3_RSS_H */\n",
    "prefixes": [
        "15/16"
    ]
}