From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <yskoh@mellanox.com>
Received: from EUR03-DB5-obe.outbound.protection.outlook.com
 (mail-eopbgr40089.outbound.protection.outlook.com [40.107.4.89])
 by dpdk.org (Postfix) with ESMTP id C87901B116
 for <dev@dpdk.org>; Mon, 24 Sep 2018 21:55:16 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=9gbt8AtpcwS6Gb70b1QmpC88dT6ZkTw170fPE3BLT1Q=;
 b=IsLAVcPFSaWiENOSIyLJfUG8AcaAtMTxOrnogm7P7ODpvnBxX8vZfaYcRtLUf8UzWk4zz2sGboJhKcNFR8wjdDJHXbTfAPQ8oNIrsWLfujKVQmQVcaow6865aZBaPzFe8xmfEHKCdcOZEK/xcPIE+zS5+KmKsKr/pX13bd4VAC4=
Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com (52.134.72.27) by
 DB3PR0502MB3995.eurprd05.prod.outlook.com (52.134.72.30) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.1164.25; Mon, 24 Sep 2018 19:55:14 +0000
Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com
 ([fe80::1cb0:661b:ecab:6045]) by DB3PR0502MB3980.eurprd05.prod.outlook.com
 ([fe80::1cb0:661b:ecab:6045%2]) with mapi id 15.20.1164.017; Mon, 24 Sep 2018
 19:55:14 +0000
From: Yongseok Koh <yskoh@mellanox.com>
To: Thomas Monjalon <thomas@monjalon.net>, Shahaf Shuler <shahafs@mellanox.com>
CC: "dev@dpdk.org" <dev@dpdk.org>, Yongseok Koh <yskoh@mellanox.com>
Thread-Topic: [PATCH v2 1/3] net/mlx5: add abstraction for multiple flow
 drivers
Thread-Index: AQHUVECCvK86LeA+1EKg3UsJkP17Lw==
Date: Mon, 24 Sep 2018 19:55:14 +0000
Message-ID: <20180924195503.18894-2-yskoh@mellanox.com>
References: <20180919072143.23211-1-yskoh@mellanox.com>
 <20180924195503.18894-1-yskoh@mellanox.com>
In-Reply-To: <20180924195503.18894-1-yskoh@mellanox.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-clientproxiedby: MWHPR2001CA0016.namprd20.prod.outlook.com
 (2603:10b6:301:15::26) To DB3PR0502MB3980.eurprd05.prod.outlook.com
 (2603:10a6:8:10::27)
authentication-results: spf=none (sender IP is )
 smtp.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; DB3PR0502MB3995;
 6:Y+K+Hj/cZaXev09vutOzAHqZU793QFvWmPAG/0LrnoqOixa1jLZB9H5Pgfa3twUJVkA4he7hzWIk5KAhimf3ud0CfHuwYirqq6wFOqSuA7D/ZxS4hCADvBVd/12AxOsO2wE6xABspip5E5yBPUyQNC0jdtgG5i989iNdzkqDqideLlgS3Ad1VJSF5btmXDSRabGnGhI9CFfYUxQMei3muQC0R97zdsPbG5vvbsMMUbex83CHrFPySYVTrcgymt9Sn+lBsE66HT5X7eGDFIJ8RxlBOxnSepmLBkbLuMFu/P7qBShmCq2jDCNKr3B5+zCqlGsz8QXl3VvR896WKmO32fyGY/2zhM4FbcVUDYbsADqD1h9uEJp09Vp/IP6lKMh2E6ko1908qYFL2BcSpdh2MufyOHtrx5/qfOATuWIOTRF3w5zjgk7MwQxT8YXkds6MgLUzrpkzsvrKl0r6dx9ddg==;
 5:CXxIU2f0Ur2y5piQIrLRnQcRafkKsV+bjSAFhYQN25PE0alEgb9eLUiY5k6ZYTs4hXIYmzZtZYTGXP0+AjhPjIWDlaDm832iYoMamO85kw9BG5A2nG5tfuY7IePOUsKT50nLrNfBGStPMtYyDHSfMFb7TwU9m43100Sp1SgRaRU=;
 7:FL+1jv8ScUQohd4e2Xs5j5nle8LlSqqoYbqIRKI9O3UrAI+jMjoJztjtx5lEO3VjsRZ0CfZdL1T9C5UkS0pykPBAbG68O0F3F+dQYmQH0mwra2tRPBY84QaFztQ73P/+rygG8mrV8ZxcVorCDgb/8akbdqd3KZ1MjEXjql7nxCqrYVQVrEeboAwedVWfskcJI0D4Fxk7Z0wieJwTBdZ9TATdJSgYlDutrSRlUbFI2aU6MtuwuMXcFz+Djc5DWmIo
