Show a patch.

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

{
    "id": 45255,
    "url": "http://patches.dpdk.org/api/patches/45255/",
    "web_url": "http://patches.dpdk.org/patch/45255/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/",
        "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"
    },
    "msgid": "<20180924231721.15799-8-yskoh@mellanox.com>",
    "date": "2018-09-24T23:17:47",
    "name": "[v3,07/11] net/mlx5: add Direct Verbs translate items",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "f31abb2a6352d57f9390a70f8c3c08d8383da7d3",
    "submitter": {
        "id": 636,
        "url": "http://patches.dpdk.org/api/people/636/",
        "name": "Yongseok Koh",
        "email": "yskoh@mellanox.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/patch/45255/mbox/",
    "series": [
        {
            "id": 1476,
            "url": "http://patches.dpdk.org/api/series/1476/",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1476",
            "date": "2018-09-24T23:17:33",
            "name": "net/mlx5: add Direct Verbs flow driver support",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/1476/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/45255/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/45255/checks/",
    "tags": {},
    "headers": {
        "x-forefront-antispam-report": "SFV:NSPM;\n\tSFS:(10009020)(1496009)(396003)(376002)(346002)(366004)(39860400002)(136003)(199004)(189003)(66066001)(2616005)(476003)(446003)(486006)(11346002)(16200700003)(6436002)(305945005)(7736002)(53946003)(575784001)(386003)(6506007)(6486002)(6512007)(186003)(102836004)(5250100002)(76176011)(25786009)(26005)(68736007)(6116002)(54906003)(110136005)(99286004)(1076002)(3846002)(71200400001)(52116002)(86362001)(53936002)(71190400001)(97736004)(8936002)(107886003)(14444005)(256004)(4326008)(316002)(2900100001)(81156014)(8676002)(36756003)(81166006)(105586002)(2906002)(106356001)(6636002)(478600001)(5660300001)(14454004)(579004)(559001)(569006);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0502MB3996;\n\tH:DB3PR0502MB3980.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; \n\tPTR:InfoNoRecords; A:1; MX:1; ",
        "X-Mailman-Version": "2.1.15",
        "In-Reply-To": "<20180924231721.15799-1-yskoh@mellanox.com>",
        "Errors-To": "dev-bounces@dpdk.org",
        "X-MS-Exchange-CrossTenant-originalarrivaltime": "24 Sep 2018 23:17:47.6701\n\t(UTC)",
        "x-ms-office365-filtering-correlation-id": "5d40577e-0656-43a7-8430-08d62273f077",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id E45CC1B143;\n\tTue, 25 Sep 2018 01:17:57 +0200 (CEST)",
            "from EUR02-HE1-obe.outbound.protection.outlook.com\n\t(mail-eopbgr10059.outbound.protection.outlook.com [40.107.1.59])\n\tby dpdk.org (Postfix) with ESMTP id 6E64E1B133\n\tfor <dev@dpdk.org>; Tue, 25 Sep 2018 01:17:49 +0200 (CEST)",
            "from DB3PR0502MB3980.eurprd05.prod.outlook.com (52.134.72.27) by\n\tDB3PR0502MB3996.eurprd05.prod.outlook.com (52.134.65.142) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n\t15.20.1164.25; Mon, 24 Sep 2018 23:17:47 +0000",
            "from DB3PR0502MB3980.eurprd05.prod.outlook.com\n\t([fe80::1cb0:661b:ecab:6045]) by\n\tDB3PR0502MB3980.eurprd05.prod.outlook.com\n\t([fe80::1cb0:661b:ecab:6045%2]) with mapi id 15.20.1164.017;\n\tMon, 24 Sep 2018 23:17:47 +0000"
        ],
        "References": "<20180919072143.23211-1-yskoh@mellanox.com>\n\t<20180924231721.15799-1-yskoh@mellanox.com>",
        "spamdiagnosticmetadata": "NSPM",
        "x-ms-exchange-senderadcheck": "1",
        "MIME-Version": "1.0",
        "Accept-Language": "en-US",
        "Thread-Index": "AQHUVFzOsXnxE5lHPEyoB7tByi0PDQ==",
        "x-microsoft-antispam": "BCL:0; PCL:0;\n\tRULEID:(7020095)(4652040)(8989299)(5600074)(711020)(4618075)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060)(7193020);\n\tSRVR:DB3PR0502MB3996; ",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "x-ms-traffictypediagnostic": "DB3PR0502MB3996:",
        "X-Original-To": "patchwork@dpdk.org",
        "Content-Type": "text/plain; charset=\"iso-8859-1\"",
        "x-ms-publictraffictype": "Email",
        "x-microsoft-antispam-prvs": "<DB3PR0502MB3996F90BB980D917A4C8D477C3170@DB3PR0502MB3996.eurprd05.prod.outlook.com>",
        "x-clientproxiedby": "BN6PR03CA0021.namprd03.prod.outlook.com\n\t(2603:10b6:404:23::31) To DB3PR0502MB3980.eurprd05.prod.outlook.com\n\t(2603:10a6:8:10::27)",
        "CC": "\"dev@dpdk.org\" <dev@dpdk.org>, Ori Kam <orika@mellanox.com>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "received-spf": "None (protection.outlook.com: mellanox.com does not designate\n\tpermitted sender hosts)",
        "List-Post": "<mailto:dev@dpdk.org>",
        "To": "Thomas Monjalon <thomas@monjalon.net>,\n\tShahaf Shuler <shahafs@mellanox.com>",
        "x-exchange-antispam-report-cfa-test": "BCL:0; PCL:0;\n\tRULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(3231355)(944501410)(52105095)(6055026)(149066)(150027)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123560045)(20161123562045)(20161123564045)(201708071742011)(7699051);\n\tSRVR:DB3PR0502MB3996; BCL:0; PCL:0; RULEID:; SRVR:DB3PR0502MB3996; ",
        "Delivered-To": "patchwork@dpdk.org",
        "X-MS-Exchange-CrossTenant-id": "a652971c-7d2e-4d9b-a6a4-d149256f461b",
        "x-forefront-prvs": "0805EC9467",
        "Precedence": "list",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "Date": "Mon, 24 Sep 2018 23:17:47 +0000",
        "x-ld-processed": "a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr",
        "From": "Yongseok Koh <yskoh@mellanox.com>",
        "Thread-Topic": "[PATCH v3 07/11] net/mlx5: add Direct Verbs translate items",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "5d40577e-0656-43a7-8430-08d62273f077",
        "x-originating-ip": "[209.116.155.178]",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com;\n\ts=selector1;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n\tbh=TjtYuE2qDGB7qItXtlF1U6Jlc8gjmXABMEN9IqOd7vU=;\n\tb=B311b/07x4fHzGoEn3FiHGIHT5D1TADv7LZ0oUkqW8NXVRKgzHyIJUIVI+sxDd8pjd02BEGCxNiVqVj/XRiqXsO9OCUxY9pxDJumXXgofzml3QzgCSBxw2id+krCKWVIImzfFgfeR37Ows6l83SzegqhNKP2YPAc+W9B5SQSHUc=",
        "Message-ID": "<20180924231721.15799-8-yskoh@mellanox.com>",
        "spamdiagnosticoutput": "1:99",
        "x-ms-office365-filtering-ht": "Tenant",
        "Content-Language": "en-US",
        "Content-Transfer-Encoding": "quoted-printable",
        "X-MS-TNEF-Correlator": "",
        "x-exchange-antispam-report-test": "UriScan:;",
        "X-OriginatorOrg": "Mellanox.com",
        "Return-Path": "<dev-bounces@dpdk.org>",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>",
        "x-microsoft-exchange-diagnostics": "1; DB3PR0502MB3996;\n\t6:LpZmfzk8bZESlGcaqRVZPmLO1LXTLyMRp/NMgiVqc5ex3p1fuQKnwlXLWQVyLPdxHa6CCq+iAto9eVVQlBw7ImdcTbYKz0iMZ69sUioudG7gl+xUrbaCBhiWW48hH87wxvieBAyTyE0SKF5KQOFR7lf2xzKduOXyDuUzaNJQsqNQDGcvtev4cMSJXpZtMMI9D2hcZsiU0KUOyAJuR8h+nW6WOWJc6VmgFwV8Z8cvyST+7to/eFzbzN2s7lWnVJI7ta0A0d0ZcB9aKnlzibzcW6rXtX1qnMDBF2PCwoV7T/baiZ2lXEjuDu1UFaxs3MsRDtZcYL5xlEjX5jML5SueCIwEe4LO/6h9B8uq+oeL9AvwUAS2OIRAV0DL3KOzDnjku6nNGHwdlI5fjUqfAA59Y+LcZtXowGqUPCDq0mAhdCO7TvLmNxnHzLMEAAPq0dOUfejGo/UAkyGawtT3GuHd3Q==;\n\t5:PicmYHFRFSisO7s8lWiUyjQ8wjyEAyyx/usH6axPWJfL4vIitdVLKRjFJLSGUlGvejWzTqaxG5UTYfCfsLH7f1iLEgOWRZ3cIICrY8PZZHIHsNCtP1OREaTDi+7Gjd2NAJ85nGqulQ2emDjabqZsvhrx8ZvZocsRdTaYQ7dVYmw=;\n\t7:hUtQnYGeU5xvuIwEbkIvvFCf2BLhNQqcWCKVR0eJxshZmoOrIOFmY9qbDaU8+URmYwwbnXVMQsltDpIDpBf179JMR1fDrV3dEYbFGTgrg9VW9zcRvJ0uG4Xof/zxS/C+ZjcM38Ho4uvkjzzXIssaB0zVedfZcC5dl+bV+WMaO1T5rA9iZxG64XkvdbdHmFwlzhHCO3Xws9MqamIEpTRtcuIeyLkkoWwSZWD8HMLE5JKmhN/pNLFj0vSfox+9uln9",
        "X-MS-Exchange-CrossTenant-fromentityheader": "Hosted",
        "X-MS-Has-Attach": "",
        "authentication-results": "spf=none (sender IP is )\n\tsmtp.mailfrom=yskoh@mellanox.com; ",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "x-ms-exchange-messagesentrepresentingtype": "1",
        "X-BeenThere": "dev@dpdk.org",
        "x-microsoft-antispam-message-info": "I1v8Y3pnxIW2RvLyB6hbWKn03RU2I0t8rjk0Qvg/OP+EhmsmDdt7qKNOF2vRxuJ7EcdDw1AsI3GQOZ5axuRdo7dPIi51ExuTcsuEMwjcp6erwH7FxL8hyHi5O30yMGigWLNpu5PEqwB1Fg7X5hXOKmgngB2Wu+/aTBEsxuWEHZ6j5e1eBnZ7R42Xd+Rz6Sz94fRJ4bm1pGSSPRKg66P6+eaN1zO+ArWp9sT2L734Tt+sgPj74rSAuGOJjkcp9rCF8ccQkQQGE5+BXYjl9ejs5PE4Nd426NkNvKYApATGNWZlNFCJVrRBHR3d3QKmrWyzt7+W4FVf9NBpzcTfubELbHW0LBbe/Cxdup3lRasd/1M=",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DB3PR0502MB3996",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Subject": "[dpdk-dev] [PATCH v3 07/11] net/mlx5: add Direct Verbs translate\n\titems"
    },
    "content": "From: Ori Kam <orika@mellanox.com>\n\nThis commit handles the translation of the requested flow into Direct\nVerbs API.\n\nThe Direct Verbs introduce the matcher object which acts as shared mask\nfor all flows that are using the same mask. So in this commit we\ntranslate the item and get in return a matcher and the value that should\nbe matched.\n\nSigned-off-by: Ori Kam <orika@mellanox.com>\nAcked-by: Yongseok Koh <yskoh@mellanox.com>\n---\n drivers/net/mlx5/mlx5_flow.c       |  36 ++\n drivers/net/mlx5/mlx5_flow.h       |  25 ++\n drivers/net/mlx5/mlx5_flow_dv.c    | 775 ++++++++++++++++++++++++++++++++++++-\n drivers/net/mlx5/mlx5_flow_verbs.c |  72 +---\n drivers/net/mlx5/mlx5_prm.h        |   7 +\n 5 files changed, 858 insertions(+), 57 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 1c177b9c8..5632e31c5 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -444,6 +444,42 @@ mlx5_flow_item_acceptable(const struct rte_flow_item *item,\n }\n \n /**\n+ * Adjust the hash fields according to the @p flow information.\n+ *\n+ * @param[in] dev_flow.\n+ *   Pointer to the mlx5_flow.\n+ * @param[in] tunnel\n+ *   1 when the hash field is for a tunnel item.\n+ * @param[in] layer_types\n+ *   ETH_RSS_* types.\n+ * @param[in] hash_fields\n+ *   Item hash fields.\n+ *\n+ * @return\n+ *   The hash fileds that should be used.\n+ */\n+uint64_t\n+mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow,\n+\t\t\t    int tunnel __rte_unused, uint32_t layer_types,\n+\t\t\t    uint64_t hash_fields)\n+{\n+\tstruct rte_flow *flow = dev_flow->flow;\n+#ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT\n+\tint rss_request_inner = flow->rss.level >= 2;\n+\n+\t/* Check RSS hash level for tunnel. */\n+\tif (tunnel && rss_request_inner)\n+\t\thash_fields |= IBV_RX_HASH_INNER;\n+\telse if (tunnel || rss_request_inner)\n+\t\treturn 0;\n+#endif\n+\t/* Check if requested layer matches RSS hash fields. */\n+\tif (!(flow->rss.types & layer_types))\n+\t\treturn 0;\n+\treturn hash_fields;\n+}\n+\n+/**\n  * Lookup and set the ptype in the data Rx part.  A single Ptype can be used,\n  * if several tunnel rules are used on this queue, the tunnel ptype will be\n  * cleared.\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 0cf496db3..7f0566fc9 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -89,6 +89,10 @@\n #define MLX5_IP_PROTOCOL_GRE 47\n #define MLX5_IP_PROTOCOL_MPLS 147\n \n+/* Internent Protocol versions. */\n+#define MLX5_VXLAN 4789\n+#define MLX5_VXLAN_GPE 4790\n+\n /* Priority reserved for default flows. */\n #define MLX5_FLOW_PRIO_RSVD ((uint32_t)-1)\n \n@@ -103,6 +107,24 @@\n #define MLX5_PRIORITY_MAP_L4 0\n #define MLX5_PRIORITY_MAP_MAX 3\n \n+/* Valid layer type for IPV4 RSS. */\n+#define MLX5_IPV4_LAYER_TYPES \\\n+\t(ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 | \\\n+\t ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP | \\\n+\t ETH_RSS_NONFRAG_IPV4_OTHER)\n+\n+/* IBV hash source bits  for IPV4. */\n+#define MLX5_IPV4_IBV_RX_HASH (IBV_RX_HASH_SRC_IPV4 | IBV_RX_HASH_DST_IPV4)\n+\n+/* Valid layer type for IPV6 RSS. */\n+#define MLX5_IPV6_LAYER_TYPES \\\n+\t(ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 | ETH_RSS_NONFRAG_IPV6_TCP | \\\n+\t ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_IPV6_EX  | ETH_RSS_IPV6_TCP_EX | \\\n+\t ETH_RSS_IPV6_UDP_EX | ETH_RSS_NONFRAG_IPV6_OTHER)\n+\n+/* IBV hash source bits  for IPV6. */\n+#define MLX5_IPV6_IBV_RX_HASH (IBV_RX_HASH_SRC_IPV6 | IBV_RX_HASH_DST_IPV6)\n+\n /* Max number of actions per DV flow. */\n #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8\n \n@@ -223,6 +245,9 @@ struct mlx5_flow_driver_ops {\n \n /* mlx5_flow.c */\n \n+uint64_t mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow, int tunnel,\n+\t\t\t\t     uint32_t layer_types,\n+\t\t\t\t     uint64_t hash_fields);\n uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\t\t\t   uint32_t subpriority);\n int mlx5_flow_validate_action_count(struct rte_eth_dev *dev,\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 30d501a61..acb1b7549 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -334,6 +334,779 @@ flow_dv_prepare(const struct rte_flow_attr *attr __rte_unused,\n }\n \n /**\n+ * Add Ethernet item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_eth(void *matcher, void *key,\n+\t\t\t   const struct rte_flow_item *item, int inner)\n+{\n+\tconst struct rte_flow_item_eth *eth_m = item->mask;\n+\tconst struct rte_flow_item_eth *eth_v = item->spec;\n+\tconst struct rte_flow_item_eth nic_mask = {\n+\t\t.dst.addr_bytes = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n+\t\t.src.addr_bytes = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n+\t\t.type = RTE_BE16(0xffff),\n+\t};\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tchar *l24_v;\n+\tunsigned int i;\n+\n+\tif (!eth_v)\n+\t\treturn;\n+\tif (!eth_m)\n+\t\teth_m = &nic_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tmemcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, dmac_47_16),\n+\t       &eth_m->dst, sizeof(eth_m->dst));\n+\t/* The value must be in the range of the mask. */\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dmac_47_16);\n+\tfor (i = 0; i < sizeof(eth_m->dst); ++i)\n+\t\tl24_v[i] = eth_m->dst.addr_bytes[i] & eth_v->dst.addr_bytes[i];\n+\tmemcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m, smac_47_16),\n+\t       &eth_m->src, sizeof(eth_m->src));\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, smac_47_16);\n+\t/* The value must be in the range of the mask. */\n+\tfor (i = 0; i < sizeof(eth_m->dst); ++i)\n+\t\tl24_v[i] = eth_m->src.addr_bytes[i] & eth_v->src.addr_bytes[i];\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,\n+\t\t rte_be_to_cpu_16(eth_m->type));\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, ethertype);\n+\t*(uint16_t *)(l24_v) = eth_m->type & eth_v->type;\n+}\n+\n+/**\n+ * Add VLAN item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_vlan(void *matcher, void *key,\n+\t\t\t    const struct rte_flow_item *item,\n+\t\t\t    int inner)\n+{\n+\tconst struct rte_flow_item_vlan *vlan_m = item->mask;\n+\tconst struct rte_flow_item_vlan *vlan_v = item->spec;\n+\tconst struct rte_flow_item_vlan nic_mask = {\n+\t\t.tci = RTE_BE16(0x0fff),\n+\t\t.inner_type = RTE_BE16(0xffff),\n+\t};\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tuint16_t tci_m;\n+\tuint16_t tci_v;\n+\n+\tif (!vlan_v)\n+\t\treturn;\n+\tif (!vlan_m)\n+\t\tvlan_m = &nic_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\ttci_m = rte_be_to_cpu_16(vlan_m->tci);\n+\ttci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, first_vid, tci_m);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, tci_v);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, first_cfi, tci_m >> 12);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, first_cfi, tci_v >> 12);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, first_prio, tci_m >> 13);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, tci_v >> 13);\n+}\n+\n+/**\n+ * Add IPV4 item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_ipv4(void *matcher, void *key,\n+\t\t\t    const struct rte_flow_item *item,\n+\t\t\t    int inner)\n+{\n+\tconst struct rte_flow_item_ipv4 *ipv4_m = item->mask;\n+\tconst struct rte_flow_item_ipv4 *ipv4_v = item->spec;\n+\tconst struct rte_flow_item_ipv4 nic_mask = {\n+\t\t.hdr = {\n+\t\t\t.src_addr = RTE_BE32(0xffffffff),\n+\t\t\t.dst_addr = RTE_BE32(0xffffffff),\n+\t\t\t.type_of_service = 0xff,\n+\t\t\t.next_proto_id = 0xff,\n+\t\t},\n+\t};\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tchar *l24_m;\n+\tchar *l24_v;\n+\tuint8_t tos;\n+\n+\tif (!ipv4_v)\n+\t\treturn;\n+\tif (!ipv4_m)\n+\t\tipv4_m = &nic_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 0xf);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 4);\n+\tl24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,\n+\t\t\t     dst_ipv4_dst_ipv6.ipv4_layout.ipv4);\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,\n+\t\t\t     dst_ipv4_dst_ipv6.ipv4_layout.ipv4);\n+\t*(uint32_t *)l24_m = ipv4_m->hdr.dst_addr;\n+\t*(uint32_t *)l24_v = ipv4_m->hdr.dst_addr & ipv4_v->hdr.dst_addr;\n+\tl24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,\n+\t\t\t  src_ipv4_src_ipv6.ipv4_layout.ipv4);\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,\n+\t\t\t  src_ipv4_src_ipv6.ipv4_layout.ipv4);\n+\t*(uint32_t *)l24_m = ipv4_m->hdr.src_addr;\n+\t*(uint32_t *)l24_v = ipv4_m->hdr.src_addr & ipv4_v->hdr.src_addr;\n+\ttos = ipv4_m->hdr.type_of_service & ipv4_v->hdr.type_of_service;\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ecn,\n+\t\t ipv4_m->hdr.type_of_service);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, tos);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_dscp,\n+\t\t ipv4_m->hdr.type_of_service >> 2);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, tos >> 2);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol,\n+\t\t ipv4_m->hdr.next_proto_id);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,\n+\t\t ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);\n+}\n+\n+/**\n+ * Add IPV6 item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_ipv6(void *matcher, void *key,\n+\t\t\t    const struct rte_flow_item *item,\n+\t\t\t    int inner)\n+{\n+\tconst struct rte_flow_item_ipv6 *ipv6_m = item->mask;\n+\tconst struct rte_flow_item_ipv6 *ipv6_v = item->spec;\n+\tconst struct rte_flow_item_ipv6 nic_mask = {\n+\t\t.hdr = {\n+\t\t\t.src_addr =\n+\t\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n+\t\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\",\n+\t\t\t.dst_addr =\n+\t\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n+\t\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\",\n+\t\t\t.vtc_flow = RTE_BE32(0xffffffff),\n+\t\t\t.proto = 0xff,\n+\t\t\t.hop_limits = 0xff,\n+\t\t},\n+\t};\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tvoid *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);\n+\tvoid *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);\n+\tchar *l24_m;\n+\tchar *l24_v;\n+\tuint32_t vtc_m;\n+\tuint32_t vtc_v;\n+\tint i;\n+\tint size;\n+\n+\tif (!ipv6_v)\n+\t\treturn;\n+\tif (!ipv6_m)\n+\t\tipv6_m = &nic_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tsize = sizeof(ipv6_m->hdr.dst_addr);\n+\tl24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,\n+\t\t\t     dst_ipv4_dst_ipv6.ipv6_layout.ipv6);\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,\n+\t\t\t     dst_ipv4_dst_ipv6.ipv6_layout.ipv6);\n+\tmemcpy(l24_m, ipv6_m->hdr.dst_addr, size);\n+\tfor (i = 0; i < size; ++i)\n+\t\tl24_v[i] = l24_m[i] & ipv6_v->hdr.dst_addr[i];\n+\tl24_m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_m,\n+\t\t\t     src_ipv4_src_ipv6.ipv6_layout.ipv6);\n+\tl24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,\n+\t\t\t     src_ipv4_src_ipv6.ipv6_layout.ipv6);\n+\tmemcpy(l24_m, ipv6_m->hdr.src_addr, size);\n+\tfor (i = 0; i < size; ++i)\n+\t\tl24_v[i] = l24_m[i] & ipv6_v->hdr.src_addr[i];\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 0xf);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 6);\n+\t/* TOS. */\n+\tvtc_m = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow);\n+\tvtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_ecn, vtc_m >> 20);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_dscp, vtc_m >> 22);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, vtc_v >> 22);\n+\t/* Label. */\n+\tif (inner) {\n+\t\tMLX5_SET(fte_match_set_misc, misc_m, inner_ipv6_flow_label,\n+\t\t\t vtc_m);\n+\t\tMLX5_SET(fte_match_set_misc, misc_v, inner_ipv6_flow_label,\n+\t\t\t vtc_v);\n+\t} else {\n+\t\tMLX5_SET(fte_match_set_misc, misc_m, outer_ipv6_flow_label,\n+\t\t\t vtc_m);\n+\t\tMLX5_SET(fte_match_set_misc, misc_v, outer_ipv6_flow_label,\n+\t\t\t vtc_v);\n+\t}\n+\t/* Protocol. */\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol,\n+\t\t ipv6_m->hdr.proto);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,\n+\t\t ipv6_v->hdr.proto & ipv6_m->hdr.proto);\n+}\n+\n+/**\n+ * Add TCP item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_tcp(void *matcher, void *key,\n+\t\t\t   const struct rte_flow_item *item,\n+\t\t\t   int inner)\n+{\n+\tconst struct rte_flow_item_tcp *tcp_m = item->mask;\n+\tconst struct rte_flow_item_tcp *tcp_v = item->spec;\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\n+\tif (!tcp_v)\n+\t\treturn;\n+\tif (!tcp_m)\n+\t\ttcp_m = &rte_flow_item_tcp_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_TCP);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, tcp_sport,\n+\t\t rte_be_to_cpu_16(tcp_m->hdr.src_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,\n+\t\t rte_be_to_cpu_16(tcp_v->hdr.src_port & tcp_m->hdr.src_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, tcp_dport,\n+\t\t rte_be_to_cpu_16(tcp_m->hdr.dst_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,\n+\t\t rte_be_to_cpu_16(tcp_v->hdr.dst_port & tcp_m->hdr.dst_port));\n+}\n+\n+/**\n+ * Add UDP item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_udp(void *matcher, void *key,\n+\t\t\t   const struct rte_flow_item *item,\n+\t\t\t   int inner)\n+{\n+\tconst struct rte_flow_item_udp *udp_m = item->mask;\n+\tconst struct rte_flow_item_udp *udp_v = item->spec;\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\n+\tif (!udp_v)\n+\t\treturn;\n+\tif (!udp_m)\n+\t\tudp_m = &rte_flow_item_udp_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_sport,\n+\t\t rte_be_to_cpu_16(udp_m->hdr.src_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,\n+\t\t rte_be_to_cpu_16(udp_v->hdr.src_port & udp_m->hdr.src_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport,\n+\t\t rte_be_to_cpu_16(udp_m->hdr.dst_port));\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,\n+\t\t rte_be_to_cpu_16(udp_v->hdr.dst_port & udp_m->hdr.dst_port));\n+}\n+\n+/**\n+ * Add GRE item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_gre(void *matcher, void *key,\n+\t\t\t   const struct rte_flow_item *item,\n+\t\t\t   int inner)\n+{\n+\tconst struct rte_flow_item_gre *gre_m = item->mask;\n+\tconst struct rte_flow_item_gre *gre_v = item->spec;\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tvoid *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);\n+\tvoid *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);\n+\n+\tif (!gre_v)\n+\t\treturn;\n+\tif (!gre_m)\n+\t\tgre_m = &rte_flow_item_gre_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);\n+\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_GRE);\n+\tMLX5_SET(fte_match_set_misc, misc_m, gre_protocol,\n+\t\t rte_be_to_cpu_16(gre_m->protocol));\n+\tMLX5_SET(fte_match_set_misc, misc_v, gre_protocol,\n+\t\t rte_be_to_cpu_16(gre_v->protocol & gre_m->protocol));\n+}\n+\n+/**\n+ * Add NVGRE item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_nvgre(void *matcher, void *key,\n+\t\t\t     const struct rte_flow_item *item,\n+\t\t\t     int inner)\n+{\n+\tconst struct rte_flow_item_nvgre *nvgre_m = item->mask;\n+\tconst struct rte_flow_item_nvgre *nvgre_v = item->spec;\n+\tvoid *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);\n+\tvoid *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);\n+\tchar *gre_key_m;\n+\tchar *gre_key_v;\n+\tint size;\n+\tint i;\n+\n+\tif (!nvgre_v)\n+\t\treturn;\n+\tif (!nvgre_m)\n+\t\tnvgre_m = &rte_flow_item_nvgre_mask;\n+\tsize = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);\n+\tgre_key_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, gre_key_h);\n+\tgre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);\n+\tmemcpy(gre_key_m, nvgre_m->tni, size);\n+\tfor (i = 0; i < size; ++i)\n+\t\tgre_key_v[i] = gre_key_m[i] & ((const char *)(nvgre_v->tni))[i];\n+\tflow_dv_translate_item_gre(matcher, key, item, inner);\n+}\n+\n+/**\n+ * Add VXLAN item to matcher and to the value.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_translate_item_vxlan(void *matcher, void *key,\n+\t\t\t     const struct rte_flow_item *item,\n+\t\t\t     int inner)\n+{\n+\tconst struct rte_flow_item_vxlan *vxlan_m = item->mask;\n+\tconst struct rte_flow_item_vxlan *vxlan_v = item->spec;\n+\tvoid *headers_m;\n+\tvoid *headers_v;\n+\tvoid *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);\n+\tvoid *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);\n+\tchar *vni_m;\n+\tchar *vni_v;\n+\tuint16_t dport;\n+\tint size;\n+\tint i;\n+\n+\tif (!vxlan_v)\n+\t\treturn;\n+\tif (!vxlan_m)\n+\t\tvxlan_m = &rte_flow_item_vxlan_mask;\n+\tif (inner) {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t inner_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);\n+\t} else {\n+\t\theaders_m = MLX5_ADDR_OF(fte_match_param, matcher,\n+\t\t\t\t\t outer_headers);\n+\t\theaders_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);\n+\t}\n+\tdport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ? MLX5_VXLAN :\n+\t\t\t\t\t\t\t MLX5_VXLAN_GPE;\n+\tif (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {\n+\t\tMLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF);\n+\t\tMLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport);\n+\t}\n+\tsize = sizeof(vxlan_m->vni);\n+\tvni_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, vxlan_vni);\n+\tvni_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, vxlan_vni);\n+\tmemcpy(vni_m, vxlan_m->vni, size);\n+\tfor (i = 0; i < size; ++i)\n+\t\tvni_v[i] = vni_m[i] & vxlan_v->vni[i];\n+}\n+\n+/**\n+ * Update the matcher and the value based the selected item.\n+ *\n+ * @param[in, out] matcher\n+ *   Flow matcher.\n+ * @param[in, out] key\n+ *   Flow matcher value.\n+ * @param[in] item\n+ *   Flow pattern to translate.\n+ * @param[in, out] dev_flow\n+ *   Pointer to the mlx5_flow.\n+ * @param[in] inner\n+ *   Item is inner pattern.\n+ */\n+static void\n+flow_dv_create_item(void *matcher, void *key,\n+\t\t    const struct rte_flow_item *item,\n+\t\t    struct mlx5_flow *dev_flow,\n+\t\t    int inner)\n+{\n+\tstruct mlx5_flow_dv_matcher *tmatcher = matcher;\n+\n+\tswitch (item->type) {\n+\tcase RTE_FLOW_ITEM_TYPE_VOID:\n+\tcase RTE_FLOW_ITEM_TYPE_END:\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_ETH:\n+\t\tflow_dv_translate_item_eth(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t   inner);\n+\t\ttmatcher->priority = MLX5_PRIORITY_MAP_L2;\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n+\t\tflow_dv_translate_item_vlan(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t    inner);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n+\t\tflow_dv_translate_item_ipv4(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t    inner);\n+\t\ttmatcher->priority = MLX5_PRIORITY_MAP_L3;\n+\t\tdev_flow->dv.hash_fields |=\n+\t\t\tmlx5_flow_hashfields_adjust(dev_flow, inner,\n+\t\t\t\t\t\t    MLX5_IPV4_LAYER_TYPES,\n+\t\t\t\t\t\t    MLX5_IPV4_IBV_RX_HASH);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n+\t\tflow_dv_translate_item_ipv6(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t    inner);\n+\t\ttmatcher->priority = MLX5_PRIORITY_MAP_L3;\n+\t\tdev_flow->dv.hash_fields |=\n+\t\t\tmlx5_flow_hashfields_adjust(dev_flow, inner,\n+\t\t\t\t\t\t    MLX5_IPV6_LAYER_TYPES,\n+\t\t\t\t\t\t    MLX5_IPV6_IBV_RX_HASH);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_TCP:\n+\t\tflow_dv_translate_item_tcp(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t   inner);\n+\t\ttmatcher->priority = MLX5_PRIORITY_MAP_L4;\n+\t\tdev_flow->dv.hash_fields |=\n+\t\t\tmlx5_flow_hashfields_adjust(dev_flow, inner,\n+\t\t\t\t\t\t    ETH_RSS_TCP,\n+\t\t\t\t\t\t    (IBV_RX_HASH_SRC_PORT_TCP |\n+\t\t\t\t\t\t     IBV_RX_HASH_DST_PORT_TCP));\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_UDP:\n+\t\tflow_dv_translate_item_udp(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t   inner);\n+\t\ttmatcher->priority = MLX5_PRIORITY_MAP_L4;\n+\t\tdev_flow->verbs.hash_fields |=\n+\t\t\tmlx5_flow_hashfields_adjust(dev_flow, inner,\n+\t\t\t\t\t\t    ETH_RSS_TCP,\n+\t\t\t\t\t\t    (IBV_RX_HASH_SRC_PORT_TCP |\n+\t\t\t\t\t\t     IBV_RX_HASH_DST_PORT_TCP));\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_NVGRE:\n+\t\tflow_dv_translate_item_nvgre(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t     inner);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_GRE:\n+\t\tflow_dv_translate_item_gre(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t   inner);\n+\t\tbreak;\n+\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n+\tcase RTE_FLOW_ITEM_TYPE_VXLAN_GPE:\n+\t\tflow_dv_translate_item_vxlan(tmatcher->mask.buf, key, item,\n+\t\t\t\t\t     inner);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+static uint32_t matcher_zero[MLX5_ST_SZ_DW(fte_match_param)] = { 0 };\n+\n+#define HEADER_IS_ZERO(match_criteria, headers)\t\t\t\t     \\\n+\t!(memcmp(MLX5_ADDR_OF(fte_match_param, match_criteria, headers),     \\\n+\t\t matcher_zero, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \\\n+\n+/**\n+ * Calculate flow matcher enable bitmap.\n+ *\n+ * @param match_criteria\n+ *   Pointer to flow matcher criteria.\n+ *\n+ * @return\n+ *   Bitmap of enabled fields.\n+ */\n+static uint8_t\n+flow_dv_matcher_enable(uint32_t *match_criteria)\n+{\n+\tuint8_t match_criteria_enable;\n+\n+\tmatch_criteria_enable =\n+\t\t(!HEADER_IS_ZERO(match_criteria, outer_headers)) <<\n+\t\tMLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT;\n+\tmatch_criteria_enable |=\n+\t\t(!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<\n+\t\tMLX5_MATCH_CRITERIA_ENABLE_MISC_BIT;\n+\tmatch_criteria_enable |=\n+\t\t(!HEADER_IS_ZERO(match_criteria, inner_headers)) <<\n+\t\tMLX5_MATCH_CRITERIA_ENABLE_INNER_BIT;\n+\tmatch_criteria_enable |=\n+\t\t(!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<\n+\t\tMLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;\n+\n+\treturn match_criteria_enable;\n+}\n+\n+/**\n+ * Register the flow matcher.\n+ *\n+ * @param dev[in, out]\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in, out] matcher\n+ *   Pointer to flow matcher.\n+ * @parm[in, out] dev_flow\n+ *   Pointer to the dev_flow.\n+ * @param[out] error\n+ *   pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success otherwise -errno and errno is set.\n+ */\n+static int\n+flow_dv_matcher_register(struct rte_eth_dev *dev,\n+\t\t\t struct mlx5_flow_dv_matcher *matcher,\n+\t\t\t struct mlx5_flow *dev_flow,\n+\t\t\t struct rte_flow_error *error)\n+{\n+\tstruct priv *priv = dev->data->dev_private;\n+\tstruct mlx5_flow_dv_matcher *cache;\n+\tstruct mlx5dv_flow_matcher_attr dv_attr = {\n+\t\t.type = IBV_FLOW_ATTR_NORMAL,\n+\t\t.match_mask = (void *)&matcher->mask,\n+\t};\n+\n+\t/* Lookup from cache. */\n+\tLIST_FOREACH(cache, &priv->matchers, cache.next) {\n+\t\tif (matcher->crc == cache->crc &&\n+\t\t    matcher->priority == cache->priority &&\n+\t\t    matcher->egress == cache->egress &&\n+\t\t    !memcmp((const void *)matcher->mask.buf,\n+\t\t\t    (const void *)cache->mask.buf, cache->mask.size)) {\n+\t\t\tDRV_LOG(DEBUG,\n+\t\t\t\t\"priority %hd use %s matcher %p: refcnt %d++\",\n+\t\t\t\tcache->priority, cache->egress ? \"tx\" : \"rx\",\n+\t\t\t\t(void *)cache,\n+\t\t\t\trte_atomic32_read(&cache->cache.refcnt));\n+\t\t\trte_atomic32_inc(&cache->cache.refcnt);\n+\t\t\tdev_flow->dv.matcher = cache;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\t/* Register new matcher. */\n+\tcache = rte_calloc(__func__, 1, sizeof(*cache), 0);\n+\tif (!cache)\n+\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"cannot allocate matcher memory\");\n+\t*cache = *matcher;\n+\tdv_attr.match_criteria_enable =\n+\t\tflow_dv_matcher_enable(cache->mask.buf);\n+\tdv_attr.priority = matcher->priority;\n+\tif (matcher->egress)\n+\t\tdv_attr.flags |= IBV_FLOW_ATTR_FLAGS_EGRESS;\n+\tcache->cache.resource =\n+\t\tmlx5dv_create_flow_matcher(priv->ctx, &dv_attr);\n+\tif (!cache->cache.resource)\n+\t\treturn rte_flow_error_set(error, ENOMEM,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\t  NULL, \"cannot create matcher\");\n+\trte_atomic32_inc(&cache->cache.refcnt);\n+\tLIST_INSERT_HEAD(&priv->matchers, &cache->cache, next);\n+\tdev_flow->dv.matcher = cache;\n+\tDRV_LOG(DEBUG, \"priority %hd new %s matcher %p: refcnt %d\",\n+\t\tcache->priority,\n+\t\tcache->egress ? \"tx\" : \"rx\", (void *)cache,\n+\t\trte_atomic32_read(&cache->cache.refcnt));\n+\treturn 0;\n+}\n+\n+\n+/**\n+ * Fill the flow with DV spec.\n+ *\n+ * @param[in] dev\n+ *   Pointer to rte_eth_dev structure.\n+ * @param[in, out] dev_flow\n+ *   Pointer to the sub flow.\n+ * @param[in] attr\n+ *   Pointer to the flow attributes.\n+ * @param[in] items\n+ *   Pointer to the list of items.\n+ * @param[in] actions\n+ *   Pointer to the list of actions.\n+ * @param[out] error\n+ *   Pointer to the error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_ernno is set.\n+ */\n+static int\n+flow_dv_translate(struct rte_eth_dev *dev,\n+\t\t  struct mlx5_flow *dev_flow,\n+\t\t  const struct rte_flow_attr *attr,\n+\t\t  const struct rte_flow_item items[],\n+\t\t  const struct rte_flow_action actions[] __rte_unused,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tstruct priv *priv = dev->data->dev_private;\n+\tuint64_t priority = attr->priority;\n+\tstruct mlx5_flow_dv_matcher matcher = {\n+\t\t.mask = {\n+\t\t\t.size = sizeof(matcher.mask.buf),\n+\t\t},\n+\t};\n+\tvoid *match_value = dev_flow->dv.value.buf;\n+\tuint8_t inner = 0;\n+\n+\tif (priority == MLX5_FLOW_PRIO_RSVD)\n+\t\tpriority = priv->config.flow_prio - 1;\n+\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++)\n+\t\tflow_dv_create_item(&matcher, match_value, items, dev_flow,\n+\t\t\t\t    inner);\n+\tmatcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,\n+\t\t\t\t     matcher.mask.size);\n+\tif (priority == MLX5_FLOW_PRIO_RSVD)\n+\t\tpriority = priv->config.flow_prio - 1;\n+\tmatcher.priority = mlx5_flow_adjust_priority(dev, priority,\n+\t\t\t\t\t\t     matcher.priority);\n+\tmatcher.egress = attr->egress;\n+\tif (flow_dv_matcher_register(dev, &matcher, dev_flow, error))\n+\t\treturn -rte_errno;\n+\treturn 0;\n+}\n+\n+/**\n  * Fills the flow_ops with the function pointers.\n  *\n  * @param[out] flow_ops\n@@ -345,7 +1118,7 @@ mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)\n \t*flow_ops = (struct mlx5_flow_driver_ops) {\n \t\t.validate = flow_dv_validate,\n \t\t.prepare = flow_dv_prepare,\n-\t\t.translate = NULL,\n+\t\t.translate = flow_dv_translate,\n \t\t.apply = NULL,\n \t\t.remove = NULL,\n \t\t.destroy = NULL,\ndiff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c\nindex e8e16cc37..f4a264232 100644\n--- a/drivers/net/mlx5/mlx5_flow_verbs.c\n+++ b/drivers/net/mlx5/mlx5_flow_verbs.c\n@@ -132,37 +132,6 @@ flow_verbs_spec_add(struct mlx5_flow *flow, void *src, unsigned int size)\n }\n \n /**\n- * Adjust verbs hash fields according to the @p flow information.\n- *\n- * @param[in] dev_flow.\n- *   Pointer to dev flow structure.\n- * @param[in] tunnel\n- *   1 when the hash field is for a tunnel item.\n- * @param[in] layer_types\n- *   ETH_RSS_* types.\n- * @param[in] hash_fields\n- *   Item hash fields.\n- */\n-static void\n-flow_verbs_hashfields_adjust(struct mlx5_flow *dev_flow,\n-\t\t\t     int tunnel __rte_unused,\n-\t\t\t     uint32_t layer_types, uint64_t hash_fields)\n-{\n-#ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT\n-\tint rss_request_inner = dev_flow->flow->rss.level >= 2;\n-\n-\thash_fields |= (tunnel ? IBV_RX_HASH_INNER : 0);\n-\tif (rss_request_inner && !tunnel)\n-\t\thash_fields = 0;\n-\telse if (rss_request_inner < 2 && tunnel)\n-\t\thash_fields = 0;\n-#endif\n-\tif (!(dev_flow->flow->rss.types & layer_types))\n-\t\thash_fields = 0;\n-\tdev_flow->verbs.hash_fields |= hash_fields;\n-}\n-\n-/**\n  * Convert the @p item into a Verbs specification. This function assumes that\n  * the input is valid and that there is space to insert the requested item\n  * into the flow.\n@@ -346,13 +315,10 @@ flow_verbs_translate_item_ipv4(const struct rte_flow_item *item,\n \t\tipv4.val.proto &= ipv4.mask.proto;\n \t\tipv4.val.tos &= ipv4.mask.tos;\n \t}\n-\tflow_verbs_hashfields_adjust(dev_flow, tunnel,\n-\t\t\t\t     (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV4_TCP |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV4_UDP |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV4_OTHER),\n-\t\t\t\t     (IBV_RX_HASH_SRC_IPV4 |\n-\t\t\t\t      IBV_RX_HASH_DST_IPV4));\n+\tdev_flow->verbs.hash_fields |=\n+\t\tmlx5_flow_hashfields_adjust(dev_flow, tunnel,\n+\t\t\t\t\t    MLX5_IPV4_LAYER_TYPES,\n+\t\t\t\t\t    MLX5_IPV4_IBV_RX_HASH);\n \tdev_flow->verbs.attr->priority = MLX5_PRIORITY_MAP_L3;\n \tflow_verbs_spec_add(dev_flow, &ipv4, size);\n }\n@@ -426,16 +392,10 @@ flow_verbs_translate_item_ipv6(const struct rte_flow_item *item,\n \t\tipv6.val.next_hdr &= ipv6.mask.next_hdr;\n \t\tipv6.val.hop_limit &= ipv6.mask.hop_limit;\n \t}\n-\tflow_verbs_hashfields_adjust(dev_flow, tunnel,\n-\t\t\t\t     (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV6_TCP |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV6_UDP |\n-\t\t\t\t      ETH_RSS_IPV6_EX  |\n-\t\t\t\t      ETH_RSS_IPV6_TCP_EX |\n-\t\t\t\t      ETH_RSS_IPV6_UDP_EX |\n-\t\t\t\t      ETH_RSS_NONFRAG_IPV6_OTHER),\n-\t\t\t\t     (IBV_RX_HASH_SRC_IPV6 |\n-\t\t\t\t      IBV_RX_HASH_DST_IPV6));\n+\tdev_flow->verbs.hash_fields |=\n+\t\tmlx5_flow_hashfields_adjust(dev_flow, tunnel,\n+\t\t\t\t\t    MLX5_IPV6_LAYER_TYPES,\n+\t\t\t\t\t    MLX5_IPV6_IBV_RX_HASH);\n \tdev_flow->verbs.attr->priority = MLX5_PRIORITY_MAP_L3;\n \tflow_verbs_spec_add(dev_flow, &ipv6, size);\n }\n@@ -479,10 +439,10 @@ flow_verbs_translate_item_udp(const struct rte_flow_item *item,\n \t\tudp.val.src_port &= udp.mask.src_port;\n \t\tudp.val.dst_port &= udp.mask.dst_port;\n \t}\n-\tflow_verbs_hashfields_adjust(dev_flow,\n-\t\t\t\t     tunnel, ETH_RSS_UDP,\n-\t\t\t\t     (IBV_RX_HASH_SRC_PORT_UDP |\n-\t\t\t\t      IBV_RX_HASH_DST_PORT_UDP));\n+\tdev_flow->verbs.hash_fields |=\n+\t\tmlx5_flow_hashfields_adjust(dev_flow, tunnel, ETH_RSS_UDP,\n+\t\t\t\t\t    (IBV_RX_HASH_SRC_PORT_UDP |\n+\t\t\t\t\t     IBV_RX_HASH_DST_PORT_UDP));\n \tdev_flow->verbs.attr->priority = MLX5_PRIORITY_MAP_L4;\n \tflow_verbs_spec_add(dev_flow, &udp, size);\n }\n@@ -526,10 +486,10 @@ flow_verbs_translate_item_tcp(const struct rte_flow_item *item,\n \t\ttcp.val.src_port &= tcp.mask.src_port;\n \t\ttcp.val.dst_port &= tcp.mask.dst_port;\n \t}\n-\tflow_verbs_hashfields_adjust(dev_flow,\n-\t\t\t\t     tunnel, ETH_RSS_TCP,\n-\t\t\t\t     (IBV_RX_HASH_SRC_PORT_TCP |\n-\t\t\t\t      IBV_RX_HASH_DST_PORT_TCP));\n+\tdev_flow->verbs.hash_fields |=\n+\t\tmlx5_flow_hashfields_adjust(dev_flow, tunnel, ETH_RSS_TCP,\n+\t\t\t\t\t    (IBV_RX_HASH_SRC_PORT_TCP |\n+\t\t\t\t\t     IBV_RX_HASH_DST_PORT_TCP));\n \tdev_flow->verbs.attr->priority = MLX5_PRIORITY_MAP_L4;\n \tflow_verbs_spec_add(dev_flow, &tcp, size);\n }\ndiff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h\nindex 2222e7fbd..4e2f9f43d 100644\n--- a/drivers/net/mlx5/mlx5_prm.h\n+++ b/drivers/net/mlx5/mlx5_prm.h\n@@ -493,6 +493,13 @@ struct mlx5_ifc_fte_match_param_bits {\n \tu8 reserved_at_800[0x800];\n };\n \n+enum {\n+\tMLX5_MATCH_CRITERIA_ENABLE_OUTER_BIT,\n+\tMLX5_MATCH_CRITERIA_ENABLE_MISC_BIT,\n+\tMLX5_MATCH_CRITERIA_ENABLE_INNER_BIT,\n+\tMLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT\n+};\n+\n /* CQE format mask. */\n #define MLX5E_CQE_FORMAT_MASK 0xc\n \n",
    "prefixes": [
        "v3",
        "07/11"
    ]
}