get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 86168,
    "url": "http://patches.dpdk.org/api/patches/86168/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210108053540.11184-3-alvinx.zhang@intel.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": "<20210108053540.11184-3-alvinx.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210108053540.11184-3-alvinx.zhang@intel.com",
    "date": "2021-01-08T05:35:40",
    "name": "[v4,3/3] net/i40e: refactor RSS flow",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "0443f8ba08b1e7087e118b3c3f9879ec3566392a",
    "submitter": {
        "id": 1398,
        "url": "http://patches.dpdk.org/api/people/1398/?format=api",
        "name": "Alvin Zhang",
        "email": "alvinx.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "http://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20210108053540.11184-3-alvinx.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 14590,
            "url": "http://patches.dpdk.org/api/series/14590/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=14590",
            "date": "2021-01-08T05:35:38",
            "name": "[v4,1/3] doc: fix testpmd command for i40e RSS flow",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/14590/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/86168/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/86168/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 6ACCBA0524;\n\tFri,  8 Jan 2021 06:36:13 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 2F522140E1D;\n\tFri,  8 Jan 2021 06:35:58 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n by mails.dpdk.org (Postfix) with ESMTP id 902A2140E05\n for <dev@dpdk.org>; Fri,  8 Jan 2021 06:35:55 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 07 Jan 2021 21:35:54 -0800",
            "from shwdenpg235.ccr.corp.intel.com ([10.240.182.60])\n by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 07 Jan 2021 21:35:51 -0800"
        ],
        "IronPort-SDR": [
            "\n xztaWVqH5zMqbr6+msc1eklFnlPyVtwZe1noi9LpWUPF6oftCeCDKxM0VHF0q0JcWbydj0h86j\n nvvYOq2xL7eQ==",
            "\n g6L42wPd0kPTqUqyVT9cyRmWA3WNawJzU8twaR95aET+6W2dJ9N0x0jIYqfz0aFPgMdjkwCgby\n yK4f/fylp6yA=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9857\"; a=\"177693940\"",
            "E=Sophos;i=\"5.79,330,1602572400\"; d=\"scan'208\";a=\"177693940\"",
            "E=Sophos;i=\"5.79,330,1602572400\"; d=\"scan'208\";a=\"398872185\""
        ],
        "From": "\"Zhang,Alvin\" <alvinx.zhang@intel.com>",
        "To": "jia.guo@intel.com, beilei.xing@intel.com, qi.z.zhang@intel.com,\n Simei.Su@intel.com, qiming.yang@intel.com",
        "Cc": "dev@dpdk.org,\n\tAlvin Zhang <alvinx.zhang@intel.com>",
        "Date": "Fri,  8 Jan 2021 13:35:40 +0800",
        "Message-Id": "<20210108053540.11184-3-alvinx.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.21.0.windows.1",
        "In-Reply-To": "<20210108053540.11184-1-alvinx.zhang@intel.com>",
        "References": "<20210107080230.7836-1-alvinx.zhang@intel.com>\n <20210108053540.11184-1-alvinx.zhang@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v4 3/3] net/i40e: refactor RSS flow",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Alvin Zhang <alvinx.zhang@intel.com>\n\n1. Delete original code.\n2. Add 2 tables(One maps flow pattern and RSS type to PCTYPE,\n   another maps RSS type to input set).\n3. Parse RSS pattern and RSS type to get PCTYPE.\n4. Parse RSS action to get queues, RSS function and hash field.\n5. Create and destroy RSS filters.\n6. Create new files for hash flows.\n\nSigned-off-by: Alvin Zhang <alvinx.zhang@intel.com>\n---\n\nV3: Refine RSS key\nV4: Fix build at x86-32\n---\n drivers/net/i40e/i40e_ethdev.c |  905 +++++---------------------\n drivers/net/i40e/i40e_ethdev.h |   53 +-\n drivers/net/i40e/i40e_flow.c   |  617 +-----------------\n drivers/net/i40e/i40e_hash.c   | 1383 ++++++++++++++++++++++++++++++++++++++++\n drivers/net/i40e/i40e_hash.h   |   34 +\n drivers/net/i40e/meson.build   |    1 +\n 6 files changed, 1625 insertions(+), 1368 deletions(-)\n create mode 100644 drivers/net/i40e/i40e_hash.c\n create mode 100644 drivers/net/i40e/i40e_hash.h",
    "diff": "diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex 2034008..b8c2cf3 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -39,6 +39,7 @@\n #include \"i40e_pf.h\"\n #include \"i40e_regs.h\"\n #include \"rte_pmd_i40e.h\"\n+#include \"i40e_hash.h\"\n \n #define ETH_I40E_FLOATING_VEB_ARG\t\"enable_floating_veb\"\n #define ETH_I40E_FLOATING_VEB_LIST_ARG\t\"floating_veb_list\"\n@@ -396,7 +397,6 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,\n static void i40e_tunnel_filter_restore(struct i40e_pf *pf);\n static void i40e_filter_restore(struct i40e_pf *pf);\n static void i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev);\n-static int i40e_pf_config_rss(struct i40e_pf *pf);\n \n static const char *const valid_keys[] = {\n \tETH_I40E_FLOATING_VEB_ARG,\n@@ -1764,10 +1764,6 @@ static inline void i40e_config_automask(struct i40e_pf *pf)\n \t/* initialize queue region configuration */\n \ti40e_init_queue_region_conf(dev);\n \n-\t/* initialize RSS configuration from rte_flow */\n-\tmemset(&pf->rss_info, 0,\n-\t\tsizeof(struct i40e_rte_flow_rss_conf));\n-\n \t/* reset all stats of the device, including pf and main vsi */\n \ti40e_dev_stats_reset(dev);\n \n@@ -7576,7 +7572,7 @@ struct i40e_vsi *\n }\n \n /* Disable RSS */\n-static void\n+void\n i40e_pf_disable_rss(struct i40e_pf *pf)\n {\n \tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n@@ -8789,7 +8785,7 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n }\n \n /* Calculate the maximum number of contiguous PF queues that are configured */\n-static int\n+int\n i40e_pf_calc_configured_queues_num(struct i40e_pf *pf)\n {\n \tstruct rte_eth_dev_data *data = pf->dev_data;\n@@ -8808,19 +8804,72 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n \treturn num;\n }\n \n-/* Configure RSS */\n-static int\n-i40e_pf_config_rss(struct i40e_pf *pf)\n+/* Reset the global configure of hash function and input sets */\n+static void\n+i40e_pf_global_rss_reset(struct i40e_pf *pf)\n {\n-\tenum rte_eth_rx_mq_mode mq_mode = pf->dev_data->dev_conf.rxmode.mq_mode;\n \tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tstruct rte_eth_rss_conf rss_conf;\n-\tuint32_t i, lut = 0;\n-\tuint16_t j, num;\n+\tuint32_t reg, reg_val;\n+\tint i;\n \n-\t/*\n-\t * If both VMDQ and RSS enabled, not all of PF queues are configured.\n-\t * It's necessary to calculate the actual PF queues that are configured.\n+\t/* Reset global RSS function sets */\n+\treg_val = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);\n+\tif (!(reg_val & I40E_GLQF_CTL_HTOEP_MASK)) {\n+\t\treg_val |= I40E_GLQF_CTL_HTOEP_MASK;\n+\t\ti40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg_val);\n+\t}\n+\n+\tfor (i = 0; i <= I40E_FILTER_PCTYPE_L2_PAYLOAD; i++) {\n+\t\tuint64_t inset;\n+\t\tint j, pctype;\n+\n+\t\tif (hw->mac.type == I40E_MAC_X722)\n+\t\t\tpctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(i));\n+\t\telse\n+\t\t\tpctype = i;\n+\n+\t\t/* Reset pctype insets */\n+\t\tinset = i40e_get_default_input_set(i);\n+\t\tif (inset) {\n+\t\t\tpf->hash_input_set[pctype] = inset;\n+\t\t\tinset = i40e_translate_input_set_reg(hw->mac.type,\n+\t\t\t\t\t\t\t     inset);\n+\n+\t\t\treg = I40E_GLQF_HASH_INSET(0, pctype);\n+\t\t\ti40e_check_write_global_reg(hw, reg, (uint32_t)inset);\n+\t\t\treg = I40E_GLQF_HASH_INSET(1, pctype);\n+\t\t\ti40e_check_write_global_reg(hw, reg,\n+\t\t\t\t\t\t    (uint32_t)(inset >> 32));\n+\n+\t\t\t/* Clear unused mask registers of the pctype */\n+\t\t\tfor (j = 0; j < I40E_INSET_MASK_NUM_REG; j++) {\n+\t\t\t\treg = I40E_GLQF_HASH_MSK(j, pctype);\n+\t\t\t\ti40e_check_write_global_reg(hw, reg, 0);\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Reset pctype symmetric sets */\n+\t\treg = I40E_GLQF_HSYM(pctype);\n+\t\treg_val = i40e_read_rx_ctl(hw, reg);\n+\t\tif (reg_val & I40E_GLQF_HSYM_SYMH_ENA_MASK) {\n+\t\t\treg_val &= ~I40E_GLQF_HSYM_SYMH_ENA_MASK;\n+\t\t\ti40e_write_global_rx_ctl(hw, reg, reg_val);\n+\t\t}\n+\t}\n+\tI40E_WRITE_FLUSH(hw);\n+}\n+\n+int\n+i40e_pf_reset_rss_reta(struct i40e_pf *pf)\n+{\n+\tstruct i40e_hw *hw = &pf->adapter->hw;\n+\tuint8_t lut[ETH_RSS_RETA_SIZE_512];\n+\tuint32_t i;\n+\tint num;\n+\n+\t/* If both VMDQ and RSS enabled, not all of PF queues are\n+\t * configured. It's necessary to calculate the actual PF\n+\t * queues that are configured.\n \t */\n \tif (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG)\n \t\tnum = i40e_pf_calc_configured_queues_num(pf);\n@@ -8828,48 +8877,89 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n \t\tnum = pf->dev_data->nb_rx_queues;\n \n \tnum = RTE_MIN(num, I40E_MAX_Q_PER_TC);\n-\tPMD_INIT_LOG(INFO, \"Max of contiguous %u PF queues are configured\",\n-\t\t\tnum);\n+\tif (num <= 0)\n+\t\treturn 0;\n \n-\tif (num == 0) {\n-\t\tPMD_INIT_LOG(ERR,\n-\t\t\t\"No PF queues are configured to enable RSS for port %u\",\n-\t\t\tpf->dev_data->port_id);\n-\t\treturn -ENOTSUP;\n-\t}\n+\tfor (i = 0; i < hw->func_caps.rss_table_size; i++)\n+\t\tlut[i] = (uint8_t)(i % (uint32_t)num);\n \n-\tif (pf->adapter->rss_reta_updated == 0) {\n-\t\tfor (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) {\n-\t\t\tif (j == num)\n-\t\t\t\tj = 0;\n-\t\t\tlut = (lut << 8) | (j & ((0x1 <<\n-\t\t\t\thw->func_caps.rss_table_entry_width) - 1));\n-\t\t\tif ((i & 3) == 3)\n-\t\t\t\tI40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2),\n-\t\t\t\t\t       rte_bswap32(lut));\n-\t\t}\n-\t}\n+\treturn i40e_set_rss_lut(pf->main_vsi, lut, (uint16_t)i);\n+}\n \n-\trss_conf = pf->dev_data->dev_conf.rx_adv_conf.rss_conf;\n-\tif ((rss_conf.rss_hf & pf->adapter->flow_types_mask) == 0 ||\n-\t    !(mq_mode & ETH_MQ_RX_RSS_FLAG)) {\n-\t\ti40e_pf_disable_rss(pf);\n-\t\treturn 0;\n-\t}\n-\tif (rss_conf.rss_key == NULL || rss_conf.rss_key_len <\n-\t\t(I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) {\n-\t\t/* Random default keys */\n+int\n+i40e_pf_reset_rss_key(struct i40e_pf *pf)\n+{\n+\tconst uint8_t key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) *\n+\t\t\tsizeof(uint32_t);\n+\tuint8_t *rss_key;\n+\n+\t/* Reset key */\n+\trss_key = pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_key;\n+\tif (!rss_key ||\n+\t    pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_key_len < key_len) {\n \t\tstatic uint32_t rss_key_default[] = {0x6b793944,\n \t\t\t0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8,\n \t\t\t0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605,\n \t\t\t0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581};\n \n-\t\trss_conf.rss_key = (uint8_t *)rss_key_default;\n-\t\trss_conf.rss_key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) *\n-\t\t\t\t\t\t\tsizeof(uint32_t);\n+\t\trss_key = (uint8_t *)rss_key_default;\n \t}\n \n-\treturn i40e_hw_rss_hash_set(pf, &rss_conf);\n+\treturn i40e_set_rss_key(pf->main_vsi, rss_key, key_len);\n+}\n+\n+static int\n+i40e_pf_rss_reset(struct i40e_pf *pf)\n+{\n+\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n+\n+\tint ret;\n+\n+\tpf->hash_filter_enabled = 0;\n+\ti40e_pf_disable_rss(pf);\n+\ti40e_set_symmetric_hash_enable_per_port(hw, 0);\n+\n+\tif (!pf->support_multi_driver)\n+\t\ti40e_pf_global_rss_reset(pf);\n+\n+\t/* Reset RETA table */\n+\tif (pf->adapter->rss_reta_updated == 0) {\n+\t\tret = i40e_pf_reset_rss_reta(pf);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn i40e_pf_reset_rss_key(pf);\n+}\n+\n+/* Configure RSS */\n+int\n+i40e_pf_config_rss(struct i40e_pf *pf)\n+{\n+\tstruct i40e_hw *hw;\n+\tenum rte_eth_rx_mq_mode mq_mode;\n+\tuint64_t rss_hf, hena;\n+\tint ret;\n+\n+\tret = i40e_pf_rss_reset(pf);\n+\tif (ret) {\n+\t\tPMD_DRV_LOG(ERR, \"Reset RSS failed, RSS has been disabled\");\n+\t\treturn ret;\n+\t}\n+\n+\trss_hf = pf->dev_data->dev_conf.rx_adv_conf.rss_conf.rss_hf;\n+\tmq_mode = pf->dev_data->dev_conf.rxmode.mq_mode;\n+\tif (!(rss_hf & pf->adapter->flow_types_mask) ||\n+\t    !(mq_mode & ETH_MQ_RX_RSS_FLAG))\n+\t\treturn 0;\n+\n+\thw = I40E_PF_TO_HW(pf);\n+\thena = i40e_config_hena(pf->adapter, rss_hf);\n+\ti40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena);\n+\ti40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32));\n+\tI40E_WRITE_FLUSH(hw);\n+\n+\treturn 0;\n }\n \n #define I40E_GL_PRS_FVBM_MSK_ENA 0x80000000\n@@ -8917,24 +9007,20 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n }\n \n /* Set the symmetric hash enable configurations per port */\n-static void\n+void\n i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable)\n {\n \tuint32_t reg = i40e_read_rx_ctl(hw, I40E_PRTQF_CTL_0);\n \n \tif (enable > 0) {\n-\t\tif (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) {\n-\t\t\tPMD_DRV_LOG(INFO,\n-\t\t\t\t\"Symmetric hash has already been enabled\");\n+\t\tif (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)\n \t\t\treturn;\n-\t\t}\n+\n \t\treg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK;\n \t} else {\n-\t\tif (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) {\n-\t\t\tPMD_DRV_LOG(INFO,\n-\t\t\t\t\"Symmetric hash has already been disabled\");\n+\t\tif (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK))\n \t\t\treturn;\n-\t\t}\n+\n \t\treg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK;\n \t}\n \ti40e_write_rx_ctl(hw, I40E_PRTQF_CTL_0, reg);\n@@ -9280,103 +9366,6 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n }\n \n /**\n- * Parse the input set from index to logical bit masks\n- */\n-static int\n-i40e_parse_input_set(uint64_t *inset,\n-\t\t     enum i40e_filter_pctype pctype,\n-\t\t     enum rte_eth_input_set_field *field,\n-\t\t     uint16_t size)\n-{\n-\tuint16_t i, j;\n-\tint ret = -EINVAL;\n-\n-\tstatic const struct {\n-\t\tenum rte_eth_input_set_field field;\n-\t\tuint64_t inset;\n-\t} inset_convert_table[] = {\n-\t\t{RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE},\n-\t\t{RTE_ETH_INPUT_SET_L2_SRC_MAC, I40E_INSET_SMAC},\n-\t\t{RTE_ETH_INPUT_SET_L2_DST_MAC, I40E_INSET_DMAC},\n-\t\t{RTE_ETH_INPUT_SET_L2_OUTER_VLAN, I40E_INSET_VLAN_OUTER},\n-\t\t{RTE_ETH_INPUT_SET_L2_INNER_VLAN, I40E_INSET_VLAN_INNER},\n-\t\t{RTE_ETH_INPUT_SET_L2_ETHERTYPE, I40E_INSET_LAST_ETHER_TYPE},\n-\t\t{RTE_ETH_INPUT_SET_L3_SRC_IP4, I40E_INSET_IPV4_SRC},\n-\t\t{RTE_ETH_INPUT_SET_L3_DST_IP4, I40E_INSET_IPV4_DST},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP4_TOS, I40E_INSET_IPV4_TOS},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP4_PROTO, I40E_INSET_IPV4_PROTO},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP4_TTL, I40E_INSET_IPV4_TTL},\n-\t\t{RTE_ETH_INPUT_SET_L3_SRC_IP6, I40E_INSET_IPV6_SRC},\n-\t\t{RTE_ETH_INPUT_SET_L3_DST_IP6, I40E_INSET_IPV6_DST},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP6_TC, I40E_INSET_IPV6_TC},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER,\n-\t\t\tI40E_INSET_IPV6_NEXT_HDR},\n-\t\t{RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS,\n-\t\t\tI40E_INSET_IPV6_HOP_LIMIT},\n-\t\t{RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT, I40E_INSET_SRC_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT, I40E_INSET_SRC_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT, I40E_INSET_SRC_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_UDP_DST_PORT, I40E_INSET_DST_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_TCP_DST_PORT, I40E_INSET_DST_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT, I40E_INSET_DST_PORT},\n-\t\t{RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG,\n-\t\t\tI40E_INSET_SCTP_VT},\n-\t\t{RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_DST_MAC,\n-\t\t\tI40E_INSET_TUNNEL_DMAC},\n-\t\t{RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_VLAN,\n-\t\t\tI40E_INSET_VLAN_TUNNEL},\n-\t\t{RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY,\n-\t\t\tI40E_INSET_TUNNEL_ID},\n-\t\t{RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY, I40E_INSET_TUNNEL_ID},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W1},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W2},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W3},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W4},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W5},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W6},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W7},\n-\t\t{RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD,\n-\t\t\tI40E_INSET_FLEX_PAYLOAD_W8},\n-\t};\n-\n-\tif (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX)\n-\t\treturn ret;\n-\n-\t/* Only one item allowed for default or all */\n-\tif (size == 1) {\n-\t\tif (field[0] == RTE_ETH_INPUT_SET_DEFAULT) {\n-\t\t\t*inset = i40e_get_default_input_set(pctype);\n-\t\t\treturn 0;\n-\t\t} else if (field[0] == RTE_ETH_INPUT_SET_NONE) {\n-\t\t\t*inset = I40E_INSET_NONE;\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n-\n-\tfor (i = 0, *inset = 0; i < size; i++) {\n-\t\tfor (j = 0; j < RTE_DIM(inset_convert_table); j++) {\n-\t\t\tif (field[i] == inset_convert_table[j].field) {\n-\t\t\t\t*inset |= inset_convert_table[j].inset;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\n-\t\t/* It contains unsupported input set, return immediately */\n-\t\tif (j == RTE_DIM(inset_convert_table))\n-\t\t\treturn ret;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/**\n  * Translate the input set from bit masks to register aware bit masks\n  * and vice versa\n  */\n@@ -9616,50 +9605,25 @@ i40e_status_code i40e_replace_gtp_cloud_filter(struct i40e_pf *pf)\n }\n \n int\n-i40e_hash_filter_inset_select(struct i40e_hw *hw,\n-\t\t\t struct rte_eth_input_set_conf *conf)\n+i40e_set_hash_inset(struct i40e_hw *hw, uint64_t input_set,\n+\t\t    uint32_t pctype, bool add)\n {\n \tstruct i40e_pf *pf = &((struct i40e_adapter *)hw->back)->pf;\n-\tenum i40e_filter_pctype pctype;\n-\tuint64_t input_set, inset_reg = 0;\n \tuint32_t mask_reg[I40E_INSET_MASK_NUM_REG] = {0};\n-\tint ret, i, num;\n-\n-\tif (!conf) {\n-\t\tPMD_DRV_LOG(ERR, \"Invalid pointer\");\n-\t\treturn -EFAULT;\n-\t}\n-\tif (conf->op != RTE_ETH_INPUT_SET_SELECT &&\n-\t    conf->op != RTE_ETH_INPUT_SET_ADD) {\n-\t\tPMD_DRV_LOG(ERR, \"Unsupported input set operation\");\n-\t\treturn -EINVAL;\n-\t}\n+\tuint64_t inset_reg = 0;\n+\tint num, i;\n \n \tif (pf->support_multi_driver) {\n-\t\tPMD_DRV_LOG(ERR, \"Hash input set setting is not supported.\");\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\tpctype = i40e_flowtype_to_pctype(pf->adapter, conf->flow_type);\n-\tif (pctype == I40E_FILTER_PCTYPE_INVALID) {\n-\t\tPMD_DRV_LOG(ERR, \"invalid flow_type input.\");\n-\t\treturn -EINVAL;\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Modify input set is not permitted when multi-driver enabled.\");\n+\t\treturn -EPERM;\n \t}\n \n-\tif (hw->mac.type == I40E_MAC_X722) {\n-\t\t/* get translated pctype value in fd pctype register */\n-\t\tpctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,\n-\t\t\tI40E_GLQF_FD_PCTYPES((int)pctype));\n-\t}\n+\t/* For X722, get translated pctype in fd pctype register */\n+\tif (hw->mac.type == I40E_MAC_X722)\n+\t\tpctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(pctype));\n \n-\tret = i40e_parse_input_set(&input_set, pctype, conf->field,\n-\t\t\t\t   conf->inset_size);\n-\tif (ret) {\n-\t\tPMD_DRV_LOG(ERR, \"Failed to parse input set\");\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tif (conf->op == RTE_ETH_INPUT_SET_ADD) {\n+\tif (add) {\n \t\t/* get inset value in register */\n \t\tinset_reg = i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, pctype));\n \t\tinset_reg <<= I40E_32_BIT_WIDTH;\n@@ -11860,25 +11824,13 @@ static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,\n \t}\n }\n \n-/* Restore RSS filter */\n-static inline void\n-i40e_rss_filter_restore(struct i40e_pf *pf)\n-{\n-\tstruct i40e_rss_conf_list *list = &pf->rss_config_list;\n-\tstruct i40e_rss_filter *filter;\n-\n-\tTAILQ_FOREACH(filter, list, next) {\n-\t\ti40e_config_rss_filter(pf, &filter->rss_filter_info, TRUE);\n-\t}\n-}\n-\n static void\n i40e_filter_restore(struct i40e_pf *pf)\n {\n \ti40e_ethertype_filter_restore(pf);\n \ti40e_tunnel_filter_restore(pf);\n \ti40e_fdir_filter_restore(pf);\n-\ti40e_rss_filter_restore(pf);\n+\t(void)i40e_hash_filter_restore(pf);\n }\n \n bool\n@@ -12456,551 +12408,6 @@ struct i40e_customized_pctype*\n \treturn ret;\n }\n \n-int\n-i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,\n-\t\t   const struct rte_flow_action_rss *in)\n-{\n-\tif (in->key_len > RTE_DIM(out->key) ||\n-\t    in->queue_num > RTE_DIM(out->queue))\n-\t\treturn -EINVAL;\n-\tif (!in->key && in->key_len)\n-\t\treturn -EINVAL;\n-\tout->conf = (struct rte_flow_action_rss){\n-\t\t.func = in->func,\n-\t\t.level = in->level,\n-\t\t.types = in->types,\n-\t\t.key_len = in->key_len,\n-\t\t.queue_num = in->queue_num,\n-\t\t.queue = memcpy(out->queue, in->queue,\n-\t\t\t\tsizeof(*in->queue) * in->queue_num),\n-\t};\n-\tif (in->key)\n-\t\tout->conf.key = memcpy(out->key, in->key, in->key_len);\n-\treturn 0;\n-}\n-\n-/* Write HENA register to enable hash */\n-static int\n-i40e_rss_hash_set(struct i40e_pf *pf, struct i40e_rte_flow_rss_conf *rss_conf)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tuint8_t *key = (void *)(uintptr_t)rss_conf->conf.key;\n-\tuint64_t hena;\n-\tint ret;\n-\n-\tret = i40e_set_rss_key(pf->main_vsi, key,\n-\t\t\t       rss_conf->conf.key_len);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\thena = i40e_config_hena(pf->adapter, rss_conf->conf.types);\n-\ti40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena);\n-\ti40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32));\n-\tI40E_WRITE_FLUSH(hw);\n-\n-\treturn 0;\n-}\n-\n-/* Configure hash input set */\n-static int\n-i40e_rss_conf_hash_inset(struct i40e_pf *pf, uint64_t types)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tstruct rte_eth_input_set_conf conf;\n-\tuint64_t mask0;\n-\tint ret = 0;\n-\tuint32_t j;\n-\tint i;\n-\tstatic const struct {\n-\t\tuint64_t type;\n-\t\tenum rte_eth_input_set_field field;\n-\t} inset_match_table[] = {\n-\t\t{ETH_RSS_FRAG_IPV4 | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP4},\n-\t\t{ETH_RSS_FRAG_IPV4 | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP4},\n-\t\t{ETH_RSS_FRAG_IPV4 | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\t\t{ETH_RSS_FRAG_IPV4 | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_TCP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_UDP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\t\t{ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\n-\t\t{ETH_RSS_FRAG_IPV6 | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP6},\n-\t\t{ETH_RSS_FRAG_IPV6 | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP6},\n-\t\t{ETH_RSS_FRAG_IPV6 | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\t\t{ETH_RSS_FRAG_IPV6 | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_TCP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_UDP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},\n-\t\t{ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},\n-\n-\t\t{ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L3_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_SRC_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L3_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_L3_DST_IP6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L4_SRC_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\t\t{ETH_RSS_NONFRAG_IPV6_OTHER | ETH_RSS_L4_DST_ONLY,\n-\t\t\tRTE_ETH_INPUT_SET_UNKNOWN},\n-\t};\n-\n-\tmask0 = types & pf->adapter->flow_types_mask;\n-\tconf.op = RTE_ETH_INPUT_SET_SELECT;\n-\tconf.inset_size = 0;\n-\tfor (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX; i++) {\n-\t\tif (mask0 & (1ULL << i)) {\n-\t\t\tconf.flow_type = i;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\tfor (j = 0; j < RTE_DIM(inset_match_table); j++) {\n-\t\tif ((types & inset_match_table[j].type) ==\n-\t\t    inset_match_table[j].type) {\n-\t\t\tif (inset_match_table[j].field ==\n-\t\t\t    RTE_ETH_INPUT_SET_UNKNOWN)\n-\t\t\t\treturn -EINVAL;\n-\n-\t\t\tconf.field[conf.inset_size] =\n-\t\t\t\tinset_match_table[j].field;\n-\t\t\tconf.inset_size++;\n-\t\t}\n-\t}\n-\n-\tif (conf.inset_size) {\n-\t\tret = i40e_hash_filter_inset_select(hw, &conf);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\t}\n-\n-\treturn ret;\n-}\n-\n-/* Look up the conflicted rule then mark it as invalid */\n-static void\n-i40e_rss_mark_invalid_rule(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_rss_filter *rss_item;\n-\tuint64_t rss_inset;\n-\n-\t/* Clear input set bits before comparing the pctype */\n-\trss_inset = ~(ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY |\n-\t\tETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY);\n-\n-\t/* Look up the conflicted rule then mark it as invalid */\n-\tTAILQ_FOREACH(rss_item, &pf->rss_config_list, next) {\n-\t\tif (!rss_item->rss_filter_info.valid)\n-\t\t\tcontinue;\n-\n-\t\tif (conf->conf.queue_num &&\n-\t\t    rss_item->rss_filter_info.conf.queue_num)\n-\t\t\trss_item->rss_filter_info.valid = false;\n-\n-\t\tif (conf->conf.types &&\n-\t\t    (rss_item->rss_filter_info.conf.types &\n-\t\t    rss_inset) ==\n-\t\t    (conf->conf.types & rss_inset))\n-\t\t\trss_item->rss_filter_info.valid = false;\n-\n-\t\tif (conf->conf.func ==\n-\t\t    RTE_ETH_HASH_FUNCTION_SIMPLE_XOR &&\n-\t\t    rss_item->rss_filter_info.conf.func ==\n-\t\t    RTE_ETH_HASH_FUNCTION_SIMPLE_XOR)\n-\t\t\trss_item->rss_filter_info.valid = false;\n-\t}\n-}\n-\n-/* Configure RSS hash function */\n-static int\n-i40e_rss_config_hash_function(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tuint32_t reg, i;\n-\tuint64_t mask0;\n-\tuint16_t j;\n-\n-\tif (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {\n-\t\treg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);\n-\t\tif (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) {\n-\t\t\tPMD_DRV_LOG(DEBUG, \"Hash function already set to Simple XOR\");\n-\t\t\tI40E_WRITE_FLUSH(hw);\n-\t\t\ti40e_rss_mark_invalid_rule(pf, conf);\n-\n-\t\t\treturn 0;\n-\t\t}\n-\t\treg &= ~I40E_GLQF_CTL_HTOEP_MASK;\n-\n-\t\ti40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg);\n-\t\tI40E_WRITE_FLUSH(hw);\n-\t\ti40e_rss_mark_invalid_rule(pf, conf);\n-\t} else if (conf->conf.func ==\n-\t\t   RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {\n-\t\tmask0 = conf->conf.types & pf->adapter->flow_types_mask;\n-\n-\t\ti40e_set_symmetric_hash_enable_per_port(hw, 1);\n-\t\tfor (i = RTE_ETH_FLOW_UNKNOWN + 1; i < UINT64_BIT; i++) {\n-\t\t\tif (mask0 & (1UL << i))\n-\t\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (i == UINT64_BIT)\n-\t\t\treturn -EINVAL;\n-\n-\t\tfor (j = I40E_FILTER_PCTYPE_INVALID + 1;\n-\t\t     j < I40E_FILTER_PCTYPE_MAX; j++) {\n-\t\t\tif (pf->adapter->pctypes_tbl[i] & (1ULL << j))\n-\t\t\t\ti40e_write_global_rx_ctl(hw,\n-\t\t\t\t\tI40E_GLQF_HSYM(j),\n-\t\t\t\t\tI40E_GLQF_HSYM_SYMH_ENA_MASK);\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Enable RSS according to the configuration */\n-static int\n-i40e_rss_enable_hash(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n-\tstruct i40e_rte_flow_rss_conf rss_conf;\n-\n-\tif (!(conf->conf.types & pf->adapter->flow_types_mask))\n-\t\treturn -ENOTSUP;\n-\n-\tmemset(&rss_conf, 0, sizeof(rss_conf));\n-\trte_memcpy(&rss_conf, conf, sizeof(rss_conf));\n-\n-\t/* Configure hash input set */\n-\tif (i40e_rss_conf_hash_inset(pf, conf->conf.types))\n-\t\treturn -EINVAL;\n-\n-\tif (rss_conf.conf.key == NULL || rss_conf.conf.key_len <\n-\t    (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) {\n-\t\t/* Random default keys */\n-\t\tstatic uint32_t rss_key_default[] = {0x6b793944,\n-\t\t\t0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8,\n-\t\t\t0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605,\n-\t\t\t0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581};\n-\n-\t\trss_conf.conf.key = (uint8_t *)rss_key_default;\n-\t\trss_conf.conf.key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) *\n-\t\t\t\tsizeof(uint32_t);\n-\t\tPMD_DRV_LOG(INFO,\n-\t\t\t\"No valid RSS key config for i40e, using default\\n\");\n-\t}\n-\n-\trss_conf.conf.types |= rss_info->conf.types;\n-\ti40e_rss_hash_set(pf, &rss_conf);\n-\n-\tif (conf->conf.func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)\n-\t\ti40e_rss_config_hash_function(pf, conf);\n-\n-\ti40e_rss_mark_invalid_rule(pf, conf);\n-\n-\treturn 0;\n-}\n-\n-/* Configure RSS queue region */\n-static int\n-i40e_rss_config_queue_region(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tuint32_t lut = 0;\n-\tuint16_t j, num;\n-\tuint32_t i;\n-\n-\t/* If both VMDQ and RSS enabled, not all of PF queues are configured.\n-\t * It's necessary to calculate the actual PF queues that are configured.\n-\t */\n-\tif (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG)\n-\t\tnum = i40e_pf_calc_configured_queues_num(pf);\n-\telse\n-\t\tnum = pf->dev_data->nb_rx_queues;\n-\n-\tnum = RTE_MIN(num, conf->conf.queue_num);\n-\tPMD_DRV_LOG(INFO, \"Max of contiguous %u PF queues are configured\",\n-\t\t\tnum);\n-\n-\tif (num == 0) {\n-\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\"No PF queues are configured to enable RSS for port %u\",\n-\t\t\tpf->dev_data->port_id);\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\t/* Fill in redirection table */\n-\tfor (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) {\n-\t\tif (j == num)\n-\t\t\tj = 0;\n-\t\tlut = (lut << 8) | (conf->conf.queue[j] & ((0x1 <<\n-\t\t\thw->func_caps.rss_table_entry_width) - 1));\n-\t\tif ((i & 3) == 3)\n-\t\t\tI40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut);\n-\t}\n-\n-\ti40e_rss_mark_invalid_rule(pf, conf);\n-\n-\treturn 0;\n-}\n-\n-/* Configure RSS hash function to default */\n-static int\n-i40e_rss_clear_hash_function(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tuint32_t i, reg;\n-\tuint64_t mask0;\n-\tuint16_t j;\n-\n-\tif (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {\n-\t\treg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);\n-\t\tif (reg & I40E_GLQF_CTL_HTOEP_MASK) {\n-\t\t\tPMD_DRV_LOG(DEBUG,\n-\t\t\t\t\"Hash function already set to Toeplitz\");\n-\t\t\tI40E_WRITE_FLUSH(hw);\n-\n-\t\t\treturn 0;\n-\t\t}\n-\t\treg |= I40E_GLQF_CTL_HTOEP_MASK;\n-\n-\t\ti40e_write_global_rx_ctl(hw, I40E_GLQF_CTL, reg);\n-\t\tI40E_WRITE_FLUSH(hw);\n-\t} else if (conf->conf.func ==\n-\t\t   RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {\n-\t\tmask0 = conf->conf.types & pf->adapter->flow_types_mask;\n-\n-\t\tfor (i = RTE_ETH_FLOW_UNKNOWN + 1; i < UINT64_BIT; i++) {\n-\t\t\tif (mask0 & (1UL << i))\n-\t\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (i == UINT64_BIT)\n-\t\t\treturn -EINVAL;\n-\n-\t\tfor (j = I40E_FILTER_PCTYPE_INVALID + 1;\n-\t\t     j < I40E_FILTER_PCTYPE_MAX; j++) {\n-\t\t\tif (pf->adapter->pctypes_tbl[i] & (1ULL << j))\n-\t\t\t\ti40e_write_global_rx_ctl(hw,\n-\t\t\t\t\tI40E_GLQF_HSYM(j),\n-\t\t\t\t\t0);\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* Disable RSS hash and configure default input set */\n-static int\n-i40e_rss_disable_hash(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tstruct i40e_rte_flow_rss_conf rss_conf;\n-\tuint32_t i;\n-\n-\tmemset(&rss_conf, 0, sizeof(rss_conf));\n-\trte_memcpy(&rss_conf, conf, sizeof(rss_conf));\n-\n-\t/* Disable RSS hash */\n-\trss_conf.conf.types = rss_info->conf.types & ~(conf->conf.types);\n-\ti40e_rss_hash_set(pf, &rss_conf);\n-\n-\tfor (i = RTE_ETH_FLOW_IPV4; i <= RTE_ETH_FLOW_L2_PAYLOAD; i++) {\n-\t\tif (!(pf->adapter->flow_types_mask & (1ULL << i)) ||\n-\t\t    !(conf->conf.types & (1ULL << i)))\n-\t\t\tcontinue;\n-\n-\t\t/* Configure default input set */\n-\t\tstruct rte_eth_input_set_conf input_conf = {\n-\t\t\t.op = RTE_ETH_INPUT_SET_SELECT,\n-\t\t\t.flow_type = i,\n-\t\t\t.inset_size = 1,\n-\t\t};\n-\t\tinput_conf.field[0] = RTE_ETH_INPUT_SET_DEFAULT;\n-\t\ti40e_hash_filter_inset_select(hw, &input_conf);\n-\t}\n-\n-\trss_info->conf.types = rss_conf.conf.types;\n-\n-\ti40e_rss_clear_hash_function(pf, conf);\n-\n-\treturn 0;\n-}\n-\n-/* Configure RSS queue region to default */\n-static int\n-i40e_rss_clear_queue_region(struct i40e_pf *pf)\n-{\n-\tstruct i40e_hw *hw = I40E_PF_TO_HW(pf);\n-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n-\tuint16_t queue[I40E_MAX_Q_PER_TC];\n-\tuint32_t num_rxq, i;\n-\tuint32_t lut = 0;\n-\tuint16_t j, num;\n-\n-\tnum_rxq = RTE_MIN(pf->dev_data->nb_rx_queues, I40E_MAX_Q_PER_TC);\n-\n-\tfor (j = 0; j < num_rxq; j++)\n-\t\tqueue[j] = j;\n-\n-\t/* If both VMDQ and RSS enabled, not all of PF queues are configured.\n-\t * It's necessary to calculate the actual PF queues that are configured.\n-\t */\n-\tif (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG)\n-\t\tnum = i40e_pf_calc_configured_queues_num(pf);\n-\telse\n-\t\tnum = pf->dev_data->nb_rx_queues;\n-\n-\tnum = RTE_MIN(num, num_rxq);\n-\tPMD_DRV_LOG(INFO, \"Max of contiguous %u PF queues are configured\",\n-\t\t\tnum);\n-\n-\tif (num == 0) {\n-\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\"No PF queues are configured to enable RSS for port %u\",\n-\t\t\tpf->dev_data->port_id);\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\t/* Fill in redirection table */\n-\tfor (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) {\n-\t\tif (j == num)\n-\t\t\tj = 0;\n-\t\tlut = (lut << 8) | (queue[j] & ((0x1 <<\n-\t\t\thw->func_caps.rss_table_entry_width) - 1));\n-\t\tif ((i & 3) == 3)\n-\t\t\tI40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut);\n-\t}\n-\n-\trss_info->conf.queue_num = 0;\n-\tmemset(&rss_info->conf.queue, 0, sizeof(uint16_t));\n-\n-\treturn 0;\n-}\n-\n-int\n-i40e_config_rss_filter(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf, bool add)\n-{\n-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n-\tstruct rte_flow_action_rss update_conf = rss_info->conf;\n-\tint ret = 0;\n-\n-\tif (add) {\n-\t\tif (conf->conf.queue_num) {\n-\t\t\t/* Configure RSS queue region */\n-\t\t\tret = i40e_rss_config_queue_region(pf, conf);\n-\t\t\tif (ret)\n-\t\t\t\treturn ret;\n-\n-\t\t\tupdate_conf.queue_num = conf->conf.queue_num;\n-\t\t\tupdate_conf.queue = conf->conf.queue;\n-\t\t} else if (conf->conf.func ==\n-\t\t\t   RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {\n-\t\t\t/* Configure hash function */\n-\t\t\tret = i40e_rss_config_hash_function(pf, conf);\n-\t\t\tif (ret)\n-\t\t\t\treturn ret;\n-\n-\t\t\tupdate_conf.func = conf->conf.func;\n-\t\t} else {\n-\t\t\t/* Configure hash enable and input set */\n-\t\t\tret = i40e_rss_enable_hash(pf, conf);\n-\t\t\tif (ret)\n-\t\t\t\treturn ret;\n-\n-\t\t\tupdate_conf.types |= conf->conf.types;\n-\t\t\tupdate_conf.key = conf->conf.key;\n-\t\t\tupdate_conf.key_len = conf->conf.key_len;\n-\t\t}\n-\n-\t\t/* Update RSS info in pf */\n-\t\tif (i40e_rss_conf_init(rss_info, &update_conf))\n-\t\t\treturn -EINVAL;\n-\t} else {\n-\t\tif (!conf->valid)\n-\t\t\treturn 0;\n-\n-\t\tif (conf->conf.queue_num)\n-\t\t\ti40e_rss_clear_queue_region(pf);\n-\t\telse if (conf->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR)\n-\t\t\ti40e_rss_clear_hash_function(pf, conf);\n-\t\telse\n-\t\t\ti40e_rss_disable_hash(pf, conf);\n-\t}\n-\n-\treturn 0;\n-}\n-\n RTE_LOG_REGISTER(i40e_logtype_init, pmd.net.i40e.init, NOTICE);\n RTE_LOG_REGISTER(i40e_logtype_driver, pmd.net.i40e.driver, NOTICE);\n #ifdef RTE_LIBRTE_I40E_DEBUG_RX\ndiff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h\nindex 696c5aa..9dabeed 100644\n--- a/drivers/net/i40e/i40e_ethdev.h\n+++ b/drivers/net/i40e/i40e_ethdev.h\n@@ -16,6 +16,8 @@\n #include \"rte_pmd_i40e.h\"\n \n #include \"base/i40e_register.h\"\n+#include \"base/i40e_type.h\"\n+#include \"base/virtchnl.h\"\n \n #define I40E_VLAN_TAG_SIZE        4\n \n@@ -1062,16 +1064,32 @@ struct i40e_customized_pctype {\n };\n \n struct i40e_rte_flow_rss_conf {\n-\tstruct rte_flow_action_rss conf; /**< RSS parameters. */\n-\tuint16_t queue_region_conf; /**< Queue region config flag */\n+\tstruct rte_flow_action_rss conf;\t/**< RSS parameters. */\n+\n \tuint8_t key[(I40E_VFQF_HKEY_MAX_INDEX > I40E_PFQF_HKEY_MAX_INDEX ?\n \t\t     I40E_VFQF_HKEY_MAX_INDEX : I40E_PFQF_HKEY_MAX_INDEX + 1) *\n-\t\t    sizeof(uint32_t)]; /* Hash key. */\n-\tuint16_t queue[I40E_MAX_Q_PER_TC]; /**< Queues indices to use. */\n-\tbool valid; /* Check if it's valid */\n-};\n+\t\t    sizeof(uint32_t)];\t\t/**< Hash key. */\n+\tuint16_t queue[ETH_RSS_RETA_SIZE_512];\t/**< Queues indices to use. */\n \n-TAILQ_HEAD(i40e_rss_conf_list, i40e_rss_filter);\n+\tbool symmetric_enable;\t\t/**< true, if enable symmetric */\n+\tuint64_t config_pctypes;\t/**< All PCTYPES with the flow  */\n+\tuint64_t inset;\t\t\t/**< input sets */\n+\n+\tuint8_t region_priority;\t/**< queue region priority */\n+\tuint8_t region_queue_num;\t/**< region queue number */\n+\tuint16_t region_queue_start;\t/**< region queue start */\n+\n+\tuint32_t misc_reset_flags;\n+#define I40E_HASH_FLOW_RESET_FLAG_FUNC\t\t0x01UL\n+#define I40E_HASH_FLOW_RESET_FLAG_KEY\t\t0x02UL\n+#define I40E_HASH_FLOW_RESET_FLAG_QUEUE\t\t0x04UL\n+#define I40E_HASH_FLOW_RESET_FLAG_REGION\t0x08UL\n+\n+\t/**< All PCTYPES that reset with the flow  */\n+\tuint64_t reset_config_pctypes;\n+\t/**< Symmetric function should reset on PCTYPES */\n+\tuint64_t reset_symmetric_pctypes;\n+};\n \n /* RSS filter list structure */\n struct i40e_rss_filter {\n@@ -1079,6 +1097,8 @@ struct i40e_rss_filter {\n \tstruct i40e_rte_flow_rss_conf rss_filter_info;\n };\n \n+TAILQ_HEAD(i40e_rss_conf_list, i40e_rss_filter);\n+\n struct i40e_vf_msg_cfg {\n \t/* maximal VF message during a statistic period */\n \tuint32_t max_msg;\n@@ -1133,6 +1153,8 @@ struct i40e_pf {\n \tuint16_t fdir_qp_offset;\n \n \tuint16_t hash_lut_size; /* The size of hash lookup table */\n+\tbool hash_filter_enabled;\n+\tuint64_t hash_enabled_queues;\n \t/* input set bits for each pctype */\n \tuint64_t hash_input_set[I40E_FILTER_PCTYPE_MAX];\n \t/* store VXLAN UDP ports */\n@@ -1147,7 +1169,6 @@ struct i40e_pf {\n \tstruct i40e_fdir_info fdir; /* flow director info */\n \tstruct i40e_ethertype_rule ethertype; /* Ethertype filter rule */\n \tstruct i40e_tunnel_rule tunnel; /* Tunnel filter rule */\n-\tstruct i40e_rte_flow_rss_conf rss_info; /* RSS info */\n \tstruct i40e_rss_conf_list rss_config_list; /* RSS rule list */\n \tstruct i40e_queue_regions queue_region; /* queue region info */\n \tstruct i40e_fc_conf fc_conf; /* Flow control conf */\n@@ -1376,8 +1397,8 @@ int i40e_select_filter_input_set(struct i40e_hw *hw,\n \t\t\t\t struct rte_eth_input_set_conf *conf,\n \t\t\t\t enum rte_filter_type filter);\n void i40e_fdir_filter_restore(struct i40e_pf *pf);\n-int i40e_hash_filter_inset_select(struct i40e_hw *hw,\n-\t\t\t     struct rte_eth_input_set_conf *conf);\n+int i40e_set_hash_inset(struct i40e_hw *hw, uint64_t input_set,\n+\t\t\tuint32_t pctype, bool add);\n int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode,\n \t\t\t\tuint32_t retval, uint8_t *msg,\n \t\t\t\tuint16_t msglen);\n@@ -1432,7 +1453,8 @@ int i40e_add_macvlan_filters(struct i40e_vsi *vsi,\n bool is_device_supported(struct rte_eth_dev *dev, struct rte_pci_driver *drv);\n bool is_i40e_supported(struct rte_eth_dev *dev);\n bool is_i40evf_supported(struct rte_eth_dev *dev);\n-\n+void i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw,\n+\t\t\t\t\t     uint8_t enable);\n int i40e_validate_input_set(enum i40e_filter_pctype pctype,\n \t\t\t    enum rte_filter_type filter, uint64_t inset);\n int i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask,\n@@ -1455,12 +1477,13 @@ int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,\n \t\tstruct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);\n void i40e_init_queue_region_conf(struct rte_eth_dev *dev);\n void i40e_flex_payload_reg_set_default(struct i40e_hw *hw);\n+void i40e_pf_disable_rss(struct i40e_pf *pf);\n+int i40e_pf_calc_configured_queues_num(struct i40e_pf *pf);\n+int i40e_pf_reset_rss_reta(struct i40e_pf *pf);\n+int i40e_pf_reset_rss_key(struct i40e_pf *pf);\n+int i40e_pf_config_rss(struct i40e_pf *pf);\n int i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len);\n int i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size);\n-int i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,\n-\t\t       const struct rte_flow_action_rss *in);\n-int i40e_config_rss_filter(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf, bool add);\n int i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params);\n int i40e_vf_representor_uninit(struct rte_eth_dev *ethdev);\n \ndiff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c\nindex b09ff65..d69a794 100644\n--- a/drivers/net/i40e/i40e_flow.c\n+++ b/drivers/net/i40e/i40e_flow.c\n@@ -23,6 +23,7 @@\n #include \"base/i40e_type.h\"\n #include \"base/i40e_prototype.h\"\n #include \"i40e_ethdev.h\"\n+#include \"i40e_hash.h\"\n \n #define I40E_IPV6_TC_MASK\t(0xFF << I40E_FDIR_IPv6_TC_OFFSET)\n #define I40E_IPV6_FRAG_HEADER\t44\n@@ -118,7 +119,6 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,\n static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);\n static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);\n static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);\n-static int i40e_flow_flush_rss_filter(struct rte_eth_dev *dev);\n static int\n i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,\n \t\t\t      const struct rte_flow_attr *attr,\n@@ -4530,566 +4530,6 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \treturn ret;\n }\n \n-/**\n- * This function is used to do configuration i40e existing RSS with rte_flow.\n- * It also enable queue region configuration using flow API for i40e.\n- * pattern can be used indicate what parameters will be include in flow,\n- * like user_priority or flowtype for queue region or HASH function for RSS.\n- * Action is used to transmit parameter like queue index and HASH\n- * function for RSS, or flowtype for queue region configuration.\n- * For example:\n- * pattern:\n- * Case 1: try to transform patterns to pctype. valid pctype will be\n- *         used in parse action.\n- * Case 2: only ETH, indicate flowtype for queue region will be parsed.\n- * Case 3: only VLAN, indicate user_priority for queue region will be parsed.\n- * So, pattern choice is depened on the purpose of configuration of\n- * that flow.\n- * action:\n- * action RSS will be used to transmit valid parameter with\n- * struct rte_flow_action_rss for all the 3 case.\n- */\n-static int\n-i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,\n-\t\t\t     const struct rte_flow_item *pattern,\n-\t\t\t     struct rte_flow_error *error,\n-\t\t\t     struct i40e_rss_pattern_info *p_info,\n-\t\t\t     struct i40e_queue_regions *info)\n-{\n-\tconst struct rte_flow_item_vlan *vlan_spec, *vlan_mask;\n-\tconst struct rte_flow_item *item = pattern;\n-\tenum rte_flow_item_type item_type;\n-\tstruct rte_flow_item *items;\n-\tuint32_t item_num = 0; /* non-void item number of pattern*/\n-\tuint32_t i = 0;\n-\tstatic const struct {\n-\t\tenum rte_flow_item_type *item_array;\n-\t\tuint64_t type;\n-\t} i40e_rss_pctype_patterns[] = {\n-\t\t{ pattern_fdir_ipv4,\n-\t\t\tETH_RSS_FRAG_IPV4 | ETH_RSS_NONFRAG_IPV4_OTHER },\n-\t\t{ pattern_fdir_ipv4_tcp, ETH_RSS_NONFRAG_IPV4_TCP },\n-\t\t{ pattern_fdir_ipv4_udp, ETH_RSS_NONFRAG_IPV4_UDP },\n-\t\t{ pattern_fdir_ipv4_sctp, ETH_RSS_NONFRAG_IPV4_SCTP },\n-\t\t{ pattern_fdir_ipv4_esp, ETH_RSS_ESP },\n-\t\t{ pattern_fdir_ipv4_udp_esp, ETH_RSS_ESP },\n-\t\t{ pattern_fdir_ipv6,\n-\t\t\tETH_RSS_FRAG_IPV6 | ETH_RSS_NONFRAG_IPV6_OTHER },\n-\t\t{ pattern_fdir_ipv6_tcp, ETH_RSS_NONFRAG_IPV6_TCP },\n-\t\t{ pattern_fdir_ipv6_udp, ETH_RSS_NONFRAG_IPV6_UDP },\n-\t\t{ pattern_fdir_ipv6_sctp, ETH_RSS_NONFRAG_IPV6_SCTP },\n-\t\t{ pattern_ethertype, ETH_RSS_L2_PAYLOAD },\n-\t\t{ pattern_fdir_ipv6_esp, ETH_RSS_ESP },\n-\t\t{ pattern_fdir_ipv6_udp_esp, ETH_RSS_ESP },\n-\t};\n-\n-\tp_info->types = I40E_RSS_TYPE_INVALID;\n-\n-\tif (item->type == RTE_FLOW_ITEM_TYPE_END) {\n-\t\tp_info->types = I40E_RSS_TYPE_NONE;\n-\t\treturn 0;\n-\t}\n-\n-\t/* Convert pattern to RSS offload types */\n-\twhile ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {\n-\t\tif ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)\n-\t\t\titem_num++;\n-\t\ti++;\n-\t}\n-\titem_num++;\n-\n-\titems = rte_zmalloc(\"i40e_pattern\",\n-\t\t\t    item_num * sizeof(struct rte_flow_item), 0);\n-\tif (!items) {\n-\t\trte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,\n-\t\t\t\t   NULL, \"No memory for PMD internal items.\");\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\ti40e_pattern_skip_void_item(items, pattern);\n-\n-\tfor (i = 0; i < RTE_DIM(i40e_rss_pctype_patterns); i++) {\n-\t\tif (i40e_match_pattern(i40e_rss_pctype_patterns[i].item_array,\n-\t\t\t\t\titems)) {\n-\t\t\tp_info->types = i40e_rss_pctype_patterns[i].type;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\trte_free(items);\n-\n-\tfor (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {\n-\t\tif (item->last) {\n-\t\t\trte_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   \"Not support range\");\n-\t\t\treturn -rte_errno;\n-\t\t}\n-\t\titem_type = item->type;\n-\t\tswitch (item_type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tp_info->action_flag = 1;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t\tvlan_spec = item->spec;\n-\t\t\tvlan_mask = item->mask;\n-\t\t\tif (vlan_spec && vlan_mask) {\n-\t\t\t\tif (vlan_mask->tci ==\n-\t\t\t\t\trte_cpu_to_be_16(I40E_VLAN_TCI_MASK)) {\n-\t\t\t\t\tinfo->region[0].user_priority[0] =\n-\t\t\t\t\t\t(rte_be_to_cpu_16(\n-\t\t\t\t\t\tvlan_spec->tci) >> 13) & 0x7;\n-\t\t\t\t\tinfo->region[0].user_priority_num = 1;\n-\t\t\t\t\tinfo->queue_region_number = 1;\n-\t\t\t\t\tp_info->action_flag = 0;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tp_info->action_flag = 0;\n-\t\t\tmemset(info, 0, sizeof(struct i40e_queue_regions));\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/**\n- * This function is used to parse RSS queue index, total queue number and\n- * hash functions, If the purpose of this configuration is for queue region\n- * configuration, it will set queue_region_conf flag to TRUE, else to FALSE.\n- * In queue region configuration, it also need to parse hardware flowtype\n- * and user_priority from configuration, it will also cheeck the validity\n- * of these parameters. For example, The queue region sizes should\n- * be any of the following values: 1, 2, 4, 8, 16, 32, 64, the\n- * hw_flowtype or PCTYPE max index should be 63, the user priority\n- * max index should be 7, and so on. And also, queue index should be\n- * continuous sequence and queue region index should be part of RSS\n- * queue index for this port.\n- * For hash params, the pctype in action and pattern must be same.\n- * Set queue index must be with non-types.\n- */\n-static int\n-i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\n-\t\t\t    const struct rte_flow_action *actions,\n-\t\t\t    struct rte_flow_error *error,\n-\t\t\t\tstruct i40e_rss_pattern_info p_info,\n-\t\t\t    struct i40e_queue_regions *conf_info,\n-\t\t\t    union i40e_filter_t *filter)\n-{\n-\tconst struct rte_flow_action *act;\n-\tconst struct rte_flow_action_rss *rss;\n-\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n-\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct i40e_queue_regions *info = &pf->queue_region;\n-\tstruct i40e_rte_flow_rss_conf *rss_config =\n-\t\t\t&filter->rss_conf;\n-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n-\tuint16_t i, j, n, m, tmp, nb_types;\n-\tuint32_t index = 0;\n-\tuint64_t hf_bit = 1;\n-\n-\tstatic const struct {\n-\t\tuint64_t rss_type;\n-\t\tenum i40e_filter_pctype pctype;\n-\t} pctype_match_table[] = {\n-\t\t{ETH_RSS_FRAG_IPV4,\n-\t\t\tI40E_FILTER_PCTYPE_FRAG_IPV4},\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_TCP},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_UDP},\n-\t\t{ETH_RSS_NONFRAG_IPV4_SCTP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_SCTP},\n-\t\t{ETH_RSS_NONFRAG_IPV4_OTHER,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_OTHER},\n-\t\t{ETH_RSS_FRAG_IPV6,\n-\t\t\tI40E_FILTER_PCTYPE_FRAG_IPV6},\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_TCP},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_UDP},\n-\t\t{ETH_RSS_NONFRAG_IPV6_SCTP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_SCTP},\n-\t\t{ETH_RSS_NONFRAG_IPV6_OTHER,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_OTHER},\n-\t\t{ETH_RSS_L2_PAYLOAD,\n-\t\t\tI40E_FILTER_PCTYPE_L2_PAYLOAD},\n-\t};\n-\n-\tstatic const struct {\n-\t\tuint64_t rss_type;\n-\t\tenum i40e_filter_pctype pctype;\n-\t} pctype_match_table_x722[] = {\n-\t\t{ETH_RSS_NONFRAG_IPV4_TCP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP},\n-\t\t{ETH_RSS_NONFRAG_IPV4_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP},\n-\t\t{ETH_RSS_NONFRAG_IPV6_TCP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP},\n-\t\t{ETH_RSS_NONFRAG_IPV6_UDP,\n-\t\t\tI40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP},\n-\t};\n-\n-\tNEXT_ITEM_OF_ACTION(act, actions, index);\n-\trss = act->conf;\n-\n-\t/**\n-\t * RSS only supports forwarding,\n-\t * check if the first not void action is RSS.\n-\t */\n-\tif (act->type != RTE_FLOW_ACTION_TYPE_RSS) {\n-\t\tmemset(rss_config, 0, sizeof(struct i40e_rte_flow_rss_conf));\n-\t\trte_flow_error_set(error, EINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\tact, \"Not supported action.\");\n-\t\treturn -rte_errno;\n-\t}\n-\n-\tif (p_info.action_flag && rss->queue_num) {\n-\t\tfor (j = 0; j < RTE_DIM(pctype_match_table); j++) {\n-\t\t\tif (rss->types & pctype_match_table[j].rss_type) {\n-\t\t\t\tconf_info->region[0].hw_flowtype[0] =\n-\t\t\t\t\t(uint8_t)pctype_match_table[j].pctype;\n-\t\t\t\tconf_info->region[0].flowtype_num = 1;\n-\t\t\t\tconf_info->queue_region_number = 1;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\n-\t\tif (hw->mac.type == I40E_MAC_X722)\n-\t\t\tfor (j = 0; j < RTE_DIM(pctype_match_table_x722); j++) {\n-\t\t\t\tif (rss->types &\n-\t\t\t\t    pctype_match_table_x722[j].rss_type) {\n-\t\t\t\t\tm = conf_info->region[0].flowtype_num;\n-\t\t\t\t\tconf_info->region[0].hw_flowtype[m] =\n-\t\t\t\t\t\tpctype_match_table_x722[j].pctype;\n-\t\t\t\t\tconf_info->region[0].flowtype_num++;\n-\t\t\t\t\tconf_info->queue_region_number = 1;\n-\t\t\t\t}\n-\t\t\t}\n-\t}\n-\n-\t/**\n-\t * Do some queue region related parameters check\n-\t * in order to keep queue index for queue region to be\n-\t * continuous sequence and also to be part of RSS\n-\t * queue index for this port.\n-\t */\n-\tif (conf_info->queue_region_number) {\n-\t\tfor (i = 0; i < rss->queue_num; i++) {\n-\t\t\tfor (j = 0; j < rss_info->conf.queue_num; j++) {\n-\t\t\t\tif (rss->queue[i] == rss_info->conf.queue[j])\n-\t\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (j == rss_info->conf.queue_num) {\n-\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\tact,\n-\t\t\t\t\t\"no valid queues\");\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\t\t}\n-\n-\t\tfor (i = 0; i < rss->queue_num - 1; i++) {\n-\t\t\tif (rss->queue[i + 1] != rss->queue[i] + 1) {\n-\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\tact,\n-\t\t\t\t\t\"no valid queues\");\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\t\t}\n-\t}\n-\n-\t/* Parse queue region related parameters from configuration */\n-\tfor (n = 0; n < conf_info->queue_region_number; n++) {\n-\t\tif (conf_info->region[n].user_priority_num ||\n-\t\t\t\tconf_info->region[n].flowtype_num) {\n-\t\t\tif (!((rte_is_power_of_2(rss->queue_num)) &&\n-\t\t\t\t\trss->queue_num <= 64)) {\n-\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\tact,\n-\t\t\t\t\t\"The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the \"\n-\t\t\t\t\t\"total number of queues do not exceed the VSI allocation\");\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\n-\t\t\tif (conf_info->region[n].user_priority[n] >=\n-\t\t\t\t\tI40E_MAX_USER_PRIORITY) {\n-\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\tact,\n-\t\t\t\t\t\"the user priority max index is 7\");\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\n-\t\t\tif (conf_info->region[n].hw_flowtype[n] >=\n-\t\t\t\t\tI40E_FILTER_PCTYPE_MAX) {\n-\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\tact,\n-\t\t\t\t\t\"the hw_flowtype or PCTYPE max index is 63\");\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\n-\t\t\tfor (i = 0; i < info->queue_region_number; i++) {\n-\t\t\t\tif (info->region[i].queue_num ==\n-\t\t\t\t    rss->queue_num &&\n-\t\t\t\t\tinfo->region[i].queue_start_index ==\n-\t\t\t\t\t\trss->queue[0])\n-\t\t\t\t\tbreak;\n-\t\t\t}\n-\n-\t\t\tif (i == info->queue_region_number) {\n-\t\t\t\tif (i > I40E_REGION_MAX_INDEX) {\n-\t\t\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\tact,\n-\t\t\t\t\t\t\"the queue region max index is 7\");\n-\t\t\t\t\treturn -rte_errno;\n-\t\t\t\t}\n-\n-\t\t\t\tinfo->region[i].queue_num =\n-\t\t\t\t\trss->queue_num;\n-\t\t\t\tinfo->region[i].queue_start_index =\n-\t\t\t\t\trss->queue[0];\n-\t\t\t\tinfo->region[i].region_id =\n-\t\t\t\t\tinfo->queue_region_number;\n-\n-\t\t\t\tj = info->region[i].user_priority_num;\n-\t\t\t\ttmp = conf_info->region[n].user_priority[0];\n-\t\t\t\tif (conf_info->region[n].user_priority_num) {\n-\t\t\t\t\tinfo->region[i].user_priority[j] = tmp;\n-\t\t\t\t\tinfo->region[i].user_priority_num++;\n-\t\t\t\t}\n-\n-\t\t\t\tfor (m = 0; m < conf_info->region[n].flowtype_num; m++) {\n-\t\t\t\t\tj = info->region[i].flowtype_num;\n-\t\t\t\t\ttmp = conf_info->region[n].hw_flowtype[m];\n-\t\t\t\t\tinfo->region[i].hw_flowtype[j] = tmp;\n-\t\t\t\t\tinfo->region[i].flowtype_num++;\n-\t\t\t\t}\n-\t\t\t\tinfo->queue_region_number++;\n-\t\t\t} else {\n-\t\t\t\tj = info->region[i].user_priority_num;\n-\t\t\t\ttmp = conf_info->region[n].user_priority[0];\n-\t\t\t\tif (conf_info->region[n].user_priority_num) {\n-\t\t\t\t\tinfo->region[i].user_priority[j] = tmp;\n-\t\t\t\t\tinfo->region[i].user_priority_num++;\n-\t\t\t\t}\n-\n-\t\t\t\tfor (m = 0; m < conf_info->region[n].flowtype_num; m++) {\n-\t\t\t\t\tj = info->region[i].flowtype_num;\n-\t\t\t\t\ttmp = conf_info->region[n].hw_flowtype[m];\n-\t\t\t\t\tinfo->region[i].hw_flowtype[j] = tmp;\n-\t\t\t\t\tinfo->region[i].flowtype_num++;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\n-\t\trss_config->queue_region_conf = TRUE;\n-\t}\n-\n-\t/**\n-\t * Return function if this flow is used for queue region configuration\n-\t */\n-\tif (rss_config->queue_region_conf)\n-\t\treturn 0;\n-\n-\tif (!rss) {\n-\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\tact,\n-\t\t\t\t\"invalid rule\");\n-\t\treturn -rte_errno;\n-\t}\n-\n-\tfor (n = 0; n < rss->queue_num; n++) {\n-\t\tif (rss->queue[n] >= dev->data->nb_rx_queues) {\n-\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t   act,\n-\t\t\t\t   \"queue id > max number of queues\");\n-\t\t\treturn -rte_errno;\n-\t\t}\n-\t}\n-\n-\tif (rss->queue_num && (p_info.types || rss->types))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"RSS types must be empty while configuring queue region\");\n-\n-\t/* validate pattern and pctype */\n-\tif (!(rss->types & p_info.types) &&\n-\t    (rss->types || p_info.types) && !rss->queue_num)\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t act, \"invalid pctype\");\n-\n-\tnb_types = 0;\n-\tfor (n = 0; n < RTE_ETH_FLOW_MAX; n++) {\n-\t\tif (rss->types & (hf_bit << n))\n-\t\t\tnb_types++;\n-\t\tif (nb_types > 1)\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t act, \"multi pctype is not supported\");\n-\t}\n-\n-\tif (rss->func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR &&\n-\t    (p_info.types || rss->types || rss->queue_num))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"pattern, type and queues must be empty while\"\n-\t\t\t \" setting hash function as simple_xor\");\n-\n-\tif (rss->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ &&\n-\t    !(p_info.types && rss->types))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"pctype and queues can not be empty while\"\n-\t\t\t \" setting hash function as symmetric toeplitz\");\n-\n-\t/* Parse RSS related parameters from configuration */\n-\tif (rss->func >= RTE_ETH_HASH_FUNCTION_MAX ||\n-\t    rss->func == RTE_ETH_HASH_FUNCTION_TOEPLITZ)\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"RSS hash functions are not supported\");\n-\tif (rss->level)\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"a nonzero RSS encapsulation level is not supported\");\n-\tif (rss->key_len && rss->key_len > RTE_DIM(rss_config->key))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"RSS hash key too large\");\n-\tif (rss->queue_num > RTE_DIM(rss_config->queue))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"too many queues for RSS context\");\n-\tif (i40e_rss_conf_init(rss_config, rss))\n-\t\treturn rte_flow_error_set\n-\t\t\t(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, act,\n-\t\t\t \"RSS context initialization failure\");\n-\n-\tindex++;\n-\n-\t/* check if the next not void action is END */\n-\tNEXT_ITEM_OF_ACTION(act, actions, index);\n-\tif (act->type != RTE_FLOW_ACTION_TYPE_END) {\n-\t\tmemset(rss_config, 0, sizeof(struct i40e_rte_flow_rss_conf));\n-\t\trte_flow_error_set(error, EINVAL,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\tact, \"Not supported action.\");\n-\t\treturn -rte_errno;\n-\t}\n-\trss_config->queue_region_conf = FALSE;\n-\n-\treturn 0;\n-}\n-\n-static int\n-i40e_parse_rss_filter(struct rte_eth_dev *dev,\n-\t\t\tconst struct rte_flow_attr *attr,\n-\t\t\tconst struct rte_flow_item pattern[],\n-\t\t\tconst struct rte_flow_action actions[],\n-\t\t\tunion i40e_filter_t *filter,\n-\t\t\tstruct rte_flow_error *error)\n-{\n-\tstruct i40e_rss_pattern_info p_info;\n-\tstruct i40e_queue_regions info;\n-\tint ret;\n-\n-\tmemset(&info, 0, sizeof(struct i40e_queue_regions));\n-\tmemset(&p_info, 0, sizeof(struct i40e_rss_pattern_info));\n-\n-\tret = i40e_flow_parse_rss_pattern(dev, pattern,\n-\t\t\t\t\terror, &p_info, &info);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tret = i40e_flow_parse_rss_action(dev, actions, error,\n-\t\t\t\t\tp_info, &info, filter);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tret = i40e_flow_parse_attr(attr, error);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tcons_filter_type = RTE_ETH_FILTER_HASH;\n-\n-\treturn 0;\n-}\n-\n-static int\n-i40e_config_rss_filter_set(struct rte_eth_dev *dev,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n-\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct i40e_rss_filter *rss_filter;\n-\tint ret;\n-\n-\tif (conf->queue_region_conf) {\n-\t\tret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);\n-\t} else {\n-\t\tret = i40e_config_rss_filter(pf, conf, 1);\n-\t}\n-\n-\tif (ret)\n-\t\treturn ret;\n-\n-\trss_filter = rte_zmalloc(\"i40e_rss_filter\",\n-\t\t\t\tsizeof(*rss_filter), 0);\n-\tif (rss_filter == NULL) {\n-\t\tPMD_DRV_LOG(ERR, \"Failed to alloc memory.\");\n-\t\treturn -ENOMEM;\n-\t}\n-\trss_filter->rss_filter_info = *conf;\n-\t/* the rule new created is always valid\n-\t * the existing rule covered by new rule will be set invalid\n-\t */\n-\trss_filter->rss_filter_info.valid = true;\n-\n-\tTAILQ_INSERT_TAIL(&pf->rss_config_list, rss_filter, next);\n-\n-\treturn 0;\n-}\n-\n-static int\n-i40e_config_rss_filter_del(struct rte_eth_dev *dev,\n-\t\tstruct i40e_rte_flow_rss_conf *conf)\n-{\n-\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n-\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct i40e_rss_filter *rss_filter;\n-\tvoid *temp;\n-\n-\tif (conf->queue_region_conf)\n-\t\ti40e_flush_queue_region_all_conf(dev, hw, pf, 0);\n-\telse\n-\t\ti40e_config_rss_filter(pf, conf, 0);\n-\n-\tTAILQ_FOREACH_SAFE(rss_filter, &pf->rss_config_list, next, temp) {\n-\t\tif (!memcmp(&rss_filter->rss_filter_info, conf,\n-\t\t\tsizeof(struct rte_flow_action_rss))) {\n-\t\t\tTAILQ_REMOVE(&pf->rss_config_list, rss_filter, next);\n-\t\t\trte_free(rss_filter);\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n static int\n i40e_flow_validate(struct rte_eth_dev *dev,\n \t\t   const struct rte_flow_attr *attr,\n@@ -5130,9 +4570,13 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \t\ti++;\n \n \tif ((actions + i)->type == RTE_FLOW_ACTION_TYPE_RSS) {\n-\t\tret = i40e_parse_rss_filter(dev, attr, pattern,\n-\t\t\t\t\tactions, &cons_filter, error);\n-\t\treturn ret;\n+\t\tret = i40e_flow_parse_attr(attr, error);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tcons_filter_type = RTE_ETH_FILTER_HASH;\n+\t\treturn i40e_hash_parse(dev, pattern, actions + i,\n+\t\t\t\t       &cons_filter.rss_conf, error);\n \t}\n \n \ti = 0;\n@@ -5247,12 +4691,11 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \t\t\t\t\ti40e_tunnel_filter_list);\n \t\tbreak;\n \tcase RTE_ETH_FILTER_HASH:\n-\t\tret = i40e_config_rss_filter_set(dev,\n-\t\t\t    &cons_filter.rss_conf);\n+\t\tret = i40e_hash_filter_create(pf, &cons_filter.rss_conf);\n \t\tif (ret)\n \t\t\tgoto free_flow;\n \t\tflow->rule = TAILQ_LAST(&pf->rss_config_list,\n-\t\t\t\ti40e_rss_conf_list);\n+\t\t\t\t\ti40e_rss_conf_list);\n \t\tbreak;\n \tdefault:\n \t\tgoto free_flow;\n@@ -5305,8 +4748,7 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \t\t}\n \t\tbreak;\n \tcase RTE_ETH_FILTER_HASH:\n-\t\tret = i40e_config_rss_filter_del(dev,\n-\t\t\t&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);\n+\t\tret = i40e_hash_filter_destroy(pf, flow->rule);\n \t\tbreak;\n \tdefault:\n \t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n@@ -5454,14 +4896,11 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \t\treturn -rte_errno;\n \t}\n \n-\tret = i40e_flow_flush_rss_filter(dev);\n-\tif (ret) {\n+\tret = i40e_hash_filter_flush(pf);\n+\tif (ret)\n \t\trte_flow_error_set(error, -ret,\n \t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n \t\t\t\t   \"Failed to flush RSS flows.\");\n-\t\treturn -rte_errno;\n-\t}\n-\n \treturn ret;\n }\n \n@@ -5578,36 +5017,6 @@ static int i40e_flow_parse_l4_cloud_filter(struct rte_eth_dev *dev,\n \treturn ret;\n }\n \n-/* remove the RSS filter */\n-static int\n-i40e_flow_flush_rss_filter(struct rte_eth_dev *dev)\n-{\n-\tstruct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n-\tstruct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct rte_flow *flow;\n-\tvoid *temp;\n-\tint32_t ret = -EINVAL;\n-\n-\tret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);\n-\n-\t/* Delete RSS flows in flow list. */\n-\tTAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {\n-\t\tif (flow->filter_type != RTE_ETH_FILTER_HASH)\n-\t\t\tcontinue;\n-\n-\t\tif (flow->rule) {\n-\t\t\tret = i40e_config_rss_filter_del(dev,\n-\t\t\t\t&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);\n-\t\t\tif (ret)\n-\t\t\t\treturn ret;\n-\t\t}\n-\t\tTAILQ_REMOVE(&pf->flow_list, flow, node);\n-\t\trte_free(flow);\n-\t}\n-\n-\treturn ret;\n-}\n-\n static int\n i40e_flow_query(struct rte_eth_dev *dev __rte_unused,\n \t\tstruct rte_flow *flow,\ndiff --git a/drivers/net/i40e/i40e_hash.c b/drivers/net/i40e/i40e_hash.c\nnew file mode 100644\nindex 0000000..e07f806\n--- /dev/null\n+++ b/drivers/net/i40e/i40e_hash.c\n@@ -0,0 +1,1383 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <sys/queue.h>\n+#include <stdio.h>\n+#include <errno.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <assert.h>\n+\n+#include <rte_malloc.h>\n+#include <rte_tailq.h>\n+#include \"base/i40e_prototype.h\"\n+#include \"i40e_logs.h\"\n+#include \"i40e_ethdev.h\"\n+#include \"i40e_hash.h\"\n+\n+#ifndef BIT\n+#define BIT(n)\t\t\t\t(1UL << (n))\n+#endif\n+\n+#ifndef BIT_ULL\n+#define BIT_ULL(n)\t\t\t(1ULL << (n))\n+#endif\n+\n+/* Pattern item headers */\n+#define I40E_HASH_HDR_ETH\t\t0x01ULL\n+#define I40E_HASH_HDR_IPV4\t\t0x10ULL\n+#define I40E_HASH_HDR_IPV6\t\t0x20ULL\n+#define I40E_HASH_HDR_TCP\t\t0x100ULL\n+#define I40E_HASH_HDR_UDP\t\t0x200ULL\n+#define I40E_HASH_HDR_SCTP\t\t0x400ULL\n+#define I40E_HASH_HDR_ESP\t\t0x10000ULL\n+#define I40E_HASH_HDR_L2TPV3\t\t0x20000ULL\n+#define I40E_HASH_HDR_AH\t\t0x40000ULL\n+#define I40E_HASH_HDR_GTPC\t\t0x100000ULL\n+#define I40E_HASH_HDR_GTPU\t\t0x200000ULL\n+\n+#define I40E_HASH_HDR_INNER_SHIFT\t32\n+#define I40E_HASH_HDR_IPV4_INNER\t(I40E_HASH_HDR_IPV4 << \\\n+\t\t\t\t\tI40E_HASH_HDR_INNER_SHIFT)\n+#define I40E_HASH_HDR_IPV6_INNER\t(I40E_HASH_HDR_IPV6 << \\\n+\t\t\t\t\tI40E_HASH_HDR_INNER_SHIFT)\n+\n+/* ETH */\n+#define I40E_PHINT_ETH\t\t\tI40E_HASH_HDR_ETH\n+\n+/* IPv4 */\n+#define I40E_PHINT_IPV4\t\t\t(I40E_HASH_HDR_ETH | I40E_HASH_HDR_IPV4)\n+#define I40E_PHINT_IPV4_TCP\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_TCP)\n+#define I40E_PHINT_IPV4_UDP\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_UDP)\n+#define I40E_PHINT_IPV4_SCTP\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_SCTP)\n+\n+/* IPv6 */\n+#define I40E_PHINT_IPV6\t\t\t(I40E_HASH_HDR_ETH | I40E_HASH_HDR_IPV6)\n+#define I40E_PHINT_IPV6_TCP\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_TCP)\n+#define I40E_PHINT_IPV6_UDP\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_UDP)\n+#define I40E_PHINT_IPV6_SCTP\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_SCTP)\n+\n+/* ESP */\n+#define I40E_PHINT_IPV4_ESP\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_ESP)\n+#define I40E_PHINT_IPV6_ESP\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_ESP)\n+#define I40E_PHINT_IPV4_UDP_ESP\t\t(I40E_PHINT_IPV4_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_ESP)\n+#define I40E_PHINT_IPV6_UDP_ESP\t\t(I40E_PHINT_IPV6_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_ESP)\n+\n+/* GTPC */\n+#define I40E_PHINT_IPV4_GTPC\t\t(I40E_PHINT_IPV4_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_GTPC)\n+#define I40E_PHINT_IPV6_GTPC\t\t(I40E_PHINT_IPV6_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_GTPC)\n+\n+/* GTPU */\n+#define I40E_PHINT_IPV4_GTPU\t\t(I40E_PHINT_IPV4_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_GTPU)\n+#define I40E_PHINT_IPV4_GTPU_IPV4\t(I40E_PHINT_IPV4_GTPU | \\\n+\t\t\t\t\tI40E_HASH_HDR_IPV4_INNER)\n+#define I40E_PHINT_IPV4_GTPU_IPV6\t(I40E_PHINT_IPV4_GTPU | \\\n+\t\t\t\t\tI40E_HASH_HDR_IPV6_INNER)\n+#define I40E_PHINT_IPV6_GTPU\t\t(I40E_PHINT_IPV6_UDP | \\\n+\t\t\t\t\tI40E_HASH_HDR_GTPU)\n+#define I40E_PHINT_IPV6_GTPU_IPV4\t(I40E_PHINT_IPV6_GTPU | \\\n+\t\t\t\t\tI40E_HASH_HDR_IPV4_INNER)\n+#define I40E_PHINT_IPV6_GTPU_IPV6\t(I40E_PHINT_IPV6_GTPU | \\\n+\t\t\t\t\tI40E_HASH_HDR_IPV6_INNER)\n+\n+/* L2TPV3 */\n+#define I40E_PHINT_IPV4_L2TPV3\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_L2TPV3)\n+#define I40E_PHINT_IPV6_L2TPV3\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_L2TPV3)\n+\n+/* AH */\n+#define I40E_PHINT_IPV4_AH\t\t(I40E_PHINT_IPV4 | I40E_HASH_HDR_AH)\n+#define I40E_PHINT_IPV6_AH\t\t(I40E_PHINT_IPV6 | I40E_HASH_HDR_AH)\n+\n+/* Structure of mapping RSS type to input set */\n+struct i40e_hash_map_rss_inset {\n+\tuint64_t rss_type;\n+\tuint64_t inset;\n+};\n+\n+const struct i40e_hash_map_rss_inset i40e_hash_rss_inset[] = {\n+\t/* IPv4 */\n+\t{ ETH_RSS_IPV4, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },\n+\t{ ETH_RSS_FRAG_IPV4, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },\n+\n+\t{ ETH_RSS_NONFRAG_IPV4_OTHER,\n+\t  I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },\n+\n+\t{ ETH_RSS_NONFRAG_IPV4_TCP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },\n+\n+\t{ ETH_RSS_NONFRAG_IPV4_UDP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },\n+\n+\t{ ETH_RSS_NONFRAG_IPV4_SCTP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT },\n+\n+\t/* IPv6 */\n+\t{ ETH_RSS_IPV6, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },\n+\t{ ETH_RSS_FRAG_IPV6, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },\n+\n+\t{ ETH_RSS_NONFRAG_IPV6_OTHER,\n+\t  I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },\n+\n+\t{ ETH_RSS_NONFRAG_IPV6_TCP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },\n+\n+\t{ ETH_RSS_NONFRAG_IPV6_UDP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },\n+\n+\t{ ETH_RSS_NONFRAG_IPV6_SCTP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |\n+\t  I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT },\n+\n+\t/* Port */\n+\t{ ETH_RSS_PORT, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },\n+\n+\t/* Ether */\n+\t{ ETH_RSS_L2_PAYLOAD, I40E_INSET_LAST_ETHER_TYPE },\n+\t{ ETH_RSS_ETH, I40E_INSET_DMAC | I40E_INSET_SMAC },\n+\n+\t/* VLAN */\n+\t{ ETH_RSS_S_VLAN, I40E_INSET_VLAN_OUTER },\n+\t{ ETH_RSS_C_VLAN, I40E_INSET_VLAN_INNER },\n+};\n+\n+#define I40E_HASH_VOID_NEXT_ALLOW\tBIT_ULL(RTE_FLOW_ITEM_TYPE_ETH)\n+\n+#define I40E_HASH_ETH_NEXT_ALLOW\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_VLAN))\n+\n+#define I40E_HASH_IP_NEXT_ALLOW\t\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_TCP) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_UDP) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_SCTP) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_ESP) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_L2TPV3OIP) |\\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_AH))\n+\n+#define I40E_HASH_UDP_NEXT_ALLOW\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_GTPU) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_GTPC))\n+\n+#define I40E_HASH_GTPU_NEXT_ALLOW\t(BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \\\n+\t\t\t\t\tBIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6))\n+\n+static const uint64_t pattern_next_allow_items[] = {\n+\t[RTE_FLOW_ITEM_TYPE_VOID] = I40E_HASH_VOID_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_ETH] = I40E_HASH_ETH_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_IPV4] = I40E_HASH_IP_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_IPV6] = I40E_HASH_IP_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_UDP] = I40E_HASH_UDP_NEXT_ALLOW,\n+\t[RTE_FLOW_ITEM_TYPE_GTPU] = I40E_HASH_GTPU_NEXT_ALLOW,\n+};\n+\n+static const uint64_t pattern_item_header[] = {\n+\t[RTE_FLOW_ITEM_TYPE_ETH] = I40E_HASH_HDR_ETH,\n+\t[RTE_FLOW_ITEM_TYPE_IPV4] = I40E_HASH_HDR_IPV4,\n+\t[RTE_FLOW_ITEM_TYPE_IPV6] = I40E_HASH_HDR_IPV6,\n+\t[RTE_FLOW_ITEM_TYPE_TCP] = I40E_HASH_HDR_TCP,\n+\t[RTE_FLOW_ITEM_TYPE_UDP] = I40E_HASH_HDR_UDP,\n+\t[RTE_FLOW_ITEM_TYPE_SCTP] = I40E_HASH_HDR_SCTP,\n+\t[RTE_FLOW_ITEM_TYPE_ESP] = I40E_HASH_HDR_ESP,\n+\t[RTE_FLOW_ITEM_TYPE_GTPC] = I40E_HASH_HDR_GTPC,\n+\t[RTE_FLOW_ITEM_TYPE_GTPU] = I40E_HASH_HDR_GTPU,\n+\t[RTE_FLOW_ITEM_TYPE_L2TPV3OIP] = I40E_HASH_HDR_L2TPV3,\n+\t[RTE_FLOW_ITEM_TYPE_AH] = I40E_HASH_HDR_AH,\n+};\n+\n+/* Structure of matched pattern */\n+struct i40e_hash_match_pattern {\n+\tuint64_t pattern_type;\n+\tuint64_t rss_mask;\t/* Supported RSS type for this pattern */\n+\tbool custom_pctype_flag;/* true for custom packet type */\n+\tuint8_t pctype;\n+};\n+\n+#define I40E_HASH_MAP_PATTERN(pattern, rss_mask, pctype) { \\\n+\tpattern, rss_mask, false, pctype  }\n+\n+#define I40E_HASH_MAP_CUS_PATTERN(pattern, rss_mask, cus_pctype) { \\\n+\tpattern, rss_mask, true, cus_pctype }\n+\n+#define I40E_HASH_L2_RSS_MASK\t\t(ETH_RSS_ETH | ETH_RSS_L2_SRC_ONLY | \\\n+\t\t\t\t\tETH_RSS_L2_DST_ONLY)\n+\n+#define I40E_HASH_L23_RSS_MASK\t\t(I40E_HASH_L2_RSS_MASK | \\\n+\t\t\t\t\tETH_RSS_VLAN | \\\n+\t\t\t\t\tETH_RSS_L3_SRC_ONLY | \\\n+\t\t\t\t\tETH_RSS_L3_DST_ONLY)\n+\n+#define I40E_HASH_IPV4_L23_RSS_MASK\t(ETH_RSS_IPV4 | I40E_HASH_L23_RSS_MASK)\n+#define I40E_HASH_IPV6_L23_RSS_MASK\t(ETH_RSS_IPV6 | I40E_HASH_L23_RSS_MASK)\n+\n+#define I40E_HASH_L234_RSS_MASK\t\t(I40E_HASH_L23_RSS_MASK | \\\n+\t\t\t\t\tETH_RSS_PORT | ETH_RSS_L4_SRC_ONLY | \\\n+\t\t\t\t\tETH_RSS_L4_DST_ONLY)\n+\n+#define I40E_HASH_IPV4_L234_RSS_MASK\t(I40E_HASH_L234_RSS_MASK | ETH_RSS_IPV4)\n+#define I40E_HASH_IPV6_L234_RSS_MASK\t(I40E_HASH_L234_RSS_MASK | ETH_RSS_IPV6)\n+\n+#define I40E_HASH_L4_TYPES\t\t(ETH_RSS_NONFRAG_IPV4_TCP | \\\n+\t\t\t\t\tETH_RSS_NONFRAG_IPV4_UDP | \\\n+\t\t\t\t\tETH_RSS_NONFRAG_IPV4_SCTP | \\\n+\t\t\t\t\tETH_RSS_NONFRAG_IPV6_TCP | \\\n+\t\t\t\t\tETH_RSS_NONFRAG_IPV6_UDP | \\\n+\t\t\t\t\tETH_RSS_NONFRAG_IPV6_SCTP)\n+\n+/* Current supported patterns and RSS types.\n+ * All items that have the same pattern types are together.\n+ */\n+static const struct i40e_hash_match_pattern match_patterns[] = {\n+\t/* Ether */\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_ETH,\n+\t\t\t      ETH_RSS_L2_PAYLOAD | I40E_HASH_L2_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_L2_PAYLOAD),\n+\n+\t/* IPv4 */\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4,\n+\t\t\t      ETH_RSS_FRAG_IPV4 | I40E_HASH_IPV4_L23_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_FRAG_IPV4),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4,\n+\t\t\t      ETH_RSS_NONFRAG_IPV4_OTHER |\n+\t\t\t      I40E_HASH_IPV4_L23_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV4_OTHER),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_TCP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV4_TCP |\n+\t\t\t      I40E_HASH_IPV4_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV4_TCP),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_UDP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV4_UDP |\n+\t\t\t      I40E_HASH_IPV4_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV4_UDP),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_SCTP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV4_SCTP |\n+\t\t\t      I40E_HASH_IPV4_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV4_SCTP),\n+\n+\t/* IPv6 */\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6,\n+\t\t\t      ETH_RSS_FRAG_IPV6 | I40E_HASH_IPV6_L23_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_FRAG_IPV6),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6,\n+\t\t\t      ETH_RSS_NONFRAG_IPV6_OTHER |\n+\t\t\t      I40E_HASH_IPV6_L23_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV6_OTHER),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_TCP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV6_TCP |\n+\t\t\t      I40E_HASH_IPV6_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV6_TCP),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_UDP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV6_UDP |\n+\t\t\t      I40E_HASH_IPV6_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV6_UDP),\n+\n+\tI40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_SCTP,\n+\t\t\t      ETH_RSS_NONFRAG_IPV6_SCTP |\n+\t\t\t      I40E_HASH_IPV6_L234_RSS_MASK,\n+\t\t\t      I40E_FILTER_PCTYPE_NONF_IPV6_SCTP),\n+\n+\t/* ESP */\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_ESP,\n+\t\t\t\t  ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV4),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_ESP,\n+\t\t\t\t  ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV6),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_UDP_ESP,\n+\t\t\t\t  ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV4_UDP),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_UDP_ESP,\n+\t\t\t\t  ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV6_UDP),\n+\n+\t/* GTPC */\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPC,\n+\t\t\t\t  I40E_HASH_IPV4_L234_RSS_MASK,\n+\t\t\t\t  I40E_CUSTOMIZED_GTPC),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPC,\n+\t\t\t\t  I40E_HASH_IPV6_L234_RSS_MASK,\n+\t\t\t\t  I40E_CUSTOMIZED_GTPC),\n+\n+\t/* GTPU */\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU,\n+\t\t\t\t  I40E_HASH_IPV4_L234_RSS_MASK,\n+\t\t\t\t  I40E_CUSTOMIZED_GTPU),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU_IPV4,\n+\t\t\t\t  ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV4),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU_IPV6,\n+\t\t\t\t  ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV6),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU,\n+\t\t\t\t  I40E_HASH_IPV6_L234_RSS_MASK,\n+\t\t\t\t  I40E_CUSTOMIZED_GTPU),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU_IPV4,\n+\t\t\t\t  ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV4),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU_IPV6,\n+\t\t\t\t  ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV6),\n+\n+\t/* L2TPV3 */\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_L2TPV3,\n+\t\t\t\t  ETH_RSS_L2TPV3, I40E_CUSTOMIZED_IPV4_L2TPV3),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_L2TPV3,\n+\t\t\t\t  ETH_RSS_L2TPV3, I40E_CUSTOMIZED_IPV6_L2TPV3),\n+\n+\t/* AH */\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_AH, ETH_RSS_AH,\n+\t\t\t\t  I40E_CUSTOMIZED_AH_IPV4),\n+\tI40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_AH, ETH_RSS_AH,\n+\t\t\t\t  I40E_CUSTOMIZED_AH_IPV6),\n+};\n+\n+static int\n+i40e_hash_get_pattern_type(const struct rte_flow_item pattern[],\n+\t\t\t   uint64_t *pattern_types,\n+\t\t\t   struct rte_flow_error *error)\n+{\n+\tconst char *message = \"Pattern not supported\";\n+\tenum rte_flow_item_type prev_item_type = RTE_FLOW_ITEM_TYPE_VOID;\n+\tenum rte_flow_item_type last_item_type = prev_item_type;\n+\tuint64_t item_hdr, pattern_hdrs = 0;\n+\tbool inner_flag = false;\n+\tint vlan_count = 0;\n+\n+\tfor (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {\n+\t\tif (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\t\tcontinue;\n+\n+\t\tif (pattern->mask || pattern->spec || pattern->last) {\n+\t\t\tmessage = \"Header info should not be specified\";\n+\t\t\tgoto not_sup;\n+\t\t}\n+\n+\t\t/* Check the previous item allows this sub-item. */\n+\t\tif (prev_item_type >= RTE_DIM(pattern_next_allow_items) ||\n+\t\t    !(pattern_next_allow_items[prev_item_type] &\n+\t\t    BIT_ULL(pattern->type)))\n+\t\t\tgoto not_sup;\n+\n+\t\t/* For VLAN item, it does no matter about to pattern type\n+\t\t * recognition. So just count the number of VLAN and do not\n+\t\t * change the value of variable `prev_item_type`.\n+\t\t */\n+\t\tlast_item_type = pattern->type;\n+\t\tif (last_item_type == RTE_FLOW_ITEM_TYPE_VLAN) {\n+\t\t\tif (vlan_count >= 2)\n+\t\t\t\tgoto not_sup;\n+\t\t\tvlan_count++;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tprev_item_type = last_item_type;\n+\t\tassert(last_item_type < RTE_DIM(pattern_item_header));\n+\t\titem_hdr = pattern_item_header[last_item_type];\n+\t\tassert(item_hdr);\n+\n+\t\tif (inner_flag) {\n+\t\t\titem_hdr <<= I40E_HASH_HDR_INNER_SHIFT;\n+\n+\t\t\t/* Inner layer should not have GTPU item */\n+\t\t\tif (last_item_type == RTE_FLOW_ITEM_TYPE_GTPU)\n+\t\t\t\tgoto not_sup;\n+\t\t} else {\n+\t\t\tif (last_item_type == RTE_FLOW_ITEM_TYPE_GTPU) {\n+\t\t\t\tinner_flag = true;\n+\t\t\t\tvlan_count = 0;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (item_hdr & pattern_hdrs)\n+\t\t\tgoto not_sup;\n+\n+\t\tpattern_hdrs |= item_hdr;\n+\t}\n+\n+\tif (pattern_hdrs && last_item_type != RTE_FLOW_ITEM_TYPE_VLAN) {\n+\t\t*pattern_types = pattern_hdrs;\n+\t\treturn 0;\n+\t}\n+\n+not_sup:\n+\treturn rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t  pattern, message);\n+}\n+\n+static uint64_t\n+i40e_hash_get_x722_ext_pctypes(uint8_t match_pctype)\n+{\n+\tuint64_t pctypes = 0;\n+\n+\tswitch (match_pctype) {\n+\tcase I40E_FILTER_PCTYPE_NONF_IPV4_TCP:\n+\t\tpctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);\n+\t\tbreak;\n+\n+\tcase I40E_FILTER_PCTYPE_NONF_IPV4_UDP:\n+\t\tpctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |\n+\t\t\t  BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);\n+\t\tbreak;\n+\n+\tcase I40E_FILTER_PCTYPE_NONF_IPV6_TCP:\n+\t\tpctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);\n+\t\tbreak;\n+\n+\tcase I40E_FILTER_PCTYPE_NONF_IPV6_UDP:\n+\t\tpctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |\n+\t\t\t  BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);\n+\t\tbreak;\n+\t}\n+\n+\treturn pctypes;\n+}\n+\n+static int\n+i40e_hash_translate_gtp_inset(struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\t      struct rte_flow_error *error)\n+{\n+\tif (rss_conf->inset &\n+\t    (I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC |\n+\t    I40E_INSET_DST_PORT | I40E_INSET_SRC_PORT))\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Only support external destination IP\");\n+\n+\tif (rss_conf->inset & I40E_INSET_IPV4_DST)\n+\t\trss_conf->inset = (rss_conf->inset & ~I40E_INSET_IPV4_DST) |\n+\t\t\t\t  I40E_INSET_TUNNEL_IPV4_DST;\n+\n+\tif (rss_conf->inset & I40E_INSET_IPV6_DST)\n+\t\trss_conf->inset = (rss_conf->inset & ~I40E_INSET_IPV6_DST) |\n+\t\t\t\t  I40E_INSET_TUNNEL_IPV6_DST;\n+\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_get_pctypes(const struct rte_eth_dev *dev,\n+\t\t      const struct i40e_hash_match_pattern *match,\n+\t\t      struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t      struct rte_flow_error *error)\n+{\n+\tif (match->custom_pctype_flag) {\n+\t\tstruct i40e_pf *pf;\n+\t\tstruct i40e_customized_pctype *custom_type;\n+\n+\t\tpf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\t\tcustom_type = i40e_find_customized_pctype(pf, match->pctype);\n+\t\tif (!custom_type || !custom_type->valid)\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  NULL, \"PCTYPE not supported\");\n+\n+\t\trss_conf->config_pctypes |= BIT_ULL(custom_type->pctype);\n+\n+\t\tif (match->pctype == I40E_CUSTOMIZED_GTPU ||\n+\t\t    match->pctype == I40E_CUSTOMIZED_GTPC)\n+\t\t\treturn i40e_hash_translate_gtp_inset(rss_conf, error);\n+\t} else {\n+\t\tstruct i40e_hw *hw =\n+\t\t\t\tI40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\t\tuint64_t types;\n+\n+\t\trss_conf->config_pctypes |= BIT_ULL(match->pctype);\n+\t\tif (hw->mac.type == I40E_MAC_X722) {\n+\t\t\ttypes = i40e_hash_get_x722_ext_pctypes(match->pctype);\n+\t\t\trss_conf->config_pctypes |= types;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_get_pattern_pctypes(const struct rte_eth_dev *dev,\n+\t\t\t      const struct rte_flow_item pattern[],\n+\t\t\t      const struct rte_flow_action_rss *rss_act,\n+\t\t\t      struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\t      struct rte_flow_error *error)\n+{\n+\tuint64_t pattern_types = 0;\n+\tbool match_flag = false;\n+\tint i, ret;\n+\n+\tret = i40e_hash_get_pattern_type(pattern, &pattern_types, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfor (i = 0; i < (int)RTE_DIM(match_patterns); i++) {\n+\t\tconst struct i40e_hash_match_pattern *match =\n+\t\t\t\t\t\t\t&match_patterns[i];\n+\n+\t\t/* Check pattern types match. All items that have the same\n+\t\t * pattern types are together, so if the pattern types match\n+\t\t * previous item but they doesn't match current item, it means\n+\t\t * the pattern types do not match all remain items.\n+\t\t */\n+\t\tif (pattern_types != match->pattern_type) {\n+\t\t\tif (match_flag)\n+\t\t\t\tbreak;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tmatch_flag = true;\n+\n+\t\t/* Check RSS types match */\n+\t\tif (!(rss_act->types & ~match->rss_mask)) {\n+\t\t\tret = i40e_hash_get_pctypes(dev, match,\n+\t\t\t\t\t\t    rss_conf, error);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (rss_conf->config_pctypes)\n+\t\treturn 0;\n+\n+\tif (match_flag)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"RSS types not supported\");\n+\n+\treturn rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t  NULL, \"Pattern not supported\");\n+}\n+\n+static uint64_t\n+i40e_hash_get_inset(uint64_t rss_types)\n+{\n+\tuint64_t mask, inset = 0;\n+\tint i;\n+\n+\tfor (i = 0; i < (int)RTE_DIM(i40e_hash_rss_inset); i++) {\n+\t\tif (rss_types & i40e_hash_rss_inset[i].rss_type)\n+\t\t\tinset |= i40e_hash_rss_inset[i].inset;\n+\t}\n+\n+\tif (!inset)\n+\t\treturn 0;\n+\n+\t/* If SRC_ONLY and DST_ONLY of the same level are used simultaneously,\n+\t * it is the same case as none of them are added.\n+\t */\n+\tmask = rss_types & (ETH_RSS_L2_SRC_ONLY | ETH_RSS_L2_DST_ONLY);\n+\tif (mask == ETH_RSS_L2_SRC_ONLY)\n+\t\tinset &= ~I40E_INSET_DMAC;\n+\telse if (mask == ETH_RSS_L2_DST_ONLY)\n+\t\tinset &= ~I40E_INSET_SMAC;\n+\n+\tmask = rss_types & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY);\n+\tif (mask == ETH_RSS_L3_SRC_ONLY)\n+\t\tinset &= ~(I40E_INSET_IPV4_DST | I40E_INSET_IPV6_DST);\n+\telse if (mask == ETH_RSS_L3_DST_ONLY)\n+\t\tinset &= ~(I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC);\n+\n+\tmask = rss_types & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY);\n+\tif (mask == ETH_RSS_L4_SRC_ONLY)\n+\t\tinset &= ~I40E_INSET_DST_PORT;\n+\telse if (mask == ETH_RSS_L4_DST_ONLY)\n+\t\tinset &= ~I40E_INSET_SRC_PORT;\n+\n+\tif (rss_types & I40E_HASH_L4_TYPES) {\n+\t\tuint64_t l3_mask = rss_types &\n+\t\t\t\t   (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY);\n+\t\tuint64_t l4_mask = rss_types &\n+\t\t\t\t   (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY);\n+\n+\t\tif (l3_mask && !l4_mask)\n+\t\t\tinset &= ~(I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT);\n+\t\telse if (!l3_mask && l4_mask)\n+\t\t\tinset &= ~(I40E_INSET_IPV4_DST | I40E_INSET_IPV6_DST |\n+\t\t\t\t I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC);\n+\t}\n+\n+\treturn inset;\n+}\n+\n+static int\n+i40e_hash_config_func(struct i40e_hw *hw, enum rte_eth_hash_function func)\n+{\n+\tstruct i40e_pf *pf;\n+\tuint32_t reg;\n+\tuint8_t symmetric = 0;\n+\n+\treg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);\n+\n+\tif (func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {\n+\t\tif (!(reg & I40E_GLQF_CTL_HTOEP_MASK))\n+\t\t\tgoto set_symmetric;\n+\n+\t\treg &= ~I40E_GLQF_CTL_HTOEP_MASK;\n+\t} else {\n+\t\tif (func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)\n+\t\t\tsymmetric = 1;\n+\n+\t\tif (reg & I40E_GLQF_CTL_HTOEP_MASK)\n+\t\t\tgoto set_symmetric;\n+\n+\t\treg |= I40E_GLQF_CTL_HTOEP_MASK;\n+\t}\n+\n+\tpf = &((struct i40e_adapter *)hw->back)->pf;\n+\tif (pf->support_multi_driver) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Modify hash function is not permitted when multi-driver enabled\");\n+\t\treturn -EPERM;\n+\t}\n+\n+\tPMD_DRV_LOG(INFO, \"NIC hash function is setting to %d\", func);\n+\ti40e_write_rx_ctl(hw, I40E_GLQF_CTL, reg);\n+\tI40E_WRITE_FLUSH(hw);\n+\n+set_symmetric:\n+\ti40e_set_symmetric_hash_enable_per_port(hw, symmetric);\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_config_pctype_symmetric(struct i40e_hw *hw,\n+\t\t\t\t  uint32_t pctype,\n+\t\t\t\t  bool symmetric)\n+{\n+\tstruct i40e_pf *pf = &((struct i40e_adapter *)hw->back)->pf;\n+\tuint32_t reg;\n+\n+\t/* For X722, get translated pctype in fd pctype register */\n+\tif (hw->mac.type == I40E_MAC_X722)\n+\t\tpctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(pctype));\n+\n+\treg = i40e_read_rx_ctl(hw, I40E_GLQF_HSYM(pctype));\n+\tif (symmetric) {\n+\t\tif (reg & I40E_GLQF_HSYM_SYMH_ENA_MASK)\n+\t\t\treturn 0;\n+\t\treg |= I40E_GLQF_HSYM_SYMH_ENA_MASK;\n+\t} else {\n+\t\tif (!(reg & I40E_GLQF_HSYM_SYMH_ENA_MASK))\n+\t\t\treturn 0;\n+\t\treg &= ~I40E_GLQF_HSYM_SYMH_ENA_MASK;\n+\t}\n+\n+\tif (pf->support_multi_driver) {\n+\t\tPMD_DRV_LOG(ERR,\n+\t\t\t    \"Enable/Disable symmetric hash is not permitted when multi-driver enabled\");\n+\t\treturn -EPERM;\n+\t}\n+\n+\ti40e_write_rx_ctl(hw, I40E_GLQF_HSYM(pctype), reg);\n+\tI40E_WRITE_FLUSH(hw);\n+\treturn 0;\n+}\n+\n+static void\n+i40e_hash_enable_pctype(struct i40e_hw *hw,\n+\t\t\tuint32_t pctype, bool enable)\n+{\n+\tuint32_t reg, reg_val, mask;\n+\n+\t/* For X722, get translated pctype in fd pctype register */\n+\tif (hw->mac.type == I40E_MAC_X722)\n+\t\tpctype = i40e_read_rx_ctl(hw, I40E_GLQF_FD_PCTYPES(pctype));\n+\n+\tif (pctype < 32) {\n+\t\tmask = BIT(pctype);\n+\t\treg = I40E_PFQF_HENA(0);\n+\t} else {\n+\t\tmask = BIT(pctype - 32);\n+\t\treg = I40E_PFQF_HENA(1);\n+\t}\n+\n+\treg_val = i40e_read_rx_ctl(hw, reg);\n+\n+\tif (enable) {\n+\t\tif (reg_val & mask)\n+\t\t\treturn;\n+\n+\t\treg_val |= mask;\n+\t} else {\n+\t\tif (!(reg_val & mask))\n+\t\t\treturn;\n+\n+\t\treg_val &= ~mask;\n+\t}\n+\n+\ti40e_write_rx_ctl(hw, reg, reg_val);\n+\tI40E_WRITE_FLUSH(hw);\n+}\n+\n+static int\n+i40e_hash_config_pctype(struct i40e_hw *hw,\n+\t\t\tstruct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\tuint32_t pctype)\n+{\n+\tuint64_t rss_types = rss_conf->conf.types;\n+\tint ret;\n+\n+\tif (rss_types == 0) {\n+\t\ti40e_hash_enable_pctype(hw, pctype, false);\n+\t\treturn 0;\n+\t}\n+\n+\tif (rss_conf->inset) {\n+\t\tret = i40e_set_hash_inset(hw, rss_conf->inset, pctype, false);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\ti40e_hash_enable_pctype(hw, pctype, true);\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_config_region(struct i40e_pf *pf,\n+\t\t\tconst struct i40e_rte_flow_rss_conf *rss_conf)\n+{\n+\tstruct i40e_hw *hw = &pf->adapter->hw;\n+\tstruct rte_eth_dev *dev = pf->adapter->eth_dev;\n+\tstruct i40e_queue_region_info *regions = pf->queue_region.region;\n+\tuint32_t num = pf->queue_region.queue_region_number;\n+\tuint32_t i, region_id_mask = 0;\n+\n+\t/* Use a 32 bit variable to represent all regions */\n+\tRTE_BUILD_BUG_ON(I40E_REGION_MAX_INDEX > 31);\n+\n+\t/* Re-configure the region if it existed */\n+\tfor (i = 0; i < num; i++) {\n+\t\tif (rss_conf->region_queue_start ==\n+\t\t    regions[i].queue_start_index &&\n+\t\t    rss_conf->region_queue_num == regions[i].queue_num) {\n+\t\t\tuint32_t j;\n+\n+\t\t\tfor (j = 0; j < regions[i].user_priority_num; j++) {\n+\t\t\t\tif (regions[i].user_priority[j] ==\n+\t\t\t\t    rss_conf->region_priority)\n+\t\t\t\t\treturn 0;\n+\t\t\t}\n+\n+\t\t\tif (j >= I40E_MAX_USER_PRIORITY) {\n+\t\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t\t    \"Priority number exceed the maximum %d\",\n+\t\t\t\t\t    I40E_MAX_USER_PRIORITY);\n+\t\t\t\treturn -ENOSPC;\n+\t\t\t}\n+\n+\t\t\tregions[i].user_priority[j] = rss_conf->region_priority;\n+\t\t\tregions[i].user_priority_num++;\n+\t\t\treturn i40e_flush_queue_region_all_conf(dev, hw, pf, 1);\n+\t\t}\n+\n+\t\tregion_id_mask |= BIT(regions[i].region_id);\n+\t}\n+\n+\tif (num > I40E_REGION_MAX_INDEX) {\n+\t\tPMD_DRV_LOG(ERR, \"Queue region resource used up\");\n+\t\treturn -ENOSPC;\n+\t}\n+\n+\t/* Add a new region */\n+\n+\tpf->queue_region.queue_region_number++;\n+\tmemset(&regions[num], 0, sizeof(regions[0]));\n+\n+\tregions[num].region_id = rte_bsf32(~region_id_mask);\n+\tregions[num].queue_num = rss_conf->region_queue_num;\n+\tregions[num].queue_start_index = rss_conf->region_queue_start;\n+\tregions[num].user_priority[0] = rss_conf->region_priority;\n+\tregions[num].user_priority_num = 1;\n+\n+\treturn i40e_flush_queue_region_all_conf(dev, hw, pf, 1);\n+}\n+\n+static int\n+i40e_hash_config(struct i40e_pf *pf,\n+\t\t struct i40e_rte_flow_rss_conf *rss_conf)\n+{\n+\tstruct rte_flow_action_rss *rss_info = &rss_conf->conf;\n+\tstruct i40e_hw *hw = &pf->adapter->hw;\n+\tuint64_t pctypes;\n+\tint ret;\n+\n+\tif (rss_info->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {\n+\t\tret = i40e_hash_config_func(hw, rss_info->func);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif (rss_info->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ)\n+\t\t\trss_conf->misc_reset_flags |=\n+\t\t\t\t\tI40E_HASH_FLOW_RESET_FLAG_FUNC;\n+\t}\n+\n+\tif (rss_conf->region_queue_num > 0) {\n+\t\tret = i40e_hash_config_region(pf, rss_conf);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;\n+\t}\n+\n+\tif (rss_info->key_len > 0) {\n+\t\tret = i40e_set_rss_key(pf->main_vsi, rss_conf->key,\n+\t\t\t\t       rss_info->key_len);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_KEY;\n+\t}\n+\n+\t/* Update lookup table */\n+\tif (rss_info->queue_num > 0) {\n+\t\tuint8_t lut[ETH_RSS_RETA_SIZE_512];\n+\t\tuint32_t i, j = 0;\n+\n+\t\tfor (i = 0; i < hw->func_caps.rss_table_size; i++) {\n+\t\t\tlut[i] = (uint8_t)rss_info->queue[j];\n+\t\t\tj = (j == rss_info->queue_num - 1) ? 0 : (j + 1);\n+\t\t}\n+\n+\t\tret = i40e_set_rss_lut(pf->main_vsi, lut, (uint16_t)i);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tpf->hash_enabled_queues = 0;\n+\t\tfor (i = 0; i < rss_info->queue_num; i++)\n+\t\t\tpf->hash_enabled_queues |= BIT_ULL(lut[i]);\n+\n+\t\tpf->adapter->rss_reta_updated = 0;\n+\t\trss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_QUEUE;\n+\t}\n+\n+\t/* The codes behind configure the input sets and symmetric hash\n+\t * function of the packet types and enable hash on them.\n+\t */\n+\tpctypes = rss_conf->config_pctypes;\n+\tif (!pctypes)\n+\t\treturn 0;\n+\n+\t/* For first flow that will enable hash on any packet type, we clean\n+\t * the RSS sets that by legacy configuration commands and parameters.\n+\t */\n+\tif (!pf->hash_filter_enabled) {\n+\t\ti40e_pf_disable_rss(pf);\n+\t\tpf->hash_filter_enabled = true;\n+\t}\n+\n+\tdo {\n+\t\tuint32_t idx = rte_bsf64(pctypes);\n+\t\tuint64_t bit = BIT_ULL(idx);\n+\n+\t\tif (rss_conf->symmetric_enable) {\n+\t\t\tret = i40e_hash_config_pctype_symmetric(hw, idx, true);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\trss_conf->reset_symmetric_pctypes |= bit;\n+\t\t}\n+\n+\t\tret = i40e_hash_config_pctype(hw, rss_conf, idx);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->reset_config_pctypes |= bit;\n+\t\tpctypes &= ~bit;\n+\t} while (pctypes);\n+\n+\treturn 0;\n+}\n+\n+static void\n+i40e_hash_parse_key(const struct rte_flow_action_rss *rss_act,\n+\t\t    struct i40e_rte_flow_rss_conf *rss_conf)\n+{\n+\tconst uint8_t *key = rss_act->key;\n+\n+\tif (!key || rss_act->key_len != sizeof(rss_conf->key)) {\n+\t\tconst uint32_t rss_key_default[] = {0x6b793944,\n+\t\t\t0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8,\n+\t\t\t0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605,\n+\t\t\t0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581};\n+\n+\t\tif (rss_act->key_len != sizeof(rss_conf->key))\n+\t\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t\t    \"RSS key length invalid, must be %u bytes, now set key to default\",\n+\t\t\t\t    (uint32_t)sizeof(rss_conf->key));\n+\t\tkey = (const uint8_t *)rss_key_default;\n+\t}\n+\n+\tmemcpy(rss_conf->key, key, sizeof(rss_conf->key));\n+\trss_conf->conf.key = rss_conf->key;\n+\trss_conf->conf.key_len = sizeof(rss_conf->key);\n+}\n+\n+static int\n+i40e_hash_parse_queues(const struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_action_rss *rss_act,\n+\t\t       struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t       struct rte_flow_error *error)\n+{\n+\tstruct i40e_pf *pf;\n+\tstruct i40e_hw *hw;\n+\tuint16_t i;\n+\tint max_queue;\n+\n+\thw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tif (!rss_act->queue_num ||\n+\t    rss_act->queue_num > hw->func_caps.rss_table_size)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"Invalid RSS queue number\");\n+\n+\tif (rss_act->key_len)\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t    \"RSS key is ignored when queues specified\");\n+\n+\tpf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tif (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG)\n+\t\tmax_queue = i40e_pf_calc_configured_queues_num(pf);\n+\telse\n+\t\tmax_queue = pf->dev_data->nb_rx_queues;\n+\n+\tmax_queue = RTE_MIN(max_queue, I40E_MAX_Q_PER_TC);\n+\n+\tfor (i = 0; i < rss_act->queue_num; i++) {\n+\t\tif ((int)rss_act->queue[i] >= max_queue)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i < rss_act->queue_num)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"Invalid RSS queues\");\n+\n+\tmemcpy(rss_conf->queue, rss_act->queue,\n+\t       rss_act->queue_num * sizeof(rss_conf->queue[0]));\n+\trss_conf->conf.queue = rss_conf->queue;\n+\trss_conf->conf.queue_num = rss_act->queue_num;\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_parse_queue_region(const struct rte_eth_dev *dev,\n+\t\t\t     const struct rte_flow_item pattern[],\n+\t\t\t     const struct rte_flow_action_rss *rss_act,\n+\t\t\t     struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\t     struct rte_flow_error *error)\n+{\n+\tstruct i40e_pf *pf;\n+\tconst struct rte_flow_item_vlan *vlan_spec, *vlan_mask;\n+\tuint64_t hash_queues;\n+\tuint32_t i;\n+\n+\tif (pattern[1].type != RTE_FLOW_ITEM_TYPE_END)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_NUM,\n+\t\t\t\t\t  &pattern[1],\n+\t\t\t\t\t  \"Pattern not supported.\");\n+\n+\tvlan_spec = pattern->spec;\n+\tvlan_mask = pattern->mask;\n+\tif (!vlan_spec || !vlan_mask ||\n+\t    (rte_be_to_cpu_16(vlan_mask->tci) >> 13) != 7)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, pattern,\n+\t\t\t\t\t  \"Pattern error.\");\n+\n+\tif (!rss_act->queue)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"Queues not specified\");\n+\n+\tif (rss_act->key_len)\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t    \"RSS key is ignored when configure queue region\");\n+\n+\t/* Use a 64 bit variable to represent all queues in a region. */\n+\tRTE_BUILD_BUG_ON(I40E_MAX_Q_PER_TC > 64);\n+\n+\tif (!rss_act->queue_num ||\n+\t    !rte_is_power_of_2(rss_act->queue_num) ||\n+\t    rss_act->queue_num + rss_act->queue[0] > I40E_MAX_Q_PER_TC)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"Queue number error\");\n+\n+\tfor (i = 1; i < rss_act->queue_num; i++) {\n+\t\tif (rss_act->queue[i - 1] + 1 != rss_act->queue[i])\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i < rss_act->queue_num)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Queues must be incremented continuously\");\n+\n+\t/* Map all queues to bits of uint64_t */\n+\thash_queues = (BIT_ULL(rss_act->queue[0] + rss_act->queue_num) - 1) &\n+\t\t      ~(BIT_ULL(rss_act->queue[0]) - 1);\n+\n+\tpf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);\n+\tif (hash_queues & ~pf->hash_enabled_queues)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"Some queues are not in LUT\");\n+\n+\trss_conf->region_queue_num = (uint8_t)rss_act->queue_num;\n+\trss_conf->region_queue_start = rss_act->queue[0];\n+\trss_conf->region_priority = rte_be_to_cpu_16(vlan_spec->tci) >> 13;\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_parse_global_conf(const struct rte_eth_dev *dev,\n+\t\t\t    const struct rte_flow_item pattern[],\n+\t\t\t    const struct rte_flow_action_rss *rss_act,\n+\t\t\t    struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tif (rss_act->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Symmetric function should be set with pattern types\");\n+\n+\trss_conf->conf.func = rss_act->func;\n+\n+\tif (rss_act->types)\n+\t\tPMD_DRV_LOG(WARNING,\n+\t\t\t    \"RSS types are ignored when no pattern specified\");\n+\n+\tif (pattern[0].type == RTE_FLOW_ITEM_TYPE_VLAN)\n+\t\treturn i40e_hash_parse_queue_region(dev, pattern, rss_act,\n+\t\t\t\t\t\t    rss_conf, error);\n+\n+\tif (rss_act->queue)\n+\t\treturn i40e_hash_parse_queues(dev, rss_act, rss_conf, error);\n+\n+\tif (rss_act->key_len) {\n+\t\ti40e_hash_parse_key(rss_act, rss_conf);\n+\t\treturn 0;\n+\t}\n+\n+\tif (rss_act->func == RTE_ETH_HASH_FUNCTION_DEFAULT)\n+\t\tPMD_DRV_LOG(WARNING, \"Nothing change\");\n+\treturn 0;\n+}\n+\n+static bool\n+i40e_hash_validate_rss_types(uint64_t rss_types)\n+{\n+\tuint64_t type, mask;\n+\n+\t/* Validate L2 */\n+\ttype = ETH_RSS_ETH & rss_types;\n+\tmask = (ETH_RSS_L2_SRC_ONLY | ETH_RSS_L2_DST_ONLY) & rss_types;\n+\tif (!type && mask)\n+\t\treturn false;\n+\n+\t/* Validate L3 */\n+\ttype = (I40E_HASH_L4_TYPES | ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |\n+\t       ETH_RSS_NONFRAG_IPV4_OTHER | ETH_RSS_IPV6 |\n+\t       ETH_RSS_FRAG_IPV6 | ETH_RSS_NONFRAG_IPV6_OTHER) & rss_types;\n+\tmask = (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY) & rss_types;\n+\tif (!type && mask)\n+\t\treturn false;\n+\n+\t/* Validate L4 */\n+\ttype = (I40E_HASH_L4_TYPES | ETH_RSS_PORT) & rss_types;\n+\tmask = (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY) & rss_types;\n+\tif (!type && mask)\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+static int\n+i40e_hash_parse_pattern_act(const struct rte_eth_dev *dev,\n+\t\t\t    const struct rte_flow_item pattern[],\n+\t\t\t    const struct rte_flow_action_rss *rss_act,\n+\t\t\t    struct i40e_rte_flow_rss_conf *rss_conf,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tif (rss_act->queue)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"RSS Queues not supported when pattern specified\");\n+\n+\tif (rss_act->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)\n+\t\trss_conf->symmetric_enable = true;\n+\telse if (rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT)\n+\t\treturn rte_flow_error_set(error, -EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL,\n+\t\t\t\t\t  \"Only symmetric TOEPLITZ supported when pattern specified\");\n+\n+\tif (!i40e_hash_validate_rss_types(rss_act->types))\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  NULL, \"RSS types are invalid\");\n+\n+\tif (rss_act->key_len)\n+\t\ti40e_hash_parse_key(rss_act, rss_conf);\n+\n+\trss_conf->conf.func = rss_act->func;\n+\trss_conf->conf.types = rss_act->types;\n+\trss_conf->inset = i40e_hash_get_inset(rss_act->types);\n+\n+\treturn i40e_hash_get_pattern_pctypes(dev, pattern, rss_act,\n+\t\t\t\t\t     rss_conf, error);\n+}\n+\n+int\n+i40e_hash_parse(const struct rte_eth_dev *dev,\n+\t\tconst struct rte_flow_item pattern[],\n+\t\tconst struct rte_flow_action actions[],\n+\t\tstruct i40e_rte_flow_rss_conf *rss_conf,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_action_rss *rss_act;\n+\n+\tif (actions[1].type != RTE_FLOW_ACTION_TYPE_END)\n+\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t  &actions[1],\n+\t\t\t\t\t  \"Only support one action for RSS.\");\n+\n+\trss_act = (const struct rte_flow_action_rss *)actions[0].conf;\n+\tif (rss_act->level)\n+\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n+\t\t\t\t\t  actions,\n+\t\t\t\t\t  \"RSS level is not supported\");\n+\n+\twhile (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)\n+\t\tpattern++;\n+\n+\tif (pattern[0].type == RTE_FLOW_ITEM_TYPE_END ||\n+\t    pattern[0].type == RTE_FLOW_ITEM_TYPE_VLAN)\n+\t\treturn i40e_hash_parse_global_conf(dev, pattern, rss_act,\n+\t\t\t\t\t\t   rss_conf, error);\n+\n+\treturn i40e_hash_parse_pattern_act(dev, pattern, rss_act,\n+\t\t\t\t\t   rss_conf, error);\n+}\n+\n+static void\n+i40e_invalid_rss_filter(const struct i40e_rte_flow_rss_conf *ref_conf,\n+\t\t\tstruct i40e_rte_flow_rss_conf *conf)\n+{\n+\tuint32_t reset_flags = conf->misc_reset_flags;\n+\n+\tconf->misc_reset_flags &= ~ref_conf->misc_reset_flags;\n+\n+\tif ((reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&\n+\t    (ref_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&\n+\t    (conf->region_queue_start != ref_conf->region_queue_start ||\n+\t     conf->region_queue_num != ref_conf->region_queue_num))\n+\t\tconf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;\n+\n+\tconf->reset_config_pctypes &= ~ref_conf->reset_config_pctypes;\n+\tconf->reset_symmetric_pctypes &= ~ref_conf->reset_symmetric_pctypes;\n+}\n+\n+int\n+i40e_hash_filter_restore(struct i40e_pf *pf)\n+{\n+\tstruct i40e_rss_filter *filter;\n+\tint ret;\n+\n+\tTAILQ_FOREACH(filter, &pf->rss_config_list, next) {\n+\t\tstruct i40e_rte_flow_rss_conf *rss_conf =\n+\t\t\t\t\t\t&filter->rss_filter_info;\n+\t\tstruct i40e_rss_filter *prev;\n+\n+\t\trss_conf->misc_reset_flags = 0;\n+\t\trss_conf->reset_config_pctypes = 0;\n+\t\trss_conf->reset_symmetric_pctypes = 0;\n+\n+\t\tret = i40e_hash_config(pf, rss_conf);\n+\t\tif (ret) {\n+\t\t\tpf->hash_filter_enabled = 0;\n+\t\t\ti40e_pf_disable_rss(pf);\n+\t\t\tPMD_DRV_LOG(ERR,\n+\t\t\t\t    \"Re-configure RSS failed, RSS has been disabled\");\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\t/* Invalid previous RSS filter */\n+\t\tTAILQ_FOREACH(prev, &pf->rss_config_list, next) {\n+\t\t\tif (prev == filter)\n+\t\t\t\tbreak;\n+\t\t\ti40e_invalid_rss_filter(rss_conf,\n+\t\t\t\t\t\t&prev->rss_filter_info);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+i40e_hash_filter_create(struct i40e_pf *pf,\n+\t\t\tstruct i40e_rte_flow_rss_conf *rss_conf)\n+{\n+\tstruct i40e_rss_filter *filter, *prev;\n+\tstruct i40e_rte_flow_rss_conf *new_conf;\n+\tint ret;\n+\n+\tfilter = rte_zmalloc(\"i40e_rss_filter\", sizeof(*filter), 0);\n+\tif (!filter) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to allocate memory.\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tnew_conf = &filter->rss_filter_info;\n+\n+\tmemcpy(new_conf, rss_conf, sizeof(*new_conf));\n+\tif (new_conf->conf.queue_num)\n+\t\tnew_conf->conf.queue = new_conf->queue;\n+\tif (new_conf->conf.key_len)\n+\t\tnew_conf->conf.key = new_conf->key;\n+\n+\tret = i40e_hash_config(pf, new_conf);\n+\tif (ret) {\n+\t\trte_free(filter);\n+\t\tif (i40e_pf_config_rss(pf))\n+\t\t\treturn ret;\n+\n+\t\t(void)i40e_hash_filter_restore(pf);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Invalid previous RSS filter */\n+\tTAILQ_FOREACH(prev, &pf->rss_config_list, next)\n+\t\ti40e_invalid_rss_filter(new_conf, &prev->rss_filter_info);\n+\n+\tTAILQ_INSERT_TAIL(&pf->rss_config_list, filter, next);\n+\treturn 0;\n+}\n+\n+static int\n+i40e_hash_reset_conf(struct i40e_pf *pf,\n+\t\t     struct i40e_rte_flow_rss_conf *rss_conf)\n+{\n+\tstruct i40e_hw *hw = &pf->adapter->hw;\n+\tuint64_t inset;\n+\tuint32_t idx;\n+\tint ret;\n+\n+\tif (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_FUNC) {\n+\t\tret = i40e_hash_config_func(hw, RTE_ETH_HASH_FUNCTION_TOEPLITZ);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_FUNC;\n+\t}\n+\n+\tif (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) {\n+\t\tret = i40e_flush_queue_region_all_conf(pf->adapter->eth_dev,\n+\t\t\t\t\t\t       hw, pf, 0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_REGION;\n+\t}\n+\n+\tif (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_KEY) {\n+\t\tret = i40e_pf_reset_rss_key(pf);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_KEY;\n+\t}\n+\n+\tif (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_QUEUE) {\n+\t\tif (!pf->adapter->rss_reta_updated) {\n+\t\t\tret = i40e_pf_reset_rss_reta(pf);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\n+\t\tpf->hash_enabled_queues = 0;\n+\t\trss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_QUEUE;\n+\t}\n+\n+\twhile (rss_conf->reset_config_pctypes) {\n+\t\tidx = rte_bsf64(rss_conf->reset_config_pctypes);\n+\n+\t\ti40e_hash_enable_pctype(hw, idx, false);\n+\t\tinset = i40e_get_default_input_set(idx);\n+\t\tif (inset) {\n+\t\t\tret = i40e_set_hash_inset(hw, inset, idx, false);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\n+\t\trss_conf->reset_config_pctypes &= ~BIT_ULL(idx);\n+\t}\n+\n+\twhile (rss_conf->reset_symmetric_pctypes) {\n+\t\tidx = rte_bsf64(rss_conf->reset_symmetric_pctypes);\n+\n+\t\tret = i40e_hash_config_pctype_symmetric(hw, idx, false);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\trss_conf->reset_symmetric_pctypes &= ~BIT_ULL(idx);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+i40e_hash_filter_destroy(struct i40e_pf *pf,\n+\t\t\t const struct i40e_rss_filter *rss_filter)\n+{\n+\tstruct i40e_rss_filter *filter;\n+\tint ret;\n+\n+\tTAILQ_FOREACH(filter, &pf->rss_config_list, next) {\n+\t\tif (rss_filter == filter) {\n+\t\t\tret = i40e_hash_reset_conf(pf,\n+\t\t\t\t\t\t   &filter->rss_filter_info);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\tTAILQ_REMOVE(&pf->rss_config_list, filter, next);\n+\t\t\trte_free(filter);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn -ENOENT;\n+}\n+\n+int\n+i40e_hash_filter_flush(struct i40e_pf *pf)\n+{\n+\tstruct rte_flow *flow, *next;\n+\n+\tTAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, next) {\n+\t\tif (flow->filter_type != RTE_ETH_FILTER_HASH)\n+\t\t\tcontinue;\n+\n+\t\tif (flow->rule) {\n+\t\t\tstruct i40e_rss_filter *filter = flow->rule;\n+\t\t\tint ret;\n+\n+\t\t\tret = i40e_hash_reset_conf(pf,\n+\t\t\t\t\t\t   &filter->rss_filter_info);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\tTAILQ_REMOVE(&pf->rss_config_list, filter, next);\n+\t\t\trte_free(filter);\n+\t\t}\n+\n+\t\tTAILQ_REMOVE(&pf->flow_list, flow, node);\n+\t\trte_free(flow);\n+\t}\n+\n+\tassert(!pf->rss_config_list.tqh_first);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/i40e/i40e_hash.h b/drivers/net/i40e/i40e_hash.h\nnew file mode 100644\nindex 0000000..ff8c91c\n--- /dev/null\n+++ b/drivers/net/i40e/i40e_hash.h\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _I40E_HASH_H_\n+#define _I40E_HASH_H_\n+\n+#include <rte_ethdev.h>\n+#include <rte_flow.h>\n+#include \"i40e_ethdev.h\"\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+int i40e_hash_parse(const 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 i40e_rte_flow_rss_conf *rss_conf,\n+\t\t    struct rte_flow_error *error);\n+\n+int i40e_hash_filter_create(struct i40e_pf *pf,\n+\t\t\t    struct i40e_rte_flow_rss_conf *rss_conf);\n+\n+int i40e_hash_filter_restore(struct i40e_pf *pf);\n+int i40e_hash_filter_destroy(struct i40e_pf *pf,\n+\t\t\t     const struct i40e_rss_filter *rss_filter);\n+int i40e_hash_filter_flush(struct i40e_pf *pf);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* I40E_HASH_H_ */\ndiff --git a/drivers/net/i40e/meson.build b/drivers/net/i40e/meson.build\nindex bb0c542..882168c 100644\n--- a/drivers/net/i40e/meson.build\n+++ b/drivers/net/i40e/meson.build\n@@ -17,6 +17,7 @@ sources = files(\n \t'i40e_fdir.c',\n \t'i40e_flow.c',\n \t'i40e_tm.c',\n+\t'i40e_hash.c',\n \t'i40e_vf_representor.c',\n \t'rte_pmd_i40e.c'\n \t)\n",
    "prefixes": [
        "v4",
        "3/3"
    ]
}