get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 44898,
    "url": "http://patches.dpdk.org/api/patches/44898/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180919072143.23211-2-yskoh@mellanox.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": "<20180919072143.23211-2-yskoh@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180919072143.23211-2-yskoh@mellanox.com",
    "date": "2018-09-19T07:21:54",
    "name": "[1/3] net/mlx5: add abstraction for multiple flow drivers",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "a3ac7d71e7584adf6d60b2899fb8008e7f25dd00",
    "submitter": {
        "id": 636,
        "url": "http://patches.dpdk.org/api/people/636/?format=api",
        "name": "Yongseok Koh",
        "email": "yskoh@mellanox.com"
    },
    "delegate": {
        "id": 6624,
        "url": "http://patches.dpdk.org/api/users/6624/?format=api",
        "username": "shahafs",
        "first_name": "Shahaf",
        "last_name": "Shuler",
        "email": "shahafs@mellanox.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20180919072143.23211-2-yskoh@mellanox.com/mbox/",
    "series": [
        {
            "id": 1381,
            "url": "http://patches.dpdk.org/api/series/1381/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1381",
            "date": "2018-09-19T07:21:53",
            "name": "migrate Linux TC flower driver to new flow engine",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/1381/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/44898/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/44898/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 35F8C4CA6;\n\tWed, 19 Sep 2018 09:22:00 +0200 (CEST)",
            "from EUR01-HE1-obe.outbound.protection.outlook.com\n\t(mail-he1eur01on0073.outbound.protection.outlook.com [104.47.0.73])\n\tby dpdk.org (Postfix) with ESMTP id D231F378B\n\tfor <dev@dpdk.org>; Wed, 19 Sep 2018 09:21:56 +0200 (CEST)",
            "from DB3PR0502MB3980.eurprd05.prod.outlook.com (52.134.72.27) by\n\tDB3PR0502MB4060.eurprd05.prod.outlook.com (52.134.72.153) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n\t15.20.1143.18; Wed, 19 Sep 2018 07:21:55 +0000",
            "from DB3PR0502MB3980.eurprd05.prod.outlook.com\n\t([fe80::452:cfe7:8363:61c1]) by\n\tDB3PR0502MB3980.eurprd05.prod.outlook.com\n\t([fe80::452:cfe7:8363:61c1%2]) with mapi id 15.20.1143.017;\n\tWed, 19 Sep 2018 07:21:55 +0000"
        ],
        "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=oncnDQLZ9PkXkYHojUlp/YGY1YAua7nGl9h0DBg0dEY=;\n\tb=WUnHZGKJbwNx64dUx4oxpIjZTQ7fEfke04zTS+H7bM+rVF3Ypl0xgJ3iDyR+vZbonrd3Luw5KYrEtxvGGmzo1qN9J5LfNhSj6npfbj5q2zTWftZNkTZ8QJtkLG0vQG293+Q5MJWq+NONp/uvGuCBv52CRHzA0YNWLgp+yBrXZeM=",
        "From": "Yongseok Koh <yskoh@mellanox.com>",
        "To": "Shahaf Shuler <shahafs@mellanox.com>",
        "CC": "\"dev@dpdk.org\" <dev@dpdk.org>, Yongseok Koh <yskoh@mellanox.com>",
        "Thread-Topic": "[PATCH 1/3] net/mlx5: add abstraction for multiple flow drivers",
        "Thread-Index": "AQHUT+lx0K5QmXSaw0qhPWK5YpR2OQ==",
        "Date": "Wed, 19 Sep 2018 07:21:54 +0000",
        "Message-ID": "<20180919072143.23211-2-yskoh@mellanox.com>",
        "References": "<20180919072143.23211-1-yskoh@mellanox.com>",
        "In-Reply-To": "<20180919072143.23211-1-yskoh@mellanox.com>",
        "Accept-Language": "en-US",
        "Content-Language": "en-US",
        "X-MS-Has-Attach": "",
        "X-MS-TNEF-Correlator": "",
        "x-clientproxiedby": "BYAPR03CA0020.namprd03.prod.outlook.com\n\t(2603:10b6:a02:a8::33) To DB3PR0502MB3980.eurprd05.prod.outlook.com\n\t(2603:10a6:8:10::27)",
        "authentication-results": "spf=none (sender IP is )\n\tsmtp.mailfrom=yskoh@mellanox.com; ",
        "x-ms-exchange-messagesentrepresentingtype": "1",
        "x-originating-ip": "[209.116.155.178]",
        "x-ms-publictraffictype": "Email",
        "x-microsoft-exchange-diagnostics": "1; DB3PR0502MB4060;\n\t6:EdkIvryFdxixjdUbw1W2PyZyJ1Pg2v7mJR8poFoMOJAUWDxyS7RZPGqetk7IOXGHHBmTB1GelQnWC0bG7ICQzA1EY/XCDIggUswnYSuaVs8d1A8JXNLr4XshUa9GFKGQ17LaDW0Zrq4dXHS7d2nmDL6xIE/jSbwaFLnTSehMZhFKa4mlrl/kCixSTtfrUsIhR//rtqPzD67B24uQBMSfKPUdqBYqMg7Fn38xdGS5WWdVwjgPLwcwbLaXjNZbPiI3l/Qx9bKQ4pGgLL44EFySamQIiVtlhyqDN5E2IpCURWbZ0ELOJbek3W+J2bCLqlYAobBez6B3PBB6M9oUiFmlV942urt81RFBQgvAvn8IKXex6YSSFsQPAw++4W5Blvz0iwdlU32z4aAVnHlDeC084lkDBPvqsRc01ibUzH7kzdDHVM3XilHI2pzeC+5N9LAoFWEjMLmyDnbbccxKv3PMqQ==;\n\t5:T7a7t1mTzpu3Ep28PNlEyviK22Q5vd08Io2ZYpSpsREg1mDfhq5pClfCz07IFGXujmFH12jZmca1BCUYUWedovXCp5AoXaA7ec3nHRgljeQkh/GePSw48HcW/7IORaTIs2qiwo3/Iyu4CmcABOgZV2Jat2qnqME33BFtmm/OAdg=;\n\t7:HvbU29ARy2hFsdBpyYs/iYQzFTuicDO4Q/mgXetO7YrSMqU+qq1LBLGFBbX8zKmioLDvGNOHFIA3q6CuLY35ejkejF3Eom1wy1ewUls2KyxliS2qTMj4j2TueUBdzO2f1YUOTRJ//25smR9anl6fATZKTYqe1eu32ccJbY1B+tYqYqR17ptZ0Pbr/PBdDY22lgluEzyyNHSIume6erlD+SMngZqK3eWGM81zyVgadc07EzK2r+k/7Xpt/BQZjzMk",
        "x-ms-office365-filtering-correlation-id": "7fda890d-0f8a-4343-bbb3-08d61e0093a9",
        "x-ms-office365-filtering-ht": "Tenant",
        "x-microsoft-antispam": "BCL:0; PCL:0;\n\tRULEID:(7020095)(4652040)(8989299)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020);\n\tSRVR:DB3PR0502MB4060; ",
        "x-ms-traffictypediagnostic": "DB3PR0502MB4060:",
        "x-microsoft-antispam-prvs": "<DB3PR0502MB406043F1274A8641029A563CC31C0@DB3PR0502MB4060.eurprd05.prod.outlook.com>",
        "x-exchange-antispam-report-test": "UriScan:;",
        "x-ms-exchange-senderadcheck": "1",
        "x-exchange-antispam-report-cfa-test": "BCL:0; PCL:0;\n\tRULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(10201501046)(93006095)(93001095)(3231355)(944501410)(52105095)(6055026)(149027)(150027)(6041310)(20161123562045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123564045)(20161123560045)(201708071742011)(7699050);\n\tSRVR:DB3PR0502MB4060; BCL:0; PCL:0; RULEID:; SRVR:DB3PR0502MB4060; ",
        "x-forefront-prvs": "0800C0C167",
        "x-forefront-antispam-report": "SFV:NSPM;\n\tSFS:(10009020)(136003)(366004)(346002)(396003)(376002)(39860400002)(199004)(189003)(3846002)(6512007)(68736007)(99286004)(6436002)(575784001)(6486002)(86362001)(97736004)(478600001)(2900100001)(6116002)(4326008)(2906002)(6862004)(1076002)(106356001)(54906003)(25786009)(36756003)(8676002)(8936002)(81156014)(316002)(486006)(5660300001)(66066001)(105586002)(446003)(37006003)(107886003)(102836004)(81166006)(476003)(305945005)(7736002)(2616005)(11346002)(6636002)(5250100002)(76176011)(256004)(53936002)(386003)(14444005)(14454004)(26005)(52116002)(53946003)(6506007);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0502MB4060;\n\tH:DB3PR0502MB3980.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; \n\tPTR:InfoNoRecords; A:1; MX:1; ",
        "received-spf": "None (protection.outlook.com: mellanox.com does not designate\n\tpermitted sender hosts)",
        "x-microsoft-antispam-message-info": "SwlZ+heeS7y7QClzAXIKBZwEEsyGH/rAzBakGwNu3sQC3w2xRIkuMgVsXF5P5TIxUYUshVaxdJVG05Ay5W3AgYV67PONcF9T1wiNuIquWPFqetF8eO4Y6q/SeveJsOCbt24tnoiz8MUNJGScNrGa70H7wncsZpA5e44vZrlz0I4citnvvFaZ5dvnCuQTmSxuEbhaEPcARbf5s92OOm6KKLVCkyYDPljye6WGUypOp+o8UOf1MoyMwhLfiAvGozZ5BIKSvvhlBLu234wPfHf7bqF0p/BPx610hVazBbfHTX57DPU6UTY3srNNudORWKcUAztC7pCagKiZSiSQ7AXjFMu84LzMqHmxAW5MW6gV6sw=",
        "spamdiagnosticoutput": "1:99",
        "spamdiagnosticmetadata": "NSPM",
        "Content-Type": "text/plain; charset=\"iso-8859-1\"",
        "Content-Transfer-Encoding": "quoted-printable",
        "MIME-Version": "1.0",
        "X-OriginatorOrg": "Mellanox.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "7fda890d-0f8a-4343-bbb3-08d61e0093a9",
        "X-MS-Exchange-CrossTenant-originalarrivaltime": "19 Sep 2018 07:21:54.9964\n\t(UTC)",
        "X-MS-Exchange-CrossTenant-fromentityheader": "Hosted",
        "X-MS-Exchange-CrossTenant-id": "a652971c-7d2e-4d9b-a6a4-d149256f461b",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DB3PR0502MB4060",
        "Subject": "[dpdk-dev] [PATCH 1/3] net/mlx5: add abstraction for multiple flow\n\tdrivers",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Flow engine has to support multiple driver paths. Verbs/DV for NIC flow\nsteering and Linux TC flower for E-Switch flow steering. In the future,\nanother flow driver could be added (devX).\n\nSigned-off-by: Yongseok Koh <yskoh@mellanox.com>\n---\n drivers/net/mlx5/mlx5.c            |   1 -\n drivers/net/mlx5/mlx5_flow.c       | 348 +++++++++++++++++++++++++++++++++----\n drivers/net/mlx5/mlx5_flow.h       |  17 +-\n drivers/net/mlx5/mlx5_flow_dv.c    |  26 +--\n drivers/net/mlx5/mlx5_flow_verbs.c |  20 +--\n 5 files changed, 335 insertions(+), 77 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex d5936091b..02324ef4f 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -1192,7 +1192,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \tif (err < 0)\n \t\tgoto error;\n \tpriv->config.flow_prio = err;\n-\tmlx5_flow_init_driver_ops(eth_dev);\n \t/*\n \t * Once the device is added to the list of memory event\n \t * callback, its global MR cache table cannot be expanded\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 677cc7a32..2d3158a6f 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -37,6 +37,23 @@\n extern const struct eth_dev_ops mlx5_dev_ops;\n extern const struct eth_dev_ops mlx5_dev_ops_isolate;\n \n+/** Device flow drivers. */\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+extern const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops;\n+#endif\n+extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops;\n+\n+const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops;\n+\n+const struct mlx5_flow_driver_ops *flow_drv_ops[] = {\n+\t[MLX5_FLOW_TYPE_MIN] = &mlx5_flow_null_drv_ops,\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t[MLX5_FLOW_TYPE_DV] = &mlx5_flow_dv_drv_ops,\n+#endif\n+\t[MLX5_FLOW_TYPE_VERBS] = &mlx5_flow_verbs_drv_ops,\n+\t[MLX5_FLOW_TYPE_MAX] = &mlx5_flow_null_drv_ops\n+};\n+\n enum mlx5_expansion {\n \tMLX5_EXPANSION_ROOT,\n \tMLX5_EXPANSION_ROOT_OUTER,\n@@ -282,9 +299,6 @@ static struct mlx5_flow_tunnel_info tunnels_info[] = {\n \t},\n };\n \n-/* Holds the nic operations that should be used. */\n-struct mlx5_flow_driver_ops nic_ops;\n-\n /**\n  * Discover the maximum number of priority available.\n  *\n@@ -1511,6 +1525,284 @@ mlx5_flow_validate_item_mpls(const struct rte_flow_item *item __rte_unused,\n \t\t\t\t  \" update.\");\n }\n \n+static int\n+flow_null_validate(struct rte_eth_dev *dev __rte_unused,\n+\t\t   const struct rte_flow_attr *attr __rte_unused,\n+\t\t   const struct rte_flow_item items[] __rte_unused,\n+\t\t   const struct rte_flow_action actions[] __rte_unused,\n+\t\t   struct rte_flow_error *error __rte_unused)\n+{\n+\trte_errno = ENOTSUP;\n+\treturn -rte_errno;\n+}\n+\n+static struct mlx5_flow *\n+flow_null_prepare(const struct rte_flow_attr *attr __rte_unused,\n+\t\t  const struct rte_flow_item items[] __rte_unused,\n+\t\t  const struct rte_flow_action actions[] __rte_unused,\n+\t\t  uint64_t *item_flags __rte_unused,\n+\t\t  uint64_t *action_flags __rte_unused,\n+\t\t  struct rte_flow_error *error __rte_unused)\n+{\n+\trte_errno = ENOTSUP;\n+\treturn NULL;\n+}\n+\n+static int\n+flow_null_translate(struct rte_eth_dev *dev __rte_unused,\n+\t\t    struct mlx5_flow *dev_flow __rte_unused,\n+\t\t    const struct rte_flow_attr *attr __rte_unused,\n+\t\t    const struct rte_flow_item items[] __rte_unused,\n+\t\t    const struct rte_flow_action actions[] __rte_unused,\n+\t\t    struct rte_flow_error *error __rte_unused)\n+{\n+\trte_errno = ENOTSUP;\n+\treturn -rte_errno;\n+}\n+\n+static int\n+flow_null_apply(struct rte_eth_dev *dev __rte_unused,\n+\t\tstruct rte_flow *flow __rte_unused,\n+\t\tstruct rte_flow_error *error __rte_unused)\n+{\n+\trte_errno = ENOTSUP;\n+\treturn -rte_errno;\n+}\n+\n+static void\n+flow_null_remove(struct rte_eth_dev *dev __rte_unused,\n+\t\t struct rte_flow *flow __rte_unused)\n+{\n+}\n+\n+static void\n+flow_null_destroy(struct rte_eth_dev *dev __rte_unused,\n+\t\t  struct rte_flow *flow __rte_unused)\n+{\n+}\n+\n+/* Void driver to protect from null pointer reference. */\n+const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops = {\n+\t.validate = flow_null_validate,\n+\t.prepare = flow_null_prepare,\n+\t.translate = flow_null_translate,\n+\t.apply = flow_null_apply,\n+\t.remove = flow_null_remove,\n+\t.destroy = flow_null_destroy,\n+};\n+\n+/**\n+ * Select flow driver type according to flow attributes and device\n+ * configuration.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the dev structure.\n+ * @param[in] attr\n+ *   Pointer to the flow attributes.\n+ *\n+ * @return\n+ *   flow driver type if supported, MLX5_FLOW_TYPE_MAX otherwise.\n+ */\n+static enum mlx5_flow_drv_type\n+flow_get_drv_type(struct rte_eth_dev *dev __rte_unused,\n+\t\t  const struct rte_flow_attr *attr)\n+{\n+\tstruct priv *priv __rte_unused = dev->data->dev_private;\n+\tenum mlx5_flow_drv_type type = MLX5_FLOW_TYPE_MAX;\n+\n+\tif (!attr->transfer) {\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t\ttype = priv->config.dv_flow_en ?  MLX5_FLOW_TYPE_DV :\n+\t\t\t\t\t\t  MLX5_FLOW_TYPE_VERBS;\n+#else\n+\t\ttype = MLX5_FLOW_TYPE_VERBS;\n+#endif\n+\t}\n+\treturn type;\n+}\n+\n+#define flow_get_drv_ops(type) flow_drv_ops[type]\n+\n+/**\n+ * Flow driver validation API. This abstracts calling driver specific functions.\n+ * The type of flow driver is determined according to flow attributes.\n+ *\n+ * @param[in] dev\n+ *   Pointer to the dev structure.\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 inline int\n+flow_drv_validate(struct rte_eth_dev *dev,\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[],\n+\t\t  struct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr);\n+\n+\tfops = flow_get_drv_ops(type);\n+\treturn fops->validate(dev, attr, items, actions, error);\n+}\n+\n+/**\n+ * Flow driver preparation API. This abstracts calling driver specific\n+ * functions. Parent flow (rte_flow) should have driver type (drv_type). It\n+ * calculates the size of memory required for device flow, allocates the memory,\n+ * initializes the device flow and returns the pointer.\n+ *\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] item_flags\n+ *   Pointer to bit mask of all items detected.\n+ * @param[out] action_flags\n+ *   Pointer to bit mask of all actions detected.\n+ * @param[out] error\n+ *   Pointer to the error structure.\n+ *\n+ * @return\n+ *   Pointer to device flow on success, otherwise NULL and rte_ernno is set.\n+ */\n+static inline struct mlx5_flow *\n+flow_drv_prepare(struct rte_flow *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[],\n+\t\t uint64_t *item_flags,\n+\t\t uint64_t *action_flags,\n+\t\t struct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n+\n+\tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n+\tfops = flow_get_drv_ops(type);\n+\treturn fops->prepare(attr, items, actions, item_flags, action_flags,\n+\t\t\t     error);\n+}\n+\n+/**\n+ * Flow driver translation API. This abstracts calling driver specific\n+ * functions. Parent flow (rte_flow) should have driver type (drv_type). It\n+ * translates a generic flow into a driver flow. flow_drv_prepare() must\n+ * precede.\n+ *\n+ *\n+ * @param[in] dev\n+ *   Pointer to the rte dev structure.\n+ * @param[in, out] dev_flow\n+ *   Pointer to the mlx5 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 inline int\n+flow_drv_translate(struct rte_eth_dev *dev, 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[],\n+\t\t   struct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = dev_flow->flow->drv_type;\n+\n+\tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n+\tfops = flow_get_drv_ops(type);\n+\treturn fops->translate(dev, dev_flow, attr, items, actions, error);\n+}\n+\n+/**\n+ * Flow driver apply API. This abstracts calling driver specific functions.\n+ * Parent flow (rte_flow) should have driver type (drv_type). It applies\n+ * translated driver flows on to device. flow_drv_translate() must precede.\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device structure.\n+ * @param[in, out] flow\n+ *   Pointer to flow structure.\n+ * @param[out] error\n+ *   Pointer to error structure.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static inline int\n+flow_drv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,\n+\t       struct rte_flow_error *error)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n+\n+\tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n+\tfops = flow_get_drv_ops(type);\n+\treturn fops->apply(dev, flow, error);\n+}\n+\n+/**\n+ * Flow driver remove API. This abstracts calling driver specific functions.\n+ * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow\n+ * on device. All the resources of the flow should be freed by calling\n+ * flow_dv_destroy().\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[in, out] flow\n+ *   Pointer to flow structure.\n+ */\n+static inline void\n+flow_drv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n+\n+\tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n+\tfops = flow_get_drv_ops(type);\n+\tfops->remove(dev, flow);\n+}\n+\n+/**\n+ * Flow driver destroy API. This abstracts calling driver specific functions.\n+ * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow\n+ * on device and releases resources of the flow.\n+ *\n+ * @param[in] dev\n+ *   Pointer to Ethernet device.\n+ * @param[in, out] flow\n+ *   Pointer to flow structure.\n+ */\n+static inline void\n+flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n+{\n+\tconst struct mlx5_flow_driver_ops *fops;\n+\tenum mlx5_flow_drv_type type = flow->drv_type;\n+\n+\tassert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);\n+\tfops = flow_get_drv_ops(type);\n+\tfops->destroy(dev, flow);\n+}\n+\n /**\n  * Validate a flow supported by the NIC.\n  *\n@@ -1526,7 +1818,7 @@ mlx5_flow_validate(struct rte_eth_dev *dev,\n {\n \tint ret;\n \n-\tret =  nic_ops.validate(dev, attr, items, actions, error);\n+\tret = flow_drv_validate(dev, attr, items, actions, error);\n \tif (ret < 0)\n \t\treturn ret;\n \treturn 0;\n@@ -1616,7 +1908,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,\n \tuint32_t i;\n \tuint32_t flow_size;\n \n-\tret = mlx5_flow_validate(dev, attr, items, actions, error);\n+\tret = flow_drv_validate(dev, attr, items, actions, error);\n \tif (ret < 0)\n \t\treturn NULL;\n \tflow_size = sizeof(struct rte_flow);\n@@ -1627,6 +1919,9 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,\n \telse\n \t\tflow_size += RTE_ALIGN_CEIL(sizeof(uint16_t), sizeof(void *));\n \tflow = rte_calloc(__func__, 1, flow_size, 0);\n+\tflow->drv_type = flow_get_drv_type(dev, attr);\n+\tassert(flow->drv_type > MLX5_FLOW_TYPE_MIN &&\n+\t       flow->drv_type < MLX5_FLOW_TYPE_MAX);\n \tflow->queue = (void *)(flow + 1);\n \tLIST_INIT(&flow->dev_flows);\n \tif (rss && rss->types) {\n@@ -1644,21 +1939,21 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,\n \t\tbuf->entry[0].pattern = (void *)(uintptr_t)items;\n \t}\n \tfor (i = 0; i < buf->entries; ++i) {\n-\t\tdev_flow = nic_ops.prepare(attr, buf->entry[i].pattern,\n-\t\t\t\t\t   actions, &item_flags,\n-\t\t\t\t\t   &action_flags, error);\n+\t\tdev_flow = flow_drv_prepare(flow, attr, buf->entry[i].pattern,\n+\t\t\t\t\t    actions, &item_flags, &action_flags,\n+\t\t\t\t\t    error);\n \t\tif (!dev_flow)\n \t\t\tgoto error;\n \t\tdev_flow->flow = flow;\n \t\tLIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);\n-\t\tret = nic_ops.translate(dev, dev_flow, attr,\n-\t\t\t\t\tbuf->entry[i].pattern,\n-\t\t\t\t\tactions, error);\n+\t\tret = flow_drv_translate(dev, dev_flow, attr,\n+\t\t\t\t\t buf->entry[i].pattern,\n+\t\t\t\t\t actions, error);\n \t\tif (ret < 0)\n \t\t\tgoto error;\n \t}\n \tif (dev->data->dev_started) {\n-\t\tret = nic_ops.apply(dev, flow, error);\n+\t\tret = flow_drv_apply(dev, flow, error);\n \t\tif (ret < 0)\n \t\t\tgoto error;\n \t}\n@@ -1668,7 +1963,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,\n error:\n \tret = rte_errno; /* Save rte_errno before cleanup. */\n \tassert(flow);\n-\tnic_ops.destroy(dev, flow);\n+\tflow_drv_destroy(dev, flow);\n \trte_free(flow);\n \trte_errno = ret; /* Restore rte_errno. */\n \treturn NULL;\n@@ -1706,7 +2001,7 @@ static void\n mlx5_flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list,\n \t\t       struct rte_flow *flow)\n {\n-\tnic_ops.destroy(dev, flow);\n+\tflow_drv_destroy(dev, flow);\n \tTAILQ_REMOVE(list, flow, next);\n \t/*\n \t * Update RX queue flags only if port is started, otherwise it is\n@@ -1750,7 +2045,7 @@ mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_flows *list)\n \tstruct rte_flow *flow;\n \n \tTAILQ_FOREACH_REVERSE(flow, list, mlx5_flows, next)\n-\t\tnic_ops.remove(dev, flow);\n+\t\tflow_drv_remove(dev, flow);\n \tmlx5_flow_rxq_flags_clear(dev);\n }\n \n@@ -1773,7 +2068,7 @@ mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_flows *list)\n \tint ret = 0;\n \n \tTAILQ_FOREACH(flow, list, next) {\n-\t\tret = nic_ops.apply(dev, flow, &error);\n+\t\tret = flow_drv_apply(dev, flow, &error);\n \t\tif (ret < 0)\n \t\t\tgoto error;\n \t\tmlx5_flow_rxq_flags_set(dev, flow);\n@@ -2464,24 +2759,3 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,\n \t}\n \treturn 0;\n }\n-\n-/**\n- * Init the driver ops structure.\n- *\n- * @param dev\n- *   Pointer to Ethernet device structure.\n- */\n-void\n-mlx5_flow_init_driver_ops(struct rte_eth_dev *dev)\n-{\n-\tstruct priv *priv __rte_unused = dev->data->dev_private;\n-\n-#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n-\tif (priv->config.dv_flow_en)\n-\t\tmlx5_flow_dv_get_driver_ops(&nic_ops);\n-\telse\n-\t\tmlx5_flow_verbs_get_driver_ops(&nic_ops);\n-#else\n-\tmlx5_flow_verbs_get_driver_ops(&nic_ops);\n-#endif\n-}\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex 53c0eeb56..2bc3bee8c 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -128,6 +128,13 @@\n /* Max number of actions per DV flow. */\n #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8\n \n+enum mlx5_flow_drv_type {\n+\tMLX5_FLOW_TYPE_MIN,\n+\tMLX5_FLOW_TYPE_DV,\n+\tMLX5_FLOW_TYPE_VERBS,\n+\tMLX5_FLOW_TYPE_MAX,\n+};\n+\n /* Matcher PRM representation */\n struct mlx5_flow_dv_match_params {\n \tsize_t size;\n@@ -210,7 +217,7 @@ struct mlx5_flow_counter {\n /* Flow structure. */\n struct rte_flow {\n \tTAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */\n-\tstruct rte_flow_attr attributes; /**< User flow attribute. */\n+\tenum mlx5_flow_drv_type drv_type; /**< Drvier type. */\n \tuint32_t layers;\n \t/**< Bit-fields of present layers see MLX5_FLOW_LAYER_*. */\n \tstruct mlx5_flow_counter *counter; /**< Holds flow counter. */\n@@ -314,13 +321,5 @@ int mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,\n \t\t\t\t      uint64_t item_flags,\n \t\t\t\t      struct rte_eth_dev *dev,\n \t\t\t\t      struct rte_flow_error *error);\n-void mlx5_flow_init_driver_ops(struct rte_eth_dev *dev);\n-\n-/* mlx5_flow_dv.c */\n-void mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops);\n-\n-/* mlx5_flow_verbs.c */\n-\n-void mlx5_flow_verbs_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops);\n \n #endif /* RTE_PMD_MLX5_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c\nindex 71af410b2..cf663cdb8 100644\n--- a/drivers/net/mlx5/mlx5_flow_dv.c\n+++ b/drivers/net/mlx5/mlx5_flow_dv.c\n@@ -1351,23 +1351,13 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n \t}\n }\n \n-/**\n- * Fills the flow_ops with the function pointers.\n- *\n- * @param[out] flow_ops\n- *   Pointer to driver_ops structure.\n- */\n-void\n-mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)\n-{\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 = flow_dv_translate,\n-\t\t.apply = flow_dv_apply,\n-\t\t.remove = flow_dv_remove,\n-\t\t.destroy = flow_dv_destroy,\n-\t};\n-}\n+const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = {\n+\t.validate = flow_dv_validate,\n+\t.prepare = flow_dv_prepare,\n+\t.translate = flow_dv_translate,\n+\t.apply = flow_dv_apply,\n+\t.remove = flow_dv_remove,\n+\t.destroy = flow_dv_destroy,\n+};\n \n #endif /* HAVE_IBV_FLOW_DV_SUPPORT */\ndiff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c\nindex f4a264232..05ab5fdad 100644\n--- a/drivers/net/mlx5/mlx5_flow_verbs.c\n+++ b/drivers/net/mlx5/mlx5_flow_verbs.c\n@@ -1638,15 +1638,11 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,\n \treturn -rte_errno;\n }\n \n-void\n-mlx5_flow_verbs_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)\n-{\n-\t*flow_ops = (struct mlx5_flow_driver_ops) {\n-\t\t.validate = flow_verbs_validate,\n-\t\t.prepare = flow_verbs_prepare,\n-\t\t.translate = flow_verbs_translate,\n-\t\t.apply = flow_verbs_apply,\n-\t\t.remove = flow_verbs_remove,\n-\t\t.destroy = flow_verbs_destroy,\n-\t};\n-}\n+const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = {\n+\t.validate = flow_verbs_validate,\n+\t.prepare = flow_verbs_prepare,\n+\t.translate = flow_verbs_translate,\n+\t.apply = flow_verbs_apply,\n+\t.remove = flow_verbs_remove,\n+\t.destroy = flow_verbs_destroy,\n+};\n",
    "prefixes": [
        "1/3"
    ]
}