All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Monjalon <thomas@monjalon.net>
To: dev@dpdk.org
Cc: Ajit Khaparde <ajit.khaparde@broadcom.com>,
	Haiyue Wang <haiyue.wang@intel.com>,
	Rosen Xu <rosen.xu@intel.com>,
	Hemant Agrawal <hemant.agrawal@nxp.com>,
	Ori Kam <orika@nvidia.com>,
	Somnath Kotur <somnath.kotur@broadcom.com>,
	Chas Williams <chas3@att.com>,
	"Min Hu (Connor)" <humin29@huawei.com>,
	Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>,
	Sachin Saxena <sachin.saxena@oss.nxp.com>,
	Jeff Guo <jia.guo@intel.com>, John Daley <johndale@cisco.com>,
	Hyong Youb Kim <hyonkim@cisco.com>, Gaetan Rivet <grive@u256.net>,
	Ziyang Xuan <xuanziyang2@huawei.com>,
	Xiaoyun Wang <cloud.wangxiaoyun@huawei.com>,
	Guoyang Zhou <zhouguoyang@huawei.com>,
	Yisen Zhuang <yisen.zhuang@huawei.com>,
	Lijun Ou <oulijun@huawei.com>,
	Beilei Xing <beilei.xing@intel.com>,
	Jingjing Wu <jingjing.wu@intel.com>,
	Qiming Yang <qiming.yang@intel.com>,
	Qi Zhang <qi.z.zhang@intel.com>, Matan Azrad <matan@nvidia.com>,
	Shahaf Shuler <shahafs@nvidia.com>,
	Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
	Liron Himi <lironh@marvell.com>,	Jerin Jacob <jerinj@marvell.com>,
	Nithin Dabilpuram <ndabilpuram@marvell.com>,
	Kiran Kumar K <kirankumark@marvell.com>,
	Rasesh Mody <rmody@marvell.com>,
	Shahed Shaikh <shshaikh@marvell.com>,
	Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,
	Jasvinder Singh <jasvinder.singh@intel.com>,
	Cristian Dumitrescu <cristian.dumitrescu@intel.com>,
	Keith Wiles <keith.wiles@intel.com>,
	Jiawen Wu <jiawenwu@trustnetic.com>,
	Jian Wang <jianwang@trustnetic.com>,
	Ferruh Yigit <ferruh.yigit@intel.com>
Subject: [dpdk-dev] [PATCH v3 1/2] ethdev: replace callback getting filter operations
Date: Sun, 21 Mar 2021 10:00:00 +0100	[thread overview]
Message-ID: <20210321090002.595744-2-thomas@monjalon.net> (raw)
In-Reply-To: <20210321090002.595744-1-thomas@monjalon.net>

Since rte_flow is the only API for filtering operations,
the legacy driver interface filter_ctrl was too much complicated
for the simple task of getting the struct rte_flow_ops.

The filter type RTE_ETH_FILTER_GENERIC and
the filter operarion RTE_ETH_FILTER_GET are removed.
The new driver callback flow_ops_get replaces filter_ctrl.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Acked-by: Haiyue Wang <haiyue.wang@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 doc/guides/nics/features.rst            |  4 +--
 doc/guides/prog_guide/rte_flow.rst      | 14 +-------
 drivers/net/bnxt/bnxt.h                 |  6 ++--
 drivers/net/bnxt/bnxt_ethdev.c          | 40 +++++++--------------
 drivers/net/bnxt/bnxt_reps.c            |  2 +-
 drivers/net/bonding/rte_eth_bond_pmd.c  | 13 +++----
 drivers/net/cxgbe/cxgbe_ethdev.c        |  2 +-
 drivers/net/cxgbe/cxgbe_flow.c          | 22 +++---------
 drivers/net/cxgbe/cxgbe_flow.h          |  7 ++--
 drivers/net/dpaa2/dpaa2_ethdev.c        | 44 +++--------------------
 drivers/net/dpaa2/dpaa2_flow.c          | 29 +++++----------
 drivers/net/e1000/igb_ethdev.c          | 31 ++++------------
 drivers/net/enic/enic_ethdev.c          | 30 +++++-----------
 drivers/net/enic/enic_vf_representor.c  | 33 ++++++-----------
 drivers/net/failsafe/failsafe_ops.c     | 16 +++------
 drivers/net/hinic/hinic_pmd_ethdev.c    | 36 ++++---------------
 drivers/net/hns3/hns3_ethdev.c          |  2 +-
 drivers/net/hns3/hns3_ethdev.h          |  5 ++-
 drivers/net/hns3/hns3_ethdev_vf.c       |  2 +-
 drivers/net/hns3/hns3_flow.c            | 30 ++++------------
 drivers/net/i40e/i40e_ethdev.c          | 32 ++++-------------
 drivers/net/iavf/iavf_ethdev.c          | 32 ++++-------------
 drivers/net/ice/ice_dcf_ethdev.c        | 27 +++-----------
 drivers/net/ice/ice_ethdev.c            | 32 ++++-------------
 drivers/net/igc/igc_ethdev.c            |  2 +-
 drivers/net/igc/igc_filter.c            | 23 +++---------
 drivers/net/igc/igc_filter.h            |  5 ++-
 drivers/net/ipn3ke/ipn3ke_representor.c | 28 ++++-----------
 drivers/net/ixgbe/ixgbe_ethdev.c        | 32 ++++-------------
 drivers/net/mlx4/mlx4.c                 |  2 +-
 drivers/net/mlx4/mlx4_flow.c            | 32 ++++-------------
 drivers/net/mlx4/mlx4_flow.h            |  5 +--
 drivers/net/mlx5/mlx5.c                 |  4 +--
 drivers/net/mlx5/mlx5.h                 |  5 +--
 drivers/net/mlx5/mlx5_flow.c            | 32 ++++-------------
 drivers/net/mvpp2/mrvl_ethdev.c         | 26 ++++----------
 drivers/net/octeontx2/otx2_ethdev.c     |  2 +-
 drivers/net/octeontx2/otx2_ethdev.h     |  5 ++-
 drivers/net/octeontx2/otx2_ethdev_ops.c | 21 +++--------
 drivers/net/qede/qede_ethdev.c          |  2 +-
 drivers/net/qede/qede_ethdev.h          |  7 ++--
 drivers/net/qede/qede_filter.c          | 27 ++++----------
 drivers/net/sfc/sfc_ethdev.c            | 31 +++-------------
 drivers/net/softnic/rte_eth_softnic.c   | 17 +++------
 drivers/net/tap/rte_eth_tap.c           |  2 +-
 drivers/net/tap/tap_flow.c              | 27 ++++----------
 drivers/net/tap/tap_flow.h              |  6 ++--
 drivers/net/txgbe/txgbe_ethdev.c        | 26 +++-----------
 lib/librte_ethdev/ethdev_driver.h       | 48 +++++++++++--------------
 lib/librte_ethdev/rte_eth_ctrl.h        |  2 +-
 lib/librte_ethdev/rte_flow.c            | 23 ++++++------
 lib/librte_ethdev/rte_flow_driver.h     | 25 -------------
 52 files changed, 238 insertions(+), 720 deletions(-)

diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst
index dbca9a85b9..f6d30d0af3 100644
--- a/doc/guides/nics/features.rst
+++ b/doc/guides/nics/features.rst
@@ -402,9 +402,9 @@ Supports configuring link flow control.
 Flow API
 --------
 
-Supports the DPDK Flow API for generic filtering.
+Supports flow API family.
 
-* **[implements] eth_dev_ops**: ``filter_ctrl:RTE_ETH_FILTER_GENERIC``.
+* **[implements] eth_dev_ops**: ``flow_ops_get``.
 * **[implements] rte_flow_ops**: ``All``.
 
 
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 62a57919eb..aec2ba1ec0 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -22,11 +22,6 @@ defined in ``rte_flow.h``.
   queues, to virtual/physical device functions or ports, performing tunnel
   offloads, adding marks and so on.
 
-It is slightly higher-level than the legacy filtering framework which it
-encompasses and supersedes (including all functions and filter types) in
-order to expose a single interface with an unambiguous behavior that is
-common to all poll-mode drivers (PMDs).
-
 Flow rule
 ---------
 
@@ -3104,7 +3099,6 @@ port and may return errors such as ``ENOTSUP`` ("not supported"):
 - Configuring MAC addresses.
 - Configuring multicast addresses.
 - Configuring VLAN filters.
-- Configuring Rx filters through the legacy API (e.g. FDIR).
 - Configuring global RSS settings.
 
 .. code-block:: c
@@ -3331,13 +3325,7 @@ The PMD interface is defined in ``rte_flow_driver.h``. It is not subject to
 API/ABI versioning constraints as it is not exposed to applications and may
 evolve independently.
 
-It is currently implemented on top of the legacy filtering framework through
-filter type *RTE_ETH_FILTER_GENERIC* that accepts the single operation
-*RTE_ETH_FILTER_GET* to return PMD-specific *rte_flow* callbacks wrapped
-inside ``struct rte_flow_ops``.
-
-This overhead is temporarily necessary in order to keep compatibility with
-the legacy filtering framework, which should eventually disappear.
+The PMD interface is based on callbacks pointed by the ``struct rte_flow_ops``.
 
 - PMD callbacks implement exactly the interface described in `Rules
   management`_, except for the port ID argument which has already been
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index b4370e5acd..a6c02d88aa 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -981,9 +981,7 @@ void bnxt_flow_cnt_alarm_cb(void *arg);
 int bnxt_flow_stats_req(struct bnxt *bp);
 int bnxt_flow_stats_cnt(struct bnxt *bp);
 uint32_t bnxt_get_speed_capabilities(struct bnxt *bp);