x-ms-office365-filtering-correlation-id: d691e094-9705-4805-0169-08d62257a4b2
x-ms-office365-filtering-ht: Tenant
x-microsoft-antispam: BCL:0; PCL:0;
 RULEID:(7020095)(4652040)(8989299)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020);
 SRVR:DB3PR0502MB3995; 
x-ms-traffictypediagnostic: DB3PR0502MB3995:
x-ld-processed: a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr
x-microsoft-antispam-prvs: <DB3PR0502MB39951A6315CE5816B265EBDBC3170@DB3PR0502MB3995.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;
 RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(3231355)(944501410)(52105095)(93006095)(93001095)(3002001)(6055026)(149066)(150027)(6041310)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123564045)(20161123562045)(201708071742011)(7699051);
 SRVR:DB3PR0502MB3995; BCL:0; PCL:0; RULEID:; SRVR:DB3PR0502MB3995; 
x-forefront-prvs: 0805EC9467
x-forefront-antispam-report: SFV:NSPM;
 SFS:(10009020)(136003)(346002)(396003)(376002)(366004)(39860400002)(199004)(189003)(486006)(2906002)(14444005)(99286004)(105586002)(106356001)(110136005)(71200400001)(68736007)(54906003)(107886003)(25786009)(5250100002)(316002)(11346002)(446003)(4326008)(7736002)(53936002)(476003)(2616005)(305945005)(66066001)(5660300001)(6436002)(26005)(6116002)(102836004)(1076002)(3846002)(8676002)(8936002)(478600001)(14454004)(6506007)(81156014)(386003)(81166006)(53946003)(36756003)(6636002)(6486002)(71190400001)(52116002)(86362001)(76176011)(97736004)(2900100001)(575784001)(256004)(186003)(6512007);
 DIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0502MB3995;
 H:DB3PR0502MB3980.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en;
 PTR:InfoNoRecords; A:1; MX:1; 
received-spf: None (protection.outlook.com: mellanox.com does not designate
 permitted sender hosts)
x-microsoft-antispam-message-info: Ff1K1+tVhHzK0umo3Td7OMK7i2w5D38xIFL8vhi/eGyIaB3kWxLxb62QVjuvl9s2xDweHvlvkl5M7u1JzZxvuQ6lgobvT40Behp8DkOJEr935WkXGLwsSAbGtKYN0fCRsHn9lrWEpEJxlP5ur2ZyGjNEbS2IPthfPP5h/8Ifbl+U02um7LX0myiigrQyZrUd2k465JES8Psho6O54iBmIHe1CAsJhSRlT3UmfvRhwr4zrMOcOiOt1aNB05QHnJQixwLG5ZKFMX/t7w3lVhEp/s3ixKntBrGWzjso8OhP4Y6fabBEX96v0Z5zrZEnrIml3rE2O1xJuc5zy0B+Og9OBQzz+QxFwZRGwSJRb38nQ1w=
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: d691e094-9705-4805-0169-08d62257a4b2
X-MS-Exchange-CrossTenant-originalarrivaltime: 24 Sep 2018 19:55:14.5132 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR0502MB3995
Subject: [dpdk-dev] [PATCH v2 1/3] net/mlx5: add abstraction for multiple
	flow drivers
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Mon, 24 Sep 2018 19:55:17 -0000

Flow engine has to support multiple driver paths. Verbs/DV for NIC flow
steering and Linux TC flower for E-Switch flow steering. In the future,
another flow driver could be added (devX).

Signed-off-by: Yongseok Koh <yskoh@mellanox.com>
---
 drivers/net/mlx5/mlx5.c            |   1 -
 drivers/net/mlx5/mlx5_flow.c       | 348 +++++++++++++++++++++++++++++++++=
----
 drivers/net/mlx5/mlx5_flow.h       |  17 +-
 drivers/net/mlx5/mlx5_flow_dv.c    |  26 +--
 drivers/net/mlx5/mlx5_flow_verbs.c |  20 +--
 5 files changed, 335 insertions(+), 77 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9b208109b..2f7d046e0 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1192,7 +1192,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	if (err < 0)
 		goto error;
 	priv->config.flow_prio =3D err;
