get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 89036,
    "url": "https://patches.dpdk.org/api/patches/89036/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210312174645.162801-2-thomas@monjalon.net/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210312174645.162801-2-thomas@monjalon.net>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210312174645.162801-2-thomas@monjalon.net",
    "date": "2021-03-12T17:46:44",
    "name": "[v2,1/2] ethdev: replace callback getting filter operations",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6f158106c676bc4c9b57d31f92cbe729cba253fa",
    "submitter": {
        "id": 685,
        "url": "https://patches.dpdk.org/api/people/685/?format=api",
        "name": "Thomas Monjalon",
        "email": "thomas@monjalon.net"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210312174645.162801-2-thomas@monjalon.net/mbox/",
    "series": [
        {
            "id": 15635,
            "url": "https://patches.dpdk.org/api/series/15635/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=15635",
            "date": "2021-03-12T17:46:43",
            "name": "ethdev: remove some use of legacy filtering interface",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/15635/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/89036/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/89036/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 5063DA0547;\n\tFri, 12 Mar 2021 18:47:21 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 382931608D3;\n\tFri, 12 Mar 2021 18:47:21 +0100 (CET)",
            "from new4-smtp.messagingengine.com (new4-smtp.messagingengine.com\n [66.111.4.230]) by mails.dpdk.org (Postfix) with ESMTP id 6D4691608C7\n for <dev@dpdk.org>; Fri, 12 Mar 2021 18:47:19 +0100 (CET)",
            "from compute2.internal (compute2.nyi.internal [10.202.2.42])\n by mailnew.nyi.internal (Postfix) with ESMTP id CF2C6580636;\n Fri, 12 Mar 2021 12:47:18 -0500 (EST)",
            "from mailfrontend1 ([10.202.2.162])\n by compute2.internal (MEProxy); Fri, 12 Mar 2021 12:47:18 -0500",
            "from xps.monjalon.net (184.203.134.77.rev.sfr.net [77.134.203.184])\n by mail.messagingengine.com (Postfix) with ESMTPA id 2996D24005E;\n Fri, 12 Mar 2021 12:47:12 -0500 (EST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=monjalon.net; h=\n from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding; s=fm3; bh=S7KDw314FUuek\n SHjUENSnbzva7RQfvCGrjHwV9OfKuc=; b=rUXFqEnua8dCn/SsMWHq45TgtR+e6\n aULIoBSnQC2AcHSVsMaHN2FLHzbNhYNHnrpuEdgJc10pNnaMeCjgbh8dGGoR9WeU\n KMcqddtBd0Fda3lU5tBBoDKqNLeohcQvHRwmX7f4WcsAlsZnHAaNoPzEEbmvxocV\n hyXPM9kMQE1kcRwgRfkZWBVhQRr+sjclFmiqqk6JzbSm5R1nXfW8GWO8DsWldcUq\n erMo5kzLI3I3q/wNuo8DP2KMowHwzQbYNeVIhpAQC8VLVi4ibFT6cl+046wj3tai\n WsjBpUDk/psNnxTlSKsZBRw+ny8ekbOdZ7cxjVwO0HcbhRCoA8zfWf/rA==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=\n messagingengine.com; h=cc:content-transfer-encoding:date:from\n :in-reply-to:message-id:mime-version:references:subject:to\n :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=\n fm2; bh=S7KDw314FUuekSHjUENSnbzva7RQfvCGrjHwV9OfKuc=; b=GFnsXp2K\n tOvUbMzDvTx57G2E5SG6pGGFvq4DhLKarAoR2YZ02hbcQ6zNJRnjrd7UNRd83yDT\n CIsNCbsBYrdRsqMXIuod9x1X08FmM41sQPrfd+RPKFRIrI37NYpXxBW0PdMWZtIk\n 44Krh0ENZQObWy/GJnDowpigcok5t8Mp6fvyxSZc2SfZ5PxS/GhMK5P8On7/SstZ\n jF/z+CxtFRIkXysgpECsy1bxMHR8+JS54b6QSV+cL9/LP99c1wCMUq6a+XVf7PTS\n f3PFdo7CcHOKpoz5SGCc6047OU1oJd+PHs4vbkf8+Zk6NNLz42SUAJm/8Bcj/u7u\n t+cmYDO8eEp3VA=="
        ],
        "X-ME-Sender": "<xms:I6lLYJ_rgzYKkF56aqFPyLYFQTmLv-IDaRp3BiA5bGV9T5na9x2wEQ>\n <xme:I6lLYNtIZhyUsODBdmwHCkW6wPqTPu00JZX722tXIxc_gZCvvIIzeaII6QT5GEfeK\n xIb82o5mBUgHlmljw>",
        "X-ME-Proxy-Cause": "\n gggruggvucftvghtrhhoucdtuddrgeduledruddvvddguddtgecutefuodetggdotefrod\n ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh\n necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd\n enucfjughrpefhvffufffkofgjfhgggfestdekredtredttdenucfhrhhomhepvfhhohhm\n rghsucfoohhnjhgrlhhonhcuoehthhhomhgrshesmhhonhhjrghlohhnrdhnvghtqeenuc\n ggtffrrghtthgvrhhnpeehfeeikeelfeeileejtddvheegjedvveefudefteeljeeftefh\n lefgffdukedtueenucffohhmrghinhepphhmugdrnhgvthenucfkphepjeejrddufeegrd\n dvtdefrddukeegnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhf\n rhhomhepthhhohhmrghssehmohhnjhgrlhhonhdrnhgvth",
        "X-ME-Proxy": "<xmx:JKlLYHAfRgig0-pXSA6smGA9NXohPpeciEqY-jB3MiD9KnNuLov5Hw>\n <xmx:JKlLYNduPea57rUGRLN71EcH_IzXMVx3cmFZvlCBimD7_l5tCSeUjQ>\n <xmx:JKlLYOMfNRYH_Md7RvN-OFWCElZfSW1Md8tbdBGljqTcmGFSEEwmNw>\n <xmx:JqlLYIw0xDfUpr_jQaTLtArX7gmT2u-YJAnCkVQrHGNh1NC-VKqriQ>",
        "From": "Thomas Monjalon <thomas@monjalon.net>",
        "To": "dev@dpdk.org",
        "Cc": "Ori Kam <orika@nvidia.com>,\tAjit Khaparde <ajit.khaparde@broadcom.com>,\n Somnath Kotur <somnath.kotur@broadcom.com>,\n Chas Williams <chas3@att.com>,\t\"Min Hu (Connor)\" <humin29@huawei.com>,\n Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>,\n Hemant Agrawal <hemant.agrawal@nxp.com>,\n Sachin Saxena <sachin.saxena@oss.nxp.com>,\tJeff Guo <jia.guo@intel.com>,\n Haiyue Wang <haiyue.wang@intel.com>,\tJohn Daley <johndale@cisco.com>,\n Hyong Youb Kim <hyonkim@cisco.com>,\tGaetan Rivet <grive@u256.net>,\n Ziyang Xuan <xuanziyang2@huawei.com>,\n Xiaoyun Wang <cloud.wangxiaoyun@huawei.com>,\n Guoyang Zhou <zhouguoyang@huawei.com>,\n Yisen Zhuang <yisen.zhuang@huawei.com>,\tLijun Ou <oulijun@huawei.com>,\n Beilei Xing <beilei.xing@intel.com>,\tJingjing Wu <jingjing.wu@intel.com>,\n Qiming Yang <qiming.yang@intel.com>,\tQi Zhang <qi.z.zhang@intel.com>,\n Rosen Xu <rosen.xu@intel.com>,\tMatan Azrad <matan@nvidia.com>,\n Shahaf Shuler <shahafs@nvidia.com>,\n Viacheslav Ovsiienko <viacheslavo@nvidia.com>,\n Liron Himi <lironh@marvell.com>,\tJerin Jacob <jerinj@marvell.com>,\n Nithin Dabilpuram <ndabilpuram@marvell.com>,\n Kiran Kumar K <kirankumark@marvell.com>,\tRasesh Mody <rmody@marvell.com>,\n Shahed Shaikh <shshaikh@marvell.com>,\n Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,\n Jasvinder Singh <jasvinder.singh@intel.com>,\n Cristian Dumitrescu <cristian.dumitrescu@intel.com>,\n Keith Wiles <keith.wiles@intel.com>,\tJiawen Wu <jiawenwu@trustnetic.com>,\n Jian Wang <jianwang@trustnetic.com>, Ferruh Yigit <ferruh.yigit@intel.com>",
        "Date": "Fri, 12 Mar 2021 18:46:44 +0100",
        "Message-Id": "<20210312174645.162801-2-thomas@monjalon.net>",
        "X-Mailer": "git-send-email 2.30.1",
        "In-Reply-To": "<20210312174645.162801-1-thomas@monjalon.net>",
        "References": "<20210311221742.3750589-1-thomas@monjalon.net>\n <20210312174645.162801-1-thomas@monjalon.net>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v2 1/2] ethdev: replace callback getting filter\n operations",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Since rte_flow is the only API for filtering operations,\nthe legacy driver interface filter_ctrl was too much complicated\nfor the simple task of getting the struct rte_flow_ops.\n\nThe filter type RTE_ETH_FILTER_GENERIC and\nthe filter operarion RTE_ETH_FILTER_GET are removed.\nThe new driver callback flow_ops_get replaces filter_ctrl.\n\nSigned-off-by: Thomas Monjalon <thomas@monjalon.net>\n---\n doc/guides/nics/features.rst            |  4 +--\n doc/guides/prog_guide/rte_flow.rst      | 14 +-------\n drivers/net/bnxt/bnxt.h                 |  6 ++--\n drivers/net/bnxt/bnxt_ethdev.c          | 40 +++++++--------------\n drivers/net/bnxt/bnxt_reps.c            |  2 +-\n drivers/net/bonding/rte_eth_bond_pmd.c  | 13 +++----\n drivers/net/cxgbe/cxgbe_ethdev.c        |  2 +-\n drivers/net/cxgbe/cxgbe_flow.c          | 22 +++---------\n drivers/net/cxgbe/cxgbe_flow.h          |  7 ++--\n drivers/net/dpaa2/dpaa2_ethdev.c        | 44 +++--------------------\n drivers/net/dpaa2/dpaa2_flow.c          | 29 +++++-----------\n drivers/net/e1000/igb_ethdev.c          | 31 ++++-------------\n drivers/net/enic/enic_ethdev.c          | 30 +++++-----------\n drivers/net/enic/enic_vf_representor.c  | 33 ++++++------------\n drivers/net/failsafe/failsafe_ops.c     | 16 +++------\n drivers/net/hinic/hinic_pmd_ethdev.c    | 36 ++++---------------\n drivers/net/hns3/hns3_ethdev.c          |  2 +-\n drivers/net/hns3/hns3_ethdev.h          |  5 ++-\n drivers/net/hns3/hns3_ethdev_vf.c       |  2 +-\n drivers/net/hns3/hns3_flow.c            | 30 ++++------------\n drivers/net/i40e/i40e_ethdev.c          | 32 ++++-------------\n drivers/net/iavf/iavf_ethdev.c          | 32 ++++-------------\n drivers/net/ice/ice_dcf_ethdev.c        | 27 +++------------\n drivers/net/ice/ice_ethdev.c            | 32 ++++-------------\n drivers/net/igc/igc_ethdev.c            |  2 +-\n drivers/net/igc/igc_filter.c            | 23 +++----------\n drivers/net/igc/igc_filter.h            |  5 ++-\n drivers/net/ipn3ke/ipn3ke_representor.c | 28 ++++-----------\n drivers/net/ixgbe/ixgbe_ethdev.c        | 32 ++++-------------\n drivers/net/mlx4/mlx4.c                 |  2 +-\n drivers/net/mlx4/mlx4_flow.c            | 32 ++++-------------\n drivers/net/mlx4/mlx4_flow.h            |  5 +--\n drivers/net/mlx5/mlx5.c                 |  4 +--\n drivers/net/mlx5/mlx5.h                 |  5 +--\n drivers/net/mlx5/mlx5_flow.c            | 32 ++++-------------\n drivers/net/mvpp2/mrvl_ethdev.c         | 26 ++++----------\n drivers/net/octeontx2/otx2_ethdev.c     |  2 +-\n drivers/net/octeontx2/otx2_ethdev.h     |  5 ++-\n drivers/net/octeontx2/otx2_ethdev_ops.c | 21 +++--------\n drivers/net/qede/qede_ethdev.c          |  2 +-\n drivers/net/qede/qede_ethdev.h          |  7 ++--\n drivers/net/qede/qede_filter.c          | 27 ++++-----------\n drivers/net/sfc/sfc_ethdev.c            | 31 +++--------------\n drivers/net/softnic/rte_eth_softnic.c   | 17 +++------\n drivers/net/tap/rte_eth_tap.c           |  2 +-\n drivers/net/tap/tap_flow.c              | 27 ++++-----------\n drivers/net/tap/tap_flow.h              |  6 ++--\n drivers/net/txgbe/txgbe_ethdev.c        | 26 +++-----------\n lib/librte_ethdev/ethdev_driver.h       | 46 +++++++++----------------\n lib/librte_ethdev/rte_eth_ctrl.h        |  2 +-\n lib/librte_ethdev/rte_flow.c            | 23 +++++++------\n lib/librte_ethdev/rte_flow_driver.h     | 25 --------------\n 52 files changed, 233 insertions(+), 723 deletions(-)",
    "diff": "diff --git a/doc/guides/nics/features.rst b/doc/guides/nics/features.rst\nindex dbca9a85b9..f6d30d0af3 100644\n--- a/doc/guides/nics/features.rst\n+++ b/doc/guides/nics/features.rst\n@@ -402,9 +402,9 @@ Supports configuring link flow control.\n Flow API\n --------\n \n-Supports the DPDK Flow API for generic filtering.\n+Supports flow API family.\n \n-* **[implements] eth_dev_ops**: ``filter_ctrl:RTE_ETH_FILTER_GENERIC``.\n+* **[implements] eth_dev_ops**: ``flow_ops_get``.\n * **[implements] rte_flow_ops**: ``All``.\n \n \ndiff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst\nindex 62a57919eb..aec2ba1ec0 100644\n--- a/doc/guides/prog_guide/rte_flow.rst\n+++ b/doc/guides/prog_guide/rte_flow.rst\n@@ -22,11 +22,6 @@ defined in ``rte_flow.h``.\n   queues, to virtual/physical device functions or ports, performing tunnel\n   offloads, adding marks and so on.\n \n-It is slightly higher-level than the legacy filtering framework which it\n-encompasses and supersedes (including all functions and filter types) in\n-order to expose a single interface with an unambiguous behavior that is\n-common to all poll-mode drivers (PMDs).\n-\n Flow rule\n ---------\n \n@@ -3104,7 +3099,6 @@ port and may return errors such as ``ENOTSUP`` (\"not supported\"):\n - Configuring MAC addresses.\n - Configuring multicast addresses.\n - Configuring VLAN filters.\n-- Configuring Rx filters through the legacy API (e.g. FDIR).\n - Configuring global RSS settings.\n \n .. code-block:: c\n@@ -3331,13 +3325,7 @@ The PMD interface is defined in ``rte_flow_driver.h``. It is not subject to\n API/ABI versioning constraints as it is not exposed to applications and may\n evolve independently.\n \n-It is currently implemented on top of the legacy filtering framework through\n-filter type *RTE_ETH_FILTER_GENERIC* that accepts the single operation\n-*RTE_ETH_FILTER_GET* to return PMD-specific *rte_flow* callbacks wrapped\n-inside ``struct rte_flow_ops``.\n-\n-This overhead is temporarily necessary in order to keep compatibility with\n-the legacy filtering framework, which should eventually disappear.\n+The PMD interface is based on callbacks pointed by the ``struct rte_flow_ops``.\n \n - PMD callbacks implement exactly the interface described in `Rules\n   management`_, except for the port ID argument which has already been\ndiff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h\nindex b4370e5acd..a6c02d88aa 100644\n--- a/drivers/net/bnxt/bnxt.h\n+++ b/drivers/net/bnxt/bnxt.h\n@@ -981,9 +981,7 @@ void bnxt_flow_cnt_alarm_cb(void *arg);\n int bnxt_flow_stats_req(struct bnxt *bp);\n int bnxt_flow_stats_cnt(struct bnxt *bp);\n uint32_t bnxt_get_speed_capabilities(struct bnxt *bp);\n+int bnxt_flow_ops_get_op(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_ops **ops);\n \n-int\n-bnxt_filter_ctrl_op(struct rte_eth_dev *dev,\n-\t\t    enum rte_filter_type filter_type,\n-\t\t    enum rte_filter_op filter_op, void *arg);\n #endif\ndiff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c\nindex 9824cdb6d8..87d298804f 100644\n--- a/drivers/net/bnxt/bnxt_ethdev.c\n+++ b/drivers/net/bnxt/bnxt_ethdev.c\n@@ -3086,9 +3086,8 @@ bnxt_tx_descriptor_status_op(void *tx_queue, uint16_t offset)\n }\n \n int\n-bnxt_filter_ctrl_op(struct rte_eth_dev *dev,\n-\t\t    enum rte_filter_type filter_type,\n-\t\t    enum rte_filter_op filter_op, void *arg)\n+bnxt_flow_ops_get_op(struct rte_eth_dev *dev,\n+\t\t     const struct rte_flow_ops **ops)\n {\n \tstruct bnxt *bp = dev->data->dev_private;\n \tint ret = 0;\n@@ -3101,10 +3100,8 @@ bnxt_filter_ctrl_op(struct rte_eth_dev *dev,\n \t\tbp = vfr->parent_dev->data->dev_private;\n \t\t/* parent is deleted while children are still valid */\n \t\tif (!bp) {\n-\t\t\tPMD_DRV_LOG(DEBUG, \"BNXT Port:%d VFR Error %d:%d\\n\",\n-\t\t\t\t    dev->data->port_id,\n-\t\t\t\t    filter_type,\n-\t\t\t\t    filter_op);\n+\t\t\tPMD_DRV_LOG(DEBUG, \"BNXT Port:%d VFR Error\\n\",\n+\t\t\t\t    dev->data->port_id);\n \t\t\treturn -EIO;\n \t\t}\n \t}\n@@ -3113,27 +3110,16 @@ bnxt_filter_ctrl_op(struct rte_eth_dev *dev,\n \tif (ret)\n \t\treturn ret;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n+\t/* PMD supports thread-safe flow operations.  rte_flow API\n+\t * functions can avoid mutex for multi-thread safety.\n+\t */\n+\tdev->data->dev_flags |= RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE;\n \n-\t\t/* PMD supports thread-safe flow operations.  rte_flow API\n-\t\t * functions can avoid mutex for multi-thread safety.\n-\t\t */\n-\t\tdev->data->dev_flags |= RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE;\n+\tif (BNXT_TRUFLOW_EN(bp))\n+\t\t*ops = &bnxt_ulp_rte_flow_ops;\n+\telse\n+\t\t*ops = &bnxt_flow_ops;\n \n-\t\tif (BNXT_TRUFLOW_EN(bp))\n-\t\t\t*(const void **)arg = &bnxt_ulp_rte_flow_ops;\n-\t\telse\n-\t\t\t*(const void **)arg = &bnxt_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\"Filter type (%d) not supported\", filter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n \treturn ret;\n }\n \n@@ -3644,7 +3630,7 @@ static const struct eth_dev_ops bnxt_dev_ops = {\n \t.rx_queue_stop = bnxt_rx_queue_stop,\n \t.tx_queue_start = bnxt_tx_queue_start,\n \t.tx_queue_stop = bnxt_tx_queue_stop,\n-\t.filter_ctrl = bnxt_filter_ctrl_op,\n+\t.flow_ops_get = bnxt_flow_ops_get_op,\n \t.dev_supported_ptypes_get = bnxt_dev_supported_ptypes_get_op,\n \t.get_eeprom_length    = bnxt_get_eeprom_length_op,\n \t.get_eeprom           = bnxt_get_eeprom_op,\ndiff --git a/drivers/net/bnxt/bnxt_reps.c b/drivers/net/bnxt/bnxt_reps.c\nindex d94874578e..b224a7d2c2 100644\n--- a/drivers/net/bnxt/bnxt_reps.c\n+++ b/drivers/net/bnxt/bnxt_reps.c\n@@ -29,7 +29,7 @@ static const struct eth_dev_ops bnxt_rep_dev_ops = {\n \t.dev_stop = bnxt_rep_dev_stop_op,\n \t.stats_get = bnxt_rep_stats_get_op,\n \t.stats_reset = bnxt_rep_stats_reset_op,\n-\t.filter_ctrl = bnxt_filter_ctrl_op\n+\t.flow_ops_get = bnxt_flow_ops_get_op\n };\n \n uint16_t\ndiff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c\nindex 5241c60089..24e3cf3c2e 100644\n--- a/drivers/net/bonding/rte_eth_bond_pmd.c\n+++ b/drivers/net/bonding/rte_eth_bond_pmd.c\n@@ -3108,14 +3108,11 @@ bond_ethdev_mac_address_set(struct rte_eth_dev *dev,\n }\n \n static int\n-bond_filter_ctrl(struct rte_eth_dev *dev __rte_unused,\n-\t\t enum rte_filter_type type, enum rte_filter_op op, void *arg)\n+bond_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t  const struct rte_flow_ops **ops)\n {\n-\tif (type == RTE_ETH_FILTER_GENERIC && op == RTE_ETH_FILTER_GET) {\n-\t\t*(const void **)arg = &bond_flow_ops;\n-\t\treturn 0;\n-\t}\n-\treturn -ENOTSUP;\n+\t*ops = &bond_flow_ops;\n+\treturn 0;\n }\n \n static int\n@@ -3207,7 +3204,7 @@ const struct eth_dev_ops default_dev_ops = {\n \t.mac_addr_set         = bond_ethdev_mac_address_set,\n \t.mac_addr_add         = bond_ethdev_mac_addr_add,\n \t.mac_addr_remove      = bond_ethdev_mac_addr_remove,\n-\t.filter_ctrl          = bond_filter_ctrl\n+\t.flow_ops_get         = bond_flow_ops_get\n };\n \n static int\ndiff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c\nindex bfa57c979d..e8a2de3ef3 100644\n--- a/drivers/net/cxgbe/cxgbe_ethdev.c\n+++ b/drivers/net/cxgbe/cxgbe_ethdev.c\n@@ -1335,7 +1335,7 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {\n \t.rx_queue_start\t\t= cxgbe_dev_rx_queue_start,\n \t.rx_queue_stop\t\t= cxgbe_dev_rx_queue_stop,\n \t.rx_queue_release\t= cxgbe_dev_rx_queue_release,\n-\t.filter_ctrl            = cxgbe_dev_filter_ctrl,\n+\t.flow_ops_get           = cxgbe_dev_flow_ops_get,\n \t.stats_get\t\t= cxgbe_dev_stats_get,\n \t.stats_reset\t\t= cxgbe_dev_stats_reset,\n \t.flow_ctrl_get\t\t= cxgbe_flow_ctrl_get,\ndiff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c\nindex 520a5a5c9a..edcbba9d7c 100644\n--- a/drivers/net/cxgbe/cxgbe_flow.c\n+++ b/drivers/net/cxgbe/cxgbe_flow.c\n@@ -1448,23 +1448,9 @@ static const struct rte_flow_ops cxgbe_flow_ops = {\n };\n \n int\n-cxgbe_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t      enum rte_filter_type filter_type,\n-\t\t      enum rte_filter_op filter_op,\n-\t\t      void *arg)\n+cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t       const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n-\tRTE_SET_USED(dev);\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &cxgbe_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tret = -ENOTSUP;\n-\t\tbreak;\n-\t}\n-\treturn ret;\n+\t*ops = &cxgbe_flow_ops;\n+\treturn 0;\n }\ndiff --git a/drivers/net/cxgbe/cxgbe_flow.h b/drivers/net/cxgbe/cxgbe_flow.h\nindex ec8e47aebe..9cf29550a9 100644\n--- a/drivers/net/cxgbe/cxgbe_flow.h\n+++ b/drivers/net/cxgbe/cxgbe_flow.h\n@@ -35,10 +35,7 @@ struct rte_flow {\n \tstruct rte_eth_dev *dev;\n };\n \n-int\n-cxgbe_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t      enum rte_filter_type filter_type,\n-\t\t      enum rte_filter_op filter_op,\n-\t\t      void *arg);\n+int cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t   const struct rte_flow_ops **ops);\n \n #endif /* _CXGBE_FLOW_H_ */\ndiff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c\nindex 0e7ebf4dc0..9011dcfc12 100644\n--- a/drivers/net/dpaa2/dpaa2_ethdev.c\n+++ b/drivers/net/dpaa2/dpaa2_ethdev.c\n@@ -99,10 +99,6 @@ static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = {\n \t{\"cgr_reject_bytes\", 4, 1},\n };\n \n-static const enum rte_filter_op dpaa2_supported_filter_ops[] = {\n-\tRTE_ETH_FILTER_GET\n-};\n-\n static struct rte_dpaa2_driver rte_dpaa2_pmd;\n static int dpaa2_dev_link_update(struct rte_eth_dev *dev,\n \t\t\t\t int wait_to_complete);\n@@ -2322,45 +2318,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev,\n \treturn ret;\n }\n \n-static inline int\n-dpaa2_dev_verify_filter_ops(enum rte_filter_op filter_op)\n-{\n-\tunsigned int i;\n-\n-\tfor (i = 0; i < RTE_DIM(dpaa2_supported_filter_ops); i++) {\n-\t\tif (dpaa2_supported_filter_ops[i] == filter_op)\n-\t\t\treturn 0;\n-\t}\n-\treturn -ENOTSUP;\n-}\n-\n static int\n-dpaa2_dev_flow_ctrl(struct rte_eth_dev *dev,\n-\t\t    enum rte_filter_type filter_type,\n-\t\t\t\t enum rte_filter_op filter_op,\n-\t\t\t\t void *arg)\n+dpaa2_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n \tif (!dev)\n \t\treturn -ENODEV;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (dpaa2_dev_verify_filter_ops(filter_op) < 0) {\n-\t\t\tret = -ENOTSUP;\n-\t\t\tbreak;\n-\t\t}\n-\t\t*(const void **)arg = &dpaa2_flow_ops;\n-\t\tdpaa2_filter_type |= filter_type;\n-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(ERR, PMD, \"Filter type (%d) not supported\",\n-\t\t\tfilter_type);\n-\t\tret = -ENOTSUP;\n-\t\tbreak;\n-\t}\n-\treturn ret;\n+\t*ops = &dpaa2_flow_ops;\n+\treturn 0;\n }\n \n static void\n@@ -2453,7 +2419,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {\n \t.mac_addr_set         = dpaa2_dev_set_mac_addr,\n \t.rss_hash_update      = dpaa2_dev_rss_hash_update,\n \t.rss_hash_conf_get    = dpaa2_dev_rss_hash_conf_get,\n-\t.filter_ctrl          = dpaa2_dev_flow_ctrl,\n+\t.flow_ops_get         = dpaa2_dev_flow_ops_get,\n \t.rxq_info_get\t      = dpaa2_rxq_info_get,\n \t.txq_info_get\t      = dpaa2_txq_info_get,\n \t.tm_ops_get\t      = dpaa2_tm_ops_get,\ndiff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c\nindex 29f1f2e654..bfe17c350a 100644\n--- a/drivers/net/dpaa2/dpaa2_flow.c\n+++ b/drivers/net/dpaa2/dpaa2_flow.c\n@@ -89,8 +89,6 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = {\n /* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/\n #define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)\n \n-enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;\n-\n #ifndef __cplusplus\n static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {\n \t.dst.addr_bytes = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n@@ -3969,24 +3967,15 @@ struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,\n \tflow->ipaddr_rule.fs_ipdst_offset =\n \t\tIP_ADDRESS_OFFSET_INVALID;\n \n-\tswitch (dpaa2_filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tret = dpaa2_generic_flow_set(flow, dev, attr, pattern,\n-\t\t\t\t\t     actions, error);\n-\t\tif (ret < 0) {\n-\t\t\tif (error->type > RTE_FLOW_ERROR_TYPE_ACTION)\n-\t\t\t\trte_flow_error_set(error, EPERM,\n-\t\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t\tattr, \"unknown\");\n-\t\t\tDPAA2_PMD_ERR(\n-\t\t\t\"Failure to create flow, return code (%d)\", ret);\n-\t\t\tgoto creation_error;\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tDPAA2_PMD_ERR(\"Filter type (%d) not supported\",\n-\t\tdpaa2_filter_type);\n-\t\tbreak;\n+\tret = dpaa2_generic_flow_set(flow, dev, attr, pattern,\n+\t\t\tactions, error);\n+\tif (ret < 0) {\n+\t\tif (error->type > RTE_FLOW_ERROR_TYPE_ACTION)\n+\t\t\trte_flow_error_set(error, EPERM,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\tattr, \"unknown\");\n+\t\tDPAA2_PMD_ERR(\"Failure to create flow, return code (%d)\", ret);\n+\t\tgoto creation_error;\n \t}\n \n \treturn flow;\ndiff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c\nindex 395dc3f5aa..7c0451ebe2 100644\n--- a/drivers/net/e1000/igb_ethdev.c\n+++ b/drivers/net/e1000/igb_ethdev.c\n@@ -194,10 +194,8 @@ static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev,\n \t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev,\n \t\t\tstruct rte_eth_ntuple_filter *ntuple_filter);\n-static int eth_igb_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg);\n+static int eth_igb_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t\tconst struct rte_flow_ops **ops);\n static int eth_igb_get_reg_length(struct rte_eth_dev *dev);\n static int eth_igb_get_regs(struct rte_eth_dev *dev,\n \t\tstruct rte_dev_reg_info *regs);\n@@ -374,7 +372,7 @@ static const struct eth_dev_ops eth_igb_ops = {\n \t.reta_query           = eth_igb_rss_reta_query,\n \t.rss_hash_update      = eth_igb_rss_hash_update,\n \t.rss_hash_conf_get    = eth_igb_rss_hash_conf_get,\n-\t.filter_ctrl          = eth_igb_filter_ctrl,\n+\t.flow_ops_get         = eth_igb_flow_ops_get,\n \t.set_mc_addr_list     = eth_igb_set_mc_addr_list,\n \t.rxq_info_get         = igb_rxq_info_get,\n \t.txq_info_get         = igb_txq_info_get,\n@@ -4579,26 +4577,11 @@ igb_add_del_ethertype_filter(struct rte_eth_dev *dev,\n }\n \n static int\n-eth_igb_filter_ctrl(struct rte_eth_dev *dev __rte_unused,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+eth_igb_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t     const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &igb_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\t\t\tfilter_type);\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &igb_flow_ops;\n+\treturn 0;\n }\n \n static int\ndiff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c\nindex b3f441c8f7..38da5e8ce4 100644\n--- a/drivers/net/enic/enic_ethdev.c\n+++ b/drivers/net/enic/enic_ethdev.c\n@@ -74,13 +74,10 @@ static const struct vic_speed_capa {\n RTE_LOG_REGISTER(enic_pmd_logtype, pmd.net.enic, INFO);\n \n static int\n-enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+enicpmd_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_ops **ops)\n {\n \tstruct enic *enic = pmd_priv(dev);\n-\tint ret = 0;\n \n \tENICPMD_FUNC_TRACE();\n \n@@ -90,23 +87,12 @@ enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,\n \t */\n \tif (enic->geneve_opt_enabled)\n \t\treturn -ENOTSUP;\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\tif (enic->flow_filter_mode == FILTER_FLOWMAN)\n-\t\t\t*(const void **)arg = &enic_fm_flow_ops;\n-\t\telse\n-\t\t\t*(const void **)arg = &enic_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tdev_warning(enic, \"Filter type (%d) not supported\",\n-\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n \n-\treturn ret;\n+\tif (enic->flow_filter_mode == FILTER_FLOWMAN)\n+\t\t*ops = &enic_fm_flow_ops;\n+\telse\n+\t\t*ops = &enic_flow_ops;\n+\treturn 0;\n }\n \n static void enicpmd_dev_tx_queue_release(void *txq)\n@@ -1121,7 +1107,7 @@ static const struct eth_dev_ops enicpmd_eth_dev_ops = {\n \t.mac_addr_remove      = enicpmd_remove_mac_addr,\n \t.mac_addr_set         = enicpmd_set_mac_addr,\n \t.set_mc_addr_list     = enicpmd_set_mc_addr_list,\n-\t.filter_ctrl          = enicpmd_dev_filter_ctrl,\n+\t.flow_ops_get         = enicpmd_dev_flow_ops_get,\n \t.reta_query           = enicpmd_dev_rss_reta_query,\n \t.reta_update          = enicpmd_dev_rss_reta_update,\n \t.rss_hash_conf_get    = enicpmd_dev_rss_hash_conf_get,\ndiff --git a/drivers/net/enic/enic_vf_representor.c b/drivers/net/enic/enic_vf_representor.c\nindex f7b79c1c4e..79dd6e5640 100644\n--- a/drivers/net/enic/enic_vf_representor.c\n+++ b/drivers/net/enic/enic_vf_representor.c\n@@ -377,34 +377,21 @@ static const struct rte_flow_ops enic_vf_flow_ops = {\n };\n \n static int\n-enic_vf_filter_ctrl(struct rte_eth_dev *eth_dev,\n-\t\t    enum rte_filter_type filter_type,\n-\t\t    enum rte_filter_op filter_op,\n-\t\t    void *arg)\n+enic_vf_flow_ops_get(struct rte_eth_dev *eth_dev,\n+\t\t     const struct rte_flow_ops **ops)\n {\n \tstruct enic_vf_representor *vf;\n-\tint ret = 0;\n \n \tENICPMD_FUNC_TRACE();\n \tvf = eth_dev->data->dev_private;\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\tif (vf->enic.flow_filter_mode == FILTER_FLOWMAN) {\n-\t\t\t*(const void **)arg = &enic_vf_flow_ops;\n-\t\t} else {\n-\t\t\tENICPMD_LOG(WARNING, \"VF representors require flowman support for rte_flow API\");\n-\t\t\tret = -EINVAL;\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tENICPMD_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t    filter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n+\tif (vf->enic.flow_filter_mode != FILTER_FLOWMAN) {\n+\t\tENICPMD_LOG(WARNING,\n+\t\t\t\t\"VF representors require flowman support for rte_flow API\");\n+\t\treturn -EINVAL;\n \t}\n-\treturn ret;\n+\n+\t*ops = &enic_vf_flow_ops;\n+\treturn 0;\n }\n \n static int enic_vf_link_update(struct rte_eth_dev *eth_dev,\n@@ -566,7 +553,7 @@ static const struct eth_dev_ops enic_vf_representor_dev_ops = {\n \t.dev_start            = enic_vf_dev_start,\n \t.dev_stop             = enic_vf_dev_stop,\n \t.dev_close            = enic_vf_dev_close,\n-\t.filter_ctrl          = enic_vf_filter_ctrl,\n+\t.flow_ops_get         = enic_vf_flow_ops_get,\n \t.link_update          = enic_vf_link_update,\n \t.promiscuous_enable   = enic_vf_promiscuous_enable,\n \t.promiscuous_disable  = enic_vf_promiscuous_disable,\ndiff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c\nindex 1343777d61..5ff33e03e0 100644\n--- a/drivers/net/failsafe/failsafe_ops.c\n+++ b/drivers/net/failsafe/failsafe_ops.c\n@@ -1514,17 +1514,11 @@ fs_rss_hash_update(struct rte_eth_dev *dev,\n }\n \n static int\n-fs_filter_ctrl(struct rte_eth_dev *dev __rte_unused,\n-\t\tenum rte_filter_type type,\n-\t\tenum rte_filter_op op,\n-\t\tvoid *arg)\n+fs_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\tconst struct rte_flow_ops **ops)\n {\n-\tif (type == RTE_ETH_FILTER_GENERIC &&\n-\t    op == RTE_ETH_FILTER_GET) {\n-\t\t*(const void **)arg = &fs_flow_ops;\n-\t\treturn 0;\n-\t}\n-\treturn -ENOTSUP;\n+\t*ops = &fs_flow_ops;\n+\treturn 0;\n }\n \n const struct eth_dev_ops failsafe_ops = {\n@@ -1565,5 +1559,5 @@ const struct eth_dev_ops failsafe_ops = {\n \t.mac_addr_set = fs_mac_addr_set,\n \t.set_mc_addr_list = fs_set_mc_addr_list,\n \t.rss_hash_update = fs_rss_hash_update,\n-\t.filter_ctrl = fs_filter_ctrl,\n+\t.flow_ops_get = fs_flow_ops_get,\n };\ndiff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c\nindex 1d6b710c9f..2352dd1615 100644\n--- a/drivers/net/hinic/hinic_pmd_ethdev.c\n+++ b/drivers/net/hinic/hinic_pmd_ethdev.c\n@@ -2504,42 +2504,20 @@ static int hinic_set_mc_addr_list(struct rte_eth_dev *dev,\n }\n \n /**\n- * DPDK callback to manage filter control operations\n+ * DPDK callback to get flow operations\n  *\n  * @param dev\n  *   Pointer to Ethernet device structure.\n- * @param filter_type\n- *   Filter type, which just supports generic type.\n- * @param filter_op\n- *   Filter operation to perform.\n- * @param arg\n+ * @param ops\n  *   Pointer to operation-specific structure.\n  *\n  * @return\n  *   0 on success, negative error value otherwise.\n  */\n-static int hinic_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t\t\t  const struct rte_flow_ops **ops)\n {\n-\tstruct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);\n-\tint func_id = hinic_global_func_id(nic_dev->hwdev);\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &hinic_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(INFO, \"Filter type (%d) not supported\",\n-\t\t\tfilter_type);\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tPMD_DRV_LOG(INFO, \"Set filter_ctrl succeed, func_id: 0x%x, filter_type: 0x%x,\"\n-\t\t\t\"filter_op: 0x%x.\", func_id, filter_type, filter_op);\n+\t*ops = &hinic_flow_ops;\n \treturn 0;\n }\n \n@@ -3047,7 +3025,7 @@ static const struct eth_dev_ops hinic_pmd_ops = {\n \t.mac_addr_remove               = hinic_mac_addr_remove,\n \t.mac_addr_add                  = hinic_mac_addr_add,\n \t.set_mc_addr_list              = hinic_set_mc_addr_list,\n-\t.filter_ctrl                   = hinic_dev_filter_ctrl,\n+\t.flow_ops_get                  = hinic_dev_flow_ops_get,\n };\n \n static const struct eth_dev_ops hinic_pmd_vf_ops = {\n@@ -3082,7 +3060,7 @@ static const struct eth_dev_ops hinic_pmd_vf_ops = {\n \t.mac_addr_remove               = hinic_mac_addr_remove,\n \t.mac_addr_add                  = hinic_mac_addr_add,\n \t.set_mc_addr_list              = hinic_set_mc_addr_list,\n-\t.filter_ctrl                   = hinic_dev_filter_ctrl,\n+\t.flow_ops_get                  = hinic_dev_flow_ops_get,\n };\n \n static int hinic_func_init(struct rte_eth_dev *eth_dev)\ndiff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c\nindex 9cbcc13de8..f6d47369b2 100644\n--- a/drivers/net/hns3/hns3_ethdev.c\n+++ b/drivers/net/hns3/hns3_ethdev.c\n@@ -6550,7 +6550,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {\n \t.rss_hash_conf_get      = hns3_dev_rss_hash_conf_get,\n \t.reta_update            = hns3_dev_rss_reta_update,\n \t.reta_query             = hns3_dev_rss_reta_query,\n-\t.filter_ctrl            = hns3_dev_filter_ctrl,\n+\t.flow_ops_get           = hns3_dev_flow_ops_get,\n \t.vlan_filter_set        = hns3_vlan_filter_set,\n \t.vlan_tpid_set          = hns3_vlan_tpid_set,\n \t.vlan_offload_set       = hns3_vlan_offload_set,\ndiff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h\nindex 932600d05b..d180dc1e7f 100644\n--- a/drivers/net/hns3/hns3_ethdev.h\n+++ b/drivers/net/hns3/hns3_ethdev.h\n@@ -963,9 +963,8 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)\n }\n \n int hns3_buffer_alloc(struct hns3_hw *hw);\n-int hns3_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\t enum rte_filter_type filter_type,\n-\t\t\t enum rte_filter_op filter_op, void *arg);\n+int hns3_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t  const struct rte_flow_ops **ops);\n bool hns3_is_reset_pending(struct hns3_adapter *hns);\n bool hns3vf_is_reset_pending(struct hns3_adapter *hns);\n void hns3_update_link_status_and_event(struct hns3_hw *hw);\ndiff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c\nindex fd20c522dc..a35e1d9aad 100644\n--- a/drivers/net/hns3/hns3_ethdev_vf.c\n+++ b/drivers/net/hns3/hns3_ethdev_vf.c\n@@ -2769,7 +2769,7 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {\n \t.rss_hash_conf_get  = hns3_dev_rss_hash_conf_get,\n \t.reta_update        = hns3_dev_rss_reta_update,\n \t.reta_query         = hns3_dev_rss_reta_query,\n-\t.filter_ctrl        = hns3_dev_filter_ctrl,\n+\t.flow_ops_get       = hns3_dev_flow_ops_get,\n \t.vlan_filter_set    = hns3vf_vlan_filter_set,\n \t.vlan_offload_set   = hns3vf_vlan_offload_set,\n \t.get_reg            = hns3_get_regs,\ndiff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c\nindex a016857aa5..0c4e91109c 100644\n--- a/drivers/net/hns3/hns3_flow.c\n+++ b/drivers/net/hns3/hns3_flow.c\n@@ -2001,34 +2001,16 @@ static const struct rte_flow_ops hns3_flow_ops = {\n \t.isolate = NULL,\n };\n \n-/*\n- * The entry of flow API.\n- * @param dev\n- *   Pointer to Ethernet device.\n- * @return\n- *   0 on success, a negative errno value otherwise is set.\n- */\n int\n-hns3_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op, void *arg)\n+hns3_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_ops **ops)\n {\n \tstruct hns3_hw *hw;\n-\tint ret = 0;\n \n \thw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\tif (hw->adapter_state >= HNS3_NIC_CLOSED)\n-\t\t\treturn -ENODEV;\n-\t\t*(const void **)arg = &hns3_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\thns3_err(hw, \"Filter type (%d) not supported\", filter_type);\n-\t\tret = -EOPNOTSUPP;\n-\t\tbreak;\n-\t}\n+\tif (hw->adapter_state >= HNS3_NIC_CLOSED)\n+\t\treturn -ENODEV;\n \n-\treturn ret;\n+\t*ops = &hns3_flow_ops;\n+\treturn 0;\n }\ndiff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c\nindex d7cd049891..e8634755f2 100644\n--- a/drivers/net/i40e/i40e_ethdev.c\n+++ b/drivers/net/i40e/i40e_ethdev.c\n@@ -319,10 +319,8 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,\n static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,\n \t\t\t\t\tstruct rte_eth_udp_tunnel *udp_tunnel);\n static void i40e_filter_input_set_init(struct i40e_pf *pf);\n-static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\t\tenum rte_filter_type filter_type,\n-\t\t\t\tenum rte_filter_op filter_op,\n-\t\t\t\tvoid *arg);\n+static int i40e_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t\t const struct rte_flow_ops **ops);\n static int i40e_dev_get_dcb_info(struct rte_eth_dev *dev,\n \t\t\t\t  struct rte_eth_dcb_info *dcb_info);\n static int i40e_dev_sync_phy_type(struct i40e_hw *hw);\n@@ -484,7 +482,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {\n \t.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,\n \t.udp_tunnel_port_add          = i40e_dev_udp_tunnel_port_add,\n \t.udp_tunnel_port_del          = i40e_dev_udp_tunnel_port_del,\n-\t.filter_ctrl                  = i40e_dev_filter_ctrl,\n+\t.flow_ops_get                 = i40e_dev_flow_ops_get,\n \t.rxq_info_get                 = i40e_rxq_info_get,\n \t.txq_info_get                 = i40e_txq_info_get,\n \t.rx_burst_mode_get            = i40e_rx_burst_mode_get,\n@@ -9785,30 +9783,14 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,\n }\n \n static int\n-i40e_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+i40e_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n \tif (dev == NULL)\n \t\treturn -EINVAL;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &i40e_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &i40e_flow_ops;\n+\treturn 0;\n }\n \n /*\ndiff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c\nindex 4d37722022..e3933cde26 100644\n--- a/drivers/net/iavf/iavf_ethdev.c\n+++ b/drivers/net/iavf/iavf_ethdev.c\n@@ -117,10 +117,8 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,\n \t\t\t\t\tuint16_t queue_id);\n static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,\n \t\t\t\t\t uint16_t queue_id);\n-static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg);\n+static int iavf_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t\t const struct rte_flow_ops **ops);\n static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,\n \t\t\tstruct rte_ether_addr *mc_addrs,\n \t\t\tuint32_t mc_addrs_num);\n@@ -195,7 +193,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {\n \t.mtu_set                    = iavf_dev_mtu_set,\n \t.rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,\n \t.rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,\n-\t.filter_ctrl                = iavf_dev_filter_ctrl,\n+\t.flow_ops_get               = iavf_dev_flow_ops_get,\n \t.tx_done_cleanup\t    = iavf_dev_tx_done_cleanup,\n };\n \n@@ -2070,30 +2068,14 @@ iavf_dev_interrupt_handler(void *param)\n }\n \n static int\n-iavf_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+iavf_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n \tif (!dev)\n \t\treturn -EINVAL;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &iavf_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t    filter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &iavf_flow_ops;\n+\treturn 0;\n }\n \n static void\ndiff --git a/drivers/net/ice/ice_dcf_ethdev.c b/drivers/net/ice/ice_dcf_ethdev.c\nindex e0772295e9..86600959f8 100644\n--- a/drivers/net/ice/ice_dcf_ethdev.c\n+++ b/drivers/net/ice/ice_dcf_ethdev.c\n@@ -743,31 +743,14 @@ ice_dcf_dev_allmulticast_disable(__rte_unused struct rte_eth_dev *dev)\n }\n \n static int\n-ice_dcf_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\tenum rte_filter_type filter_type,\n-\t\t\tenum rte_filter_op filter_op,\n-\t\t\tvoid *arg)\n+ice_dcf_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n \tif (!dev)\n \t\treturn -EINVAL;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &ice_flow_ops;\n-\t\tbreak;\n-\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t    filter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &ice_flow_ops;\n+\treturn 0;\n }\n \n #define ICE_DCF_32_BIT_WIDTH (CHAR_BIT * 4)\n@@ -984,7 +967,7 @@ static const struct eth_dev_ops ice_dcf_eth_dev_ops = {\n \t.promiscuous_disable     = ice_dcf_dev_promiscuous_disable,\n \t.allmulticast_enable     = ice_dcf_dev_allmulticast_enable,\n \t.allmulticast_disable    = ice_dcf_dev_allmulticast_disable,\n-\t.filter_ctrl             = ice_dcf_dev_filter_ctrl,\n+\t.flow_ops_get            = ice_dcf_dev_flow_ops_get,\n \t.udp_tunnel_port_add\t = ice_dcf_dev_udp_tunnel_port_add,\n \t.udp_tunnel_port_del\t = ice_dcf_dev_udp_tunnel_port_del,\n };\ndiff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c\nindex dfd99ace94..f49fad4aba 100644\n--- a/drivers/net/ice/ice_ethdev.c\n+++ b/drivers/net/ice/ice_ethdev.c\n@@ -129,10 +129,8 @@ static int ice_xstats_get(struct rte_eth_dev *dev,\n static int ice_xstats_get_names(struct rte_eth_dev *dev,\n \t\t\t\tstruct rte_eth_xstat_name *xstats_names,\n \t\t\t\tunsigned int limit);\n-static int ice_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\tenum rte_filter_type filter_type,\n-\t\t\tenum rte_filter_op filter_op,\n-\t\t\tvoid *arg);\n+static int ice_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t\tconst struct rte_flow_ops **ops);\n static int ice_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,\n \t\t\tstruct rte_eth_udp_tunnel *udp_tunnel);\n static int ice_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,\n@@ -215,7 +213,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {\n \t.xstats_get                   = ice_xstats_get,\n \t.xstats_get_names             = ice_xstats_get_names,\n \t.xstats_reset                 = ice_stats_reset,\n-\t.filter_ctrl                  = ice_dev_filter_ctrl,\n+\t.flow_ops_get                 = ice_dev_flow_ops_get,\n \t.udp_tunnel_port_add          = ice_dev_udp_tunnel_port_add,\n \t.udp_tunnel_port_del          = ice_dev_udp_tunnel_port_del,\n \t.tx_done_cleanup              = ice_tx_done_cleanup,\n@@ -5259,30 +5257,14 @@ static int ice_xstats_get_names(__rte_unused struct rte_eth_dev *dev,\n }\n \n static int\n-ice_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+ice_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t     const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n \tif (!dev)\n \t\treturn -EINVAL;\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &ice_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &ice_flow_ops;\n+\treturn 0;\n }\n \n /* Add UDP tunneling port */\ndiff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c\nindex dbaa7a83e5..25abd4ddc3 100644\n--- a/drivers/net/igc/igc_ethdev.c\n+++ b/drivers/net/igc/igc_ethdev.c\n@@ -297,7 +297,7 @@ static const struct eth_dev_ops eth_igc_ops = {\n \t.vlan_offload_set\t= eth_igc_vlan_offload_set,\n \t.vlan_tpid_set\t\t= eth_igc_vlan_tpid_set,\n \t.vlan_strip_queue_set\t= eth_igc_vlan_strip_queue_set,\n-\t.filter_ctrl\t\t= eth_igc_filter_ctrl,\n+\t.flow_ops_get\t\t= eth_igc_flow_ops_get,\n };\n \n /*\ndiff --git a/drivers/net/igc/igc_filter.c b/drivers/net/igc/igc_filter.c\nindex 836621d4c1..51fcabfb59 100644\n--- a/drivers/net/igc/igc_filter.c\n+++ b/drivers/net/igc/igc_filter.c\n@@ -369,24 +369,9 @@ igc_clear_all_filter(struct rte_eth_dev *dev)\n }\n \n int\n-eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,\n-\t\tenum rte_filter_op filter_op, void *arg)\n+eth_igc_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t     const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n-\tRTE_SET_USED(dev);\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &igc_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &igc_flow_ops;\n+\treturn 0;\n }\ndiff --git a/drivers/net/igc/igc_filter.h b/drivers/net/igc/igc_filter.h\nindex df8516bc40..781d270def 100644\n--- a/drivers/net/igc/igc_filter.h\n+++ b/drivers/net/igc/igc_filter.h\n@@ -29,9 +29,8 @@ int igc_set_syn_filter(struct rte_eth_dev *dev,\n \t\tconst struct igc_syn_filter *filter);\n void igc_clear_syn_filter(struct rte_eth_dev *dev);\n void igc_clear_all_filter(struct rte_eth_dev *dev);\n-int\n-eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,\n-\t\tenum rte_filter_op filter_op, void *arg);\n+int eth_igc_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_ops **ops);\n \n #ifdef __cplusplus\n }\ndiff --git a/drivers/net/ipn3ke/ipn3ke_representor.c b/drivers/net/ipn3ke/ipn3ke_representor.c\nindex 856d21ef9b..589d9fa587 100644\n--- a/drivers/net/ipn3ke/ipn3ke_representor.c\n+++ b/drivers/net/ipn3ke/ipn3ke_representor.c\n@@ -2821,11 +2821,9 @@ ipn3ke_rpst_mtu_set(struct rte_eth_dev *ethdev, uint16_t mtu)\n }\n \n static int\n-ipn3ke_afu_filter_ctrl(struct rte_eth_dev *ethdev,\n-\tenum rte_filter_type filter_type, enum rte_filter_op filter_op,\n-\tvoid *arg)\n+ipn3ke_afu_flow_ops_get(struct rte_eth_dev *ethdev,\n+\t\t\tconst struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n \tstruct ipn3ke_hw *hw;\n \tstruct ipn3ke_rpst *rpst;\n \n@@ -2836,27 +2834,13 @@ ipn3ke_afu_filter_ctrl(struct rte_eth_dev *ethdev,\n \trpst = IPN3KE_DEV_PRIVATE_TO_RPST(ethdev);\n \n \tif (hw->acc_flow)\n-\t\tswitch (filter_type) {\n-\t\tcase RTE_ETH_FILTER_GENERIC:\n-\t\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\t\treturn -EINVAL;\n-\t\t\t*(const void **)arg = &ipn3ke_flow_ops;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tIPN3KE_AFU_PMD_WARN(\"Filter type (%d) not supported\",\n-\t\t\t\t\tfilter_type);\n-\t\t\tret = -EINVAL;\n-\t\t\tbreak;\n-\t\t}\n+\t\t*ops = &ipn3ke_flow_ops;\n \telse if (rpst->i40e_pf_eth)\n-\t\t(*rpst->i40e_pf_eth->dev_ops->filter_ctrl)(ethdev,\n-\t\t\t\t\t\t\tfilter_type,\n-\t\t\t\t\t\t\tfilter_op,\n-\t\t\t\t\t\t\targ);\n+\t\t(*rpst->i40e_pf_eth->dev_ops->flow_ops_get)(ethdev, ops);\n \telse\n \t\treturn -EINVAL;\n \n-\treturn ret;\n+\treturn 0;\n }\n \n static const struct eth_dev_ops ipn3ke_rpst_dev_ops = {\n@@ -2874,7 +2858,7 @@ static const struct eth_dev_ops ipn3ke_rpst_dev_ops = {\n \t.stats_reset          = ipn3ke_rpst_stats_reset,\n \t.xstats_reset         = ipn3ke_rpst_stats_reset,\n \n-\t.filter_ctrl          = ipn3ke_afu_filter_ctrl,\n+\t.flow_ops_get         = ipn3ke_afu_flow_ops_get,\n \n \t.rx_queue_start       = ipn3ke_rpst_rx_queue_start,\n \t.rx_queue_stop        = ipn3ke_rpst_rx_queue_stop,\ndiff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c\nindex 761a0f26bb..d5581a243a 100644\n--- a/drivers/net/ixgbe/ixgbe_ethdev.c\n+++ b/drivers/net/ixgbe/ixgbe_ethdev.c\n@@ -304,10 +304,8 @@ static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev,\n \t\t\tstruct ixgbe_5tuple_filter *filter);\n static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev,\n \t\t\tstruct ixgbe_5tuple_filter *filter);\n-static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg);\n+static int ixgbe_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t\t  const struct rte_flow_ops **ops);\n static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu);\n \n static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,\n@@ -538,7 +536,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {\n \t.reta_query           = ixgbe_dev_rss_reta_query,\n \t.rss_hash_update      = ixgbe_dev_rss_hash_update,\n \t.rss_hash_conf_get    = ixgbe_dev_rss_hash_conf_get,\n-\t.filter_ctrl          = ixgbe_dev_filter_ctrl,\n+\t.flow_ops_get         = ixgbe_dev_flow_ops_get,\n \t.set_mc_addr_list     = ixgbe_dev_set_mc_addr_list,\n \t.rxq_info_get         = ixgbe_rxq_info_get,\n \t.txq_info_get         = ixgbe_txq_info_get,\n@@ -6798,27 +6796,11 @@ ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,\n }\n \n static int\n-ixgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+ixgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &ixgbe_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &ixgbe_flow_ops;\n+\treturn 0;\n }\n \n static u8 *\ndiff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c\nindex 041c1934f5..d048d21033 100644\n--- a/drivers/net/mlx4/mlx4.c\n+++ b/drivers/net/mlx4/mlx4.c\n@@ -437,7 +437,7 @@ static const struct eth_dev_ops mlx4_dev_ops = {\n \t.flow_ctrl_get = mlx4_flow_ctrl_get,\n \t.flow_ctrl_set = mlx4_flow_ctrl_set,\n \t.mtu_set = mlx4_mtu_set,\n-\t.filter_ctrl = mlx4_filter_ctrl,\n+\t.flow_ops_get = mlx4_flow_ops_get,\n \t.rx_queue_intr_enable = mlx4_rx_intr_enable,\n \t.rx_queue_intr_disable = mlx4_rx_intr_disable,\n \t.is_removed = mlx4_is_removed,\ndiff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c\nindex b8ecfa829b..43a65abcc0 100644\n--- a/drivers/net/mlx4/mlx4_flow.c\n+++ b/drivers/net/mlx4/mlx4_flow.c\n@@ -1590,37 +1590,19 @@ static const struct rte_flow_ops mlx4_flow_ops = {\n };\n \n /**\n- * Manage filter operations.\n+ * Get rte_flow callbacks.\n  *\n  * @param dev\n  *   Pointer to Ethernet device structure.\n- * @param filter_type\n- *   Filter type.\n- * @param filter_op\n- *   Operation to perform.\n- * @param arg\n+ * @param ops\n  *   Pointer to operation-specific structure.\n  *\n- * @return\n- *   0 on success, negative errno value otherwise and rte_errno is set.\n+ * @return 0\n  */\n int\n-mlx4_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t enum rte_filter_type filter_type,\n-\t\t enum rte_filter_op filter_op,\n-\t\t void *arg)\n+mlx4_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t  const struct rte_flow_ops **ops)\n {\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\tbreak;\n-\t\t*(const void **)arg = &mlx4_flow_ops;\n-\t\treturn 0;\n-\tdefault:\n-\t\tERROR(\"%p: filter type (%d) not supported\",\n-\t\t      (void *)dev, filter_type);\n-\t\tbreak;\n-\t}\n-\trte_errno = ENOTSUP;\n-\treturn -rte_errno;\n+\t*ops = &mlx4_flow_ops;\n+\treturn 0;\n }\ndiff --git a/drivers/net/mlx4/mlx4_flow.h b/drivers/net/mlx4/mlx4_flow.h\nindex e4366f28bb..5e82df6bd6 100644\n--- a/drivers/net/mlx4/mlx4_flow.h\n+++ b/drivers/net/mlx4/mlx4_flow.h\n@@ -51,9 +51,6 @@ uint64_t mlx4_conv_rss_types(struct mlx4_priv *priv, uint64_t types,\n \t\t\t     int verbs_to_dpdk);\n int mlx4_flow_sync(struct mlx4_priv *priv, struct rte_flow_error *error);\n void mlx4_flow_clean(struct mlx4_priv *priv);\n-int mlx4_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg);\n+int mlx4_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);\n \n #endif /* RTE_PMD_MLX4_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex abd7ff70df..d9372f0a00 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -1477,7 +1477,7 @@ const struct eth_dev_ops mlx5_dev_ops = {\n \t.reta_query = mlx5_dev_rss_reta_query,\n \t.rss_hash_update = mlx5_rss_hash_update,\n \t.rss_hash_conf_get = mlx5_rss_hash_conf_get,\n-\t.filter_ctrl = mlx5_dev_filter_ctrl,\n+\t.flow_ops_get = mlx5_flow_ops_get,\n \t.rxq_info_get = mlx5_rxq_info_get,\n \t.txq_info_get = mlx5_txq_info_get,\n \t.rx_burst_mode_get = mlx5_rx_burst_mode_get,\n@@ -1562,7 +1562,7 @@ const struct eth_dev_ops mlx5_dev_ops_isolate = {\n \t.mtu_set = mlx5_dev_set_mtu,\n \t.vlan_strip_queue_set = mlx5_vlan_strip_queue_set,\n \t.vlan_offload_set = mlx5_vlan_offload_set,\n-\t.filter_ctrl = mlx5_dev_filter_ctrl,\n+\t.flow_ops_get = mlx5_flow_ops_get,\n \t.rxq_info_get = mlx5_rxq_info_get,\n \t.txq_info_get = mlx5_txq_info_get,\n \t.rx_burst_mode_get = mlx5_rx_burst_mode_get,\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex a281fd20ea..24aff0beab 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -1192,10 +1192,7 @@ int mlx5_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,\n \t\t    struct rte_flow_error *error);\n int mlx5_flow_isolate(struct rte_eth_dev *dev, int enable,\n \t\t      struct rte_flow_error *error);\n-int mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\t enum rte_filter_type filter_type,\n-\t\t\t enum rte_filter_op filter_op,\n-\t\t\t void *arg);\n+int mlx5_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops);\n int mlx5_flow_start_default(struct rte_eth_dev *dev);\n void mlx5_flow_stop_default(struct rte_eth_dev *dev);\n int mlx5_flow_verify(struct rte_eth_dev *dev);\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 773f3e63f4..29a1677164 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -6492,40 +6492,20 @@ mlx5_flow_query(struct rte_eth_dev *dev,\n }\n \n /**\n- * Manage filter operations.\n+ * Get rte_flow callbacks.\n  *\n  * @param dev\n  *   Pointer to Ethernet device structure.\n- * @param filter_type\n- *   Filter type.\n- * @param filter_op\n- *   Operation to perform.\n- * @param arg\n+ * @param ops\n  *   Pointer to operation-specific structure.\n  *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ * @return 0\n  */\n int\n-mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t  const struct rte_flow_ops **ops)\n {\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET) {\n-\t\t\trte_errno = EINVAL;\n-\t\t\treturn -rte_errno;\n-\t\t}\n-\t\t*(const void **)arg = &mlx5_flow_ops;\n-\t\treturn 0;\n-\tdefault:\n-\t\tDRV_LOG(ERR, \"port %u filter type (%d) not supported\",\n-\t\t\tdev->data->port_id, filter_type);\n-\t\trte_errno = ENOTSUP;\n-\t\treturn -rte_errno;\n-\t}\n+\t*ops = &mlx5_flow_ops;\n \treturn 0;\n }\n \ndiff --git a/drivers/net/mvpp2/mrvl_ethdev.c b/drivers/net/mvpp2/mrvl_ethdev.c\nindex e119952340..1d41788974 100644\n--- a/drivers/net/mvpp2/mrvl_ethdev.c\n+++ b/drivers/net/mvpp2/mrvl_ethdev.c\n@@ -2340,32 +2340,18 @@ mrvl_rss_hash_conf_get(struct rte_eth_dev *dev,\n  *\n  * @param dev\n  *   Pointer to the device structure.\n- * @param filer_type\n- *   Flow filter type.\n- * @param filter_op\n- *   Flow filter operation.\n- * @param arg\n+ * @param ops\n  *   Pointer to pass the flow ops.\n  *\n  * @return\n  *   0 on success, negative error value otherwise.\n  */\n static int\n-mrvl_eth_filter_ctrl(struct rte_eth_dev *dev __rte_unused,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op, void *arg)\n+mrvl_eth_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t      const struct rte_flow_ops **ops)\n {\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &mrvl_flow_ops;\n-\t\treturn 0;\n-\tdefault:\n-\t\tMRVL_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\tfilter_type);\n-\t\treturn -EINVAL;\n-\t}\n+\t*ops = &mrvl_flow_ops;\n+\treturn 0;\n }\n \n /**\n@@ -2443,7 +2429,7 @@ static const struct eth_dev_ops mrvl_ops = {\n \t.flow_ctrl_set = mrvl_flow_ctrl_set,\n \t.rss_hash_update = mrvl_rss_hash_update,\n \t.rss_hash_conf_get = mrvl_rss_hash_conf_get,\n-\t.filter_ctrl = mrvl_eth_filter_ctrl,\n+\t.flow_ops_get = mrvl_eth_flow_ops_get,\n \t.mtr_ops_get = mrvl_mtr_ops_get,\n \t.tm_ops_get = mrvl_tm_ops_get,\n };\ndiff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c\nindex e9fbbca4da..bacf180a6d 100644\n--- a/drivers/net/octeontx2/otx2_ethdev.c\n+++ b/drivers/net/octeontx2/otx2_ethdev.c\n@@ -2322,7 +2322,7 @@ static const struct eth_dev_ops otx2_eth_dev_ops = {\n \t.tx_done_cleanup          = otx2_nix_tx_done_cleanup,\n \t.set_queue_rate_limit     = otx2_nix_tm_set_queue_rate_limit,\n \t.pool_ops_supported       = otx2_nix_pool_ops_supported,\n-\t.filter_ctrl              = otx2_nix_dev_filter_ctrl,\n+\t.flow_ops_get             = otx2_nix_dev_flow_ops_get,\n \t.get_module_info          = otx2_nix_get_module_info,\n \t.get_module_eeprom        = otx2_nix_get_module_eeprom,\n \t.fw_version_get           = otx2_nix_fw_version_get,\ndiff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h\nindex 99f0469d89..7391f09b8a 100644\n--- a/drivers/net/octeontx2/otx2_ethdev.h\n+++ b/drivers/net/octeontx2/otx2_ethdev.h\n@@ -396,9 +396,8 @@ otx2_eth_pmd_priv(struct rte_eth_dev *eth_dev)\n /* Ops */\n int otx2_nix_info_get(struct rte_eth_dev *eth_dev,\n \t\t      struct rte_eth_dev_info *dev_info);\n-int otx2_nix_dev_filter_ctrl(struct rte_eth_dev *eth_dev,\n-\t\t\t     enum rte_filter_type filter_type,\n-\t\t\t     enum rte_filter_op filter_op, void *arg);\n+int otx2_nix_dev_flow_ops_get(struct rte_eth_dev *eth_dev,\n+\t\t\t      const struct rte_flow_ops **ops);\n int otx2_nix_fw_version_get(struct rte_eth_dev *eth_dev, char *fw_version,\n \t\t\t    size_t fw_size);\n int otx2_nix_get_module_info(struct rte_eth_dev *eth_dev,\ndiff --git a/drivers/net/octeontx2/otx2_ethdev_ops.c b/drivers/net/octeontx2/otx2_ethdev_ops.c\nindex 963cc285ed..9e3f80937d 100644\n--- a/drivers/net/octeontx2/otx2_ethdev_ops.c\n+++ b/drivers/net/octeontx2/otx2_ethdev_ops.c\n@@ -471,24 +471,11 @@ otx2_nix_pool_ops_supported(struct rte_eth_dev *eth_dev, const char *pool)\n }\n \n int\n-otx2_nix_dev_filter_ctrl(struct rte_eth_dev *eth_dev,\n-\t\t\t enum rte_filter_type filter_type,\n-\t\t\t enum rte_filter_op filter_op, void *arg)\n+otx2_nix_dev_flow_ops_get(struct rte_eth_dev *eth_dev __rte_unused,\n+\t\t\t  const struct rte_flow_ops **ops)\n {\n-\tRTE_SET_USED(eth_dev);\n-\n-\tif (filter_type != RTE_ETH_FILTER_GENERIC) {\n-\t\totx2_err(\"Unsupported filter type %d\", filter_type);\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\tif (filter_op == RTE_ETH_FILTER_GET) {\n-\t\t*(const void **)arg = &otx2_flow_ops;\n-\t\treturn 0;\n-\t}\n-\n-\totx2_err(\"Invalid filter_op %d\", filter_op);\n-\treturn -EINVAL;\n+\t*ops = &otx2_flow_ops;\n+\treturn 0;\n }\n \n static struct cgx_fw_data *\ndiff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c\nindex ab5f5b1065..ff4b9255c4 100644\n--- a/drivers/net/qede/qede_ethdev.c\n+++ b/drivers/net/qede/qede_ethdev.c\n@@ -2434,7 +2434,7 @@ static const struct eth_dev_ops qede_eth_dev_ops = {\n \t.reta_update  = qede_rss_reta_update,\n \t.reta_query  = qede_rss_reta_query,\n \t.mtu_set = qede_set_mtu,\n-\t.filter_ctrl = qede_dev_filter_ctrl,\n+\t.flow_ops_get = qede_dev_flow_ops_get,\n \t.udp_tunnel_port_add = qede_udp_dst_port_add,\n \t.udp_tunnel_port_del = qede_udp_dst_port_del,\n \t.fw_version_get = qede_fw_version_get,\ndiff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h\nindex da4b87f5e2..a38b701183 100644\n--- a/drivers/net/qede/qede_ethdev.h\n+++ b/drivers/net/qede/qede_ethdev.h\n@@ -285,11 +285,8 @@ int qede_dev_set_link_state(struct rte_eth_dev *eth_dev, bool link_up);\n int qede_link_update(struct rte_eth_dev *eth_dev,\n \t\t     __rte_unused int wait_to_complete);\n \n-int qede_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type type,\n-\t\t\t enum rte_filter_op op, void *arg);\n-\n-int qede_ntuple_filter_conf(struct rte_eth_dev *eth_dev,\n-\t\t\t    enum rte_filter_op filter_op, void *arg);\n+int qede_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t  const struct rte_flow_ops **ops);\n \n int qede_check_fdir_support(struct rte_eth_dev *eth_dev);\n \ndiff --git a/drivers/net/qede/qede_filter.c b/drivers/net/qede/qede_filter.c\nindex df5c07dfe5..c756594bfc 100644\n--- a/drivers/net/qede/qede_filter.c\n+++ b/drivers/net/qede/qede_filter.c\n@@ -1050,31 +1050,18 @@ const struct rte_flow_ops qede_flow_ops = {\n \t.flush = qede_flow_flush,\n };\n \n-int qede_dev_filter_ctrl(struct rte_eth_dev *eth_dev,\n-\t\t\t enum rte_filter_type filter_type,\n-\t\t\t enum rte_filter_op filter_op,\n-\t\t\t void *arg)\n+int\n+qede_dev_flow_ops_get(struct rte_eth_dev *eth_dev,\n+\t\t      const struct rte_flow_ops **ops)\n {\n \tstruct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);\n \tstruct ecore_dev *edev = QEDE_INIT_EDEV(qdev);\n \n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (ECORE_IS_CMT(edev)) {\n-\t\t\tDP_ERR(edev, \"flowdir is not supported in 100G mode\\n\");\n-\t\t\treturn -ENOTSUP;\n-\t\t}\n-\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\n-\t\t*(const void **)arg = &qede_flow_ops;\n-\t\treturn 0;\n-\tdefault:\n-\t\tDP_ERR(edev, \"Unsupported filter type %d\\n\",\n-\t\t\tfilter_type);\n-\t\treturn -EINVAL;\n+\tif (ECORE_IS_CMT(edev)) {\n+\t\tDP_ERR(edev, \"flowdir is not supported in 100G mode\\n\");\n+\t\treturn -ENOTSUP;\n \t}\n \n+\t*ops = &qede_flow_ops;\n \treturn 0;\n }\ndiff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c\nindex 479b4f4df6..d72df2e13b 100644\n--- a/drivers/net/sfc/sfc_ethdev.c\n+++ b/drivers/net/sfc/sfc_ethdev.c\n@@ -1751,32 +1751,11 @@ sfc_dev_rss_reta_update(struct rte_eth_dev *dev,\n }\n \n static int\n-sfc_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,\n-\t\t    enum rte_filter_op filter_op,\n-\t\t    void *arg)\n+sfc_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t     const struct rte_flow_ops **ops)\n {\n-\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n-\tint rc = ENOTSUP;\n-\n-\tsfc_log_init(sa, \"entry\");\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET) {\n-\t\t\trc = EINVAL;\n-\t\t} else {\n-\t\t\t*(const void **)arg = &sfc_flow_ops;\n-\t\t\trc = 0;\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tsfc_err(sa, \"Unknown filter type %u\", filter_type);\n-\t\tbreak;\n-\t}\n-\n-\tsfc_log_init(sa, \"exit: %d\", -rc);\n-\tSFC_ASSERT(rc >= 0);\n-\treturn -rc;\n+\t*ops = &sfc_flow_ops;\n+\treturn 0;\n }\n \n static int\n@@ -1859,7 +1838,7 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {\n \t.reta_query\t\t\t= sfc_dev_rss_reta_query,\n \t.rss_hash_update\t\t= sfc_dev_rss_hash_update,\n \t.rss_hash_conf_get\t\t= sfc_dev_rss_hash_conf_get,\n-\t.filter_ctrl\t\t\t= sfc_dev_filter_ctrl,\n+\t.flow_ops_get\t\t\t= sfc_dev_flow_ops_get,\n \t.set_mc_addr_list\t\t= sfc_set_mc_addr_list,\n \t.rxq_info_get\t\t\t= sfc_rx_queue_info_get,\n \t.txq_info_get\t\t\t= sfc_tx_queue_info_get,\ndiff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c\nindex 99d8468c94..0c2a79a7d2 100644\n--- a/drivers/net/softnic/rte_eth_softnic.c\n+++ b/drivers/net/softnic/rte_eth_softnic.c\n@@ -248,18 +248,11 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,\n }\n \n static int\n-pmd_filter_ctrl(struct rte_eth_dev *dev __rte_unused,\n-\t\tenum rte_filter_type filter_type,\n-\t\tenum rte_filter_op filter_op,\n-\t\tvoid *arg)\n+pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t const struct rte_flow_ops **ops)\n {\n-\tif (filter_type == RTE_ETH_FILTER_GENERIC &&\n-\t\t\tfilter_op == RTE_ETH_FILTER_GET) {\n-\t\t*(const void **)arg = &pmd_flow_ops;\n-\t\treturn 0;\n-\t}\n-\n-\treturn -ENOTSUP;\n+\t*ops = &pmd_flow_ops;\n+\treturn 0;\n }\n \n static int\n@@ -287,7 +280,7 @@ static const struct eth_dev_ops pmd_ops = {\n \t.dev_infos_get = pmd_dev_infos_get,\n \t.rx_queue_setup = pmd_rx_queue_setup,\n \t.tx_queue_setup = pmd_tx_queue_setup,\n-\t.filter_ctrl = pmd_filter_ctrl,\n+\t.flow_ops_get = pmd_flow_ops_get,\n \t.tm_ops_get = pmd_tm_ops_get,\n \t.mtr_ops_get = pmd_mtr_ops_get,\n };\ndiff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c\nindex c36d4bf76e..68baa18523 100644\n--- a/drivers/net/tap/rte_eth_tap.c\n+++ b/drivers/net/tap/rte_eth_tap.c\n@@ -1890,7 +1890,7 @@ static const struct eth_dev_ops ops = {\n \t.stats_reset            = tap_stats_reset,\n \t.dev_supported_ptypes_get = tap_dev_supported_ptypes_get,\n \t.rss_hash_update        = tap_rss_hash_update,\n-\t.filter_ctrl            = tap_dev_filter_ctrl,\n+\t.flow_ops_get           = tap_dev_flow_ops_get,\n };\n \n static int\ndiff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c\nindex 1538349e9c..1ee6fb30ab 100644\n--- a/drivers/net/tap/tap_flow.c\n+++ b/drivers/net/tap/tap_flow.c\n@@ -2160,35 +2160,20 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,\n }\n \n /**\n- * Manage filter operations.\n+ * Get rte_flow operations.\n  *\n  * @param dev\n  *   Pointer to Ethernet device structure.\n- * @param filter_type\n- *   Filter type.\n- * @param filter_op\n- *   Operation to perform.\n- * @param arg\n+ * @param ops\n  *   Pointer to operation-specific structure.\n  *\n  * @return\n  *   0 on success, negative errno value on failure.\n  */\n int\n-tap_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t    enum rte_filter_type filter_type,\n-\t\t    enum rte_filter_op filter_op,\n-\t\t    void *arg)\n+tap_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,\n+\t\t     const struct rte_flow_ops **ops)\n {\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &tap_flow_ops;\n-\t\treturn 0;\n-\tdefault:\n-\t\tTAP_LOG(ERR, \"%p: filter type (%d) not supported\",\n-\t\t\tdev, filter_type);\n-\t}\n-\treturn -EINVAL;\n+\t*ops = &tap_flow_ops;\n+\treturn 0;\n }\ndiff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h\nindex ac60a9ae20..240fbc3dfa 100644\n--- a/drivers/net/tap/tap_flow.h\n+++ b/drivers/net/tap/tap_flow.h\n@@ -46,10 +46,8 @@ enum bpf_fd_idx {\n \tSEC_MAX,\n };\n \n-int tap_dev_filter_ctrl(struct rte_eth_dev *dev,\n-\t\t\tenum rte_filter_type filter_type,\n-\t\t\tenum rte_filter_op filter_op,\n-\t\t\tvoid *arg);\n+int tap_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t\t const struct rte_flow_ops **ops);\n int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);\n \n int tap_flow_implicit_create(struct pmd_internals *pmd,\ndiff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c\nindex 90137d0ceb..ab748e129d 100644\n--- a/drivers/net/txgbe/txgbe_ethdev.c\n+++ b/drivers/net/txgbe/txgbe_ethdev.c\n@@ -4076,27 +4076,11 @@ txgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,\n }\n \n static int\n-txgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,\n-\t\t     enum rte_filter_type filter_type,\n-\t\t     enum rte_filter_op filter_op,\n-\t\t     void *arg)\n+txgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_ops **ops)\n {\n-\tint ret = 0;\n-\n-\tswitch (filter_type) {\n-\tcase RTE_ETH_FILTER_GENERIC:\n-\t\tif (filter_op != RTE_ETH_FILTER_GET)\n-\t\t\treturn -EINVAL;\n-\t\t*(const void **)arg = &txgbe_flow_ops;\n-\t\tbreak;\n-\tdefault:\n-\t\tPMD_DRV_LOG(WARNING, \"Filter type (%d) not supported\",\n-\t\t\t\t\t\t\tfilter_type);\n-\t\tret = -EINVAL;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n+\t*ops = &txgbe_flow_ops;\n+\treturn 0;\n }\n \n static u8 *\n@@ -5206,7 +5190,7 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {\n \t.reta_query                 = txgbe_dev_rss_reta_query,\n \t.rss_hash_update            = txgbe_dev_rss_hash_update,\n \t.rss_hash_conf_get          = txgbe_dev_rss_hash_conf_get,\n-\t.filter_ctrl                = txgbe_dev_filter_ctrl,\n+\t.flow_ops_get               = txgbe_dev_flow_ops_get,\n \t.set_mc_addr_list           = txgbe_dev_set_mc_addr_list,\n \t.rxq_info_get               = txgbe_rxq_info_get,\n \t.txq_info_get               = txgbe_txq_info_get,\ndiff --git a/lib/librte_ethdev/ethdev_driver.h b/lib/librte_ethdev/ethdev_driver.h\nindex 57fdedaa1a..1c6592ec23 100644\n--- a/lib/librte_ethdev/ethdev_driver.h\n+++ b/lib/librte_ethdev/ethdev_driver.h\n@@ -465,34 +465,10 @@ typedef int (*eth_get_module_eeprom_t)(struct rte_eth_dev *dev,\n \t\t\t\t       struct rte_dev_eeprom_info *info);\n /**< @internal Retrieve plugin module eeprom data */\n \n-/**\n- * Feature filter types\n- */\n-enum rte_filter_type {\n-\tRTE_ETH_FILTER_NONE = 0,\n-\tRTE_ETH_FILTER_ETHERTYPE,\n-\tRTE_ETH_FILTER_FLEXIBLE,\n-\tRTE_ETH_FILTER_SYN,\n-\tRTE_ETH_FILTER_NTUPLE,\n-\tRTE_ETH_FILTER_TUNNEL,\n-\tRTE_ETH_FILTER_FDIR,\n-\tRTE_ETH_FILTER_HASH,\n-\tRTE_ETH_FILTER_L2_TUNNEL,\n-\tRTE_ETH_FILTER_GENERIC,\n-};\n-\n-/**\n- * Generic operations on filters\n- */\n-enum rte_filter_op {\n-\tRTE_ETH_FILTER_GET,      /**< get flow API ops */\n-};\n-\n-typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev,\n-\t\t\t\t enum rte_filter_type filter_type,\n-\t\t\t\t enum rte_filter_op filter_op,\n-\t\t\t\t void *arg);\n-/**< @internal Take operations to assigned filter type on an Ethernet device */\n+struct rte_flow_ops;\n+typedef int (*eth_flow_ops_get_t)(struct rte_eth_dev *dev,\n+\t\t\t\t  const struct rte_flow_ops **ops);\n+/**< @internal Get flow operations */\n \n typedef int (*eth_tm_ops_get_t)(struct rte_eth_dev *dev, void *ops);\n /**< @internal Get Traffic Management (TM) operations on an Ethernet device */\n@@ -880,7 +856,7 @@ struct eth_dev_ops {\n \teth_get_module_eeprom_t    get_module_eeprom;\n \t/** Get plugin module eeprom data. */\n \n-\teth_filter_ctrl_t          filter_ctrl; /**< common filter control. */\n+\teth_flow_ops_get_t         flow_ops_get; /**< Get flow operations. */\n \n \teth_get_dcb_info           get_dcb_info; /** Get DCB information. */\n \n@@ -1377,6 +1353,18 @@ rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue,\n  * Legacy ethdev API used internally by drivers.\n  */\n \n+enum rte_filter_type {\n+\tRTE_ETH_FILTER_NONE = 0,\n+\tRTE_ETH_FILTER_ETHERTYPE,\n+\tRTE_ETH_FILTER_FLEXIBLE,\n+\tRTE_ETH_FILTER_SYN,\n+\tRTE_ETH_FILTER_NTUPLE,\n+\tRTE_ETH_FILTER_TUNNEL,\n+\tRTE_ETH_FILTER_FDIR,\n+\tRTE_ETH_FILTER_HASH,\n+\tRTE_ETH_FILTER_L2_TUNNEL,\n+};\n+\n /**\n  * Define all structures for Ethertype Filter type.\n  */\ndiff --git a/lib/librte_ethdev/rte_eth_ctrl.h b/lib/librte_ethdev/rte_eth_ctrl.h\nindex 8a50dbfef9..42652f9cce 100644\n--- a/lib/librte_ethdev/rte_eth_ctrl.h\n+++ b/lib/librte_ethdev/rte_eth_ctrl.h\n@@ -339,7 +339,7 @@ struct rte_eth_fdir_action {\n };\n \n /**\n- * A structure used to define the flow director filter entry by filter_ctrl API.\n+ * A structure used to define the flow director filter entry.\n  */\n struct rte_eth_fdir_filter {\n \tuint32_t soft_id;\ndiff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c\nindex 241af6c4ca..1a896e3e64 100644\n--- a/lib/librte_ethdev/rte_flow.c\n+++ b/lib/librte_ethdev/rte_flow.c\n@@ -255,18 +255,19 @@ rte_flow_ops_get(uint16_t port_id, struct rte_flow_error *error)\n \n \tif (unlikely(!rte_eth_dev_is_valid_port(port_id)))\n \t\tcode = ENODEV;\n-\telse if (unlikely(!dev->dev_ops->filter_ctrl ||\n-\t\t\t  dev->dev_ops->filter_ctrl(dev,\n-\t\t\t\t\t\t    RTE_ETH_FILTER_GENERIC,\n-\t\t\t\t\t\t    RTE_ETH_FILTER_GET,\n-\t\t\t\t\t\t    &ops) ||\n-\t\t\t  !ops))\n-\t\tcode = ENOSYS;\n+\telse if (unlikely(dev->dev_ops->flow_ops_get == NULL))\n+\t\tcode = ENOTSUP;\n \telse\n-\t\treturn ops;\n-\trte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t   NULL, rte_strerror(code));\n-\treturn NULL;\n+\t\tcode = dev->dev_ops->flow_ops_get(dev, &ops);\n+\tif (code == 0 && ops == NULL)\n+\t\tcode = EACCES;\n+\n+\tif (code != 0) {\n+\t\trte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL, rte_strerror(code));\n+\t\treturn NULL;\n+\t}\n+\treturn ops;\n }\n \n /* Check whether a flow rule can be created on a given port. */\ndiff --git a/lib/librte_ethdev/rte_flow_driver.h b/lib/librte_ethdev/rte_flow_driver.h\nindex dabd819d10..da594d9256 100644\n--- a/lib/librte_ethdev/rte_flow_driver.h\n+++ b/lib/librte_ethdev/rte_flow_driver.h\n@@ -28,31 +28,6 @@ extern \"C\" {\n /**\n  * Generic flow operations structure implemented and returned by PMDs.\n  *\n- * To implement this API, PMDs must handle the RTE_ETH_FILTER_GENERIC filter\n- * type in their .filter_ctrl callback function (struct eth_dev_ops) as well\n- * as the RTE_ETH_FILTER_GET filter operation.\n- *\n- * If successful, this operation must result in a pointer to a PMD-specific\n- * struct rte_flow_ops written to the argument address as described below:\n- *\n- * \\code\n- *\n- * // PMD filter_ctrl callback\n- *\n- * static const struct rte_flow_ops pmd_flow_ops = { ... };\n- *\n- * switch (filter_type) {\n- * case RTE_ETH_FILTER_GENERIC:\n- *     if (filter_op != RTE_ETH_FILTER_GET)\n- *         return -EINVAL;\n- *     *(const void **)arg = &pmd_flow_ops;\n- *     return 0;\n- * }\n- *\n- * \\endcode\n- *\n- * See also rte_flow_ops_get().\n- *\n  * These callback functions are not supposed to be used by applications\n  * directly, which must rely on the API defined in rte_flow.h.\n  *\n",
    "prefixes": [
        "v2",
        "1/2"
    ]
}