+int bnxt_flow_ops_get_op(struct rte_eth_dev *dev,
+			 const struct rte_flow_ops **ops);
 
-int
-bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
-		    enum rte_filter_type filter_type,
-		    enum rte_filter_op filter_op, void *arg);
 #endif
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 9824cdb6d8..87d298804f 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3086,9 +3086,8 @@ bnxt_tx_descriptor_status_op(void *tx_queue, uint16_t offset)
 }
 
 int
-bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
-		    enum rte_filter_type filter_type,
-		    enum rte_filter_op filter_op, void *arg)
+bnxt_flow_ops_get_op(struct rte_eth_dev *dev,
+		     const struct rte_flow_ops **ops)
 {
 	struct bnxt *bp = dev->data->dev_private;
 	int ret = 0;
@@ -3101,10 +3100,8 @@ bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
 		bp = vfr->parent_dev->data->dev_private;
 		/* parent is deleted while children are still valid */
 		if (!bp) {
-			PMD_DRV_LOG(DEBUG, "BNXT Port:%d VFR Error %d:%d\n",
-				    dev->data->port_id,
-				    filter_type,
-				    filter_op);
+			PMD_DRV_LOG(DEBUG, "BNXT Port:%d VFR Error\n",
+				    dev->data->port_id);
 			return -EIO;
 		}
 	}
@@ -3113,27 +3110,16 @@ bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
 	if (ret)
 		return ret;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
+	/* PMD supports thread-safe flow operations.  rte_flow API
+	 * functions can avoid mutex for multi-thread safety.
+	 */
+	dev->data->dev_flags |= RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE;
 
-		/* PMD supports thread-safe flow operations.  rte_flow API
-		 * functions can avoid mutex for multi-thread safety.
-		 */
-		dev->data->dev_flags |= RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE;
+	if (BNXT_TRUFLOW_EN(bp))
+		*ops = &bnxt_ulp_rte_flow_ops;
+	else
+		*ops = &bnxt_flow_ops;
 
-		if (BNXT_TRUFLOW_EN(bp))
-			*(const void **)arg = &bnxt_ulp_rte_flow_ops;
-		else
-			*(const void **)arg = &bnxt_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(ERR,
-			"Filter type (%d) not supported", filter_type);
-		ret = -EINVAL;
-		break;
-	}
 	return ret;
 }
 
@@ -3644,7 +3630,7 @@ static const struct eth_dev_ops bnxt_dev_ops = {
 	.rx_queue_stop = bnxt_rx_queue_stop,
 	.tx_queue_start = bnxt_tx_queue_start,
 	.tx_queue_stop = bnxt_tx_queue_stop,
-	.filter_ctrl = bnxt_filter_ctrl_op,
+	.flow_ops_get = bnxt_flow_ops_get_op,
 	.dev_supported_ptypes_get = bnxt_dev_supported_ptypes_get_op,
 	.get_eeprom_length    = bnxt_get_eeprom_length_op,
 	.get_eeprom           = bnxt_get_eeprom_op,
diff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c
index d94874578e..b224a7d2c2 100644
--- a/drivers/net/bnxt/bnxt_reps.c
+++ b/drivers/net/bnxt/bnxt_reps.c
@@ -29,7 +29,7 @@ static const struct eth_dev_ops bnxt_rep_dev_ops = {
 	.dev_stop = bnxt_rep_dev_stop_op,
 	.stats_get = bnxt_rep_stats_get_op,
 	.stats_reset = bnxt_rep_stats_reset_op,
-	.filter_ctrl = bnxt_filter_ctrl_op
+	.flow_ops_get = bnxt_flow_ops_get_op
 };
 
 uint16_t
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 5241c60089..24e3cf3c2e 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -3108,14 +3108,11 @@ bond_ethdev_mac_address_set(struct rte_eth_dev *dev,
 }
 
 static int
-bond_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
-		 enum rte_filter_type type, enum rte_filter_op op, void *arg)
+bond_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		  const struct rte_flow_ops **ops)
 {
-	if (type == RTE_ETH_FILTER_GENERIC && op == RTE_ETH_FILTER_GET) {
-		*(const void **)arg = &bond_flow_ops;
-		return 0;
-	}
-	return -ENOTSUP;
+	*ops = &bond_flow_ops;
+	return 0;
 }
 
 static int
@@ -3207,7 +3204,7 @@ const struct eth_dev_ops default_dev_ops = {
 	.mac_addr_set         = bond_ethdev_mac_address_set,
 	.mac_addr_add         = bond_ethdev_mac_addr_add,
 	.mac_addr_remove      = bond_ethdev_mac_addr_remove,
-	.filter_ctrl          = bond_filter_ctrl
+	.flow_ops_get         = bond_flow_ops_get
 };
 
 static int
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index bfa57c979d..e8a2de3ef3 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1335,7 +1335,7 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {
 	.rx_queue_start		= cxgbe_dev_rx_queue_start,
 	.rx_queue_stop		= cxgbe_dev_rx_queue_stop,
 	.rx_queue_release	= cxgbe_dev_rx_queue_release,
-	.filter_ctrl            = cxgbe_dev_filter_ctrl,
+	.flow_ops_get           = cxgbe_dev_flow_ops_get,
 	.stats_get		= cxgbe_dev_stats_get,
 	.stats_reset		= cxgbe_dev_stats_reset,
 	.flow_ctrl_get		= cxgbe_flow_ctrl_get,
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index 520a5a5c9a..edcbba9d7c 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -1448,23 +1448,9 @@ static const struct rte_flow_ops cxgbe_flow_ops = {
 };
 
 int
-cxgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
-		      enum rte_filter_type filter_type,
-		      enum rte_filter_op filter_op,
-		      void *arg)
+cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		       const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
-	RTE_SET_USED(dev);
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &cxgbe_flow_ops;
-		break;
-	default:
-		ret = -ENOTSUP;
-		break;
-	}
-	return ret;
+	*ops = &cxgbe_flow_ops;
+	return 0;
 }
diff --git a/drivers/net/cxgbe/cxgbe_flow.h b/drivers/net/cxgbe/cxgbe_flow.h
index ec8e47aebe..9cf29550a9 100644
--- a/drivers/net/cxgbe/cxgbe_flow.h
+++ b/drivers/net/cxgbe/cxgbe_flow.h
@@ -35,10 +35,7 @@ struct rte_flow {
 	struct rte_eth_dev *dev;
 };
 
-int
-cxgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
-		      enum rte_filter_type filter_type,
-		      enum rte_filter_op filter_op,
-		      void *arg);
+int cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev,
+			   const struct rte_flow_ops **ops);
 
 #endif /* _CXGBE_FLOW_H_ */
diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
index 0e7ebf4dc0..9011dcfc12 100644
--- a/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -99,10 +99,6 @@ static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = {
 	{"cgr_reject_bytes", 4, 1},
 };
 
-static const enum rte_filter_op dpaa2_supported_filter_ops[] = {
-	RTE_ETH_FILTER_GET
-};
-
 static struct rte_dpaa2_driver rte_dpaa2_pmd;
 static int dpaa2_dev_link_update(struct rte_eth_dev *dev,
 				 int wait_to_complete);
@@ -2322,45 +2318,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev,
 	return ret;
 }
 
-static inline int
-dpaa2_dev_verify_filter_ops(enum rte_filter_op filter_op)
-{
-	unsigned int i;
-
-	for (i = 0; i < RTE_DIM(dpaa2_supported_filter_ops); i++) {
-		if (dpaa2_supported_filter_ops[i] == filter_op)
-			return 0;
-	}
-	return -ENOTSUP;
-}
-
 static int
-dpaa2_dev_flow_ctrl(struct rte_eth_dev *dev,
-		    enum rte_filter_type filter_type,
-				 enum rte_filter_op filter_op,
-				 void *arg)
+dpaa2_dev_flow_ops_get(struct rte_eth_dev *dev,
+		       const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
 	if (!dev)
 		return -ENODEV;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (dpaa2_dev_verify_filter_ops(filter_op) < 0) {
-			ret = -ENOTSUP;
-			break;
-		}
-		*(const void **)arg = &dpaa2_flow_ops;
-		dpaa2_filter_type |= filter_type;
-		break;
-	default:
-		RTE_LOG(ERR, PMD, "Filter type (%d) not supported",
-			filter_type);
-		ret = -ENOTSUP;
-		break;
-	}
-	return ret;
+	*ops = &dpaa2_flow_ops;
+	return 0;
 }
 
 static void
@@ -2453,7 +2419,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
 	.mac_addr_set         = dpaa2_dev_set_mac_addr,
 	.rss_hash_update      = dpaa2_dev_rss_hash_update,
 	.rss_hash_conf_get    = dpaa2_dev_rss_hash_conf_get,