-	mlx5_flow_init_driver_ops(eth_dev);
 	/*
 	 * Once the device is added to the list of memory event
 	 * callback, its global MR cache table cannot be expanded
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 2119211f5..54008afa4 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -37,6 +37,23 @@
 extern const struct eth_dev_ops mlx5_dev_ops;
 extern const struct eth_dev_ops mlx5_dev_ops_isolate;
=20
+/** Device flow drivers. */
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+extern const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops;
+#endif
+extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops;
+
+const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops;
+
+const struct mlx5_flow_driver_ops *flow_drv_ops[] =3D {
+	[MLX5_FLOW_TYPE_MIN] =3D &mlx5_flow_null_drv_ops,
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+	[MLX5_FLOW_TYPE_DV] =3D &mlx5_flow_dv_drv_ops,
+#endif
+	[MLX5_FLOW_TYPE_VERBS] =3D &mlx5_flow_verbs_drv_ops,
+	[MLX5_FLOW_TYPE_MAX] =3D &mlx5_flow_null_drv_ops
+};
+
 enum mlx5_expansion {
 	MLX5_EXPANSION_ROOT,
 	MLX5_EXPANSION_ROOT_OUTER,
@@ -282,9 +299,6 @@ static struct mlx5_flow_tunnel_info tunnels_info[] =3D =
{
 	},
 };
