get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 68533,
    "url": "https://patches.dpdk.org/api/patches/68533/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200415084609.57615-1-chenxux.di@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20200415084609.57615-1-chenxux.di@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200415084609.57615-1-chenxux.di@intel.com",
    "date": "2020-04-15T08:46:09",
    "name": "[v9] net/i40e: enable hash configuration in RSS flow",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "8dde6a77bbb53c522818df15961883c5085972e0",
    "submitter": {
        "id": 1409,
        "url": "https://patches.dpdk.org/api/people/1409/?format=api",
        "name": "Chenxu Di",
        "email": "chenxux.di@intel.com"
    },
    "delegate": {
        "id": 31221,
        "url": "https://patches.dpdk.org/api/users/31221/?format=api",
        "username": "yexl",
        "first_name": "xiaolong",
        "last_name": "ye",
        "email": "xiaolong.ye@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200415084609.57615-1-chenxux.di@intel.com/mbox/",
    "series": [
        {
            "id": 9388,
            "url": "https://patches.dpdk.org/api/series/9388/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=9388",
            "date": "2020-04-15T08:46:09",
            "name": "[v9] net/i40e: enable hash configuration in RSS flow",
            "version": 9,
            "mbox": "https://patches.dpdk.org/series/9388/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/68533/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/68533/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 dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 8A16BA0563;\n\tWed, 15 Apr 2020 10:58:25 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 5E4E51D58B;\n\tWed, 15 Apr 2020 10:58:25 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n by dpdk.org (Postfix) with ESMTP id 7ED5E1D589\n for <dev@dpdk.org>; Wed, 15 Apr 2020 10:58:23 +0200 (CEST)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 15 Apr 2020 01:58:22 -0700",
            "from unknown (HELO localhost.localdomain) ([10.239.255.70])\n by fmsmga001.fm.intel.com with ESMTP; 15 Apr 2020 01:58:20 -0700"
        ],
        "IronPort-SDR": [
            "\n snZi6vKJlR6XxDsLfQok3CuMH++RSSzx61aDoSaG8iw4o0kP9B6Po1Shi3BpGa+DDSIatS3xFd\n WcHlBqchPR2Q==",
            "\n O/C5BuApD4yhQ0fcCK0gGDcz8vgRLCqROgaz9NHBrPdUMD8kctKIy1MHj6TqPdK32zxz4N+0bB\n BSqJqzPVDHEQ=="
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.72,386,1580803200\"; d=\"scan'208\";a=\"363617714\"",
        "From": "Chenxu Di <chenxux.di@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Yang Qiming <qiming.yang@intel.com>, beilei.xing@intel.com,\n Chenxu Di <chenxux.di@intel.com>",
        "Date": "Wed, 15 Apr 2020 08:46:09 +0000",
        "Message-Id": "<20200415084609.57615-1-chenxux.di@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200318014710.13577-1-chenxux.di@intel.com>",
        "References": "<20200318014710.13577-1-chenxux.di@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v9] net/i40e: enable hash configuration in RSS\n\tflow",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <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": "This patch supports:\n\n- Symmetric hash configuration\n- Hash input set configuration\n\nSigned-off-by: Chenxu Di <chenxux.di@intel.com>\n---\nv9:\n-Updated code about enable hash.\n---\n doc/guides/nics/i40e.rst               |  37 ++\n doc/guides/rel_notes/release_20_05.rst |   2 +\n drivers/net/i40e/i40e_ethdev.c         | 528 ++++++++++++++++++++++---\n drivers/net/i40e/i40e_ethdev.h         |  22 +-\n drivers/net/i40e/i40e_flow.c           | 209 ++++++++--\n 5 files changed, 703 insertions(+), 95 deletions(-)",
    "diff": "diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst\nindex d6e578eda..f72a54ba6 100644\n--- a/doc/guides/nics/i40e.rst\n+++ b/doc/guides/nics/i40e.rst\n@@ -44,6 +44,7 @@ Features of the i40e PMD are:\n - Queue region configuration\n - Virtual Function Port Representors\n - Malicious Device Drive event catch and notify\n+- Generic flow API\n \n Prerequisites\n -------------\n@@ -569,6 +570,42 @@ details please refer to :doc:`../testpmd_app_ug/index`.\n    testpmd> set port (port_id) queue-region flush (on|off)\n    testpmd> show port (port_id) queue-region\n \n+Generic flow API\n+~~~~~~~~~~~~~~~~~~~\n+\n+- ``RSS Flow``\n+\n+  RSS Flow supports to set hash input set, hash function, enable hash\n+  and configure queue region.\n+  For example:\n+  Configure queue region as queue 0, 1, 2, 3.\n+\n+  .. code-block:: console\n+\n+    testpmd> flow create 0 ingress pattern end actions rss types end \\\n+      queues 0 1 2 3 end / end\n+\n+  Enable hash and set input set for ipv4-tcp.\n+\n+  .. code-block:: console\n+\n+    testpmd> flow create 0 ingress pattern eth / ipv4 / tcp / end \\\n+      actions rss types ipv4-tcp l3-src-only end queues end / end\n+\n+  Set symmetric hash enable for flow type ipv4-tcp.\n+\n+  .. code-block:: console\n+\n+    testpmd> flow create 0 ingress pattern eth / ipv4 / tcp / end \\\n+      actions rss types ipv4-tcp end queues end func symmetric_toeplitz / end\n+\n+  Set hash function as simple xor.\n+\n+  .. code-block:: console\n+\n+    testpmd> flow create 0 ingress pattern end actions rss types end \\\n+      queues end func simple_xor / end\n+\n Limitations or Known issues\n ---------------------------\n \ndiff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst\nindex e32746291..76e8dfb7d 100644\n--- a/doc/guides/rel_notes/release_20_05.rst\n+++ b/doc/guides/rel_notes/release_20_05.rst\n@@ -83,6 +83,8 @@ New Features\n   Updated i40e PMD with new features and improvements, including:\n \n   * Enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp.\n+  * Added support for RSS using L3/L4 source/destination only.\n+  * Added support for setting hash function in rte flow.\n \n * **Updated Amazon ena driver.**\n \ndiff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex 60de68fd8..5ac3714be 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -1657,6 +1657,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)\n \t/* initialize mirror rule list */\n \tTAILQ_INIT(&pf->mirror_list);\n \n+\t/* initialize RSS rule list */\n+\tTAILQ_INIT(&pf->rss_config_list);\n+\n \t/* initialize Traffic Manager configuration */\n \ti40e_tm_conf_init(dev);\n \n@@ -1676,7 +1679,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)\n \t/* initialize queue region configuration */\n \ti40e_init_queue_region_conf(dev);\n \n-\t/* initialize rss configuration from rte_flow */\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@@ -12329,14 +12332,16 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)\n \t}\n }\n \n-/* Restore rss filter */\n+/* Restore RSS filter */\n static inline void\n i40e_rss_filter_restore(struct i40e_pf *pf)\n {\n-\tstruct i40e_rte_flow_rss_conf *conf =\n-\t\t\t\t\t&pf->rss_info;\n-\tif (conf->conf.queue_num)\n-\t\ti40e_config_rss_filter(pf, conf, TRUE);\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@@ -12946,45 +12951,300 @@ i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,\n \treturn 0;\n }\n \n-int\n-i40e_action_rss_same(const struct rte_flow_action_rss *comp,\n-\t\t     const struct rte_flow_action_rss *with)\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-\treturn (comp->func == with->func &&\n-\t\tcomp->level == with->level &&\n-\t\tcomp->types == with->types &&\n-\t\tcomp->key_len == with->key_len &&\n-\t\tcomp->queue_num == with->queue_num &&\n-\t\t!memcmp(comp->key, with->key, with->key_len) &&\n-\t\t!memcmp(comp->queue, with->queue,\n-\t\t\tsizeof(*with->queue) * with->queue_num));\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-int\n-i40e_config_rss_filter(struct i40e_pf *pf,\n-\t\tstruct i40e_rte_flow_rss_conf *conf, bool add)\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-\tuint32_t i, lut = 0;\n-\tuint16_t j, num;\n-\tstruct rte_eth_rss_conf rss_conf = {\n-\t\t.rss_key = conf->conf.key_len ?\n-\t\t\t(void *)(uintptr_t)conf->conf.key : NULL,\n-\t\t.rss_key_len = conf->conf.key_len,\n-\t\t.rss_hf = conf->conf.types,\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-\tstruct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;\n \n-\tif (!add) {\n-\t\tif (i40e_action_rss_same(&rss_info->conf, &conf->conf)) {\n-\t\t\ti40e_pf_disable_rss(pf);\n-\t\t\tmemset(rss_info, 0,\n-\t\t\t\tsizeof(struct i40e_rte_flow_rss_conf));\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\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@@ -13014,29 +13274,195 @@ i40e_config_rss_filter(struct i40e_pf *pf,\n \t\t\tI40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut);\n \t}\n \n-\tif ((rss_conf.rss_hf & pf->adapter->flow_types_mask) == 0) {\n-\t\ti40e_pf_disable_rss(pf);\n-\t\treturn 0;\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\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-\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-\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\tPMD_DRV_LOG(INFO,\n-\t\t\t\"No valid RSS key config for i40e, using default\\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-\ti40e_hw_rss_hash_set(pf, &rss_conf);\n+\trss_info->conf.types = rss_conf.conf.types;\n \n-\tif (i40e_rss_conf_init(rss_info, &conf->conf))\n-\t\treturn -EINVAL;\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 }\ndiff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h\nindex 461959e08..e5d0ce53f 100644\n--- a/drivers/net/i40e/i40e_ethdev.h\n+++ b/drivers/net/i40e/i40e_ethdev.h\n@@ -192,6 +192,9 @@ enum i40e_flxpld_layer_idx {\n #define I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK  \\\n \tI40E_MASK(0xFFFF, I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT)\n \n+#define I40E_RSS_TYPE_NONE           0ULL\n+#define I40E_RSS_TYPE_INVALID        1ULL\n+\n #define I40E_INSET_NONE            0x00000000000000000ULL\n \n /* bit0 ~ bit 7 */\n@@ -754,6 +757,11 @@ struct i40e_queue_regions {\n \tstruct i40e_queue_region_info region[I40E_REGION_MAX_INDEX + 1];\n };\n \n+struct i40e_rss_pattern_info {\n+\tuint8_t action_flag;\n+\tuint64_t types;\n+};\n+\n /* Tunnel filter number HW supports */\n #define I40E_MAX_TUNNEL_FILTER_NUM 400\n \n@@ -973,6 +981,15 @@ struct i40e_rte_flow_rss_conf {\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+\n+TAILQ_HEAD(i40e_rss_conf_list, i40e_rss_filter);\n+\n+/* RSS filter list structure */\n+struct i40e_rss_filter {\n+\tTAILQ_ENTRY(i40e_rss_filter) next;\n+\tstruct i40e_rte_flow_rss_conf rss_filter_info;\n };\n \n struct i40e_vf_msg_cfg {\n@@ -1043,7 +1060,8 @@ 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_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 \tstruct i40e_mirror_rule_list mirror_list;\n@@ -1343,8 +1361,6 @@ 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_action_rss_same(const struct rte_flow_action_rss *comp,\n-\t\t\t const struct rte_flow_action_rss *with);\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);\ndiff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c\nindex b1861a7db..1d0eaf61c 100644\n--- a/drivers/net/i40e/i40e_flow.c\n+++ b/drivers/net/i40e/i40e_flow.c\n@@ -4475,29 +4475,80 @@ i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,\n  * function for RSS, or flowtype for queue region configuration.\n  * For example:\n  * pattern:\n- * Case 1: only ETH, indicate  flowtype for queue region will be parsed.\n- * Case 2: only VLAN, indicate user_priority for queue region will be parsed.\n- * Case 3: none, indicate RSS related will be parsed in action.\n- * Any pattern other the ETH or VLAN will be treated as invalid except END.\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 uaed to transmit valid parameter with\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     uint8_t *action_flag,\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-\n-\tif (item->type == RTE_FLOW_ITEM_TYPE_END)\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_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};\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\trte_free(items);\n+\t\t\treturn 0;\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@@ -4510,7 +4561,7 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,\n \t\titem_type = item->type;\n \t\tswitch (item_type) {\n \t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\t*action_flag = 1;\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@@ -4523,7 +4574,7 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,\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\t*action_flag = 0;\n+\t\t\t\t\tp_info->action_flag = 0;\n \t\t\t\t}\n \t\t\t}\n \t\t\tbreak;\n@@ -4540,7 +4591,7 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,\n }\n \n /**\n- * This function is used to parse rss queue index, total queue number and\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@@ -4549,14 +4600,16 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,\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+ * 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    uint8_t action_flag,\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@@ -4567,7 +4620,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\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, tmp;\n+\tuint16_t i, j, n, tmp, nb_types;\n \tuint32_t index = 0;\n \tuint64_t hf_bit = 1;\n \n@@ -4575,7 +4628,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\n \trss = act->conf;\n \n \t/**\n-\t * rss only supports forwarding,\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@@ -4586,7 +4639,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\n \t\treturn -rte_errno;\n \t}\n \n-\tif (action_flag) {\n+\tif (p_info.action_flag) {\n \t\tfor (n = 0; n < 64; n++) {\n \t\t\tif (rss->types & (hf_bit << n)) {\n \t\t\t\tconf_info->region[0].hw_flowtype[0] = n;\n@@ -4725,11 +4778,11 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\n \tif (rss_config->queue_region_conf)\n \t\treturn 0;\n \n-\tif (!rss || !rss->queue_num) {\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\"no valid queues\");\n+\t\t\t\t\"invalid rule\");\n \t\treturn -rte_errno;\n \t}\n \n@@ -4743,19 +4796,48 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,\n \t\t}\n \t}\n \n-\tif (rss_info->conf.queue_num) {\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\"rss only allow one valid rule\");\n-\t\treturn -rte_errno;\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, \"invaild 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_DEFAULT)\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 \"non-default RSS hash functions are not supported\");\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@@ -4797,19 +4879,20 @@ i40e_parse_rss_filter(struct rte_eth_dev *dev,\n \t\t\tunion i40e_filter_t *filter,\n \t\t\tstruct rte_flow_error *error)\n {\n-\tint ret;\n+\tstruct i40e_rss_pattern_info p_info;\n \tstruct i40e_queue_regions info;\n-\tuint8_t action_flag = 0;\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, &action_flag, &info);\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\taction_flag, &info, filter);\n+\t\t\t\t\tp_info, &info, filter);\n \tif (ret)\n \t\treturn ret;\n \n@@ -4828,15 +4911,33 @@ i40e_config_rss_filter_set(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 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\tconf->queue_region_conf = 0;\n \t} else {\n \t\tret = i40e_config_rss_filter(pf, conf, 1);\n \t}\n-\treturn ret;\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@@ -4845,10 +4946,21 @@ i40e_config_rss_filter_del(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 i40e_rss_filter *rss_filter;\n+\tvoid *temp;\n \n-\ti40e_flush_queue_region_all_conf(dev, hw, pf, 0);\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-\ti40e_config_rss_filter(pf, conf, 0);\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@@ -4991,7 +5103,8 @@ i40e_flow_create(struct rte_eth_dev *dev,\n \t\t\t    &cons_filter.rss_conf);\n \t\tif (ret)\n \t\t\tgoto free_flow;\n-\t\tflow->rule = &pf->rss_info;\n+\t\tflow->rule = TAILQ_LAST(&pf->rss_config_list,\n+\t\t\t\ti40e_rss_conf_list);\n \t\tbreak;\n \tdefault:\n \t\tgoto free_flow;\n@@ -5041,7 +5154,7 @@ i40e_flow_destroy(struct rte_eth_dev *dev,\n \t\tbreak;\n \tcase RTE_ETH_FILTER_HASH:\n \t\tret = i40e_config_rss_filter_del(dev,\n-\t\t\t   (struct i40e_rte_flow_rss_conf *)flow->rule);\n+\t\t\t&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);\n \t\tbreak;\n \tdefault:\n \t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n@@ -5189,7 +5302,7 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)\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\t\t\t   \"Failed to flush RSS flows.\");\n \t\treturn -rte_errno;\n \t}\n \n@@ -5294,18 +5407,32 @@ i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)\n \treturn ret;\n }\n \n-/* remove the rss filter */\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_rte_flow_rss_conf *rss_info = &pf->rss_info;\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-\tif (rss_info->conf.queue_num)\n-\t\tret = i40e_config_rss_filter(pf, rss_info, FALSE);\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",
    "prefixes": [
        "v9"
    ]
}