-	.filter_ctrl          = dpaa2_dev_flow_ctrl,
+	.flow_ops_get         = dpaa2_dev_flow_ops_get,
 	.rxq_info_get	      = dpaa2_rxq_info_get,
 	.txq_info_get	      = dpaa2_txq_info_get,
 	.tm_ops_get	      = dpaa2_tm_ops_get,
diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c
index 29f1f2e654..bfe17c350a 100644
--- a/drivers/net/dpaa2/dpaa2_flow.c
+++ b/drivers/net/dpaa2/dpaa2_flow.c
@@ -89,8 +89,6 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = {
 /* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/
 #define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)
 
-enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;
-
 #ifndef __cplusplus
 static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {
 	.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
@@ -3969,24 +3967,15 @@ struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,
 	flow->ipaddr_rule.fs_ipdst_offset =
 		IP_ADDRESS_OFFSET_INVALID;
 
-	switch (dpaa2_filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
-					     actions, error);
-		if (ret < 0) {
-			if (error->type > RTE_FLOW_ERROR_TYPE_ACTION)
-				rte_flow_error_set(error, EPERM,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						attr, "unknown");
-			DPAA2_PMD_ERR(
-			"Failure to create flow, return code (%d)", ret);
-			goto creation_error;
-		}
-		break;
-	default:
-		DPAA2_PMD_ERR("Filter type (%d) not supported",
-		dpaa2_filter_type);
-		break;
+	ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
+			actions, error);
+	if (ret < 0) {
+		if (error->type > RTE_FLOW_ERROR_TYPE_ACTION)
+			rte_flow_error_set(error, EPERM,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					attr, "unknown");
+		DPAA2_PMD_ERR("Failure to create flow, return code (%d)", ret);
+		goto creation_error;
 	}
 
 	return flow;
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 1716d6b904..17ee6e91a0 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -194,10 +194,8 @@ static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,
 			struct rte_eth_ntuple_filter *ntuple_filter);
 static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,
 			struct rte_eth_ntuple_filter *ntuple_filter);
-static int eth_igb_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg);
+static int eth_igb_flow_ops_get(struct rte_eth_dev *dev,
+				const struct rte_flow_ops **ops);
 static int eth_igb_get_reg_length(struct rte_eth_dev *dev);
 static int eth_igb_get_regs(struct rte_eth_dev *dev,
 		struct rte_dev_reg_info *regs);
@@ -374,7 +372,7 @@ static const struct eth_dev_ops eth_igb_ops = {
 	.reta_query           = eth_igb_rss_reta_query,
 	.rss_hash_update      = eth_igb_rss_hash_update,
 	.rss_hash_conf_get    = eth_igb_rss_hash_conf_get,
-	.filter_ctrl          = eth_igb_filter_ctrl,
+	.flow_ops_get         = eth_igb_flow_ops_get,
 	.set_mc_addr_list     = eth_igb_set_mc_addr_list,
 	.rxq_info_get         = igb_rxq_info_get,
 	.txq_info_get         = igb_txq_info_get,
@@ -4583,26 +4581,11 @@ igb_add_del_ethertype_filter(struct rte_eth_dev *dev,
 }
 
 static int
-eth_igb_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+eth_igb_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		     const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &igb_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-							filter_type);
-		break;
-	}
-
-	return ret;
+	*ops = &igb_flow_ops;
+	return 0;
 }
 
 static int
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index b3f441c8f7..38da5e8ce4 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -74,13 +74,10 @@ static const struct vic_speed_capa {
 RTE_LOG_REGISTER(enic_pmd_logtype, pmd.net.enic, INFO);
 
 static int
-enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+enicpmd_dev_flow_ops_get(struct rte_eth_dev *dev,
+			 const struct rte_flow_ops **ops)
 {
 	struct enic *enic = pmd_priv(dev);
-	int ret = 0;
 
 	ENICPMD_FUNC_TRACE();
 
@@ -90,23 +87,12 @@ enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
 	 */
 	if (enic->geneve_opt_enabled)
 		return -ENOTSUP;
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		if (enic->flow_filter_mode == FILTER_FLOWMAN)
-			*(const void **)arg = &enic_fm_flow_ops;
-		else
-			*(const void **)arg = &enic_flow_ops;
-		break;
-	default:
-		dev_warning(enic, "Filter type (%d) not supported",
-			filter_type);
-		ret = -EINVAL;
-		break;
-	}
 
-	return ret;
+	if (enic->flow_filter_mode == FILTER_FLOWMAN)
+		*ops = &enic_fm_flow_ops;
+	else
+		*ops = &enic_flow_ops;
+	return 0;
 }
 
 static void enicpmd_dev_tx_queue_release(void *txq)
@@ -1121,7 +1107,7 @@ static const struct eth_dev_ops enicpmd_eth_dev_ops = {
 	.mac_addr_remove      = enicpmd_remove_mac_addr,
 	.mac_addr_set         = enicpmd_set_mac_addr,
 	.set_mc_addr_list     = enicpmd_set_mc_addr_list,
-	.filter_ctrl          = enicpmd_dev_filter_ctrl,
+	.flow_ops_get         = enicpmd_dev_flow_ops_get,
 	.reta_query           = enicpmd_dev_rss_reta_query,
 	.reta_update          = enicpmd_dev_rss_reta_update,
 	.rss_hash_conf_get    = enicpmd_dev_rss_hash_conf_get,
diff --git a/drivers/net/enic/enic_vf_representor.c b/drivers/net/enic/enic_vf_representor.c
index f7b79c1c4e..79dd6e5640 100644
--- a/drivers/net/enic/enic_vf_representor.c
+++ b/drivers/net/enic/enic_vf_representor.c
@@ -377,34 +377,21 @@ static const struct rte_flow_ops enic_vf_flow_ops = {
 };
 
 static int
-enic_vf_filter_ctrl(struct rte_eth_dev *eth_dev,
-		    enum rte_filter_type filter_type,
-		    enum rte_filter_op filter_op,
-		    void *arg)
+enic_vf_flow_ops_get(struct rte_eth_dev *eth_dev,
+		     const struct rte_flow_ops **ops)
 {
 	struct enic_vf_representor *vf;
-	int ret = 0;
 
 	ENICPMD_FUNC_TRACE();
 	vf = eth_dev->data->dev_private;
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		if (vf->enic.flow_filter_mode == FILTER_FLOWMAN) {
-			*(const void **)arg = &enic_vf_flow_ops;
-		} else {
-			ENICPMD_LOG(WARNING, "VF representors require flowman support for rte_flow API");
-			ret = -EINVAL;
-		}
-		break;
-	default:
-		ENICPMD_LOG(WARNING, "Filter type (%d) not supported",
-			    filter_type);
-		ret = -EINVAL;
-		break;
+	if (vf->enic.flow_filter_mode != FILTER_FLOWMAN) {
+		ENICPMD_LOG(WARNING,
+				"VF representors require flowman support for rte_flow API");
+		return -EINVAL;
 	}
-	return ret;
+
+	*ops = &enic_vf_flow_ops;
+	return 0;
 }
 
 static int enic_vf_link_update(struct rte_eth_dev *eth_dev,
@@ -566,7 +553,7 @@ static const struct eth_dev_ops enic_vf_representor_dev_ops = {
 	.dev_start            = enic_vf_dev_start,
 	.dev_stop             = enic_vf_dev_stop,
 	.dev_close            = enic_vf_dev_close,
-	.filter_ctrl          = enic_vf_filter_ctrl,
+	.flow_ops_get         = enic_vf_flow_ops_get,
 	.link_update          = enic_vf_link_update,
 	.promiscuous_enable   = enic_vf_promiscuous_enable,
 	.promiscuous_disable  = enic_vf_promiscuous_disable,
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c
index 1343777d61..5ff33e03e0 100644
--- a/drivers/net/failsafe/failsafe_ops.c
+++ b/drivers/net/failsafe/failsafe_ops.c
@@ -1514,17 +1514,11 @@ fs_rss_hash_update(struct rte_eth_dev *dev,
 }
 
 static int
-fs_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
-		enum rte_filter_type type,
-		enum rte_filter_op op,
-		void *arg)
+fs_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		const struct rte_flow_ops **ops)
 {
-	if (type == RTE_ETH_FILTER_GENERIC &&
-	    op == RTE_ETH_FILTER_GET) {
-		*(const void **)arg = &fs_flow_ops;
-		return 0;
-	}
-	return -ENOTSUP;
+	*ops = &fs_flow_ops;
+	return 0;
 }
 
 const struct eth_dev_ops failsafe_ops = {
@@ -1565,5 +1559,5 @@ const struct eth_dev_ops failsafe_ops = {
 	.mac_addr_set = fs_mac_addr_set,
 	.set_mc_addr_list = fs_set_mc_addr_list,
 	.rss_hash_update = fs_rss_hash_update,
-	.filter_ctrl = fs_filter_ctrl,
+	.flow_ops_get = fs_flow_ops_get,
 };
diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c
index 1d6b710c9f..2352dd1615 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -2504,42 +2504,20 @@ static int hinic_set_mc_addr_list(struct rte_eth_dev *dev,
 }
 
 /**
- * DPDK callback to manage filter control operations
+ * DPDK callback to get flow operations
  *
  * @param dev
  *   Pointer to Ethernet device structure.
- * @param filter_type
- *   Filter type, which just supports generic type.
- * @param filter_op
- *   Filter operation to perform.
- * @param arg
+ * @param ops
  *   Pointer to operation-specific structure.
  *
  * @return
  *   0 on success, negative error value otherwise.
  */
-static int hinic_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+				  const struct rte_flow_ops **ops)
 {
-	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
-	int func_id = hinic_global_func_id(nic_dev->hwdev);
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &hinic_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(INFO, "Filter type (%d) not supported",
-			filter_type);
-		return -EINVAL;
-	}
-
-	PMD_DRV_LOG(INFO, "Set filter_ctrl succeed, func_id: 0x%x, filter_type: 0x%x,"
-			"filter_op: 0x%x.", func_id, filter_type, filter_op);
+	*ops = &hinic_flow_ops;
 	return 0;
 }
 