=20
-/* Holds the nic operations that should be used. */
-struct mlx5_flow_driver_ops nic_ops;
-
 /**
  * Discover the maximum number of priority available.
  *
@@ -1510,6 +1524,284 @@ mlx5_flow_validate_item_mpls(const struct rte_flow_=
item *item __rte_unused,
 				  " update.");
 }
=20
+static int
+flow_null_validate(struct rte_eth_dev *dev __rte_unused,
+		   const struct rte_flow_attr *attr __rte_unused,
+		   const struct rte_flow_item items[] __rte_unused,
+		   const struct rte_flow_action actions[] __rte_unused,
+		   struct rte_flow_error *error __rte_unused)
+{
+	rte_errno =3D ENOTSUP;
+	return -rte_errno;
+}
+
+static struct mlx5_flow *
+flow_null_prepare(const struct rte_flow_attr *attr __rte_unused,
+		  const struct rte_flow_item items[] __rte_unused,
+		  const struct rte_flow_action actions[] __rte_unused,
+		  uint64_t *item_flags __rte_unused,
+		  uint64_t *action_flags __rte_unused,
+		  struct rte_flow_error *error __rte_unused)
+{
+	rte_errno =3D ENOTSUP;
+	return NULL;
+}
+
+static int
+flow_null_translate(struct rte_eth_dev *dev __rte_unused,
+		    struct mlx5_flow *dev_flow __rte_unused,
+		    const struct rte_flow_attr *attr __rte_unused,
+		    const struct rte_flow_item items[] __rte_unused,
+		    const struct rte_flow_action actions[] __rte_unused,
+		    struct rte_flow_error *error __rte_unused)
+{
+	rte_errno =3D ENOTSUP;
+	return -rte_errno;
+}
+
+static int
+flow_null_apply(struct rte_eth_dev *dev __rte_unused,
+		struct rte_flow *flow __rte_unused,
+		struct rte_flow_error *error __rte_unused)
+{
+	rte_errno =3D ENOTSUP;
+	return -rte_errno;
+}
+
+static void
+flow_null_remove(struct rte_eth_dev *dev __rte_unused,
+		 struct rte_flow *flow __rte_unused)
+{
+}
+
+static void
+flow_null_destroy(struct rte_eth_dev *dev __rte_unused,
+		  struct rte_flow *flow __rte_unused)
+{
+}
+
+/* Void driver to protect from null pointer reference. */
+const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops =3D {
+	.validate =3D flow_null_validate,
+	.prepare =3D flow_null_prepare,
+	.translate =3D flow_null_translate,
+	.apply =3D flow_null_apply,
+	.remove =3D flow_null_remove,
+	.destroy =3D flow_null_destroy,
+};
+
+/**
+ * Select flow driver type according to flow attributes and device
+ * configuration.
+ *
+ * @param[in] dev
+ *   Pointer to the dev structure.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ *
+ * @return
+ *   flow driver type if supported, MLX5_FLOW_TYPE_MAX otherwise.
+ */
+static enum mlx5_flow_drv_type
+flow_get_drv_type(struct rte_eth_dev *dev __rte_unused,
+		  const struct rte_flow_attr *attr)
+{
+	struct priv *priv __rte_unused =3D dev->data->dev_private;
+	enum mlx5_flow_drv_type type =3D MLX5_FLOW_TYPE_MAX;
+
+	if (!attr->transfer) {
+#ifdef HAVE_IBV_FLOW_DV_SUPPORT
+		type =3D priv->config.dv_flow_en ?  MLX5_FLOW_TYPE_DV :
+						  MLX5_FLOW_TYPE_VERBS;
+#else
+		type =3D MLX5_FLOW_TYPE_VERBS;
+#endif
+	}
+	return type;
+}
+
+#define flow_get_drv_ops(type) flow_drv_ops[type]
+
+/**
+ * Flow driver validation API. This abstracts calling driver specific func=
tions.
+ * The type of flow driver is determined according to flow attributes.
+ *
+ * @param[in] dev
+ *   Pointer to the dev structure.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[in] items
+ *   Pointer to the list of items.
+ * @param[in] actions
+ *   Pointer to the list of actions.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static inline int
+flow_drv_validate(struct rte_eth_dev *dev,
+		  const struct rte_flow_attr *attr,
+		  const struct rte_flow_item items[],
+		  const struct rte_flow_action actions[],
+		  struct rte_flow_error *error)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D flow_get_drv_type(dev, attr);
+
+	fops =3D flow_get_drv_ops(type);
+	return fops->validate(dev, attr, items, actions, error);
+}
+
+/**
+ * Flow driver preparation API. This abstracts calling driver specific
+ * functions. Parent flow (rte_flow) should have driver type (drv_type). I=
t
+ * calculates the size of memory required for device flow, allocates the m=
emory,
+ * initializes the device flow and returns the pointer.
+ *
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[in] items
+ *   Pointer to the list of items.
+ * @param[in] actions
+ *   Pointer to the list of actions.
+ * @param[out] item_flags
+ *   Pointer to bit mask of all items detected.
+ * @param[out] action_flags
+ *   Pointer to bit mask of all actions detected.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   Pointer to device flow on success, otherwise NULL and rte_ernno is se=
t.
+ */
+static inline struct mlx5_flow *
+flow_drv_prepare(struct rte_flow *flow,
+		 const struct rte_flow_attr *attr,
+		 const struct rte_flow_item items[],
+		 const struct rte_flow_action actions[],
+		 uint64_t *item_flags,
+		 uint64_t *action_flags,
+		 struct rte_flow_error *error)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D flow->drv_type;
+
+	assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
+	fops =3D flow_get_drv_ops(type);
+	return fops->prepare(attr, items, actions, item_flags, action_flags,
+			     error);
+}
+
+/**
+ * Flow driver translation API. This abstracts calling driver specific
+ * functions. Parent flow (rte_flow) should have driver type (drv_type). I=
t
+ * translates a generic flow into a driver flow. flow_drv_prepare() must
+ * precede.
+ *
+ *
+ * @param[in] dev
+ *   Pointer to the rte dev structure.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5 flow.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[in] items
+ *   Pointer to the list of items.
+ * @param[in] actions
+ *   Pointer to the list of actions.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_ernno is set.
+ */
+static inline int
+flow_drv_translate(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow,
+		   const struct rte_flow_attr *attr,
+		   const struct rte_flow_item items[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow_error *error)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D dev_flow->flow->drv_type;
+
+	assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
+	fops =3D flow_get_drv_ops(type);
+	return fops->translate(dev, dev_flow, attr, items, actions, error);
+}
+
+/**
+ * Flow driver apply API. This abstracts calling driver specific functions=
.
+ * Parent flow (rte_flow) should have driver type (drv_type). It applies
+ * translated driver flows on to device. flow_drv_translate() must precede=
.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device structure.
+ * @param[in, out] flow
+ *   Pointer to flow structure.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static inline int
+flow_drv_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
+	       struct rte_flow_error *error)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D flow->drv_type;
+
+	assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
+	fops =3D flow_get_drv_ops(type);
+	return fops->apply(dev, flow, error);
+}
+
+/**
+ * Flow driver remove API. This abstracts calling driver specific function=
s.
+ * Parent flow (rte_flow) should have driver type (drv_type). It removes a=
 flow
+ * on device. All the resources of the flow should be freed by calling
+ * flow_dv_destroy().
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in, out] flow
+ *   Pointer to flow structure.
+ */
+static inline void
+flow_drv_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D flow->drv_type;
+
+	assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
+	fops =3D flow_get_drv_ops(type);
+	fops->remove(dev, flow);
+}
+
+/**
+ * Flow driver destroy API. This abstracts calling driver specific functio=
ns.
+ * Parent flow (rte_flow) should have driver type (drv_type). It removes a=
 flow
+ * on device and releases resources of the flow.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in, out] flow
+ *   Pointer to flow structure.
+ */
+static inline void
+flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
+{
+	const struct mlx5_flow_driver_ops *fops;
+	enum mlx5_flow_drv_type type =3D flow->drv_type;
+
+	assert(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX);
+	fops =3D flow_get_drv_ops(type);
+	fops->destroy(dev, flow);
+}
+
 /**
  * Validate a flow supported by the NIC.
  *
@@ -1525,7 +1817,7 @@ mlx5_flow_validate(struct rte_eth_dev *dev,
 {
 	int ret;
=20
-	ret =3D  nic_ops.validate(dev, attr, items, actions, error);
+	ret =3D flow_drv_validate(dev, attr, items, actions, error);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -1615,7 +1907,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,
 	uint32_t i;
 	uint32_t flow_size;
=20
-	ret =3D mlx5_flow_validate(dev, attr, items, actions, error);
+	ret =3D flow_drv_validate(dev, attr, items, actions, error);
 	if (ret < 0)
 		return NULL;
 	flow_size =3D sizeof(struct rte_flow);
@@ -1626,6 +1918,9 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,
 	else
 		flow_size +=3D RTE_ALIGN_CEIL(sizeof(uint16_t), sizeof(void *));
 	flow =3D rte_calloc(__func__, 1, flow_size, 0);
+	flow->drv_type =3D flow_get_drv_type(dev, attr);
+	assert(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
+	       flow->drv_type < MLX5_FLOW_TYPE_MAX);
 	flow->queue =3D (void *)(flow + 1);
 	LIST_INIT(&flow->dev_flows);
 	if (rss && rss->types) {
@@ -1643,21 +1938,21 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,
 		buf->entry[0].pattern =3D (void *)(uintptr_t)items;
 	}
 	for (i =3D 0; i < buf->entries; ++i) {
-		dev_flow =3D nic_ops.prepare(attr, buf->entry[i].pattern,
-					   actions, &item_flags,
-					   &action_flags, error);
+		dev_flow =3D flow_drv_prepare(flow, attr, buf->entry[i].pattern,
+					    actions, &item_flags, &action_flags,
+					    error);
 		if (!dev_flow)
 			goto error;
 		dev_flow->flow =3D flow;
 		LIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);
-		ret =3D nic_ops.translate(dev, dev_flow, attr,
-					buf->entry[i].pattern,
-					actions, error);
+		ret =3D flow_drv_translate(dev, dev_flow, attr,
+					 buf->entry[i].pattern,
+					 actions, error);
 		if (ret < 0)
 			goto error;
 	}
 	if (dev->data->dev_started) {
-		ret =3D nic_ops.apply(dev, flow, error);
+		ret =3D flow_drv_apply(dev, flow, error);
 		if (ret < 0)
 			goto error;
 	}
@@ -1667,7 +1962,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev,
 error:
 	ret =3D rte_errno; /* Save rte_errno before cleanup. */
 	assert(flow);
