get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 57861,
    "url": "http://patches.dpdk.org/api/patches/57861/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1566568031-45991-10-git-send-email-xavier.huwei@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": "<1566568031-45991-10-git-send-email-xavier.huwei@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1566568031-45991-10-git-send-email-xavier.huwei@huawei.com",
    "date": "2019-08-23T13:46:58",
    "name": "[09/22] net/hns3: add support for flow directory of hns3 PMD driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "b4aef3fa49062093ba805128770e129d4f828534",
    "submitter": {
        "id": 1405,
        "url": "http://patches.dpdk.org/api/people/1405/?format=api",
        "name": "Wei Hu (Xavier)",
        "email": "xavier.huwei@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/1566568031-45991-10-git-send-email-xavier.huwei@huawei.com/mbox/",
    "series": [
        {
            "id": 6114,
            "url": "http://patches.dpdk.org/api/series/6114/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=6114",
            "date": "2019-08-23T13:46:49",
            "name": "add hns3 ethernet PMD driver",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/6114/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/57861/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/57861/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 0E5421C0D1;\n\tFri, 23 Aug 2019 15:50:22 +0200 (CEST)",
            "from huawei.com (szxga07-in.huawei.com [45.249.212.35])\n\tby dpdk.org (Postfix) with ESMTP id 1C5501BFB9\n\tfor <dev@dpdk.org>; Fri, 23 Aug 2019 15:49:41 +0200 (CEST)",
            "from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.59])\n\tby Forcepoint Email with ESMTP id 0DF82DE21A5F41094438;\n\tFri, 23 Aug 2019 21:49:37 +0800 (CST)",
            "from localhost.localdomain (10.67.212.132) by\n\tDGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP\n\tServer id 14.3.439.0; Fri, 23 Aug 2019 21:49:27 +0800"
        ],
        "From": "\"Wei Hu (Xavier)\" <xavier.huwei@huawei.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<linuxarm@huawei.com>, <xavier_huwei@163.com>, <liudongdong3@huawei.com>,\n\t<forest.zhouchang@huawei.com>",
        "Date": "Fri, 23 Aug 2019 21:46:58 +0800",
        "Message-ID": "<1566568031-45991-10-git-send-email-xavier.huwei@huawei.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1566568031-45991-1-git-send-email-xavier.huwei@huawei.com>",
        "References": "<1566568031-45991-1-git-send-email-xavier.huwei@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.67.212.132]",
        "X-CFilter-Loop": "Reflected",
        "Subject": "[dpdk-dev] [PATCH 09/22] net/hns3: add support for flow directory\n\tof hns3 PMD driver",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch adds support for flow directory of hns3 PMD driver.\nFlow directory feature is only supported in hns3 PF driver.\nIt supports the network L2\\L3\\L4 and tunnel packet creation,\ndeletion, flushing, and querying hit statistics.\n\nSigned-off-by: Chunsong Feng <fengchunsong@huawei.com>\nSigned-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>\nSigned-off-by: Hao Chen <chenhao164@huawei.com>\nSigned-off-by: Min Hu (Connor) <humin29@huawei.com>\nSigned-off-by: Huisong Li <lihuisong@huawei.com>\n---\n drivers/net/hns3/hns3_cmd.c    |    1 +\n drivers/net/hns3/hns3_ethdev.c |   33 +\n drivers/net/hns3/hns3_ethdev.h |    3 +\n drivers/net/hns3/hns3_fdir.c   | 1062 +++++++++++++++++++++++++++++\n drivers/net/hns3/hns3_fdir.h   |  203 ++++++\n drivers/net/hns3/hns3_flow.c   | 1450 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 2752 insertions(+)\n create mode 100644 drivers/net/hns3/hns3_fdir.c\n create mode 100644 drivers/net/hns3/hns3_fdir.h\n create mode 100644 drivers/net/hns3/hns3_flow.c",
    "diff": "diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c\nindex f272374..4fc282c 100644\n--- a/drivers/net/hns3/hns3_cmd.c\n+++ b/drivers/net/hns3/hns3_cmd.c\n@@ -27,6 +27,7 @@\n #include <rte_io.h>\n \n #include \"hns3_cmd.h\"\n+#include \"hns3_fdir.h\"\n #include \"hns3_ethdev.h\"\n #include \"hns3_regs.h\"\n #include \"hns3_logs.h\"\ndiff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c\nindex a162d7f..c1f9bcb 100644\n--- a/drivers/net/hns3/hns3_ethdev.c\n+++ b/drivers/net/hns3/hns3_ethdev.c\n@@ -30,6 +30,7 @@\n #include <rte_pci.h>\n \n #include \"hns3_cmd.h\"\n+#include \"hns3_fdir.h\"\n #include \"hns3_ethdev.h\"\n #include \"hns3_logs.h\"\n #include \"hns3_regs.h\"\n@@ -2614,6 +2615,12 @@ hns3_init_hardware(struct hns3_adapter *hns)\n \t\tgoto err_mac_init;\n \t}\n \n+\tret = hns3_init_fd_config(hns);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to init flow director: %d\", ret);\n+\t\tgoto err_mac_init;\n+\t}\n+\n \tret = hns3_config_tso(hw, HNS3_TSO_MSS_MIN, HNS3_TSO_MSS_MAX);\n \tif (ret) {\n \t\tPMD_INIT_LOG(ERR, \"Failed to config tso: %d\", ret);\n@@ -2675,8 +2682,18 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)\n \t\tgoto err_get_config;\n \t}\n \n+\t/* Initialize flow director filter list & hash */\n+\tret = hns3_fdir_filter_init(hns);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to alloc hashmap for fdir: %d\", ret);\n+\t\tgoto err_hw_init;\n+\t}\n+\n \treturn 0;\n \n+err_hw_init:\n+\thns3_uninit_umv_space(hw);\n+\n err_get_config:\n \thns3_cmd_uninit(hw);\n \n@@ -2699,6 +2716,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev)\n \n \tPMD_INIT_FUNC_TRACE();\n \n+\thns3_fdir_filter_uninit(hns);\n \thns3_uninit_umv_space(hw);\n \thns3_cmd_uninit(hw);\n \thns3_cmd_destroy_queue(hw);\n@@ -2726,6 +2744,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {\n \t.mac_addr_set           = hns3_set_default_mac_addr,\n \t.set_mc_addr_list       = hns3_set_mc_mac_addr_list,\n \t.link_update            = hns3_dev_link_update,\n+\t.filter_ctrl            = hns3_dev_filter_ctrl,\n };\n \n static int\n@@ -2739,6 +2758,16 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)\n \tint ret;\n \n \tPMD_INIT_FUNC_TRACE();\n+\teth_dev->process_private = (struct hns3_process_private *)\n+\t    rte_zmalloc_socket(\"hns3_filter_list\",\n+\t\t\t       sizeof(struct hns3_process_private),\n+\t\t\t       RTE_CACHE_LINE_SIZE, eth_dev->device->numa_node);\n+\tif (eth_dev->process_private == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to alloc memory for process private\");\n+\t\treturn -ENOMEM;\n+\t}\n+\t/* initialize flow filter lists */\n+\thns3_filterlist_init(eth_dev);\n \n \tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n \t\treturn 0;\n@@ -2788,6 +2817,8 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)\n \n err_init_pf:\n \teth_dev->dev_ops = NULL;\n+\trte_free(eth_dev->process_private);\n+\teth_dev->process_private = NULL;\n \treturn ret;\n }\n \n@@ -2808,6 +2839,8 @@ hns3_dev_uninit(struct rte_eth_dev *eth_dev)\n \tif (hw->adapter_state < HNS3_NIC_CLOSING)\n \t\thns3_dev_close(eth_dev);\n \n+\trte_free(eth_dev->process_private);\n+\teth_dev->process_private = NULL;\n \thw->adapter_state = HNS3_NIC_REMOVED;\n \treturn 0;\n }\ndiff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h\nindex d5f62fe..c46211a 100644\n--- a/drivers/net/hns3/hns3_ethdev.h\n+++ b/drivers/net/hns3/hns3_ethdev.h\n@@ -463,6 +463,9 @@ struct hns3_pf {\n \tstruct hns3_vtag_cfg vtag_config;\n \tstruct hns3_port_base_vlan_config port_base_vlan_cfg;\n \tLIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;\n+\n+\tstruct hns3_fdir_info fdir; /* flow director info */\n+\tLIST_HEAD(counters, hns3_flow_counter) flow_counters;\n };\n \n struct hns3_vf {\ndiff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c\nnew file mode 100644\nindex 0000000..aa7d968\n--- /dev/null\n+++ b/drivers/net/hns3/hns3_fdir.c\n@@ -0,0 +1,1062 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2019 Hisilicon Limited.\n+ */\n+\n+#include <stdbool.h>\n+#include <sys/queue.h>\n+#include <rte_ethdev_driver.h>\n+#include <rte_hash.h>\n+#include <rte_hash_crc.h>\n+#include <rte_io.h>\n+#include <rte_malloc.h>\n+\n+#include \"hns3_cmd.h\"\n+#include \"hns3_fdir.h\"\n+#include \"hns3_ethdev.h\"\n+#include \"hns3_logs.h\"\n+\n+#define HNS3_VLAN_TAG_TYPE_NONE\t\t0\n+#define HNS3_VLAN_TAG_TYPE_TAG2\t\t1\n+#define HNS3_VLAN_TAG_TYPE_TAG1\t\t2\n+#define HNS3_VLAN_TAG_TYPE_TAG1_2\t3\n+\n+#define HNS3_PF_ID_S\t\t\t0\n+#define HNS3_PF_ID_M\t\t\tGENMASK(2, 0)\n+#define HNS3_VF_ID_S\t\t\t3\n+#define HNS3_VF_ID_M\t\t\tGENMASK(10, 3)\n+#define HNS3_PORT_TYPE_B\t\t11\n+#define HNS3_NETWORK_PORT_ID_S\t\t0\n+#define HNS3_NETWORK_PORT_ID_M\t\tGENMASK(3, 0)\n+\n+#define HNS3_FD_EPORT_SW_EN_B\t\t0\n+\n+#define HNS3_FD_AD_DATA_S\t\t32\n+#define HNS3_FD_AD_DROP_B\t\t0\n+#define HNS3_FD_AD_DIRECT_QID_B\t1\n+#define HNS3_FD_AD_QID_S\t\t2\n+#define HNS3_FD_AD_QID_M\t\tGENMASK(12, 2)\n+#define HNS3_FD_AD_USE_COUNTER_B\t12\n+#define HNS3_FD_AD_COUNTER_NUM_S\t13\n+#define HNS3_FD_AD_COUNTER_NUM_M\tGENMASK(20, 13)\n+#define HNS3_FD_AD_NXT_STEP_B\t\t20\n+#define HNS3_FD_AD_NXT_KEY_S\t\t21\n+#define HNS3_FD_AD_NXT_KEY_M\t\tGENMASK(26, 21)\n+#define HNS3_FD_AD_WR_RULE_ID_B\t0\n+#define HNS3_FD_AD_RULE_ID_S\t\t1\n+#define HNS3_FD_AD_RULE_ID_M\t\tGENMASK(13, 1)\n+\n+enum HNS3_PORT_TYPE {\n+\tHOST_PORT,\n+\tNETWORK_PORT\n+};\n+\n+enum HNS3_FD_MODE {\n+\tHNS3_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1,\n+\tHNS3_FD_MODE_DEPTH_1K_WIDTH_400B_STAGE_2,\n+\tHNS3_FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1,\n+\tHNS3_FD_MODE_DEPTH_2K_WIDTH_200B_STAGE_2,\n+};\n+\n+enum HNS3_FD_KEY_TYPE {\n+\tHNS3_FD_KEY_BASE_ON_PTYPE,\n+\tHNS3_FD_KEY_BASE_ON_TUPLE,\n+};\n+\n+enum HNS3_FD_META_DATA {\n+\tPACKET_TYPE_ID,\n+\tIP_FRAGEMENT,\n+\tROCE_TYPE,\n+\tNEXT_KEY,\n+\tVLAN_NUMBER,\n+\tSRC_VPORT,\n+\tDST_VPORT,\n+\tTUNNEL_PACKET,\n+\tMAX_META_DATA,\n+};\n+\n+struct key_info {\n+\tuint8_t key_type;\n+\tuint8_t key_length;\n+};\n+\n+static const struct key_info meta_data_key_info[] = {\n+\t{PACKET_TYPE_ID, 6},\n+\t{IP_FRAGEMENT, 1},\n+\t{ROCE_TYPE, 1},\n+\t{NEXT_KEY, 5},\n+\t{VLAN_NUMBER, 2},\n+\t{SRC_VPORT, 12},\n+\t{DST_VPORT, 12},\n+\t{TUNNEL_PACKET, 1},\n+};\n+\n+static const struct key_info tuple_key_info[] = {\n+\t{OUTER_DST_MAC, 48},\n+\t{OUTER_SRC_MAC, 48},\n+\t{OUTER_VLAN_TAG_FST, 16},\n+\t{OUTER_VLAN_TAG_SEC, 16},\n+\t{OUTER_ETH_TYPE, 16},\n+\t{OUTER_L2_RSV, 16},\n+\t{OUTER_IP_TOS, 8},\n+\t{OUTER_IP_PROTO, 8},\n+\t{OUTER_SRC_IP, 32},\n+\t{OUTER_DST_IP, 32},\n+\t{OUTER_L3_RSV, 16},\n+\t{OUTER_SRC_PORT, 16},\n+\t{OUTER_DST_PORT, 16},\n+\t{OUTER_L4_RSV, 32},\n+\t{OUTER_TUN_VNI, 24},\n+\t{OUTER_TUN_FLOW_ID, 8},\n+\t{INNER_DST_MAC, 48},\n+\t{INNER_SRC_MAC, 48},\n+\t{INNER_VLAN_TAG1, 16},\n+\t{INNER_VLAN_TAG2, 16},\n+\t{INNER_ETH_TYPE, 16},\n+\t{INNER_L2_RSV, 16},\n+\t{INNER_IP_TOS, 8},\n+\t{INNER_IP_PROTO, 8},\n+\t{INNER_SRC_IP, 32},\n+\t{INNER_DST_IP, 32},\n+\t{INNER_L3_RSV, 16},\n+\t{INNER_SRC_PORT, 16},\n+\t{INNER_DST_PORT, 16},\n+\t{INNER_SCTP_TAG, 32},\n+};\n+\n+#define HNS3_BITS_PER_BYTE\t8\n+#define MAX_KEY_LENGTH\t\t400\n+#define MAX_200B_KEY_LENGTH\t200\n+#define MAX_META_DATA_LENGTH\t16\n+#define MAX_KEY_DWORDS\tDIV_ROUND_UP(MAX_KEY_LENGTH / HNS3_BITS_PER_BYTE, 4)\n+#define MAX_KEY_BYTES\t(MAX_KEY_DWORDS * 4)\n+\n+enum HNS3_FD_PACKET_TYPE {\n+\tNIC_PACKET,\n+\tROCE_PACKET,\n+};\n+\n+/* For each bit of TCAM entry, it uses a pair of 'x' and\n+ * 'y' to indicate which value to match, like below:\n+ * ----------------------------------\n+ * | bit x | bit y |  search value  |\n+ * ----------------------------------\n+ * |   0   |   0   |   always hit   |\n+ * ----------------------------------\n+ * |   1   |   0   |   match '0'    |\n+ * ----------------------------------\n+ * |   0   |   1   |   match '1'    |\n+ * ----------------------------------\n+ * |   1   |   1   |   invalid      |\n+ * ----------------------------------\n+ * Then for input key(k) and mask(v), we can calculate the value by\n+ * the formulae:\n+ *\tx = (~k) & v\n+ *\ty = k & v\n+ */\n+#define calc_x(x, k, v) ((x) = (~(k) & (v)))\n+#define calc_y(y, k, v) ((y) = ((k) & (v)))\n+\n+struct hns3_fd_tcam_config_1_cmd {\n+\tuint8_t stage;\n+\tuint8_t xy_sel;\n+\tuint8_t port_info;\n+\tuint8_t rsv1[1];\n+\trte_le32_t index;\n+\tuint8_t entry_vld;\n+\tuint8_t rsv2[7];\n+\tuint8_t tcam_data[8];\n+};\n+\n+struct hns3_fd_tcam_config_2_cmd {\n+\tuint8_t tcam_data[24];\n+};\n+\n+struct hns3_fd_tcam_config_3_cmd {\n+\tuint8_t tcam_data[20];\n+\tuint8_t rsv[4];\n+};\n+\n+struct hns3_get_fd_mode_cmd {\n+\tuint8_t mode;\n+\tuint8_t enable;\n+\tuint8_t rsv[22];\n+};\n+\n+struct hns3_get_fd_allocation_cmd {\n+\trte_le32_t stage1_entry_num;\n+\trte_le32_t stage2_entry_num;\n+\trte_le16_t stage1_counter_num;\n+\trte_le16_t stage2_counter_num;\n+\tuint8_t rsv[12];\n+};\n+\n+struct hns3_set_fd_key_config_cmd {\n+\tuint8_t stage;\n+\tuint8_t key_select;\n+\tuint8_t inner_sipv6_word_en;\n+\tuint8_t inner_dipv6_word_en;\n+\tuint8_t outer_sipv6_word_en;\n+\tuint8_t outer_dipv6_word_en;\n+\tuint8_t rsv1[2];\n+\trte_le32_t tuple_mask;\n+\trte_le32_t meta_data_mask;\n+\tuint8_t rsv2[8];\n+};\n+\n+struct hns3_fd_ad_config_cmd {\n+\tuint8_t stage;\n+\tuint8_t rsv1[3];\n+\trte_le32_t index;\n+\trte_le64_t ad_data;\n+\tuint8_t rsv2[8];\n+};\n+\n+struct hns3_fd_get_cnt_cmd {\n+\tuint8_t stage;\n+\tuint8_t rsv1[3];\n+\trte_le16_t index;\n+\tuint8_t rsv2[2];\n+\trte_le64_t value;\n+\tuint8_t rsv3[8];\n+};\n+\n+static int hns3_get_fd_mode(struct hns3_hw *hw, uint8_t *fd_mode)\n+{\n+\tstruct hns3_get_fd_mode_cmd *req;\n+\tstruct hns3_cmd_desc desc;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_MODE_CTRL, true);\n+\n+\treq = (struct hns3_get_fd_mode_cmd *)desc.data;\n+\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret) {\n+\t\thns3_err(hw, \"Get fd mode fail, ret=%d\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\t*fd_mode = req->mode;\n+\n+\treturn ret;\n+}\n+\n+static int hns3_get_fd_allocation(struct hns3_hw *hw,\n+\t\t\t\t  uint32_t *stage1_entry_num,\n+\t\t\t\t  uint32_t *stage2_entry_num,\n+\t\t\t\t  uint16_t *stage1_counter_num,\n+\t\t\t\t  uint16_t *stage2_counter_num)\n+{\n+\tstruct hns3_get_fd_allocation_cmd *req;\n+\tstruct hns3_cmd_desc desc;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_GET_ALLOCATION, true);\n+\n+\treq = (struct hns3_get_fd_allocation_cmd *)desc.data;\n+\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret) {\n+\t\thns3_err(hw, \"Query fd allocation fail, ret=%d\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\t*stage1_entry_num = rte_le_to_cpu_32(req->stage1_entry_num);\n+\t*stage2_entry_num = rte_le_to_cpu_32(req->stage2_entry_num);\n+\t*stage1_counter_num = rte_le_to_cpu_16(req->stage1_counter_num);\n+\t*stage2_counter_num = rte_le_to_cpu_16(req->stage2_counter_num);\n+\n+\treturn ret;\n+}\n+\n+static int hns3_set_fd_key_config(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_set_fd_key_config_cmd *req;\n+\tstruct hns3_fd_key_cfg *key_cfg;\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_cmd_desc desc;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_KEY_CONFIG, false);\n+\n+\treq = (struct hns3_set_fd_key_config_cmd *)desc.data;\n+\tkey_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];\n+\treq->stage = HNS3_FD_STAGE_1;\n+\treq->key_select = key_cfg->key_sel;\n+\treq->inner_sipv6_word_en = key_cfg->inner_sipv6_word_en;\n+\treq->inner_dipv6_word_en = key_cfg->inner_dipv6_word_en;\n+\treq->outer_sipv6_word_en = key_cfg->outer_sipv6_word_en;\n+\treq->outer_dipv6_word_en = key_cfg->outer_dipv6_word_en;\n+\treq->tuple_mask = rte_cpu_to_le_32(~key_cfg->tuple_active);\n+\treq->meta_data_mask = rte_cpu_to_le_32(~key_cfg->meta_data_active);\n+\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret)\n+\t\thns3_err(hw, \"Set fd key fail, ret=%d\", ret);\n+\n+\treturn ret;\n+}\n+\n+int hns3_init_fd_config(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_fd_key_cfg *key_cfg;\n+\tint ret;\n+\n+\tret = hns3_get_fd_mode(hw, &pf->fdir.fd_cfg.fd_mode);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tswitch (pf->fdir.fd_cfg.fd_mode) {\n+\tcase HNS3_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1:\n+\t\tpf->fdir.fd_cfg.max_key_length = MAX_KEY_LENGTH;\n+\t\tbreak;\n+\tcase HNS3_FD_MODE_DEPTH_4K_WIDTH_200B_STAGE_1:\n+\t\tpf->fdir.fd_cfg.max_key_length = MAX_200B_KEY_LENGTH;\n+\t\thns3_warn(hw, \"Unsupported tunnel filter in 4K*200Bit\");\n+\t\tbreak;\n+\tdefault:\n+\t\thns3_err(hw, \"Unsupported flow director mode %d\",\n+\t\t\t    pf->fdir.fd_cfg.fd_mode);\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tkey_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];\n+\tkey_cfg->key_sel = HNS3_FD_KEY_BASE_ON_TUPLE;\n+\tkey_cfg->inner_sipv6_word_en = IPV6_ADDR_WORD_MASK;\n+\tkey_cfg->inner_dipv6_word_en = IPV6_ADDR_WORD_MASK;\n+\tkey_cfg->outer_sipv6_word_en = 0;\n+\tkey_cfg->outer_dipv6_word_en = 0;\n+\n+\tkey_cfg->tuple_active = BIT(INNER_VLAN_TAG1) | BIT(INNER_ETH_TYPE) |\n+\t    BIT(INNER_IP_PROTO) | BIT(INNER_IP_TOS) |\n+\t    BIT(INNER_SRC_IP) | BIT(INNER_DST_IP) |\n+\t    BIT(INNER_SRC_PORT) | BIT(INNER_DST_PORT);\n+\n+\t/* If use max 400bit key, we can support tuples for ether type */\n+\tif (pf->fdir.fd_cfg.max_key_length == MAX_KEY_LENGTH) {\n+\t\tkey_cfg->tuple_active |=\n+\t\t    BIT(INNER_DST_MAC) | BIT(INNER_SRC_MAC) |\n+\t\t    BIT(OUTER_SRC_PORT) | BIT(INNER_SCTP_TAG) |\n+\t\t    BIT(OUTER_DST_PORT) | BIT(INNER_VLAN_TAG2) |\n+\t\t    BIT(OUTER_TUN_VNI) | BIT(OUTER_TUN_FLOW_ID) |\n+\t\t    BIT(OUTER_ETH_TYPE) | BIT(OUTER_IP_PROTO);\n+\t}\n+\n+\t/* roce_type is used to filter roce frames\n+\t * dst_vport is used to specify the rule\n+\t */\n+\tkey_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET) |\n+\t    BIT(VLAN_NUMBER);\n+\n+\tret = hns3_get_fd_allocation(hw,\n+\t\t\t\t     &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],\n+\t\t\t\t     &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_2],\n+\t\t\t\t     &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1],\n+\t\t\t\t     &pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_2]);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn hns3_set_fd_key_config(hns);\n+}\n+\n+static int hns3_fd_tcam_config(struct hns3_hw *hw, bool sel_x, int loc,\n+\t\t\t       uint8_t *key, bool is_add)\n+{\n+#define\tFD_TCAM_CMD_NUM 3\n+\tstruct hns3_fd_tcam_config_1_cmd *req1;\n+\tstruct hns3_fd_tcam_config_2_cmd *req2;\n+\tstruct hns3_fd_tcam_config_3_cmd *req3;\n+\tstruct hns3_cmd_desc desc[FD_TCAM_CMD_NUM];\n+\tint len;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_FD_TCAM_OP, false);\n+\tdesc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);\n+\thns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_FD_TCAM_OP, false);\n+\tdesc[1].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);\n+\thns3_cmd_setup_basic_desc(&desc[2], HNS3_OPC_FD_TCAM_OP, false);\n+\n+\treq1 = (struct hns3_fd_tcam_config_1_cmd *)desc[0].data;\n+\treq2 = (struct hns3_fd_tcam_config_2_cmd *)desc[1].data;\n+\treq3 = (struct hns3_fd_tcam_config_3_cmd *)desc[2].data;\n+\n+\treq1->stage = HNS3_FD_STAGE_1;\n+\treq1->xy_sel = sel_x ? 1 : 0;\n+\thns3_set_bit(req1->port_info, HNS3_FD_EPORT_SW_EN_B, 0);\n+\treq1->index = rte_cpu_to_le_32(loc);\n+\treq1->entry_vld = sel_x ? is_add : 0;\n+\n+\tif (key) {\n+\t\tlen = sizeof(req1->tcam_data);\n+\t\tmemcpy(req1->tcam_data, key, len);\n+\t\tkey += len;\n+\n+\t\tlen = sizeof(req2->tcam_data);\n+\t\tmemcpy(req2->tcam_data, key, len);\n+\t\tkey += len;\n+\n+\t\tlen = sizeof(req3->tcam_data);\n+\t\tmemcpy(req3->tcam_data, key, len);\n+\t}\n+\n+\tret = hns3_cmd_send(hw, desc, FD_TCAM_CMD_NUM);\n+\tif (ret)\n+\t\thns3_err(hw, \"Config tcam key fail, ret=%d loc=%d add=%d\",\n+\t\t\t    ret, loc, is_add);\n+\treturn ret;\n+}\n+\n+static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,\n+\t\t\t     struct hns3_fd_ad_data *action)\n+{\n+\tstruct hns3_fd_ad_config_cmd *req;\n+\tstruct hns3_cmd_desc desc;\n+\tuint64_t ad_data = 0;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_AD_OP, false);\n+\n+\treq = (struct hns3_fd_ad_config_cmd *)desc.data;\n+\treq->index = rte_cpu_to_le_32(loc);\n+\treq->stage = HNS3_FD_STAGE_1;\n+\n+\thns3_set_bit(ad_data, HNS3_FD_AD_WR_RULE_ID_B,\n+\t\t     action->write_rule_id_to_bd);\n+\thns3_set_field(ad_data, HNS3_FD_AD_RULE_ID_M, HNS3_FD_AD_RULE_ID_S,\n+\t\t       action->rule_id);\n+\tad_data <<= HNS3_FD_AD_DATA_S;\n+\thns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);\n+\thns3_set_bit(ad_data, HNS3_FD_AD_DIRECT_QID_B,\n+\t\t     action->forward_to_direct_queue);\n+\thns3_set_field(ad_data, HNS3_FD_AD_QID_M, HNS3_FD_AD_QID_S,\n+\t\t       action->queue_id);\n+\thns3_set_bit(ad_data, HNS3_FD_AD_USE_COUNTER_B, action->use_counter);\n+\thns3_set_field(ad_data, HNS3_FD_AD_COUNTER_NUM_M,\n+\t\t       HNS3_FD_AD_COUNTER_NUM_S, action->counter_id);\n+\thns3_set_bit(ad_data, HNS3_FD_AD_NXT_STEP_B, action->use_next_stage);\n+\thns3_set_field(ad_data, HNS3_FD_AD_NXT_KEY_M, HNS3_FD_AD_NXT_KEY_S,\n+\t\t       action->counter_id);\n+\n+\treq->ad_data = rte_cpu_to_le_64(ad_data);\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret)\n+\t\thns3_err(hw, \"Config fd ad fail, ret=%d loc=%d\", ret, loc);\n+\n+\treturn ret;\n+}\n+\n+static inline void hns3_fd_convert_mac(uint8_t *key, uint8_t *mask,\n+\t\t\t\t       uint8_t *mac_x, uint8_t *mac_y)\n+{\n+\tuint8_t tmp;\n+\tint i;\n+\n+\tfor (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {\n+\t\ttmp = RTE_ETHER_ADDR_LEN - 1 - i;\n+\t\tcalc_x(mac_x[tmp], key[i], mask[i]);\n+\t\tcalc_y(mac_y[tmp], key[i], mask[i]);\n+\t}\n+}\n+\n+static void hns3_fd_convert_int16(uint32_t tuple, struct hns3_fdir_rule *rule,\n+\t\t\t\t  uint8_t *val_x, uint8_t *val_y)\n+{\n+\tuint16_t tmp_x_s;\n+\tuint16_t tmp_y_s;\n+\tuint16_t mask;\n+\tuint16_t key;\n+\n+\tswitch (tuple) {\n+\tcase OUTER_SRC_PORT:\n+\t\tkey = rule->key_conf.spec.outer_src_port;\n+\t\tmask = rule->key_conf.mask.outer_src_port;\n+\t\tbreak;\n+\tcase OUTER_DST_PORT:\n+\t\tkey = rule->key_conf.spec.tunnel_type;\n+\t\tmask = rule->key_conf.mask.tunnel_type;\n+\t\tbreak;\n+\tcase OUTER_ETH_TYPE:\n+\t\tkey = rule->key_conf.spec.outer_ether_type;\n+\t\tmask = rule->key_conf.mask.outer_ether_type;\n+\t\tbreak;\n+\tcase INNER_SRC_PORT:\n+\t\tkey = rule->key_conf.spec.src_port;\n+\t\tmask = rule->key_conf.mask.src_port;\n+\t\tbreak;\n+\tcase INNER_DST_PORT:\n+\t\tkey = rule->key_conf.spec.dst_port;\n+\t\tmask = rule->key_conf.mask.dst_port;\n+\t\tbreak;\n+\tcase INNER_VLAN_TAG1:\n+\t\tkey = rule->key_conf.spec.vlan_tag1;\n+\t\tmask = rule->key_conf.mask.vlan_tag1;\n+\t\tbreak;\n+\tcase INNER_VLAN_TAG2:\n+\t\tkey = rule->key_conf.spec.vlan_tag2;\n+\t\tmask = rule->key_conf.mask.vlan_tag2;\n+\t\tbreak;\n+\tdefault:\n+\t\t/*  INNER_ETH_TYPE: */\n+\t\tkey = rule->key_conf.spec.ether_type;\n+\t\tmask = rule->key_conf.mask.ether_type;\n+\t\tbreak;\n+\t}\n+\tcalc_x(tmp_x_s, key, mask);\n+\tcalc_y(tmp_y_s, key, mask);\n+\tval_x[0] = rte_cpu_to_le_16(tmp_x_s) & 0xFF;\n+\tval_x[1] = rte_cpu_to_le_16(tmp_x_s) >> HNS3_BITS_PER_BYTE;\n+\tval_y[0] = rte_cpu_to_le_16(tmp_y_s) & 0xFF;\n+\tval_y[1] = rte_cpu_to_le_16(tmp_y_s) >> HNS3_BITS_PER_BYTE;\n+}\n+\n+static inline void hns3_fd_convert_int32(uint32_t key, uint32_t mask,\n+\t\t\t\t\t uint8_t *val_x, uint8_t *val_y)\n+{\n+\tuint32_t tmp_x_l;\n+\tuint32_t tmp_y_l;\n+\n+\tcalc_x(tmp_x_l, key, mask);\n+\tcalc_y(tmp_y_l, key, mask);\n+\tmemcpy(val_x, &tmp_x_l, sizeof(tmp_x_l));\n+\tmemcpy(val_y, &tmp_y_l, sizeof(tmp_y_l));\n+}\n+\n+static bool hns3_fd_convert_tuple(uint32_t tuple, uint8_t *key_x,\n+\t\t\t\t  uint8_t *key_y, struct hns3_fdir_rule *rule)\n+{\n+\tstruct hns3_fdir_key_conf *key_conf;\n+\tint tmp;\n+\tint i;\n+\n+\tif ((rule->input_set & BIT(tuple)) == 0)\n+\t\treturn true;\n+\n+\tkey_conf = &rule->key_conf;\n+\tswitch (tuple) {\n+\tcase INNER_DST_MAC:\n+\t\thns3_fd_convert_mac(key_conf->spec.dst_mac,\n+\t\t\t\t    key_conf->mask.dst_mac, key_x, key_y);\n+\t\tbreak;\n+\tcase INNER_SRC_MAC:\n+\t\thns3_fd_convert_mac(key_conf->spec.src_mac,\n+\t\t\t\t    key_conf->mask.src_mac, key_x, key_y);\n+\t\tbreak;\n+\tcase OUTER_SRC_PORT:\n+\tcase OUTER_DST_PORT:\n+\tcase OUTER_ETH_TYPE:\n+\tcase INNER_SRC_PORT:\n+\tcase INNER_DST_PORT:\n+\tcase INNER_VLAN_TAG1:\n+\tcase INNER_VLAN_TAG2:\n+\tcase INNER_ETH_TYPE:\n+\t\thns3_fd_convert_int16(tuple, rule, key_x, key_y);\n+\t\tbreak;\n+\tcase INNER_SRC_IP:\n+\t\thns3_fd_convert_int32(key_conf->spec.src_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t      key_conf->mask.src_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t      key_x, key_y);\n+\t\tbreak;\n+\tcase INNER_DST_IP:\n+\t\thns3_fd_convert_int32(key_conf->spec.dst_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t      key_conf->mask.dst_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t      key_x, key_y);\n+\t\tbreak;\n+\tcase INNER_SCTP_TAG:\n+\t\thns3_fd_convert_int32(key_conf->spec.sctp_tag,\n+\t\t\t\t      key_conf->mask.sctp_tag, key_x, key_y);\n+\t\tbreak;\n+\tcase OUTER_TUN_VNI:\n+\t\tfor (i = 0; i < VNI_OR_TNI_LEN; i++) {\n+\t\t\ttmp = VNI_OR_TNI_LEN - 1 - i;\n+\t\t\tcalc_x(key_x[tmp],\n+\t\t\t       key_conf->spec.outer_tun_vni[i],\n+\t\t\t       key_conf->mask.outer_tun_vni[i]);\n+\t\t\tcalc_y(key_y[tmp],\n+\t\t\t       key_conf->spec.outer_tun_vni[i],\n+\t\t\t       key_conf->mask.outer_tun_vni[i]);\n+\t\t}\n+\t\tbreak;\n+\tcase OUTER_TUN_FLOW_ID:\n+\t\tcalc_x(*key_x, key_conf->spec.outer_tun_flow_id,\n+\t\t       key_conf->mask.outer_tun_flow_id);\n+\t\tcalc_y(*key_y, key_conf->spec.outer_tun_flow_id,\n+\t\t       key_conf->mask.outer_tun_flow_id);\n+\t\tbreak;\n+\tcase INNER_IP_TOS:\n+\t\tcalc_x(*key_x, key_conf->spec.ip_tos, key_conf->mask.ip_tos);\n+\t\tcalc_y(*key_y, key_conf->spec.ip_tos, key_conf->mask.ip_tos);\n+\t\tbreak;\n+\tcase OUTER_IP_PROTO:\n+\t\tcalc_x(*key_x, key_conf->spec.outer_proto,\n+\t\t       key_conf->mask.outer_proto);\n+\t\tcalc_y(*key_y, key_conf->spec.outer_proto,\n+\t\t       key_conf->mask.outer_proto);\n+\t\tbreak;\n+\tcase INNER_IP_PROTO:\n+\t\tcalc_x(*key_x, key_conf->spec.ip_proto,\n+\t\t       key_conf->mask.ip_proto);\n+\t\tcalc_y(*key_y, key_conf->spec.ip_proto,\n+\t\t       key_conf->mask.ip_proto);\n+\t\tbreak;\n+\t}\n+\treturn true;\n+}\n+\n+static uint32_t hns3_get_port_number(uint8_t pf_id, uint8_t vf_id)\n+{\n+\tuint32_t port_number = 0;\n+\n+\thns3_set_field(port_number, HNS3_PF_ID_M, HNS3_PF_ID_S, pf_id);\n+\thns3_set_field(port_number, HNS3_VF_ID_M, HNS3_VF_ID_S, vf_id);\n+\thns3_set_bit(port_number, HNS3_PORT_TYPE_B, HOST_PORT);\n+\n+\treturn port_number;\n+}\n+\n+static void hns3_fd_convert_meta_data(struct hns3_fd_key_cfg *cfg,\n+\t\t\t\t      uint8_t vf_id,\n+\t\t\t\t      struct hns3_fdir_rule *rule,\n+\t\t\t\t      uint8_t *key_x, uint8_t *key_y)\n+{\n+\tuint16_t meta_data = 0;\n+\tuint16_t port_number;\n+\tuint8_t cur_pos = 0;\n+\tuint8_t tuple_size;\n+\tuint8_t shift_bits;\n+\tuint32_t tmp_x;\n+\tuint32_t tmp_y;\n+\tuint8_t i;\n+\n+\tfor (i = 0; i < MAX_META_DATA; i++) {\n+\t\tif ((cfg->meta_data_active & BIT(i)) == 0)\n+\t\t\tcontinue;\n+\n+\t\ttuple_size = meta_data_key_info[i].key_length;\n+\t\tif (i == TUNNEL_PACKET) {\n+\t\t\thns3_set_bit(meta_data, cur_pos,\n+\t\t\t\t     rule->key_conf.spec.tunnel_type ? 1 : 0);\n+\t\t\tcur_pos += tuple_size;\n+\t\t} else if (i == VLAN_NUMBER) {\n+\t\t\tuint8_t vlan_tag;\n+\t\t\tuint8_t vlan_num;\n+\t\t\tif (rule->key_conf.spec.tunnel_type == 0)\n+\t\t\t\tvlan_num = rule->key_conf.vlan_num;\n+\t\t\telse\n+\t\t\t\tvlan_num = rule->key_conf.outer_vlan_num;\n+\t\t\tif (vlan_num == 1)\n+\t\t\t\tvlan_tag = HNS3_VLAN_TAG_TYPE_TAG1;\n+\t\t\telse if (vlan_num == VLAN_TAG_NUM_MAX)\n+\t\t\t\tvlan_tag = HNS3_VLAN_TAG_TYPE_TAG1_2;\n+\t\t\telse\n+\t\t\t\tvlan_tag = HNS3_VLAN_TAG_TYPE_NONE;\n+\t\t\thns3_set_field(meta_data,\n+\t\t\t\t       GENMASK(cur_pos + tuple_size,\n+\t\t\t\t\t       cur_pos), cur_pos, vlan_tag);\n+\t\t\tcur_pos += tuple_size;\n+\t\t} else if (i == DST_VPORT) {\n+\t\t\tport_number = hns3_get_port_number(0, vf_id);\n+\t\t\thns3_set_field(meta_data,\n+\t\t\t\t       GENMASK(cur_pos + tuple_size, cur_pos),\n+\t\t\t\t       cur_pos, port_number);\n+\t\t\tcur_pos += tuple_size;\n+\t\t}\n+\t}\n+\n+\tcalc_x(tmp_x, meta_data, 0xFFFF);\n+\tcalc_y(tmp_y, meta_data, 0xFFFF);\n+\tshift_bits = sizeof(meta_data) * HNS3_BITS_PER_BYTE - cur_pos;\n+\n+\ttmp_x = rte_cpu_to_le_32(tmp_x << shift_bits);\n+\ttmp_y = rte_cpu_to_le_32(tmp_y << shift_bits);\n+\tkey_x[0] = tmp_x & 0xFF;\n+\tkey_x[1] = (tmp_x >> HNS3_BITS_PER_BYTE) & 0xFF;\n+\tkey_y[0] = tmp_y & 0xFF;\n+\tkey_y[1] = (tmp_y >> HNS3_BITS_PER_BYTE) & 0xFF;\n+}\n+\n+/* A complete key is combined with meta data key and tuple key.\n+ * Meta data key is stored at the MSB region, and tuple key is stored at\n+ * the LSB region, unused bits will be filled 0.\n+ */\n+static int hns3_config_key(struct hns3_adapter *hns,\n+\t\t\t   struct hns3_fdir_rule *rule)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_fd_key_cfg *key_cfg;\n+\tuint8_t *cur_key_x;\n+\tuint8_t *cur_key_y;\n+\tuint8_t key_x[MAX_KEY_BYTES] __attribute__((aligned(4)));\n+\tuint8_t key_y[MAX_KEY_BYTES] __attribute__((aligned(4)));\n+\tuint8_t vf_id = rule->vf_id;\n+\tuint8_t meta_data_region;\n+\tuint8_t tuple_size;\n+\tuint8_t i;\n+\tint ret;\n+\n+\tmemset(key_x, 0, sizeof(key_x));\n+\tmemset(key_y, 0, sizeof(key_y));\n+\tcur_key_x = key_x;\n+\tcur_key_y = key_y;\n+\n+\tkey_cfg = &pf->fdir.fd_cfg.key_cfg[HNS3_FD_STAGE_1];\n+\tfor (i = 0; i < MAX_TUPLE; i++) {\n+\t\tbool tuple_valid;\n+\n+\t\ttuple_size = tuple_key_info[i].key_length / HNS3_BITS_PER_BYTE;\n+\t\tif (key_cfg->tuple_active & BIT(i)) {\n+\t\t\ttuple_valid = hns3_fd_convert_tuple(i, cur_key_x,\n+\t\t\t\t\t\t\t    cur_key_y, rule);\n+\t\t\tif (tuple_valid) {\n+\t\t\t\tcur_key_x += tuple_size;\n+\t\t\t\tcur_key_y += tuple_size;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tmeta_data_region = pf->fdir.fd_cfg.max_key_length / HNS3_BITS_PER_BYTE -\n+\t    MAX_META_DATA_LENGTH / HNS3_BITS_PER_BYTE;\n+\n+\thns3_fd_convert_meta_data(key_cfg, vf_id, rule,\n+\t\t\t\t  key_x + meta_data_region,\n+\t\t\t\t  key_y + meta_data_region);\n+\n+\tret = hns3_fd_tcam_config(hw, false, rule->location, key_y, true);\n+\tif (ret) {\n+\t\thns3_err(hw, \"Config fd key_y fail, loc=%d, ret=%d\",\n+\t\t\t    rule->queue_id, ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = hns3_fd_tcam_config(hw, true, rule->location, key_x, true);\n+\tif (ret)\n+\t\thns3_err(hw, \"Config fd key_x fail, loc=%d, ret=%d\",\n+\t\t\t    rule->queue_id, ret);\n+\treturn ret;\n+}\n+\n+static int hns3_config_action(struct hns3_hw *hw, struct hns3_fdir_rule *rule)\n+{\n+\tstruct hns3_fd_ad_data ad_data;\n+\n+\tad_data.ad_id = rule->location;\n+\n+\tif (rule->action == HNS3_FD_ACTION_DROP_PACKET) {\n+\t\tad_data.drop_packet = true;\n+\t\tad_data.forward_to_direct_queue = false;\n+\t\tad_data.queue_id = 0;\n+\t} else {\n+\t\tad_data.drop_packet = false;\n+\t\tad_data.forward_to_direct_queue = true;\n+\t\tad_data.queue_id = rule->queue_id;\n+\t}\n+\n+\tif (unlikely(rule->flags & HNS3_RULE_FLAG_COUNTER)) {\n+\t\tad_data.use_counter = true;\n+\t\tad_data.counter_id = rule->act_cnt.id;\n+\t} else {\n+\t\tad_data.use_counter = false;\n+\t\tad_data.counter_id = 0;\n+\t}\n+\n+\tif (unlikely(rule->flags & HNS3_RULE_FLAG_FDID))\n+\t\tad_data.rule_id = rule->fd_id;\n+\telse\n+\t\tad_data.rule_id = rule->location;\n+\n+\tad_data.use_next_stage = false;\n+\tad_data.next_input_key = 0;\n+\n+\tad_data.write_rule_id_to_bd = true;\n+\n+\treturn hns3_fd_ad_config(hw, ad_data.ad_id, &ad_data);\n+}\n+\n+int hns3_fdir_filter_init(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_fdir_info *fdir_info = &pf->fdir;\n+\tuint32_t rule_num = fdir_info->fd_cfg.rule_num[HNS3_FD_STAGE_1];\n+\tchar fdir_hash_name[RTE_HASH_NAMESIZE];\n+\tstruct rte_hash_parameters fdir_hash_params = {\n+\t\t.name = fdir_hash_name,\n+\t\t.entries = rule_num,\n+\t\t.key_len = sizeof(struct hns3_fdir_key_conf),\n+\t\t.hash_func = rte_hash_crc,\n+\t\t.hash_func_init_val = 0,\n+\t};\n+\n+\tfdir_hash_params.socket_id = rte_socket_id();\n+\tTAILQ_INIT(&fdir_info->fdir_list);\n+\trte_spinlock_init(&fdir_info->flows_lock);\n+\tsnprintf(fdir_hash_name, RTE_HASH_NAMESIZE, \"%s\", hns->hw.data->name);\n+\tfdir_info->hash_handle = rte_hash_create(&fdir_hash_params);\n+\tif (fdir_info->hash_handle == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"Create FDIR hash handle fail!\");\n+\t\treturn -EINVAL;\n+\t}\n+\tfdir_info->hash_map = rte_zmalloc(\"hns3 FDIR hash\",\n+\t\t\t\t\t  rule_num *\n+\t\t\t\t\t  sizeof(struct hns3_fdir_rule_ele *),\n+\t\t\t\t\t  0);\n+\tif (fdir_info->hash_map == NULL) {\n+\t\tPMD_INIT_LOG(ERR, \"Allocate memory for FDIR hash map fail!\");\n+\t\trte_hash_free(fdir_info->hash_handle);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void hns3_fdir_filter_uninit(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_fdir_info *fdir_info = &pf->fdir;\n+\tstruct hns3_fdir_rule_ele *fdir_filter;\n+\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\tif (fdir_info->hash_map) {\n+\t\trte_free(fdir_info->hash_map);\n+\t\tfdir_info->hash_map = NULL;\n+\t}\n+\tif (fdir_info->hash_handle) {\n+\t\trte_hash_free(fdir_info->hash_handle);\n+\t\tfdir_info->hash_handle = NULL;\n+\t}\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\n+\tfdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);\n+\twhile (fdir_filter) {\n+\t\tTAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);\n+\t\thns3_fd_tcam_config(&hns->hw, true,\n+\t\t\t\t    fdir_filter->fdir_conf.location, NULL,\n+\t\t\t\t    false);\n+\t\trte_free(fdir_filter);\n+\t\tfdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);\n+\t}\n+}\n+\n+/*\n+ * Find a key in the hash table.\n+ * @return\n+ *   - Zero and positive values are key location.\n+ *   - -EINVAL if the parameters are invalid.\n+ *   - -ENOENT if the key is not found.\n+ */\n+static int hns3_fdir_filter_lookup(struct hns3_fdir_info *fdir_info,\n+\t\t\t\t    struct hns3_fdir_key_conf *key)\n+{\n+\thash_sig_t sig;\n+\tint ret;\n+\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\tsig = rte_hash_crc(key, sizeof(*key), 0);\n+\tret = rte_hash_lookup_with_hash(fdir_info->hash_handle, key, sig);\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\n+\treturn ret;\n+}\n+\n+static int hns3_insert_fdir_filter(struct hns3_hw *hw,\n+\t\t\t\t   struct hns3_fdir_info *fdir_info,\n+\t\t\t\t   struct hns3_fdir_rule_ele *fdir_filter)\n+{\n+\tstruct hns3_fdir_key_conf *key;\n+\thash_sig_t sig;\n+\tint ret;\n+\n+\tkey = &fdir_filter->fdir_conf.key_conf;\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\tsig = rte_hash_crc(key, sizeof(*key), 0);\n+\tret = rte_hash_add_key_with_hash(fdir_info->hash_handle, key, sig);\n+\tif (ret < 0) {\n+\t\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\t\thns3_err(hw, \"Hash table full? err:%d(%s)!\", ret,\n+\t\t\t strerror(ret));\n+\t\treturn ret;\n+\t}\n+\n+\tfdir_info->hash_map[ret] = fdir_filter;\n+\tTAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries);\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\n+\treturn ret;\n+}\n+\n+static int hns3_remove_fdir_filter(struct hns3_hw *hw,\n+\t\t\t\t   struct hns3_fdir_info *fdir_info,\n+\t\t\t\t   struct hns3_fdir_key_conf *key)\n+{\n+\tstruct hns3_fdir_rule_ele *fdir_filter;\n+\thash_sig_t sig;\n+\tint ret;\n+\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\tsig = rte_hash_crc(key, sizeof(*key), 0);\n+\tret = rte_hash_del_key_with_hash(fdir_info->hash_handle, key, sig);\n+\tif (ret < 0) {\n+\t\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\t\thns3_err(hw, \"Delete hash key fail ret=%d\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tfdir_filter = fdir_info->hash_map[ret];\n+\tfdir_info->hash_map[ret] = NULL;\n+\tTAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\n+\trte_free(fdir_filter);\n+\n+\treturn 0;\n+}\n+\n+int hns3_fdir_filter_program(struct hns3_adapter *hns,\n+\t\t\t     struct hns3_fdir_rule *rule, bool del)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_fdir_info *fdir_info = &pf->fdir;\n+\tstruct hns3_fdir_rule_ele *node;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tint ret;\n+\n+\tif (del) {\n+\t\tret = hns3_fd_tcam_config(hw, true, rule->location, NULL,\n+\t\t\t\t\t  false);\n+\t\tif (ret)\n+\t\t\thns3_err(hw, \"Failed to delete fdir: %d src_ip:%x \"\n+\t\t\t\t \"dst_ip:%x src_port:%d dst_port:%d\",\n+\t\t\t\t rule->location,\n+\t\t\t\t rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],\n+\t\t\t\t rule->key_conf.spec.src_port,\n+\t\t\t\t rule->key_conf.spec.dst_port);\n+\t\telse\n+\t\t\thns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf);\n+\n+\t\treturn ret;\n+\t}\n+\n+\tret = hns3_fdir_filter_lookup(fdir_info, &rule->key_conf);\n+\tif (ret >= 0) {\n+\t\thns3_err(hw, \"Conflict with existing fdir loc: %d\", ret);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tnode = rte_zmalloc(\"hns3 fdir rule\", sizeof(struct hns3_fdir_rule_ele),\n+\t\t\t   0);\n+\tif (node == NULL) {\n+\t\thns3_err(hw, \"Failed to allocate fdir_rule memory\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\trte_memcpy(&node->fdir_conf, rule, sizeof(struct hns3_fdir_rule));\n+\tret = hns3_insert_fdir_filter(hw, fdir_info, node);\n+\tif (ret < 0) {\n+\t\trte_free(node);\n+\t\treturn ret;\n+\t}\n+\trule->location = ret;\n+\tnode->fdir_conf.location = ret;\n+\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\tret = hns3_config_action(hw, rule);\n+\tif (!ret)\n+\t\tret = hns3_config_key(hns, rule);\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\tif (ret) {\n+\t\thns3_err(hw, \"Failed to config fdir: %d src_ip:%x dst_ip:%x \"\n+\t\t\t \"src_port:%d dst_port:%d\",\n+\t\t\t rule->location,\n+\t\t\t rule->key_conf.spec.src_ip[IP_ADDR_KEY_ID],\n+\t\t\t rule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID],\n+\t\t\t rule->key_conf.spec.src_port,\n+\t\t\t rule->key_conf.spec.dst_port);\n+\t\t(void)hns3_remove_fdir_filter(hw, fdir_info, &rule->key_conf);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* remove all the flow director filters */\n+int hns3_clear_all_fdir_filter(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_fdir_info *fdir_info = &pf->fdir;\n+\tstruct hns3_fdir_rule_ele *fdir_filter;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tint ret = 0;\n+\n+\t/* flush flow director */\n+\trte_spinlock_lock(&fdir_info->flows_lock);\n+\trte_hash_reset(fdir_info->hash_handle);\n+\trte_spinlock_unlock(&fdir_info->flows_lock);\n+\n+\tfdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);\n+\twhile (fdir_filter) {\n+\t\tTAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries);\n+\t\tret += hns3_fd_tcam_config(hw, true,\n+\t\t\t\t\t   fdir_filter->fdir_conf.location,\n+\t\t\t\t\t   NULL, false);\n+\t\trte_free(fdir_filter);\n+\t\tfdir_filter = TAILQ_FIRST(&fdir_info->fdir_list);\n+\t}\n+\n+\tif (ret) {\n+\t\thns3_err(hw, \"Fail to delete FDIR filter!\");\n+\t\tret = -EIO;\n+\t}\n+\treturn ret;\n+}\n+\n+int hns3_restore_all_fdir_filter(struct hns3_adapter *hns)\n+{\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_fdir_info *fdir_info = &pf->fdir;\n+\tstruct hns3_fdir_rule_ele *fdir_filter;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tbool err = false;\n+\tint ret;\n+\n+\tTAILQ_FOREACH(fdir_filter, &fdir_info->fdir_list, entries) {\n+\t\tret = hns3_config_action(hw, &fdir_filter->fdir_conf);\n+\t\tif (!ret)\n+\t\t\tret = hns3_config_key(hns, &fdir_filter->fdir_conf);\n+\t\tif (ret) {\n+\t\t\terr = true;\n+\t\t\tif (ret == -EBUSY)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (err) {\n+\t\thns3_err(hw, \"Fail to restore FDIR filter!\");\n+\t\treturn -EIO;\n+\t}\n+\treturn 0;\n+}\n+\n+int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value)\n+{\n+\tstruct hns3_fd_get_cnt_cmd *req;\n+\tstruct hns3_cmd_desc desc;\n+\tint ret;\n+\n+\thns3_cmd_setup_basic_desc(&desc, HNS3_OPC_FD_COUNTER_OP, true);\n+\n+\treq = (struct hns3_fd_get_cnt_cmd *)desc.data;\n+\treq->stage = HNS3_FD_STAGE_1;\n+\treq->index = rte_cpu_to_le_32(id);\n+\n+\tret = hns3_cmd_send(hw, &desc, 1);\n+\tif (ret) {\n+\t\thns3_err(hw, \"Read counter fail, ret=%d\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\t*value = req->value;\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h\nnew file mode 100644\nindex 0000000..4825086\n--- /dev/null\n+++ b/drivers/net/hns3/hns3_fdir.h\n@@ -0,0 +1,203 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2019 Hisilicon Limited.\n+ */\n+\n+#ifndef _HNS3_FDIR_H_\n+#define _HNS3_FDIR_H_\n+\n+#include <rte_flow.h>\n+\n+struct hns3_fd_key_cfg {\n+\tuint8_t key_sel;\n+\tuint8_t inner_sipv6_word_en;\n+\tuint8_t inner_dipv6_word_en;\n+\tuint8_t outer_sipv6_word_en;\n+\tuint8_t outer_dipv6_word_en;\n+\tuint32_t tuple_active;\n+\tuint32_t meta_data_active;\n+};\n+\n+enum HNS3_FD_STAGE {\n+\tHNS3_FD_STAGE_1,\n+\tHNS3_FD_STAGE_2,\n+\tHNS3_FD_STAGE_NUM,\n+};\n+\n+enum HNS3_FD_ACTION {\n+\tHNS3_FD_ACTION_ACCEPT_PACKET,\n+\tHNS3_FD_ACTION_DROP_PACKET,\n+};\n+\n+struct hns3_fd_cfg {\n+\tuint8_t fd_mode;\n+\tuint16_t max_key_length;\n+\tuint32_t rule_num[HNS3_FD_STAGE_NUM]; /* rule entry number */\n+\tuint16_t cnt_num[HNS3_FD_STAGE_NUM];  /* rule hit counter number */\n+\tstruct hns3_fd_key_cfg key_cfg[HNS3_FD_STAGE_NUM];\n+};\n+\n+/* OUTER_XXX indicates tuples in tunnel header of tunnel packet\n+ * INNER_XXX indicate tuples in tunneled header of tunnel packet or\n+ *           tuples of non-tunnel packet\n+ */\n+enum HNS3_FD_TUPLE {\n+\tOUTER_DST_MAC,\n+\tOUTER_SRC_MAC,\n+\tOUTER_VLAN_TAG_FST,\n+\tOUTER_VLAN_TAG_SEC,\n+\tOUTER_ETH_TYPE,\n+\tOUTER_L2_RSV,\n+\tOUTER_IP_TOS,\n+\tOUTER_IP_PROTO,\n+\tOUTER_SRC_IP,\n+\tOUTER_DST_IP,\n+\tOUTER_L3_RSV,\n+\tOUTER_SRC_PORT,\n+\tOUTER_DST_PORT,\n+\tOUTER_L4_RSV,\n+\tOUTER_TUN_VNI,\n+\tOUTER_TUN_FLOW_ID,\n+\tINNER_DST_MAC,\n+\tINNER_SRC_MAC,\n+\tINNER_VLAN_TAG1,\n+\tINNER_VLAN_TAG2,\n+\tINNER_ETH_TYPE,\n+\tINNER_L2_RSV,\n+\tINNER_IP_TOS,\n+\tINNER_IP_PROTO,\n+\tINNER_SRC_IP,\n+\tINNER_DST_IP,\n+\tINNER_L3_RSV,\n+\tINNER_SRC_PORT,\n+\tINNER_DST_PORT,\n+\tINNER_SCTP_TAG,\n+\tMAX_TUPLE,\n+};\n+\n+#define VLAN_TAG_NUM_MAX 2\n+#define VNI_OR_TNI_LEN 3\n+#define IP_ADDR_LEN    4 /* Length of IPv6 address. */\n+#define IP_ADDR_KEY_ID 3 /* The last 32bit of IP address as FDIR search key */\n+#define IPV6_ADDR_WORD_MASK 3 /* The last two word of IPv6 as FDIR search key */\n+\n+struct hns3_fd_rule_tuples {\n+\tuint8_t src_mac[RTE_ETHER_ADDR_LEN];\n+\tuint8_t dst_mac[RTE_ETHER_ADDR_LEN];\n+\tuint32_t src_ip[IP_ADDR_LEN];\n+\tuint32_t dst_ip[IP_ADDR_LEN];\n+\tuint16_t src_port;\n+\tuint16_t dst_port;\n+\tuint16_t vlan_tag1;\n+\tuint16_t vlan_tag2;\n+\tuint16_t ether_type;\n+\tuint8_t ip_tos;\n+\tuint8_t ip_proto;\n+\tuint32_t sctp_tag;\n+\tuint16_t outer_src_port;\n+\tuint16_t tunnel_type;\n+\tuint16_t outer_ether_type;\n+\tuint8_t outer_proto;\n+\tuint8_t outer_tun_vni[VNI_OR_TNI_LEN];\n+\tuint8_t outer_tun_flow_id;\n+};\n+\n+struct hns3_fd_ad_data {\n+\tuint16_t ad_id;\n+\tuint8_t drop_packet;\n+\tuint8_t forward_to_direct_queue;\n+\tuint16_t queue_id;\n+\tuint8_t use_counter;\n+\tuint8_t counter_id;\n+\tuint8_t use_next_stage;\n+\tuint8_t write_rule_id_to_bd;\n+\tuint8_t next_input_key;\n+\tuint16_t rule_id;\n+};\n+\n+struct hns3_flow_counter {\n+\tLIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */\n+\tuint32_t shared:1;   /* Share counter ID with other flow rules. */\n+\tuint32_t ref_cnt:31; /* Reference counter. */\n+\tuint16_t id;   /* Counter ID. */\n+\tuint64_t hits; /* Number of packets matched by the rule. */\n+};\n+\n+#define HNS3_RULE_FLAG_FDID\t\t0x1\n+#define HNS3_RULE_FLAG_VF_ID\t\t0x2\n+#define HNS3_RULE_FLAG_COUNTER\t\t0x4\n+\n+struct hns3_fdir_key_conf {\n+\tstruct hns3_fd_rule_tuples spec;\n+\tstruct hns3_fd_rule_tuples mask;\n+\tuint8_t vlan_num;\n+\tuint8_t outer_vlan_num;\n+};\n+\n+struct hns3_fdir_rule {\n+\tstruct hns3_fdir_key_conf key_conf;\n+\tuint32_t input_set;\n+\tuint32_t flags;\n+\tuint32_t fd_id; /* APP marked unique value for this rule. */\n+\tuint8_t action;\n+\t/* VF id, avaiblable when flags with HNS3_RULE_FLAG_VF_ID. */\n+\tuint8_t vf_id;\n+\tuint16_t queue_id;\n+\tuint16_t location;\n+\tstruct rte_flow_action_count act_cnt;\n+};\n+\n+/* FDIR filter list structure */\n+struct hns3_fdir_rule_ele {\n+\tTAILQ_ENTRY(hns3_fdir_rule_ele) entries;\n+\tstruct hns3_fdir_rule fdir_conf;\n+};\n+/* rss filter list structure */\n+struct hns3_rss_conf_ele {\n+\tTAILQ_ENTRY(hns3_rss_conf_ele) entries;\n+\tstruct hns3_rss_conf filter_info;\n+};\n+/* hns3_flow memory list structure */\n+struct hns3_flow_mem {\n+\tTAILQ_ENTRY(hns3_flow_mem) entries;\n+\tstruct rte_flow *flow;\n+};\n+\n+TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);\n+TAILQ_HEAD(hns3_rss_filter_list, hns3_rss_conf_ele);\n+TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);\n+\n+struct hns3_process_private {\n+\tstruct hns3_fdir_rule_list fdir_list;\n+\tstruct hns3_rss_filter_list filter_rss_list;\n+\tstruct hns3_flow_mem_list flow_list;\n+};\n+\n+/*\n+ *  A structure used to define fields of a FDIR related info.\n+ */\n+struct hns3_fdir_info {\n+\trte_spinlock_t flows_lock;\n+\tstruct hns3_fdir_rule_list fdir_list;\n+\tstruct hns3_fdir_rule_ele **hash_map;\n+\tstruct rte_hash *hash_handle;\n+\tstruct hns3_fd_cfg fd_cfg;\n+};\n+\n+struct rte_flow {\n+\tenum rte_filter_type filter_type;\n+\tvoid *rule;\n+\tuint32_t counter_id;\n+};\n+struct hns3_adapter;\n+\n+int hns3_init_fd_config(struct hns3_adapter *hns);\n+int hns3_fdir_filter_init(struct hns3_adapter *hns);\n+void hns3_fdir_filter_uninit(struct hns3_adapter *hns);\n+int hns3_fdir_filter_program(struct hns3_adapter *hns,\n+\t\t\t     struct hns3_fdir_rule *rule, bool del);\n+int hns3_clear_all_fdir_filter(struct hns3_adapter *hns);\n+int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value);\n+void hns3_filterlist_init(struct rte_eth_dev *dev);\n+int hns3_restore_all_fdir_filter(struct hns3_adapter *hns);\n+\n+#endif /* _HNS3_FDIR_H_ */\ndiff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c\nnew file mode 100644\nindex 0000000..98ed818\n--- /dev/null\n+++ b/drivers/net/hns3/hns3_flow.c\n@@ -0,0 +1,1450 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2019 Hisilicon Limited.\n+ */\n+\n+#include <stdbool.h>\n+#include <sys/queue.h>\n+#include <rte_flow_driver.h>\n+#include <rte_io.h>\n+#include <rte_malloc.h>\n+\n+#include \"hns3_cmd.h\"\n+#include \"hns3_fdir.h\"\n+#include \"hns3_ethdev.h\"\n+#include \"hns3_logs.h\"\n+\n+/* Default default keys */\n+static uint8_t hns3_hash_key[] = {\n+\t0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,\n+\t0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,\n+\t0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,\n+\t0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,\n+\t0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA\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+/* Special Filter id for non-specific packet flagging. Don't change value */\n+#define HNS3_MAX_FILTER_ID\t0x0FFF\n+\n+#define ETHER_TYPE_MASK\t\t0xFFFF\n+#define IPPROTO_MASK\t\t0xFF\n+#define TUNNEL_TYPE_MASK\t0xFFFF\n+\n+#define HNS3_TUNNEL_TYPE_VXLAN\t\t0x12B5\n+#define HNS3_TUNNEL_TYPE_VXLAN_GPE\t0x12B6\n+#define HNS3_TUNNEL_TYPE_GENEVE\t\t0x17C1\n+#define HNS3_TUNNEL_TYPE_NVGRE\t\t0x6558\n+\n+static enum rte_flow_item_type first_items[] = {\n+\tRTE_FLOW_ITEM_TYPE_ETH,\n+\tRTE_FLOW_ITEM_TYPE_IPV4,\n+\tRTE_FLOW_ITEM_TYPE_IPV6,\n+\tRTE_FLOW_ITEM_TYPE_TCP,\n+\tRTE_FLOW_ITEM_TYPE_UDP,\n+\tRTE_FLOW_ITEM_TYPE_SCTP,\n+\tRTE_FLOW_ITEM_TYPE_ICMP,\n+\tRTE_FLOW_ITEM_TYPE_NVGRE,\n+\tRTE_FLOW_ITEM_TYPE_VXLAN,\n+\tRTE_FLOW_ITEM_TYPE_GENEVE,\n+\tRTE_FLOW_ITEM_TYPE_VXLAN_GPE,\n+\tRTE_FLOW_ITEM_TYPE_MPLS\n+};\n+\n+static enum rte_flow_item_type L2_next_items[] = {\n+\tRTE_FLOW_ITEM_TYPE_VLAN,\n+\tRTE_FLOW_ITEM_TYPE_IPV4,\n+\tRTE_FLOW_ITEM_TYPE_IPV6\n+};\n+\n+static enum rte_flow_item_type L3_next_items[] = {\n+\tRTE_FLOW_ITEM_TYPE_TCP,\n+\tRTE_FLOW_ITEM_TYPE_UDP,\n+\tRTE_FLOW_ITEM_TYPE_SCTP,\n+\tRTE_FLOW_ITEM_TYPE_NVGRE,\n+\tRTE_FLOW_ITEM_TYPE_ICMP\n+};\n+\n+static enum rte_flow_item_type L4_next_items[] = {\n+\tRTE_FLOW_ITEM_TYPE_VXLAN,\n+\tRTE_FLOW_ITEM_TYPE_GENEVE,\n+\tRTE_FLOW_ITEM_TYPE_VXLAN_GPE,\n+\tRTE_FLOW_ITEM_TYPE_MPLS\n+};\n+\n+static enum rte_flow_item_type tunnel_next_items[] = {\n+\tRTE_FLOW_ITEM_TYPE_ETH,\n+\tRTE_FLOW_ITEM_TYPE_VLAN\n+};\n+\n+struct items_step_mngr {\n+\tenum rte_flow_item_type *items;\n+\tint count;\n+};\n+\n+static inline void\n+net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; i < len; i++)\n+\t\tdst[i] = rte_be_to_cpu_32(src[i]);\n+}\n+\n+static inline const struct rte_flow_action *\n+find_rss_action(const struct rte_flow_action actions[])\n+{\n+\tconst struct rte_flow_action *next = &actions[0];\n+\n+\tfor (; next->type != RTE_FLOW_ACTION_TYPE_END; next++) {\n+\t\tif (next->type == RTE_FLOW_ACTION_TYPE_RSS)\n+\t\t\treturn next;\n+\t}\n+\treturn NULL;\n+}\n+\n+static inline struct hns3_flow_counter *\n+hns3_counter_lookup(struct rte_eth_dev *dev, uint32_t id)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_flow_counter *cnt;\n+\n+\tLIST_FOREACH(cnt, &pf->flow_counters, next) {\n+\t\tif (cnt->id == id)\n+\t\t\treturn cnt;\n+\t}\n+\treturn NULL;\n+}\n+\n+static int\n+hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,\n+\t\t struct rte_flow_error *error)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_flow_counter *cnt;\n+\n+\tcnt = hns3_counter_lookup(dev, id);\n+\tif (cnt) {\n+\t\tif (!cnt->shared || cnt->shared != shared)\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t  cnt,\n+\t\t\t\t\t\t  \"Counter id is used,shared flag not match\");\n+\t\tcnt->ref_cnt++;\n+\t\treturn 0;\n+\t}\n+\n+\tcnt = rte_zmalloc(\"hns3 counter\", sizeof(*cnt), 0);\n+\tif (cnt == NULL)\n+\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, cnt,\n+\t\t\t\t\t  \"Alloc mem for counter failed\");\n+\tcnt->id = id;\n+\tcnt->shared = shared;\n+\tcnt->ref_cnt = 1;\n+\tcnt->hits = 0;\n+\tLIST_INSERT_HEAD(&pf->flow_counters, cnt, next);\n+\treturn 0;\n+}\n+\n+static int\n+hns3_counter_query(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t\t   struct rte_flow_query_count *qc,\n+\t\t   struct rte_flow_error *error)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_flow_counter *cnt;\n+\tuint64_t value;\n+\tint ret;\n+\n+\t/* FDIR is available only in PF driver */\n+\tif (hns->is_vf)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t\t  \"Fdir is not supported in VF\");\n+\tcnt = hns3_counter_lookup(dev, flow->counter_id);\n+\tif (cnt == NULL)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"Can't find counter id\");\n+\n+\tret = hns3_get_count(&hns->hw, flow->counter_id, &value);\n+\tif (ret) {\n+\t\trte_flow_error_set(error, -ret,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL, \"Read counter fail.\");\n+\t\treturn ret;\n+\t}\n+\tqc->hits_set = 1;\n+\tqc->hits = value;\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_counter_release(struct rte_eth_dev *dev, uint32_t id)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_flow_counter *cnt;\n+\n+\tcnt = hns3_counter_lookup(dev, id);\n+\tif (cnt == NULL) {\n+\t\thns3_err(hw, \"Can't find available counter to release\");\n+\t\treturn -EINVAL;\n+\t}\n+\tcnt->ref_cnt--;\n+\tif (cnt->ref_cnt == 0) {\n+\t\tLIST_REMOVE(cnt, next);\n+\t\trte_free(cnt);\n+\t}\n+\treturn 0;\n+}\n+\n+static void\n+hns3_counter_flush(struct rte_eth_dev *dev)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tstruct hns3_flow_counter *cnt_ptr;\n+\n+\tcnt_ptr = LIST_FIRST(&pf->flow_counters);\n+\twhile (cnt_ptr) {\n+\t\tLIST_REMOVE(cnt_ptr, next);\n+\t\trte_free(cnt_ptr);\n+\t\tcnt_ptr = LIST_FIRST(&pf->flow_counters);\n+\t}\n+}\n+\n+static int\n+hns3_handle_action_queue(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_action *action,\n+\t\t\t struct hns3_fdir_rule *rule,\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_queue *queue;\n+\n+\tqueue = (const struct rte_flow_action_queue *)action->conf;\n+\tif (queue->index >= hw->data->nb_rx_queues)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n+\t\t\t\t\t  \"Invalid queue ID in PF\");\n+\trule->queue_id = queue->index;\n+\trule->action = HNS3_FD_ACTION_ACCEPT_PACKET;\n+\treturn 0;\n+}\n+\n+/*\n+ * Parse actions structure from the provided pattern.\n+ * The pattern is validated as the items are copied.\n+ *\n+ * @param actions[in]\n+ * @param rule[out]\n+ *   NIC specfilc actions derived from the actions.\n+ * @param error[out]\n+ */\n+static int\n+hns3_handle_actions(struct rte_eth_dev *dev,\n+\t\t    const struct rte_flow_action actions[],\n+\t\t    struct hns3_fdir_rule *rule, struct rte_flow_error *error)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tconst struct rte_flow_action_count *act_count;\n+\tconst struct rte_flow_action_mark *mark;\n+\tstruct hns3_pf *pf = &hns->pf;\n+\tuint32_t counter_num;\n+\tint ret;\n+\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_QUEUE:\n+\t\t\tret = hns3_handle_action_queue(dev, actions, rule,\n+\t\t\t\t\t\t       error);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n+\t\t\trule->action = HNS3_FD_ACTION_DROP_PACKET;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n+\t\t\tmark =\n+\t\t\t    (const struct rte_flow_action_mark *)actions->conf;\n+\t\t\tif (mark->id >= HNS3_MAX_FILTER_ID)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t     RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t     actions,\n+\t\t\t\t\t\t     \"Invalid Mark ID\");\n+\t\t\trule->fd_id = mark->id;\n+\t\t\trule->flags |= HNS3_RULE_FLAG_FDID;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_FLAG:\n+\t\t\trule->fd_id = HNS3_MAX_FILTER_ID;\n+\t\t\trule->flags |= HNS3_RULE_FLAG_FDID;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t\tact_count =\n+\t\t\t    (const struct rte_flow_action_count *)actions->conf;\n+\t\t\tcounter_num = pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1];\n+\t\t\tif (act_count->id >= counter_num)\n+\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t     RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t     actions,\n+\t\t\t\t\t\t     \"Invalid counter id\");\n+\t\t\trule->act_cnt = *act_count;\n+\t\t\trule->flags |= HNS3_RULE_FLAG_COUNTER;\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t  NULL, \"Unsupported action\");\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* Parse to get the attr and action info of flow director rule. */\n+static int\n+hns3_check_attr(const struct rte_flow_attr *attr, struct rte_flow_error *error)\n+{\n+\tif (!attr->ingress)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,\n+\t\t\t\t\t  attr, \"Ingress can't be zero\");\n+\tif (attr->egress)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,\n+\t\t\t\t\t  attr, \"Not support egress\");\n+\tif (attr->transfer)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,\n+\t\t\t\t\t  attr, \"No support for transfer\");\n+\tif (attr->priority)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,\n+\t\t\t\t\t  attr, \"Not support priority\");\n+\tif (attr->group)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_GROUP,\n+\t\t\t\t\t  attr, \"Not support group\");\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_eth(const struct rte_flow_item *item,\n+\t\t   struct hns3_fdir_rule *rule, struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_eth *eth_spec;\n+\tconst struct rte_flow_item_eth *eth_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\teth_mask = item->mask;\n+\t\tif (eth_mask->type) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_ETH_TYPE, 1);\n+\t\t\trule->key_conf.mask.ether_type =\n+\t\t\t    rte_be_to_cpu_16(eth_mask->type);\n+\t\t}\n+\t\tif (!rte_is_zero_ether_addr(&eth_mask->src)) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_MAC, 1);\n+\t\t\tmemcpy(rule->key_conf.mask.src_mac,\n+\t\t\t       eth_mask->src.addr_bytes, RTE_ETHER_ADDR_LEN);\n+\t\t}\n+\t\tif (!rte_is_zero_ether_addr(&eth_mask->dst)) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_MAC, 1);\n+\t\t\tmemcpy(rule->key_conf.mask.dst_mac,\n+\t\t\t       eth_mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN);\n+\t\t}\n+\t}\n+\n+\teth_spec = item->spec;\n+\trule->key_conf.spec.ether_type = rte_be_to_cpu_16(eth_spec->type);\n+\tmemcpy(rule->key_conf.spec.src_mac, eth_spec->src.addr_bytes,\n+\t       RTE_ETHER_ADDR_LEN);\n+\tmemcpy(rule->key_conf.spec.dst_mac, eth_spec->dst.addr_bytes,\n+\t       RTE_ETHER_ADDR_LEN);\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_vlan(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_vlan *vlan_spec;\n+\tconst struct rte_flow_item_vlan *vlan_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\trule->key_conf.vlan_num++;\n+\tif (rule->key_conf.vlan_num > VLAN_TAG_NUM_MAX)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Vlan_num is more than 2\");\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\tvlan_mask = item->mask;\n+\t\tif (vlan_mask->tci) {\n+\t\t\tif (rule->key_conf.vlan_num == 1) {\n+\t\t\t\thns3_set_bit(rule->input_set, INNER_VLAN_TAG1,\n+\t\t\t\t\t     1);\n+\t\t\t\trule->key_conf.mask.vlan_tag1 =\n+\t\t\t\t    rte_be_to_cpu_16(vlan_mask->tci);\n+\t\t\t} else {\n+\t\t\t\thns3_set_bit(rule->input_set, INNER_VLAN_TAG2,\n+\t\t\t\t\t     1);\n+\t\t\t\trule->key_conf.mask.vlan_tag2 =\n+\t\t\t\t    rte_be_to_cpu_16(vlan_mask->tci);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tvlan_spec = item->spec;\n+\tif (rule->key_conf.vlan_num == 1)\n+\t\trule->key_conf.spec.vlan_tag1 =\n+\t\t    rte_be_to_cpu_16(vlan_spec->tci);\n+\telse\n+\t\trule->key_conf.spec.vlan_tag2 =\n+\t\t    rte_be_to_cpu_16(vlan_spec->tci);\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_ipv4(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_ipv4 *ipv4_spec;\n+\tconst struct rte_flow_item_ipv4 *ipv4_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\thns3_set_bit(rule->input_set, INNER_ETH_TYPE, 1);\n+\trule->key_conf.spec.ether_type = RTE_ETHER_TYPE_IPV4;\n+\trule->key_conf.mask.ether_type = ETHER_TYPE_MASK;\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\tipv4_mask = item->mask;\n+\n+\t\tif (ipv4_mask->hdr.total_length ||\n+\t\t    ipv4_mask->hdr.packet_id ||\n+\t\t    ipv4_mask->hdr.fragment_offset ||\n+\t\t    ipv4_mask->hdr.time_to_live ||\n+\t\t    ipv4_mask->hdr.hdr_checksum) {\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  item,\n+\t\t\t\t\t\t  \"Only support src & dst ip,tos,proto in IPV4\");\n+\t\t}\n+\n+\t\tif (ipv4_mask->hdr.src_addr) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_IP, 1);\n+\t\t\trule->key_conf.mask.src_ip[IP_ADDR_KEY_ID] =\n+\t\t\t    rte_be_to_cpu_32(ipv4_mask->hdr.src_addr);\n+\t\t}\n+\n+\t\tif (ipv4_mask->hdr.dst_addr) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_IP, 1);\n+\t\t\trule->key_conf.mask.dst_ip[IP_ADDR_KEY_ID] =\n+\t\t\t    rte_be_to_cpu_32(ipv4_mask->hdr.dst_addr);\n+\t\t}\n+\n+\t\tif (ipv4_mask->hdr.type_of_service) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_IP_TOS, 1);\n+\t\t\trule->key_conf.mask.ip_tos =\n+\t\t\t    ipv4_mask->hdr.type_of_service;\n+\t\t}\n+\n+\t\tif (ipv4_mask->hdr.next_proto_id) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 1);\n+\t\t\trule->key_conf.mask.ip_proto =\n+\t\t\t    ipv4_mask->hdr.next_proto_id;\n+\t\t}\n+\t}\n+\n+\tipv4_spec = item->spec;\n+\trule->key_conf.spec.src_ip[IP_ADDR_KEY_ID] =\n+\t    rte_be_to_cpu_32(ipv4_spec->hdr.src_addr);\n+\trule->key_conf.spec.dst_ip[IP_ADDR_KEY_ID] =\n+\t    rte_be_to_cpu_32(ipv4_spec->hdr.dst_addr);\n+\trule->key_conf.spec.ip_tos = ipv4_spec->hdr.type_of_service;\n+\trule->key_conf.spec.ip_proto = ipv4_spec->hdr.next_proto_id;\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_ipv6 *ipv6_spec;\n+\tconst struct rte_flow_item_ipv6 *ipv6_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\thns3_set_bit(rule->input_set, INNER_ETH_TYPE, 1);\n+\trule->key_conf.spec.ether_type = RTE_ETHER_TYPE_IPV6;\n+\trule->key_conf.mask.ether_type = ETHER_TYPE_MASK;\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\tipv6_mask = item->mask;\n+\t\tif (ipv6_mask->hdr.vtc_flow ||\n+\t\t    ipv6_mask->hdr.payload_len || ipv6_mask->hdr.hop_limits) {\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  item,\n+\t\t\t\t\t\t  \"Only support src & dst ip,proto in IPV6\");\n+\t\t}\n+\t\tnet_addr_to_host(rule->key_conf.mask.src_ip,\n+\t\t\t\t (const rte_be32_t *)ipv6_mask->hdr.src_addr,\n+\t\t\t\t IP_ADDR_LEN);\n+\t\tnet_addr_to_host(rule->key_conf.mask.dst_ip,\n+\t\t\t\t (const rte_be32_t *)ipv6_mask->hdr.dst_addr,\n+\t\t\t\t IP_ADDR_LEN);\n+\t\trule->key_conf.mask.ip_proto = ipv6_mask->hdr.proto;\n+\t\tif (rule->key_conf.mask.src_ip[IP_ADDR_KEY_ID])\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_IP, 1);\n+\t\tif (rule->key_conf.mask.dst_ip[IP_ADDR_KEY_ID])\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_IP, 1);\n+\t\tif (ipv6_mask->hdr.proto)\n+\t\t\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 1);\n+\t}\n+\n+\tipv6_spec = item->spec;\n+\tnet_addr_to_host(rule->key_conf.spec.src_ip,\n+\t\t\t (const rte_be32_t *)ipv6_spec->hdr.src_addr,\n+\t\t\t IP_ADDR_LEN);\n+\tnet_addr_to_host(rule->key_conf.spec.dst_ip,\n+\t\t\t (const rte_be32_t *)ipv6_spec->hdr.dst_addr,\n+\t\t\t IP_ADDR_LEN);\n+\trule->key_conf.spec.ip_proto = ipv6_spec->hdr.proto;\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_tcp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t       struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_tcp *tcp_spec;\n+\tconst struct rte_flow_item_tcp *tcp_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 1);\n+\trule->key_conf.spec.ip_proto = IPPROTO_TCP;\n+\trule->key_conf.mask.ip_proto = IPPROTO_MASK;\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\ttcp_mask = item->mask;\n+\t\tif (tcp_mask->hdr.sent_seq ||\n+\t\t    tcp_mask->hdr.recv_ack ||\n+\t\t    tcp_mask->hdr.data_off ||\n+\t\t    tcp_mask->hdr.tcp_flags ||\n+\t\t    tcp_mask->hdr.rx_win ||\n+\t\t    tcp_mask->hdr.cksum || tcp_mask->hdr.tcp_urp) {\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  item,\n+\t\t\t\t\t\t  \"Only support src & dst port in TCP\");\n+\t\t}\n+\n+\t\tif (tcp_mask->hdr.src_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_PORT, 1);\n+\t\t\trule->key_conf.mask.src_port =\n+\t\t\t    rte_be_to_cpu_16(tcp_mask->hdr.src_port);\n+\t\t}\n+\t\tif (tcp_mask->hdr.dst_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_PORT, 1);\n+\t\t\trule->key_conf.mask.dst_port =\n+\t\t\t    rte_be_to_cpu_16(tcp_mask->hdr.dst_port);\n+\t\t}\n+\t}\n+\n+\ttcp_spec = item->spec;\n+\trule->key_conf.spec.src_port = rte_be_to_cpu_16(tcp_spec->hdr.src_port);\n+\trule->key_conf.spec.dst_port = rte_be_to_cpu_16(tcp_spec->hdr.dst_port);\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_udp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t       struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_udp *udp_spec;\n+\tconst struct rte_flow_item_udp *udp_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 1);\n+\trule->key_conf.spec.ip_proto = IPPROTO_UDP;\n+\trule->key_conf.mask.ip_proto = IPPROTO_MASK;\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\tudp_mask = item->mask;\n+\t\tif (udp_mask->hdr.dgram_len || udp_mask->hdr.dgram_cksum) {\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  item,\n+\t\t\t\t\t\t  \"Only support src & dst port in UDP\");\n+\t\t}\n+\t\tif (udp_mask->hdr.src_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_PORT, 1);\n+\t\t\trule->key_conf.mask.src_port =\n+\t\t\t    rte_be_to_cpu_16(udp_mask->hdr.src_port);\n+\t\t}\n+\t\tif (udp_mask->hdr.dst_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_PORT, 1);\n+\t\t\trule->key_conf.mask.dst_port =\n+\t\t\t    rte_be_to_cpu_16(udp_mask->hdr.dst_port);\n+\t\t}\n+\t}\n+\n+\tudp_spec = item->spec;\n+\trule->key_conf.spec.src_port = rte_be_to_cpu_16(udp_spec->hdr.src_port);\n+\trule->key_conf.spec.dst_port = rte_be_to_cpu_16(udp_spec->hdr.dst_port);\n+\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_sctp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_sctp *sctp_spec;\n+\tconst struct rte_flow_item_sctp *sctp_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\n+\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 1);\n+\trule->key_conf.spec.ip_proto = IPPROTO_SCTP;\n+\trule->key_conf.mask.ip_proto = IPPROTO_MASK;\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tif (item->mask) {\n+\t\tsctp_mask = item->mask;\n+\t\tif (sctp_mask->hdr.cksum)\n+\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  item,\n+\t\t\t\t\t\t  \"Only support src & dst port in SCTP\");\n+\n+\t\tif (sctp_mask->hdr.src_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SRC_PORT, 1);\n+\t\t\trule->key_conf.mask.src_port =\n+\t\t\t    rte_be_to_cpu_16(sctp_mask->hdr.src_port);\n+\t\t}\n+\t\tif (sctp_mask->hdr.dst_port) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_DST_PORT, 1);\n+\t\t\trule->key_conf.mask.dst_port =\n+\t\t\t    rte_be_to_cpu_16(sctp_mask->hdr.dst_port);\n+\t\t}\n+\t\tif (sctp_mask->hdr.tag) {\n+\t\t\thns3_set_bit(rule->input_set, INNER_SCTP_TAG, 1);\n+\t\t\trule->key_conf.mask.sctp_tag =\n+\t\t\t    rte_be_to_cpu_32(sctp_mask->hdr.tag);\n+\t\t}\n+\t}\n+\n+\tsctp_spec = item->spec;\n+\trule->key_conf.spec.src_port =\n+\t    rte_be_to_cpu_16(sctp_spec->hdr.src_port);\n+\trule->key_conf.spec.dst_port =\n+\t    rte_be_to_cpu_16(sctp_spec->hdr.dst_port);\n+\trule->key_conf.spec.sctp_tag = rte_be_to_cpu_32(sctp_spec->hdr.tag);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Check items before tunnel, save inner configs to outer configs,and clear\n+ * inner configs.\n+ * The key consists of two parts: meta_data and tuple keys.\n+ * Meta data uses 15 bits, including vlan_num(2bit), des_port(12bit) and tunnel\n+ * packet(1bit).\n+ * Tuple keys uses 384bit, including ot_dst-mac(48bit), ot_dst-port(16bit),\n+ * ot_tun_vni(24bit), ot_flow_id(8bit), src-mac(48bit), dst-mac(48bit),\n+ * src-ip(32/128bit), dst-ip(32/128bit), src-port(16bit), dst-port(16bit),\n+ * tos(8bit), ether-proto(16bit), ip-proto(8bit), vlantag1(16bit),\n+ * Vlantag2(16bit) and sctp-tag(32bit).\n+ */\n+static int\n+hns3_handle_tunnel(const struct rte_flow_item *item,\n+\t\t   struct hns3_fdir_rule *rule, struct rte_flow_error *error)\n+{\n+\t/* check eth config */\n+\tif (rule->input_set & (BIT(INNER_SRC_MAC) | BIT(INNER_DST_MAC)))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t  item, \"Outer eth mac is unsupported\");\n+\tif (rule->input_set & BIT(INNER_ETH_TYPE)) {\n+\t\thns3_set_bit(rule->input_set, OUTER_ETH_TYPE, 1);\n+\t\trule->key_conf.spec.outer_ether_type =\n+\t\t    rule->key_conf.spec.ether_type;\n+\t\trule->key_conf.mask.outer_ether_type =\n+\t\t    rule->key_conf.mask.ether_type;\n+\t\thns3_set_bit(rule->input_set, INNER_ETH_TYPE, 0);\n+\t\trule->key_conf.spec.ether_type = 0;\n+\t\trule->key_conf.mask.ether_type = 0;\n+\t}\n+\n+\t/* check vlan config */\n+\tif (rule->input_set & (BIT(INNER_VLAN_TAG1) | BIT(INNER_VLAN_TAG2)))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t  item,\n+\t\t\t\t\t  \"Outer vlan tags is unsupported\");\n+\n+\t/* clear vlan_num for inner vlan select */\n+\trule->key_conf.outer_vlan_num = rule->key_conf.vlan_num;\n+\trule->key_conf.vlan_num = 0;\n+\n+\t/* check L3 config */\n+\tif (rule->input_set &\n+\t    (BIT(INNER_SRC_IP) | BIT(INNER_DST_IP) | BIT(INNER_IP_TOS)))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t  item, \"Outer ip is unsupported\");\n+\tif (rule->input_set & BIT(INNER_IP_PROTO)) {\n+\t\thns3_set_bit(rule->input_set, OUTER_IP_PROTO, 1);\n+\t\trule->key_conf.spec.outer_proto = rule->key_conf.spec.ip_proto;\n+\t\trule->key_conf.mask.outer_proto = rule->key_conf.mask.ip_proto;\n+\t\thns3_set_bit(rule->input_set, INNER_IP_PROTO, 0);\n+\t\trule->key_conf.spec.ip_proto = 0;\n+\t\trule->key_conf.mask.ip_proto = 0;\n+\t}\n+\n+\t/* check L4 config */\n+\tif (rule->input_set & BIT(INNER_SCTP_TAG))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Outer sctp tag is unsupported\");\n+\n+\tif (rule->input_set & BIT(INNER_SRC_PORT)) {\n+\t\thns3_set_bit(rule->input_set, OUTER_SRC_PORT, 1);\n+\t\trule->key_conf.spec.outer_src_port =\n+\t\t    rule->key_conf.spec.src_port;\n+\t\trule->key_conf.mask.outer_src_port =\n+\t\t    rule->key_conf.mask.src_port;\n+\t\thns3_set_bit(rule->input_set, INNER_SRC_PORT, 0);\n+\t\trule->key_conf.spec.src_port = 0;\n+\t\trule->key_conf.mask.src_port = 0;\n+\t}\n+\tif (rule->input_set & BIT(INNER_DST_PORT)) {\n+\t\thns3_set_bit(rule->input_set, INNER_DST_PORT, 0);\n+\t\trule->key_conf.spec.dst_port = 0;\n+\t\trule->key_conf.mask.dst_port = 0;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_vxlan(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\t struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_vxlan *vxlan_spec;\n+\tconst struct rte_flow_item_vxlan *vxlan_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\telse if (item->spec && (item->mask == NULL))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Tunnel packets must configure with mask\");\n+\n+\thns3_set_bit(rule->input_set, OUTER_DST_PORT, 1);\n+\trule->key_conf.mask.tunnel_type = TUNNEL_TYPE_MASK;\n+\tif (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)\n+\t\trule->key_conf.spec.tunnel_type = HNS3_TUNNEL_TYPE_VXLAN;\n+\telse\n+\t\trule->key_conf.spec.tunnel_type = HNS3_TUNNEL_TYPE_VXLAN_GPE;\n+\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tvxlan_mask = item->mask;\n+\tvxlan_spec = item->spec;\n+\n+\tif (vxlan_mask->flags)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Flags is not supported in VxLAN\");\n+\n+\t/* VNI must be totally masked or not. */\n+\tif (memcmp(vxlan_mask->vni, full_mask, VNI_OR_TNI_LEN) &&\n+\t    memcmp(vxlan_mask->vni, zero_mask, VNI_OR_TNI_LEN))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"VNI must be totally masked or not in VxLAN\");\n+\tif (vxlan_mask->vni[0]) {\n+\t\thns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);\n+\t\tmemcpy(rule->key_conf.mask.outer_tun_vni, vxlan_mask->vni,\n+\t\t\t   VNI_OR_TNI_LEN);\n+\t}\n+\tmemcpy(rule->key_conf.spec.outer_tun_vni, vxlan_spec->vni,\n+\t\t   VNI_OR_TNI_LEN);\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_nvgre(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\t struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_nvgre *nvgre_spec;\n+\tconst struct rte_flow_item_nvgre *nvgre_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\telse if (item->spec && (item->mask == NULL))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Tunnel packets must configure with mask\");\n+\n+\thns3_set_bit(rule->input_set, OUTER_IP_PROTO, 1);\n+\trule->key_conf.spec.outer_proto = IPPROTO_GRE;\n+\trule->key_conf.mask.outer_proto = IPPROTO_MASK;\n+\n+\thns3_set_bit(rule->input_set, OUTER_DST_PORT, 1);\n+\trule->key_conf.spec.tunnel_type = HNS3_TUNNEL_TYPE_NVGRE;\n+\trule->key_conf.mask.tunnel_type = ~HNS3_TUNNEL_TYPE_NVGRE;\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tnvgre_mask = item->mask;\n+\tnvgre_spec = item->spec;\n+\n+\tif (nvgre_mask->protocol || nvgre_mask->c_k_s_rsvd0_ver)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Ver/protocal is not supported in NVGRE\");\n+\n+\t/* TNI must be totally masked or not. */\n+\tif (memcmp(nvgre_mask->tni, full_mask, VNI_OR_TNI_LEN) &&\n+\t    memcmp(nvgre_mask->tni, zero_mask, VNI_OR_TNI_LEN))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"TNI must be totally masked or not in NVGRE\");\n+\n+\tif (nvgre_mask->tni[0]) {\n+\t\thns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);\n+\t\tmemcpy(rule->key_conf.mask.outer_tun_vni, nvgre_mask->tni,\n+\t\t\t   VNI_OR_TNI_LEN);\n+\t}\n+\tmemcpy(rule->key_conf.spec.outer_tun_vni, nvgre_spec->tni,\n+\t\t   VNI_OR_TNI_LEN);\n+\n+\tif (nvgre_mask->flow_id) {\n+\t\thns3_set_bit(rule->input_set, OUTER_TUN_FLOW_ID, 1);\n+\t\trule->key_conf.mask.outer_tun_flow_id = nvgre_mask->flow_id;\n+\t}\n+\trule->key_conf.spec.outer_tun_flow_id = nvgre_spec->flow_id;\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_geneve(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_item_geneve *geneve_spec;\n+\tconst struct rte_flow_item_geneve *geneve_mask;\n+\n+\tif (item->spec == NULL && item->mask)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Can't configure FDIR with mask but without spec\");\n+\telse if (item->spec && (item->mask == NULL))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Tunnel packets must configure with mask\");\n+\n+\thns3_set_bit(rule->input_set, OUTER_DST_PORT, 1);\n+\trule->key_conf.spec.tunnel_type = HNS3_TUNNEL_TYPE_GENEVE;\n+\trule->key_conf.mask.tunnel_type = TUNNEL_TYPE_MASK;\n+\t/* Only used to describe the protocol stack. */\n+\tif (item->spec == NULL && item->mask == NULL)\n+\t\treturn 0;\n+\n+\tgeneve_mask = item->mask;\n+\tgeneve_spec = item->spec;\n+\n+\tif (geneve_mask->ver_opt_len_o_c_rsvd0 || geneve_mask->protocol)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"Ver/protocal is not supported in GENEVE\");\n+\t/* VNI must be totally masked or not. */\n+\tif (memcmp(geneve_mask->vni, full_mask, VNI_OR_TNI_LEN) &&\n+\t    memcmp(geneve_mask->vni, zero_mask, VNI_OR_TNI_LEN))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n+\t\t\t\t\t  \"VNI must be totally masked or not in GENEVE\");\n+\tif (geneve_mask->vni[0]) {\n+\t\thns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);\n+\t\tmemcpy(rule->key_conf.mask.outer_tun_vni, geneve_mask->vni,\n+\t\t\t   VNI_OR_TNI_LEN);\n+\t}\n+\tmemcpy(rule->key_conf.spec.outer_tun_vni, geneve_spec->vni,\n+\t\t   VNI_OR_TNI_LEN);\n+\treturn 0;\n+}\n+\n+static int\n+hns3_parse_tunnel(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tswitch (item->type) {\n+\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n+\tcase RTE_FLOW_ITEM_TYPE_VXLAN_GPE:\n+\t\tret = hns3_parse_vxlan(item, rule, error);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_NVGRE:\n+\t\tret = hns3_parse_nvgre(item, rule, error);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_GENEVE:\n+\t\tret = hns3_parse_geneve(item, rule, error);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t\t  NULL, \"Unsupported tunnel type!\");\n+\t}\n+\tif (ret)\n+\t\treturn ret;\n+\treturn hns3_handle_tunnel(item, rule, error);\n+}\n+\n+static int\n+hns3_parse_normal(const struct rte_flow_item *item,\n+\t\t  struct hns3_fdir_rule *rule,\n+\t\t  struct items_step_mngr *step_mngr,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tswitch (item->type) {\n+\tcase RTE_FLOW_ITEM_TYPE_ETH:\n+\t\tret = hns3_parse_eth(item, rule, error);\n+\t\tstep_mngr->items = L2_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L2_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n+\t\tret = hns3_parse_vlan(item, rule, error);\n+\t\tstep_mngr->items = L2_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L2_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n+\t\tret = hns3_parse_ipv4(item, rule, error);\n+\t\tstep_mngr->items = L3_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L3_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n+\t\tret = hns3_parse_ipv6(item, rule, error);\n+\t\tstep_mngr->items = L3_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L3_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_TCP:\n+\t\tret = hns3_parse_tcp(item, rule, error);\n+\t\tstep_mngr->items = L4_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L4_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_UDP:\n+\t\tret = hns3_parse_udp(item, rule, error);\n+\t\tstep_mngr->items = L4_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L4_next_items);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_SCTP:\n+\t\tret = hns3_parse_sctp(item, rule, error);\n+\t\tstep_mngr->items = L4_next_items;\n+\t\tstep_mngr->count = ARRAY_SIZE(L4_next_items);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t\t  NULL, \"Unsupported normal type!\");\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+hns3_validate_item(const struct rte_flow_item *item,\n+\t\t   struct items_step_mngr step_mngr,\n+\t\t   struct rte_flow_error *error)\n+{\n+\tint i;\n+\n+\tif (item->last)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item,\n+\t\t\t\t\t  \"Not supported last point for range\");\n+\n+\tfor (i = 0; i < step_mngr.count; i++) {\n+\t\tif (item->type == step_mngr.items[i])\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i == step_mngr.count) {\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t  item, \"Inval or missing item\");\n+\t}\n+\treturn 0;\n+}\n+\n+static inline bool\n+is_tunnel_packet(enum rte_flow_item_type type)\n+{\n+\tif (type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE ||\n+\t    type == RTE_FLOW_ITEM_TYPE_VXLAN ||\n+\t    type == RTE_FLOW_ITEM_TYPE_NVGRE ||\n+\t    type == RTE_FLOW_ITEM_TYPE_GENEVE ||\n+\t    type == RTE_FLOW_ITEM_TYPE_MPLS)\n+\t\treturn true;\n+\treturn false;\n+}\n+\n+/*\n+ * Parse the rule to see if it is a IP or MAC VLAN flow director rule.\n+ * And get the flow director filter info BTW.\n+ * UDP/TCP/SCTP PATTERN:\n+ * The first not void item can be ETH or IPV4 or IPV6\n+ * The second not void item must be IPV4 or IPV6 if the first one is ETH.\n+ * The next not void item could be UDP or TCP or SCTP (optional)\n+ * The next not void item could be RAW (for flexbyte, optional)\n+ * The next not void item must be END.\n+ * A Fuzzy Match pattern can appear at any place before END.\n+ * Fuzzy Match is optional for IPV4 but is required for IPV6\n+ * MAC VLAN PATTERN:\n+ * The first not void item must be ETH.\n+ * The second not void item must be MAC VLAN.\n+ * The next not void item must be END.\n+ * ACTION:\n+ * The first not void action should be QUEUE or DROP.\n+ * The second not void optional action should be MARK,\n+ * mark_id is a uint32_t number.\n+ * The next not void action should be END.\n+ * UDP/TCP/SCTP pattern example:\n+ * ITEM\t\tSpec\t\t\tMask\n+ * ETH\t\tNULL\t\t\tNULL\n+ * IPV4\t\tsrc_addr 192.168.1.20\t0xFFFFFFFF\n+ *\t\tdst_addr 192.167.3.50\t0xFFFFFFFF\n+ * UDP/TCP/SCTP\tsrc_port\t80\t0xFFFF\n+ *\t\tdst_port\t80\t0xFFFF\n+ * END\n+ * MAC VLAN pattern example:\n+ * ITEM\t\tSpec\t\t\tMask\n+ * ETH\t\tdst_addr\n+\t\t{0xAC, 0x7B, 0xA1,\t{0xFF, 0xFF, 0xFF,\n+\t\t0x2C, 0x6D, 0x36}\t0xFF, 0xFF, 0xFF}\n+ * MAC VLAN\ttci\t0x2016\t\t0xEFFF\n+ * END\n+ * Other members in mask and spec should set to 0x00.\n+ * Item->last should be NULL.\n+ */\n+static int\n+hns3_parse_fdir_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_fdir_rule *rule,\n+\t\t       struct rte_flow_error *error)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tconst struct rte_flow_item *item;\n+\tstruct items_step_mngr step_mngr;\n+\tint ret;\n+\n+\t/* FDIR is available only in PF driver */\n+\tif (hns->is_vf)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t\t  \"Fdir not supported in VF\");\n+\n+\tif (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,\n+\t\t\t\t\t  \"fdir_conf.mode isn't perfect\");\n+\n+\tstep_mngr.items = first_items;\n+\tstep_mngr.count = ARRAY_SIZE(first_items);\n+\tfor (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {\n+\t\tif (item->type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\t\tcontinue;\n+\n+\t\tret = hns3_validate_item(item, step_mngr, error);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif (is_tunnel_packet(item->type)) {\n+\t\t\tret = hns3_parse_tunnel(item, rule, error);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tstep_mngr.items = tunnel_next_items;\n+\t\t\tstep_mngr.count = ARRAY_SIZE(tunnel_next_items);\n+\t\t} else {\n+\t\t\tret = hns3_parse_normal(item, rule, &step_mngr, error);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn hns3_handle_actions(dev, actions, rule, error);\n+}\n+\n+void\n+hns3_filterlist_init(struct rte_eth_dev *dev)\n+{\n+\tstruct hns3_process_private *process_list = dev->process_private;\n+\n+\tTAILQ_INIT(&process_list->fdir_list);\n+\tTAILQ_INIT(&process_list->filter_rss_list);\n+\tTAILQ_INIT(&process_list->flow_list);\n+}\n+\n+static void\n+hns3_filterlist_flush(struct rte_eth_dev *dev)\n+{\n+\tstruct hns3_process_private *process_list = dev->process_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(&process_list->fdir_list);\n+\twhile (fdir_rule_ptr) {\n+\t\tTAILQ_REMOVE(&process_list->fdir_list, fdir_rule_ptr, entries);\n+\t\trte_free(fdir_rule_ptr);\n+\t\tfdir_rule_ptr = TAILQ_FIRST(&process_list->fdir_list);\n+\t}\n+\n+\trss_filter_ptr = TAILQ_FIRST(&process_list->filter_rss_list);\n+\twhile (rss_filter_ptr) {\n+\t\tTAILQ_REMOVE(&process_list->filter_rss_list, rss_filter_ptr,\n+\t\t\t     entries);\n+\t\trte_free(rss_filter_ptr);\n+\t\trss_filter_ptr = TAILQ_FIRST(&process_list->filter_rss_list);\n+\t}\n+\n+\tflow_node = TAILQ_FIRST(&process_list->flow_list);\n+\twhile (flow_node) {\n+\t\tTAILQ_REMOVE(&process_list->flow_list, flow_node, entries);\n+\t\trte_free(flow_node->flow);\n+\t\trte_free(flow_node);\n+\t\tflow_node = TAILQ_FIRST(&process_list->flow_list);\n+\t}\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+\t\t     const struct rte_flow_action actions[],\n+\t\t     struct rte_flow_error *error)\n+{\n+\tif (pattern == NULL)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_NUM,\n+\t\t\t\t\t  NULL, \"NULL pattern.\");\n+\n+\tif (actions == NULL)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_NUM,\n+\t\t\t\t\t  NULL, \"NULL action.\");\n+\n+\tif (attr == NULL)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR,\n+\t\t\t\t\t  NULL, \"NULL attribute.\");\n+\n+\treturn hns3_check_attr(attr, error);\n+}\n+\n+/*\n+ * Check if the flow rule is supported by hns3.\n+ * It only checkes the format. Don't guarantee the rule can be programmed into\n+ * the HW. Because there can be no enough room for the rule.\n+ */\n+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+{\n+\tstruct hns3_rss_conf rss_conf;\n+\tstruct hns3_fdir_rule fdir_rule;\n+\tint ret;\n+\n+\tret = hns3_flow_args_check(attr, pattern, actions, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmemset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule));\n+\treturn hns3_parse_fdir_filter(dev, pattern, actions, &fdir_rule, error);\n+}\n+\n+/*\n+ * Create or destroy a flow rule.\n+ * Theorically one rule can match more than one filters.\n+ * We will let it use the filter which it hitt first.\n+ * So, the sequence matters.\n+ */\n+static struct rte_flow *\n+hns3_flow_create(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+{\n+\tstruct hns3_process_private *process_list = dev->process_private;\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tstruct hns3_fdir_rule_ele *fdir_rule_ptr;\n+\tstruct hns3_flow_mem *flow_node;\n+\tstruct rte_flow *flow;\n+\tstruct hns3_fdir_rule fdir_rule;\n+\tint ret;\n+\n+\tret = hns3_flow_args_check(attr, pattern, actions, error);\n+\tif (ret)\n+\t\treturn NULL;\n+\n+\tflow = rte_zmalloc(\"hns3 flow\", sizeof(struct rte_flow), 0);\n+\tif (flow == NULL) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t   \"Failed to allocate flow memory\");\n+\t\treturn NULL;\n+\t}\n+\tflow_node = rte_zmalloc(\"hns3 flow node\",\n+\t\t\t\tsizeof(struct hns3_flow_mem), 0);\n+\tif (flow_node == NULL) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t   \"Failed to allocate flow list memory\");\n+\t\trte_free(flow);\n+\t\treturn NULL;\n+\t}\n+\n+\tflow_node->flow = flow;\n+\tTAILQ_INSERT_TAIL(&process_list->flow_list, flow_node, entries);\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)\n+\t\tgoto out;\n+\n+\tif (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER) {\n+\t\tret = hns3_counter_new(dev, fdir_rule.act_cnt.shared,\n+\t\t\t\t       fdir_rule.act_cnt.id, error);\n+\t\tif (ret)\n+\t\t\tgoto out;\n+\n+\t\tflow->counter_id = fdir_rule.act_cnt.id;\n+\t}\n+\tret = hns3_fdir_filter_program(hns, &fdir_rule, false);\n+\tif (!ret) {\n+\t\tfdir_rule_ptr = rte_zmalloc(\"hns3 fdir rule\",\n+\t\t\t\t\t    sizeof(struct hns3_fdir_rule_ele),\n+\t\t\t\t\t    0);\n+\t\tif (fdir_rule_ptr == NULL) {\n+\t\t\thns3_err(hw, \"Failed to allocate fdir_rule memory\");\n+\t\t\tret = -ENOMEM;\n+\t\t\tgoto err;\n+\t\t}\n+\t\tmemcpy(&fdir_rule_ptr->fdir_conf, &fdir_rule,\n+\t\t\tsizeof(struct hns3_fdir_rule));\n+\t\tTAILQ_INSERT_TAIL(&process_list->fdir_list,\n+\t\t\t\t  fdir_rule_ptr, entries);\n+\t\tflow->rule = fdir_rule_ptr;\n+\t\tflow->filter_type = RTE_ETH_FILTER_FDIR;\n+\n+\t\treturn flow;\n+\t}\n+\n+\tif (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER)\n+\t\thns3_counter_release(dev, fdir_rule.act_cnt.id);\n+\n+err:\n+\trte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t   \"Failed to create flow\");\n+out:\n+\tTAILQ_REMOVE(&process_list->flow_list, flow_node, entries);\n+\trte_free(flow_node);\n+\trte_free(flow);\n+\treturn NULL;\n+}\n+\n+/* Destroy a flow rule on hns3. */\n+static int\n+hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tstruct hns3_process_private *process_list = dev->process_private;\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tstruct hns3_fdir_rule_ele *fdir_rule_ptr;\n+\tstruct hns3_flow_mem *flow_node;\n+\tstruct hns3_hw *hw = &hns->hw;\n+\tenum rte_filter_type filter_type;\n+\tstruct hns3_fdir_rule fdir_rule;\n+\tint ret;\n+\n+\tif (flow == NULL)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t\t  flow, \"Flow is NULL\");\n+\tfilter_type = flow->filter_type;\n+\tswitch (filter_type) {\n+\tcase RTE_ETH_FILTER_FDIR:\n+\t\tfdir_rule_ptr = (struct hns3_fdir_rule_ele *)flow->rule;\n+\t\tmemcpy(&fdir_rule, &fdir_rule_ptr->fdir_conf,\n+\t\t\t   sizeof(struct hns3_fdir_rule));\n+\n+\t\tret = hns3_fdir_filter_program(hns, &fdir_rule, true);\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 FDIR fail.Try again\");\n+\t\tif (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER)\n+\t\t\thns3_counter_release(dev, fdir_rule.act_cnt.id);\n+\t\tTAILQ_REMOVE(&process_list->fdir_list, fdir_rule_ptr, entries);\n+\t\trte_free(fdir_rule_ptr);\n+\t\tfdir_rule_ptr = NULL;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_HANDLE, flow,\n+\t\t\t\t\t  \"Unsupported filter type\");\n+\t}\n+\n+\tTAILQ_FOREACH(flow_node, &process_list->flow_list, entries) {\n+\t\tif (flow_node->flow == flow) {\n+\t\t\tTAILQ_REMOVE(&process_list->flow_list, flow_node,\n+\t\t\t\t     entries);\n+\t\t\trte_free(flow_node);\n+\t\t\tflow_node = NULL;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\trte_free(flow);\n+\tflow = NULL;\n+\n+\treturn 0;\n+}\n+\n+/*  Destroy all flow rules associated with a port on hns3. */\n+static int\n+hns3_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)\n+{\n+\tstruct hns3_adapter *hns = dev->data->dev_private;\n+\tint ret;\n+\n+\t/* FDIR is available only in PF driver */\n+\tif (!hns->is_vf) {\n+\t\tret = hns3_clear_all_fdir_filter(hns);\n+\t\tif (ret) {\n+\t\t\trte_flow_error_set(error, ret,\n+\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t\t   NULL, \"Failed to flush rule\");\n+\t\t\treturn ret;\n+\t\t}\n+\t\thns3_counter_flush(dev);\n+\t}\n+\n+\thns3_filterlist_flush(dev);\n+\n+\treturn 0;\n+}\n+\n+/* Query an existing flow rule. */\n+static int\n+hns3_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t\tconst struct rte_flow_action *actions, void *data,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tstruct rte_flow_query_count *qc;\n+\tint ret;\n+\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t\tqc = (struct rte_flow_query_count *)data;\n+\t\t\tret = hns3_counter_query(dev, flow, qc, error);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t  actions,\n+\t\t\t\t\t\t  \"Query action only support count\");\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+const struct rte_flow_ops hns3_flow_ops = {\n+\t.validate = hns3_flow_validate,\n+\t.create = hns3_flow_create,\n+\t.destroy = hns3_flow_destroy,\n+\t.flush = hns3_flow_flush,\n+\t.query = hns3_flow_query,\n+\t.isolate = NULL,\n+};\n",
    "prefixes": [
        "09/22"
    ]
}