@@ -3047,7 +3025,7 @@ static const struct eth_dev_ops hinic_pmd_ops = {
 	.mac_addr_remove               = hinic_mac_addr_remove,
 	.mac_addr_add                  = hinic_mac_addr_add,
 	.set_mc_addr_list              = hinic_set_mc_addr_list,
-	.filter_ctrl                   = hinic_dev_filter_ctrl,
+	.flow_ops_get                  = hinic_dev_flow_ops_get,
 };
 
 static const struct eth_dev_ops hinic_pmd_vf_ops = {
@@ -3082,7 +3060,7 @@ static const struct eth_dev_ops hinic_pmd_vf_ops = {
 	.mac_addr_remove               = hinic_mac_addr_remove,
 	.mac_addr_add                  = hinic_mac_addr_add,
 	.set_mc_addr_list              = hinic_set_mc_addr_list,
-	.filter_ctrl                   = hinic_dev_filter_ctrl,
+	.flow_ops_get                  = hinic_dev_flow_ops_get,
 };
 
 static int hinic_func_init(struct rte_eth_dev *eth_dev)
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 9cbcc13de8..f6d47369b2 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -6550,7 +6550,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.rss_hash_conf_get      = hns3_dev_rss_hash_conf_get,
 	.reta_update            = hns3_dev_rss_reta_update,
 	.reta_query             = hns3_dev_rss_reta_query,
-	.filter_ctrl            = hns3_dev_filter_ctrl,
+	.flow_ops_get           = hns3_dev_flow_ops_get,
 	.vlan_filter_set        = hns3_vlan_filter_set,
 	.vlan_tpid_set          = hns3_vlan_tpid_set,
 	.vlan_offload_set       = hns3_vlan_offload_set,
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 932600d05b..d180dc1e7f 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -963,9 +963,8 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
 }
 
 int hns3_buffer_alloc(struct hns3_hw *hw);
-int hns3_dev_filter_ctrl(struct rte_eth_dev *dev,
-			 enum rte_filter_type filter_type,
-			 enum rte_filter_op filter_op, void *arg);
+int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
+			  const struct rte_flow_ops **ops);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
 void hns3_update_link_status_and_event(struct hns3_hw *hw);
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index fd20c522dc..a35e1d9aad 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -2769,7 +2769,7 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.rss_hash_conf_get  = hns3_dev_rss_hash_conf_get,
 	.reta_update        = hns3_dev_rss_reta_update,
 	.reta_query         = hns3_dev_rss_reta_query,
-	.filter_ctrl        = hns3_dev_filter_ctrl,
+	.flow_ops_get       = hns3_dev_flow_ops_get,
 	.vlan_filter_set    = hns3vf_vlan_filter_set,
 	.vlan_offload_set   = hns3vf_vlan_offload_set,
 	.get_reg            = hns3_get_regs,
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index a016857aa5..0c4e91109c 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -2001,34 +2001,16 @@ static const struct rte_flow_ops hns3_flow_ops = {
 	.isolate = NULL,
 };
 
-/*
- * The entry of flow API.
- * @param dev
- *   Pointer to Ethernet device.
- * @return
- *   0 on success, a negative errno value otherwise is set.
- */
 int
-hns3_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op, void *arg)
+hns3_dev_flow_ops_get(struct rte_eth_dev *dev,
+		      const struct rte_flow_ops **ops)
 {
 	struct hns3_hw *hw;
-	int ret = 0;
 
 	hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		if (hw->adapter_state >= HNS3_NIC_CLOSED)
-			return -ENODEV;
-		*(const void **)arg = &hns3_flow_ops;
-		break;
-	default:
-		hns3_err(hw, "Filter type (%d) not supported", filter_type);
-		ret = -EOPNOTSUPP;
-		break;
-	}
+	if (hw->adapter_state >= HNS3_NIC_CLOSED)
+		return -ENODEV;
 
-	return ret;
+	*ops = &hns3_flow_ops;
+	return 0;
 }
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index d7cd049891..e8634755f2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -319,10 +319,8 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
 static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 					struct rte_eth_udp_tunnel *udp_tunnel);
 static void i40e_filter_input_set_init(struct i40e_pf *pf);
-static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
-				enum rte_filter_type filter_type,
-				enum rte_filter_op filter_op,
-				void *arg);
+static int i40e_dev_flow_ops_get(struct rte_eth_dev *dev,
+				 const struct rte_flow_ops **ops);
 static int i40e_dev_get_dcb_info(struct rte_eth_dev *dev,
 				  struct rte_eth_dcb_info *dcb_info);
 static int i40e_dev_sync_phy_type(struct i40e_hw *hw);
@@ -484,7 +482,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,
 	.udp_tunnel_port_add          = i40e_dev_udp_tunnel_port_add,
 	.udp_tunnel_port_del          = i40e_dev_udp_tunnel_port_del,
-	.filter_ctrl                  = i40e_dev_filter_ctrl,
+	.flow_ops_get                 = i40e_dev_flow_ops_get,
 	.rxq_info_get                 = i40e_rxq_info_get,
 	.txq_info_get                 = i40e_txq_info_get,
 	.rx_burst_mode_get            = i40e_rx_burst_mode_get,
@@ -9785,30 +9783,14 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
 }
 
 static int
-i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+i40e_dev_flow_ops_get(struct rte_eth_dev *dev,
+		      const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
 	if (dev == NULL)
 		return -EINVAL;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &i40e_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-							filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &i40e_flow_ops;
+	return 0;
 }
 
 /*
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 4d37722022..e3933cde26 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -117,10 +117,8 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
-static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg);
+static int iavf_dev_flow_ops_get(struct rte_eth_dev *dev,
+				 const struct rte_flow_ops **ops);
 static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
 			struct rte_ether_addr *mc_addrs,
 			uint32_t mc_addrs_num);
@@ -195,7 +193,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.mtu_set                    = iavf_dev_mtu_set,
 	.rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
 	.rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
-	.filter_ctrl                = iavf_dev_filter_ctrl,
+	.flow_ops_get               = iavf_dev_flow_ops_get,
 	.tx_done_cleanup	    = iavf_dev_tx_done_cleanup,
 };
 
@@ -2070,30 +2068,14 @@ iavf_dev_interrupt_handler(void *param)
 }
 
 static int
-iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+iavf_dev_flow_ops_get(struct rte_eth_dev *dev,
+		      const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
 	if (!dev)
 		return -EINVAL;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &iavf_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-			    filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &iavf_flow_ops;
+	return 0;
 }
 
 static void
diff --git a/drivers/net/ice/ice_dcf_ethdev.c b/drivers/net/ice/ice_dcf_ethdev.c
index e0772295e9..86600959f8 100644
--- a/drivers/net/ice/ice_dcf_ethdev.c
+++ b/drivers/net/ice/ice_dcf_ethdev.c
@@ -743,31 +743,14 @@ ice_dcf_dev_allmulticast_disable(__rte_unused struct rte_eth_dev *dev)
 }
 
 static int
-ice_dcf_dev_filter_ctrl(struct rte_eth_dev *dev,
-			enum rte_filter_type filter_type,
-			enum rte_filter_op filter_op,
-			void *arg)
+ice_dcf_dev_flow_ops_get(struct rte_eth_dev *dev,
+			 const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
 	if (!dev)
 		return -EINVAL;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &ice_flow_ops;
-		break;
-
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-			    filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &ice_flow_ops;
+	return 0;
 }
 
 #define ICE_DCF_32_BIT_WIDTH (CHAR_BIT * 4)
@@ -984,7 +967,7 @@ static const struct eth_dev_ops ice_dcf_eth_dev_ops = {
 	.promiscuous_disable     = ice_dcf_dev_promiscuous_disable,
 	.allmulticast_enable     = ice_dcf_dev_allmulticast_enable,
 	.allmulticast_disable    = ice_dcf_dev_allmulticast_disable,
-	.filter_ctrl             = ice_dcf_dev_filter_ctrl,
+	.flow_ops_get            = ice_dcf_dev_flow_ops_get,
 	.udp_tunnel_port_add	 = ice_dcf_dev_udp_tunnel_port_add,
 	.udp_tunnel_port_del	 = ice_dcf_dev_udp_tunnel_port_del,
 };
diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c
index 8999d441ac..3d1c32247a 100644
--- a/drivers/net/ice/ice_ethdev.c
+++ b/drivers/net/ice/ice_ethdev.c
@@ -129,10 +129,8 @@ static int ice_xstats_get(struct rte_eth_dev *dev,
 static int ice_xstats_get_names(struct rte_eth_dev *dev,
 				struct rte_eth_xstat_name *xstats_names,
 				unsigned int limit);
-static int ice_dev_filter_ctrl(struct rte_eth_dev *dev,
-			enum rte_filter_type filter_type,
-			enum rte_filter_op filter_op,
-			void *arg);
+static int ice_dev_flow_ops_get(struct rte_eth_dev *dev,
+				const struct rte_flow_ops **ops);
 static int ice_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
 			struct rte_eth_udp_tunnel *udp_tunnel);
 static int ice_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
@@ -215,7 +213,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
 	.xstats_get                   = ice_xstats_get,
 	.xstats_get_names             = ice_xstats_get_names,
 	.xstats_reset                 = ice_stats_reset,
-	.filter_ctrl                  = ice_dev_filter_ctrl,
+	.flow_ops_get                 = ice_dev_flow_ops_get,
 	.udp_tunnel_port_add          = ice_dev_udp_tunnel_port_add,
 	.udp_tunnel_port_del          = ice_dev_udp_tunnel_port_del,
 	.tx_done_cleanup              = ice_tx_done_cleanup,
@@ -5255,30 +5253,14 @@ static int ice_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-ice_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+ice_dev_flow_ops_get(struct rte_eth_dev *dev,
+		     const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
 	if (!dev)
 		return -EINVAL;
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &ice_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-					filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &ice_flow_ops;
+	return 0;
 }
 
 /* Add UDP tunneling port */
diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c
index 0ea6e2a045..56d1024af6 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -297,7 +297,7 @@ static const struct eth_dev_ops eth_igc_ops = {
 	.vlan_offload_set	= eth_igc_vlan_offload_set,
 	.vlan_tpid_set		= eth_igc_vlan_tpid_set,
 	.vlan_strip_queue_set	= eth_igc_vlan_strip_queue_set,
-	.filter_ctrl		= eth_igc_filter_ctrl,
+	.flow_ops_get		= eth_igc_flow_ops_get,
 };
 
 /*
diff --git a/drivers/net/igc/igc_filter.c b/drivers/net/igc/igc_filter.c
index 836621d4c1..51fcabfb59 100644
--- a/drivers/net/igc/igc_filter.c
+++ b/drivers/net/igc/igc_filter.c
@@ -369,24 +369,9 @@ igc_clear_all_filter(struct rte_eth_dev *dev)
 }
 
 int
-eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
-		enum rte_filter_op filter_op, void *arg)
+eth_igc_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		     const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
-	RTE_SET_USED(dev);
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &igc_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-							filter_type);
-		ret = -EINVAL;
-	}
-
-	return ret;
+	*ops = &igc_flow_ops;
+	return 0;
 }
diff --git a/drivers/net/igc/igc_filter.h b/drivers/net/igc/igc_filter.h
index df8516bc40..781d270def 100644
--- a/drivers/net/igc/igc_filter.h
+++ b/drivers/net/igc/igc_filter.h
@@ -29,9 +29,8 @@ int igc_set_syn_filter(struct rte_eth_dev *dev,
 		const struct igc_syn_filter *filter);
 void igc_clear_syn_filter(struct rte_eth_dev *dev);
 void igc_clear_all_filter(struct rte_eth_dev *dev);
-int
-eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
-		enum rte_filter_op filter_op, void *arg);
+int eth_igc_flow_ops_get(struct rte_eth_dev *dev,
+			 const struct rte_flow_ops **ops);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c
index 856d21ef9b..589d9fa587 100644
--- a/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -2821,11 +2821,9 @@ ipn3ke_rpst_mtu_set(struct rte_eth_dev *ethdev, uint16_t mtu)
 }
 
 static int
-ipn3ke_afu_filter_ctrl(struct rte_eth_dev *ethdev,
-	enum rte_filter_type filter_type, enum rte_filter_op filter_op,
-	void *arg)
+ipn3ke_afu_flow_ops_get(struct rte_eth_dev *ethdev,
+			const struct rte_flow_ops **ops)
 {
-	int ret = 0;
 	struct ipn3ke_hw *hw;
 	struct ipn3ke_rpst *rpst;
 
@@ -2836,27 +2834,13 @@ ipn3ke_afu_filter_ctrl(struct rte_eth_dev *ethdev,
 	rpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);
 
 	if (hw->acc_flow)
-		switch (filter_type) {
-		case RTE_ETH_FILTER_GENERIC:
-			if (filter_op != RTE_ETH_FILTER_GET)
-				return -EINVAL;
-			*(const void **)arg = &ipn3ke_flow_ops;
-			break;
-		default:
-			IPN3KE_AFU_PMD_WARN("Filter type (%d) not supported",
-					filter_type);
-			ret = -EINVAL;
-			break;
-		}
+		*ops = &ipn3ke_flow_ops;
 	else if (rpst->i40e_pf_eth)
-		(*rpst->i40e_pf_eth->dev_ops->filter_ctrl)(ethdev,
-							filter_type,
-							filter_op,
-							arg);
+		(*rpst->i40e_pf_eth->dev_ops->flow_ops_get)(ethdev, ops);
 	else
 		return -EINVAL;
 
-	return ret;
+	return 0;
 }
 
 static const struct eth_dev_ops ipn3ke_rpst_dev_ops = {
@@ -2874,7 +2858,7 @@ static const struct eth_dev_ops ipn3ke_rpst_dev_ops = {
 	.stats_reset          = ipn3ke_rpst_stats_reset,
 	.xstats_reset         = ipn3ke_rpst_stats_reset,
 
-	.filter_ctrl          = ipn3ke_afu_filter_ctrl,
+	.flow_ops_get         = ipn3ke_afu_flow_ops_get,
 
 	.rx_queue_start       = ipn3ke_rpst_rx_queue_start,
 	.rx_queue_stop        = ipn3ke_rpst_rx_queue_stop,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 761a0f26bb..d5581a243a 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -304,10 +304,8 @@ static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev,
 			struct ixgbe_5tuple_filter *filter);
 static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,
 			struct ixgbe_5tuple_filter *filter);
-static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg);
+static int ixgbe_dev_flow_ops_get(struct rte_eth_dev *dev,
+				  const struct rte_flow_ops **ops);
 static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);
 
 static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
@@ -538,7 +536,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.reta_query           = ixgbe_dev_rss_reta_query,
 	.rss_hash_update      = ixgbe_dev_rss_hash_update,
 	.rss_hash_conf_get    = ixgbe_dev_rss_hash_conf_get,
-	.filter_ctrl          = ixgbe_dev_filter_ctrl,
+	.flow_ops_get         = ixgbe_dev_flow_ops_get,
 	.set_mc_addr_list     = ixgbe_dev_set_mc_addr_list,
 	.rxq_info_get         = ixgbe_rxq_info_get,
 	.txq_info_get         = ixgbe_txq_info_get,
@@ -6798,27 +6796,11 @@ ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
 }
 
 static int
-ixgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+ixgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,
+		       const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &ixgbe_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-							filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &ixgbe_flow_ops;
+	return 0;
 }
 
 static u8 *
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 041c1934f5..d048d21033 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -437,7 +437,7 @@ static const struct eth_dev_ops mlx4_dev_ops = {
 	.flow_ctrl_get = mlx4_flow_ctrl_get,
 	.flow_ctrl_set = mlx4_flow_ctrl_set,
 	.mtu_set = mlx4_mtu_set,
-	.filter_ctrl = mlx4_filter_ctrl,
+	.flow_ops_get = mlx4_flow_ops_get,
 	.rx_queue_intr_enable = mlx4_rx_intr_enable,
 	.rx_queue_intr_disable = mlx4_rx_intr_disable,
 	.is_removed = mlx4_is_removed,
diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c
index b8ecfa829b..43a65abcc0 100644
--- a/drivers/net/mlx4/mlx4_flow.c
+++ b/drivers/net/mlx4/mlx4_flow.c
@@ -1590,37 +1590,19 @@ static const struct rte_flow_ops mlx4_flow_ops = {
 };
 
 /**
- * Manage filter operations.
+ * Get rte_flow callbacks.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
- * @param filter_type
- *   Filter type.
- * @param filter_op
- *   Operation to perform.
- * @param arg
+ * @param ops
  *   Pointer to operation-specific structure.
  *
- * @return
- *   0 on success, negative errno value otherwise and rte_errno is set.
+ * @return 0
  */
 int
-mlx4_filter_ctrl(struct rte_eth_dev *dev,
-		 enum rte_filter_type filter_type,
-		 enum rte_filter_op filter_op,
-		 void *arg)
+mlx4_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		  const struct rte_flow_ops **ops)
 {
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			break;
-		*(const void **)arg = &mlx4_flow_ops;
-		return 0;
-	default:
-		ERROR("%p: filter type (%d) not supported",
-		      (void *)dev, filter_type);
-		break;
-	}
-	rte_errno = ENOTSUP;
-	return -rte_errno;
+	*ops = &mlx4_flow_ops;
+	return 0;
 }
diff --git a/drivers/net/mlx4/mlx4_flow.h b/drivers/net/mlx4/mlx4_flow.h
index e4366f28bb..5e82df6bd6 100644
--- a/drivers/net/mlx4/mlx4_flow.h
+++ b/drivers/net/mlx4/mlx4_flow.h
@@ -51,9 +51,6 @@ uint64_t mlx4_conv_rss_types(struct mlx4_priv *priv, uint64_t types,
 			     int verbs_to_dpdk);
 int mlx4_flow_sync(struct mlx4_priv *priv, struct rte_flow_error *error);
 void mlx4_flow_clean(struct mlx4_priv *priv);