-	nic_ops.destroy(dev, flow);
+	flow_drv_destroy(dev, flow);
 	rte_free(flow);
 	rte_errno =3D ret; /* Restore rte_errno. */
 	return NULL;
@@ -1705,7 +2000,7 @@ static void
 mlx5_flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list,
 		       struct rte_flow *flow)
 {
-	nic_ops.destroy(dev, flow);
+	flow_drv_destroy(dev, flow);
 	TAILQ_REMOVE(list, flow, next);
 	/*
 	 * Update RX queue flags only if port is started, otherwise it is
@@ -1749,7 +2044,7 @@ mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_f=
lows *list)
 	struct rte_flow *flow;
=20
 	TAILQ_FOREACH_REVERSE(flow, list, mlx5_flows, next)
-		nic_ops.remove(dev, flow);
+		flow_drv_remove(dev, flow);
 	mlx5_flow_rxq_flags_clear(dev);
 }
=20
@@ -1772,7 +2067,7 @@ mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_=
flows *list)
 	int ret =3D 0;
=20
 	TAILQ_FOREACH(flow, list, next) {
-		ret =3D nic_ops.apply(dev, flow, &error);
+		ret =3D flow_drv_apply(dev, flow, &error);
 		if (ret < 0)
 			goto error;
 		mlx5_flow_rxq_flags_set(dev, flow);
@@ -2463,24 +2758,3 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
 	}
 	return 0;
 }
-
-/**
- * Init the driver ops structure.
- *
- * @param dev
- *   Pointer to Ethernet device structure.
- */
-void
-mlx5_flow_init_driver_ops(struct rte_eth_dev *dev)
-{
-	struct priv *priv __rte_unused =3D dev->data->dev_private;
-
-#ifdef HAVE_IBV_FLOW_DV_SUPPORT
-	if (priv->config.dv_flow_en)
-		mlx5_flow_dv_get_driver_ops(&nic_ops);
-	else
-		mlx5_flow_verbs_get_driver_ops(&nic_ops);
-#else
-	mlx5_flow_verbs_get_driver_ops(&nic_ops);
-#endif
-}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 53c0eeb56..2bc3bee8c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -128,6 +128,13 @@
 /* Max number of actions per DV flow. */
 #define MLX5_DV_MAX_NUMBER_OF_ACTIONS 8
=20
+enum mlx5_flow_drv_type {
+	MLX5_FLOW_TYPE_MIN,
+	MLX5_FLOW_TYPE_DV,
+	MLX5_FLOW_TYPE_VERBS,
+	MLX5_FLOW_TYPE_MAX,
+};
+
 /* Matcher PRM representation */
 struct mlx5_flow_dv_match_params {
 	size_t size;
@@ -210,7 +217,7 @@ struct mlx5_flow_counter {
 /* Flow structure. */
 struct rte_flow {
 	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
-	struct rte_flow_attr attributes; /**< User flow attribute. */
+	enum mlx5_flow_drv_type drv_type; /**< Drvier type. */
 	uint32_t layers;
 	/**< Bit-fields of present layers see MLX5_FLOW_LAYER_*. */
 	struct mlx5_flow_counter *counter; /**< Holds flow counter. */
@@ -314,13 +321,5 @@ int mlx5_flow_validate_item_vxlan_gpe(const struct rte=
_flow_item *item,
 				      uint64_t item_flags,
 				      struct rte_eth_dev *dev,
 				      struct rte_flow_error *error);
-void mlx5_flow_init_driver_ops(struct rte_eth_dev *dev);
-
-/* mlx5_flow_dv.c */
-void mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops);
-
-/* mlx5_flow_verbs.c */
-
-void mlx5_flow_verbs_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)=
;
=20
 #endif /* RTE_PMD_MLX5_FLOW_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_d=
v.c
index 71af410b2..cf663cdb8 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -1351,23 +1351,13 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte=
_flow *flow)
 	}
 }