-int mlx4_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg);
+int mlx4_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);
 
 #endif /* RTE_PMD_MLX4_FLOW_H_ */
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index abd7ff70df..d9372f0a00 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -1477,7 +1477,7 @@ const struct eth_dev_ops mlx5_dev_ops = {
 	.reta_query = mlx5_dev_rss_reta_query,
 	.rss_hash_update = mlx5_rss_hash_update,
 	.rss_hash_conf_get = mlx5_rss_hash_conf_get,
-	.filter_ctrl = mlx5_dev_filter_ctrl,
+	.flow_ops_get = mlx5_flow_ops_get,
 	.rxq_info_get = mlx5_rxq_info_get,
 	.txq_info_get = mlx5_txq_info_get,
 	.rx_burst_mode_get = mlx5_rx_burst_mode_get,
@@ -1562,7 +1562,7 @@ const struct eth_dev_ops mlx5_dev_ops_isolate = {
 	.mtu_set = mlx5_dev_set_mtu,
 	.vlan_strip_queue_set = mlx5_vlan_strip_queue_set,
 	.vlan_offload_set = mlx5_vlan_offload_set,
-	.filter_ctrl = mlx5_dev_filter_ctrl,
+	.flow_ops_get = mlx5_flow_ops_get,
 	.rxq_info_get = mlx5_rxq_info_get,
 	.txq_info_get = mlx5_txq_info_get,
 	.rx_burst_mode_get = mlx5_rx_burst_mode_get,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index a281fd20ea..24aff0beab 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1192,10 +1192,7 @@ int mlx5_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
 		    struct rte_flow_error *error);
 int mlx5_flow_isolate(struct rte_eth_dev *dev, int enable,
 		      struct rte_flow_error *error);
-int mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
-			 enum rte_filter_type filter_type,
-			 enum rte_filter_op filter_op,
-			 void *arg);
+int mlx5_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);
 int mlx5_flow_start_default(struct rte_eth_dev *dev);
 void mlx5_flow_stop_default(struct rte_eth_dev *dev);
 int mlx5_flow_verify(struct rte_eth_dev *dev);
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index ab5be3dacc..ca09d1ede9 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -6492,40 +6492,20 @@ mlx5_flow_query(struct rte_eth_dev *dev,
 }
 
 /**
- * Manage filter operations.
+ * Get rte_flow callbacks.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
- * @param filter_type
- *   Filter type.
- * @param filter_op
- *   Operation to perform.
- * @param arg
+ * @param ops
  *   Pointer to operation-specific structure.
  *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * @return 0
  */
 int
-mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		  const struct rte_flow_ops **ops)
 {
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET) {
-			rte_errno = EINVAL;
-			return -rte_errno;
-		}
-		*(const void **)arg = &mlx5_flow_ops;
-		return 0;
-	default:
-		DRV_LOG(ERR, "port %u filter type (%d) not supported",
-			dev->data->port_id, filter_type);
-		rte_errno = ENOTSUP;
-		return -rte_errno;
-	}
+	*ops = &mlx5_flow_ops;
 	return 0;
 }
 
diff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c
index e119952340..1d41788974 100644
--- a/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/drivers/net/mvpp2/mrvl_ethdev.c
@@ -2340,32 +2340,18 @@ mrvl_rss_hash_conf_get(struct rte_eth_dev *dev,
  *
  * @param dev
  *   Pointer to the device structure.
- * @param filer_type
- *   Flow filter type.
- * @param filter_op
- *   Flow filter operation.
- * @param arg
+ * @param ops
  *   Pointer to pass the flow ops.
  *
  * @return
  *   0 on success, negative error value otherwise.
  */
 static int
-mrvl_eth_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op, void *arg)
+mrvl_eth_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		      const struct rte_flow_ops **ops)
 {
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &mrvl_flow_ops;
-		return 0;
-	default:
-		MRVL_LOG(WARNING, "Filter type (%d) not supported",
-				filter_type);
-		return -EINVAL;
-	}
+	*ops = &mrvl_flow_ops;
+	return 0;
 }
 
 /**
@@ -2443,7 +2429,7 @@ static const struct eth_dev_ops mrvl_ops = {
 	.flow_ctrl_set = mrvl_flow_ctrl_set,
 	.rss_hash_update = mrvl_rss_hash_update,
 	.rss_hash_conf_get = mrvl_rss_hash_conf_get,
-	.filter_ctrl = mrvl_eth_filter_ctrl,
+	.flow_ops_get = mrvl_eth_flow_ops_get,
 	.mtr_ops_get = mrvl_mtr_ops_get,
 	.tm_ops_get = mrvl_tm_ops_get,
 };
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index e9fbbca4da..bacf180a6d 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -2322,7 +2322,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {
 	.tx_done_cleanup          = otx2_nix_tx_done_cleanup,
 	.set_queue_rate_limit     = otx2_nix_tm_set_queue_rate_limit,
 	.pool_ops_supported       = otx2_nix_pool_ops_supported,
-	.filter_ctrl              = otx2_nix_dev_filter_ctrl,
+	.flow_ops_get             = otx2_nix_dev_flow_ops_get,
 	.get_module_info          = otx2_nix_get_module_info,
 	.get_module_eeprom        = otx2_nix_get_module_eeprom,
 	.fw_version_get           = otx2_nix_fw_version_get,
diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h
index 99f0469d89..7391f09b8a 100644
--- a/drivers/net/octeontx2/otx2_ethdev.h
+++ b/drivers/net/octeontx2/otx2_ethdev.h
@@ -396,9 +396,8 @@ otx2_eth_pmd_priv(struct rte_eth_dev *eth_dev)
 /* Ops */
 int otx2_nix_info_get(struct rte_eth_dev *eth_dev,
 		      struct rte_eth_dev_info *dev_info);
-int otx2_nix_dev_filter_ctrl(struct rte_eth_dev *eth_dev,
-			     enum rte_filter_type filter_type,
-			     enum rte_filter_op filter_op, void *arg);
+int otx2_nix_dev_flow_ops_get(struct rte_eth_dev *eth_dev,
+			      const struct rte_flow_ops **ops);
 int otx2_nix_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,
 			    size_t fw_size);
 int otx2_nix_get_module_info(struct rte_eth_dev *eth_dev,
diff --git a/drivers/net/octeontx2/otx2_ethdev_ops.c b/drivers/net/octeontx2/otx2_ethdev_ops.c
index 963cc285ed..9e3f80937d 100644
--- a/drivers/net/octeontx2/otx2_ethdev_ops.c
+++ b/drivers/net/octeontx2/otx2_ethdev_ops.c
@@ -471,24 +471,11 @@ otx2_nix_pool_ops_supported(struct rte_eth_dev *eth_dev, const char *pool)
 }
 
 int
-otx2_nix_dev_filter_ctrl(struct rte_eth_dev *eth_dev,
-			 enum rte_filter_type filter_type,
-			 enum rte_filter_op filter_op, void *arg)
+otx2_nix_dev_flow_ops_get(struct rte_eth_dev *eth_dev __rte_unused,
+			  const struct rte_flow_ops **ops)
 {
-	RTE_SET_USED(eth_dev);
-
-	if (filter_type != RTE_ETH_FILTER_GENERIC) {
-		otx2_err("Unsupported filter type %d", filter_type);
-		return -ENOTSUP;
-	}
-
-	if (filter_op == RTE_ETH_FILTER_GET) {
-		*(const void **)arg = &otx2_flow_ops;
-		return 0;
-	}
-
-	otx2_err("Invalid filter_op %d", filter_op);
-	return -EINVAL;
+	*ops = &otx2_flow_ops;
+	return 0;
 }
 
 static struct cgx_fw_data *
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index ab5f5b1065..ff4b9255c4 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -2434,7 +2434,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {
 	.reta_update  = qede_rss_reta_update,
 	.reta_query  = qede_rss_reta_query,
 	.mtu_set = qede_set_mtu,
-	.filter_ctrl = qede_dev_filter_ctrl,
+	.flow_ops_get = qede_dev_flow_ops_get,
 	.udp_tunnel_port_add = qede_udp_dst_port_add,
 	.udp_tunnel_port_del = qede_udp_dst_port_del,
 	.fw_version_get = qede_fw_version_get,
diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h
index da4b87f5e2..a38b701183 100644
--- a/drivers/net/qede/qede_ethdev.h
+++ b/drivers/net/qede/qede_ethdev.h
@@ -285,11 +285,8 @@ int qede_dev_set_link_state(struct rte_eth_dev *eth_dev, bool link_up);
 int qede_link_update(struct rte_eth_dev *eth_dev,
 		     __rte_unused int wait_to_complete);
 
-int qede_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type type,
-			 enum rte_filter_op op, void *arg);
-
-int qede_ntuple_filter_conf(struct rte_eth_dev *eth_dev,
-			    enum rte_filter_op filter_op, void *arg);
+int qede_dev_flow_ops_get(struct rte_eth_dev *dev,
+			  const struct rte_flow_ops **ops);
 
 int qede_check_fdir_support(struct rte_eth_dev *eth_dev);
 
diff --git a/drivers/net/qede/qede_filter.c b/drivers/net/qede/qede_filter.c
index df5c07dfe5..c756594bfc 100644
--- a/drivers/net/qede/qede_filter.c
+++ b/drivers/net/qede/qede_filter.c
@@ -1050,31 +1050,18 @@ const struct rte_flow_ops qede_flow_ops = {
 	.flush = qede_flow_flush,
 };
 
-int qede_dev_filter_ctrl(struct rte_eth_dev *eth_dev,
-			 enum rte_filter_type filter_type,
-			 enum rte_filter_op filter_op,
-			 void *arg)
+int
+qede_dev_flow_ops_get(struct rte_eth_dev *eth_dev,
+		      const struct rte_flow_ops **ops)
 {
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (ECORE_IS_CMT(edev)) {
-			DP_ERR(edev, "flowdir is not supported in 100G mode\n");
-			return -ENOTSUP;
-		}
-
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-
-		*(const void **)arg = &qede_flow_ops;
-		return 0;
-	default:
-		DP_ERR(edev, "Unsupported filter type %d\n",
-			filter_type);
-		return -EINVAL;
+	if (ECORE_IS_CMT(edev)) {
+		DP_ERR(edev, "flowdir is not supported in 100G mode\n");
+		return -ENOTSUP;
 	}
 
+	*ops = &qede_flow_ops;
 	return 0;
 }
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 479b4f4df6..d72df2e13b 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -1751,32 +1751,11 @@ sfc_dev_rss_reta_update(struct rte_eth_dev *dev,
 }
 
 static int
-sfc_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
-		    enum rte_filter_op filter_op,
-		    void *arg)
+sfc_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		     const struct rte_flow_ops **ops)
 {
-	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-	int rc = ENOTSUP;
-
-	sfc_log_init(sa, "entry");
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET) {
-			rc = EINVAL;
-		} else {
-			*(const void **)arg = &sfc_flow_ops;
-			rc = 0;
-		}
-		break;
-	default:
-		sfc_err(sa, "Unknown filter type %u", filter_type);
-		break;
-	}
-
-	sfc_log_init(sa, "exit: %d", -rc);
-	SFC_ASSERT(rc >= 0);
-	return -rc;
+	*ops = &sfc_flow_ops;
+	return 0;
 }
 
 static int
@@ -1859,7 +1838,7 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
 	.reta_query			= sfc_dev_rss_reta_query,
 	.rss_hash_update		= sfc_dev_rss_hash_update,
 	.rss_hash_conf_get		= sfc_dev_rss_hash_conf_get,
-	.filter_ctrl			= sfc_dev_filter_ctrl,
+	.flow_ops_get			= sfc_dev_flow_ops_get,
 	.set_mc_addr_list		= sfc_set_mc_addr_list,
 	.rxq_info_get			= sfc_rx_queue_info_get,
 	.txq_info_get			= sfc_tx_queue_info_get,
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 99d8468c94..0c2a79a7d2 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -248,18 +248,11 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 }
 
 static int
-pmd_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
-		enum rte_filter_type filter_type,
-		enum rte_filter_op filter_op,
-		void *arg)
+pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		 const struct rte_flow_ops **ops)
 {
-	if (filter_type == RTE_ETH_FILTER_GENERIC &&
-			filter_op == RTE_ETH_FILTER_GET) {
-		*(const void **)arg = &pmd_flow_ops;
-		return 0;
-	}
-
-	return -ENOTSUP;
+	*ops = &pmd_flow_ops;
+	return 0;
 }
 
 static int
@@ -287,7 +280,7 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.filter_ctrl = pmd_filter_ctrl,
+	.flow_ops_get = pmd_flow_ops_get,
 	.tm_ops_get = pmd_tm_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index c36d4bf76e..68baa18523 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -1890,7 +1890,7 @@ static const struct eth_dev_ops ops = {
 	.stats_reset            = tap_stats_reset,
 	.dev_supported_ptypes_get = tap_dev_supported_ptypes_get,
 	.rss_hash_update        = tap_rss_hash_update,
-	.filter_ctrl            = tap_dev_filter_ctrl,
+	.flow_ops_get           = tap_dev_flow_ops_get,
 };
 
 static int
diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c
index 1538349e9c..1ee6fb30ab 100644
--- a/drivers/net/tap/tap_flow.c
+++ b/drivers/net/tap/tap_flow.c
@@ -2160,35 +2160,20 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,
 }
 
 /**
- * Manage filter operations.
+ * Get rte_flow operations.
  *
  * @param dev
  *   Pointer to Ethernet device structure.
- * @param filter_type
- *   Filter type.
- * @param filter_op
- *   Operation to perform.
- * @param arg
+ * @param ops
  *   Pointer to operation-specific structure.
  *
  * @return
  *   0 on success, negative errno value on failure.
  */
 int
-tap_dev_filter_ctrl(struct rte_eth_dev *dev,
-		    enum rte_filter_type filter_type,
-		    enum rte_filter_op filter_op,
-		    void *arg)
+tap_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
+		     const struct rte_flow_ops **ops)
 {
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &tap_flow_ops;
-		return 0;
-	default:
-		TAP_LOG(ERR, "%p: filter type (%d) not supported",
-			dev, filter_type);
-	}
-	return -EINVAL;
+	*ops = &tap_flow_ops;
+	return 0;
 }
diff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h
index ac60a9ae20..240fbc3dfa 100644
--- a/drivers/net/tap/tap_flow.h
+++ b/drivers/net/tap/tap_flow.h
@@ -46,10 +46,8 @@ enum bpf_fd_idx {
 	SEC_MAX,
 };
 
-int tap_dev_filter_ctrl(struct rte_eth_dev *dev,
-			enum rte_filter_type filter_type,
-			enum rte_filter_op filter_op,
-			void *arg);
+int tap_dev_flow_ops_get(struct rte_eth_dev *dev,
+			 const struct rte_flow_ops **ops);
 int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);
 
 int tap_flow_implicit_create(struct pmd_internals *pmd,
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 1ab8d2cded..be45ba9177 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -4078,27 +4078,11 @@ txgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
 }
 
 static int
-txgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,
-		     enum rte_filter_type filter_type,
-		     enum rte_filter_op filter_op,
-		     void *arg)
+txgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,
+		       const struct rte_flow_ops **ops)
 {
-	int ret = 0;
-
-	switch (filter_type) {
-	case RTE_ETH_FILTER_GENERIC:
-		if (filter_op != RTE_ETH_FILTER_GET)
-			return -EINVAL;
-		*(const void **)arg = &txgbe_flow_ops;
-		break;
-	default:
-		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-							filter_type);
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
+	*ops = &txgbe_flow_ops;
+	return 0;
 }
 
 static u8 *
@@ -5208,7 +5192,7 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {
 	.reta_query                 = txgbe_dev_rss_reta_query,
 	.rss_hash_update            = txgbe_dev_rss_hash_update,
 	.rss_hash_conf_get          = txgbe_dev_rss_hash_conf_get,
-	.filter_ctrl                = txgbe_dev_filter_ctrl,
+	.flow_ops_get               = txgbe_dev_flow_ops_get,
 	.set_mc_addr_list           = txgbe_dev_set_mc_addr_list,
 	.rxq_info_get               = txgbe_rxq_info_get,
 	.txq_info_get               = txgbe_txq_info_get,
diff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h
index 57fdedaa1a..d9b1a580d7 100644
--- a/lib/librte_ethdev/ethdev_driver.h
+++ b/lib/librte_ethdev/ethdev_driver.h
@@ -465,34 +465,16 @@ typedef int (*eth_get_module_eeprom_t)(struct rte_eth_dev *dev,
 				       struct rte_dev_eeprom_info *info);
 /**< @internal Retrieve plugin module eeprom data */
 
+struct rte_flow_ops;
 /**
- * Feature filter types
+ * @internal
+ * Get flow operations.
+ *
+ * If the flow API is not supported for the specified device,
+ * the driver can return NULL.
  */
-enum rte_filter_type {
-	RTE_ETH_FILTER_NONE = 0,
-	RTE_ETH_FILTER_ETHERTYPE,
-	RTE_ETH_FILTER_FLEXIBLE,
-	RTE_ETH_FILTER_SYN,
-	RTE_ETH_FILTER_NTUPLE,
-	RTE_ETH_FILTER_TUNNEL,
-	RTE_ETH_FILTER_FDIR,
-	RTE_ETH_FILTER_HASH,
-	RTE_ETH_FILTER_L2_TUNNEL,
-	RTE_ETH_FILTER_GENERIC,
-};
-
-/**
- * Generic operations on filters
- */
-enum rte_filter_op {
-	RTE_ETH_FILTER_GET,      /**< get flow API ops */
-};
-
-typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,
-				 enum rte_filter_type filter_type,
-				 enum rte_filter_op filter_op,
-				 void *arg);
-/**< @internal Take operations to assigned filter type on an Ethernet device */
+typedef int (*eth_flow_ops_get_t)(struct rte_eth_dev *dev,
+				  const struct rte_flow_ops **ops);
 
 typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);
 /**< @internal Get Traffic Management (TM) operations on an Ethernet device */