=20
-/**
- * Fills the flow_ops with the function pointers.
- *
- * @param[out] flow_ops
- *   Pointer to driver_ops structure.
- */
-void
-mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)
-{
-	*flow_ops =3D (struct mlx5_flow_driver_ops) {
-		.validate =3D flow_dv_validate,
-		.prepare =3D flow_dv_prepare,
-		.translate =3D flow_dv_translate,
-		.apply =3D flow_dv_apply,
-		.remove =3D flow_dv_remove,
-		.destroy =3D flow_dv_destroy,
-	};
-}
+const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops =3D {
+	.validate =3D flow_dv_validate,
+	.prepare =3D flow_dv_prepare,
+	.translate =3D flow_dv_translate,
+	.apply =3D flow_dv_apply,
+	.remove =3D flow_dv_remove,
+	.destroy =3D flow_dv_destroy,
+};
=20
 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flo=
w_verbs.c
index f4a264232..05ab5fdad 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1638,15 +1638,11 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rt=
e_flow *flow,
 	return -rte_errno;
 }
=20
-void
-mlx5_flow_verbs_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)
-{
-	*flow_ops =3D (struct mlx5_flow_driver_ops) {
-		.validate =3D flow_verbs_validate,
-		.prepare =3D flow_verbs_prepare,
-		.translate =3D flow_verbs_translate,
-		.apply =3D flow_verbs_apply,
-		.remove =3D flow_verbs_remove,
-		.destroy =3D flow_verbs_destroy,
-	};
-}
+const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops =3D {
+	.validate =3D flow_verbs_validate,
+	.prepare =3D flow_verbs_prepare,
+	.translate =3D flow_verbs_translate,
+	.apply =3D flow_verbs_apply,
+	.remove =3D flow_verbs_remove,
+	.destroy =3D flow_verbs_destroy,
+};
--=20
2.11.0