@@ -880,7 +862,7 @@ struct eth_dev_ops {
 	eth_get_module_eeprom_t    get_module_eeprom;
 	/** Get plugin module eeprom data. */
 
-	eth_filter_ctrl_t          filter_ctrl; /**< common filter control. */
+	eth_flow_ops_get_t         flow_ops_get; /**< Get flow operations. */
 
 	eth_get_dcb_info           get_dcb_info; /** Get DCB information. */
 
@@ -1377,6 +1359,18 @@ rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue,
  * Legacy ethdev API used internally by drivers.
  */
 
+enum rte_filter_type {
+	RTE_ETH_FILTER_NONE = 0,
+	RTE_ETH_FILTER_ETHERTYPE,
+	RTE_ETH_FILTER_FLEXIBLE,
+	RTE_ETH_FILTER_SYN,
+	RTE_ETH_FILTER_NTUPLE,
+	RTE_ETH_FILTER_TUNNEL,
+	RTE_ETH_FILTER_FDIR,
+	RTE_ETH_FILTER_HASH,
+	RTE_ETH_FILTER_L2_TUNNEL,
+};
+
 /**
  * Define all structures for Ethertype Filter type.
  */
diff --git a/lib/librte_ethdev/rte_eth_ctrl.h b/lib/librte_ethdev/rte_eth_ctrl.h
index 8a50dbfef9..42652f9cce 100644
--- a/lib/librte_ethdev/rte_eth_ctrl.h
+++ b/lib/librte_ethdev/rte_eth_ctrl.h
@@ -339,7 +339,7 @@ struct rte_eth_fdir_action {
 };
 
 /**
- * A structure used to define the flow director filter entry by filter_ctrl API.
+ * A structure used to define the flow director filter entry.
  */
 struct rte_eth_fdir_filter {
 	uint32_t soft_id;
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 241af6c4ca..e07e617d74 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -255,18 +255,21 @@ rte_flow_ops_get(uint16_t port_id, struct rte_flow_error *error)
 
 	if (unlikely(!rte_eth_dev_is_valid_port(port_id)))
 		code = ENODEV;
-	else if (unlikely(!dev->dev_ops->filter_ctrl ||
-			  dev->dev_ops->filter_ctrl(dev,
-						    RTE_ETH_FILTER_GENERIC,
-						    RTE_ETH_FILTER_GET,
-						    &ops) ||
-			  !ops))
+	else if (unlikely(dev->dev_ops->flow_ops_get == NULL))
+		/* flow API not supported with this driver dev_ops */
 		code = ENOSYS;
 	else
-		return ops;
-	rte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			   NULL, rte_strerror(code));
-	return NULL;
+		code = dev->dev_ops->flow_ops_get(dev, &ops);
+	if (code == 0 && ops == NULL)
+		/* flow API not supported with this device */
+		code = ENOSYS;
+
+	if (code != 0) {
+		rte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, rte_strerror(code));
+		return NULL;
+	}
+	return ops;
 }
 
 /* Check whether a flow rule can be created on a given port. */
diff --git a/lib/librte_ethdev/rte_flow_driver.h b/lib/librte_ethdev/rte_flow_driver.h
index dabd819d10..da594d9256 100644
--- a/lib/librte_ethdev/rte_flow_driver.h
+++ b/lib/librte_ethdev/rte_flow_driver.h
@@ -28,31 +28,6 @@ extern "C" {
 /**
  * Generic flow operations structure implemented and returned by PMDs.
  *
- * To implement this API, PMDs must handle the RTE_ETH_FILTER_GENERIC filter
- * type in their .filter_ctrl callback function (struct eth_dev_ops) as well
- * as the RTE_ETH_FILTER_GET filter operation.
- *
- * If successful, this operation must result in a pointer to a PMD-specific
- * struct rte_flow_ops written to the argument address as described below:
- *
- * \code
- *
- * // PMD filter_ctrl callback
- *
- * static const struct rte_flow_ops pmd_flow_ops = { ... };
- *
- * switch (filter_type) {
- * case RTE_ETH_FILTER_GENERIC:
- *     if (filter_op != RTE_ETH_FILTER_GET)
- *         return -EINVAL;
- *     *(const void **)arg = &pmd_flow_ops;
- *     return 0;
- * }
- *
- * \endcode
- *
- * See also rte_flow_ops_get().
- *
  * These callback functions are not supposed to be used by applications
  * directly, which must rely on the API defined in rte_flow.h.
  *
-- 
2.30.1


  reply	other threads:[~2021-03-21  9:00 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-11 22:17 [dpdk-dev] [PATCH 0/2] ethdev: remove some use of legacy filtering interface Thomas Monjalon
2021-03-11 22:17 ` [dpdk-dev] [PATCH 1/2] ethdev: replace callback getting filter operations Thomas Monjalon
2021-03-12  1:44   ` Wang, Haiyue
2021-03-12  8:22     ` Thomas Monjalon
2021-03-12  8:25       ` Andrew Rybchenko
2021-03-12  8:40         ` Wang, Haiyue
2021-03-12  7:09   ` Andrew Rybchenko
2021-03-12  8:26     ` Thomas Monjalon
2021-03-11 22:17 ` [dpdk-dev] [PATCH 2/2] drivers/net: remove explicit include of legacy filtering Thomas Monjalon
2021-03-12  1:21   ` Xu, Rosen
2021-03-12 17:46 ` [dpdk-dev] [PATCH v2 0/2] ethdev: remove some use of legacy filtering interface Thomas Monjalon
2021-03-12 17:46   ` [dpdk-dev] [PATCH v2 1/2] ethdev: replace callback getting filter operations Thomas Monjalon
2021-03-12 19:14     ` Ajit Khaparde
2021-03-13  4:16     ` Wang, Haiyue
2021-03-15  3:05     ` Xu, Rosen
2021-03-15  7:18     ` Andrew Rybchenko
2021-03-15  7:54       ` Thomas Monjalon
2021-03-15  8:43         ` Andrew Rybchenko
2021-03-15  8:55           ` Thomas Monjalon
2021-03-15  9:08             ` Andrew Rybchenko
2021-03-15  9:15               ` Thomas Monjalon
2021-03-19 18:12                 ` Thomas Monjalon
2021-03-20  7:54                   ` Andrew Rybchenko
2021-03-20 10:38                     ` Thomas Monjalon
2021-03-15  7:22     ` Hemant Agrawal
2021-03-12 17:46   ` [dpdk-dev] [PATCH v2 2/2] drivers/net: remove explicit include of legacy filtering Thomas Monjalon
2021-03-15  7:19     ` Hemant Agrawal
2021-03-21  8:59 ` [dpdk-dev] [PATCH v3 0/2] ethdev: remove some use " Thomas Monjalon
2021-03-21  9:00   ` Thomas Monjalon [this message]
2021-03-21  9:08     ` [dpdk-dev] [PATCH v3 1/2] ethdev: replace callback getting filter operations Andrew Rybchenko
2021-03-24 18:05     ` Ferruh Yigit
2021-03-26 17:41       ` Ferruh Yigit
2021-03-29 20:56     ` Matan Azrad
2021-03-21  9:00   ` [dpdk-dev] [PATCH v3 2/2] drivers/net: remove explicit include of legacy filtering Thomas Monjalon
2021-03-24 18:08     ` Ferruh Yigit
2021-03-24 20:00       ` Thomas Monjalon
2021-03-25  5:53         ` Andrew Rybchenko
2021-03-25 10:00           ` Ferruh Yigit
2021-03-25 10:20             ` Thomas Monjalon
2021-03-26 15:37               ` Ferruh Yigit
2021-03-26 21:45                 ` Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210321090002.595744-2-thomas@monjalon.net \
    --to=thomas@monjalon.net \
    --cc=ajit.khaparde@broadcom.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=beilei.xing@intel.com \
    --cc=chas3@att.com \
    --cc=cloud.wangxiaoyun@huawei.com \
    --cc=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=grive@u256.net \
    --cc=haiyue.wang@intel.com \
    --cc=hemant.agrawal@nxp.com \
    --cc=humin29@huawei.com \
    --cc=hyonkim@cisco.com \
    --cc=jasvinder.singh@intel.com \
    --cc=jerinj@marvell.com \
    --cc=jia.guo@intel.com \
    --cc=jianwang@trustnetic.com \
    --cc=jiawenwu@trustnetic.com \
    --cc=jingjing.wu@intel.com \
    --cc=johndale@cisco.com \
    --cc=keith.wiles@intel.com \
    --cc=kirankumark@marvell.com \
    --cc=lironh@marvell.com \
    --cc=matan@nvidia.com \
    --cc=ndabilpuram@marvell.com \
    --cc=orika@nvidia.com \
    --cc=oulijun@huawei.com \
    --cc=qi.z.zhang@intel.com \
    --cc=qiming.yang@intel.com \
    --cc=rahul.lakkireddy@chelsio.com \
    --cc=rmody@marvell.com \
    --cc=rosen.xu@intel.com \
    --cc=sachin.saxena@oss.nxp.com \
    --cc=shahafs@nvidia.com \
    --cc=shshaikh@marvell.com \
    --cc=somnath.kotur@broadcom.com \
    --cc=viacheslavo@nvidia.com \
    --cc=xuanziyang2@huawei.com \
    --cc=yisen.zhuang@huawei.com \
    --cc=zhouguoyang@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.