get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131082,
    "url": "https://patches.dpdk.org/api/patches/131082/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230901113158.1654044-6-yuying.zhang@intel.com/",
    "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": "<20230901113158.1654044-6-yuying.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230901113158.1654044-6-yuying.zhang@intel.com",
    "date": "2023-09-01T11:31:55",
    "name": "[v2,5/8] net/cpfl: set up rte flow skeleton",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "cd87121d209a18ec8045b9b215a4d0e985676ba7",
    "submitter": {
        "id": 1844,
        "url": "https://patches.dpdk.org/api/people/1844/?format=api",
        "name": "Zhang, Yuying",
        "email": "yuying.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230901113158.1654044-6-yuying.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 29402,
            "url": "https://patches.dpdk.org/api/series/29402/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29402",
            "date": "2023-09-01T11:31:50",
            "name": "add rte flow support for cpfl",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/29402/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/131082/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/131082/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 7289D4221F;\n\tFri,  1 Sep 2023 13:10:22 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 6F522402C3;\n\tFri,  1 Sep 2023 13:09:45 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [192.55.52.151])\n by mails.dpdk.org (Postfix) with ESMTP id 6010D402CD\n for <dev@dpdk.org>; Fri,  1 Sep 2023 13:09:42 +0200 (CEST)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 01 Sep 2023 04:09:42 -0700",
            "from dpdk-yuyingzh-icelake.sh.intel.com ([10.67.116.226])\n by fmsmga002.fm.intel.com with ESMTP; 01 Sep 2023 04:09:40 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1693566582; x=1725102582;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=23gbrzweCDomCzqYLKPpbwTXi7pSuPM976Z9n+K+iZs=;\n b=U+Xa9zi8m6e5dNEdnq+dyCF3rKHy0Tu75+goE66GyWVlLivdJE08Otp6\n mNp86G7MIMWhb8GhYECXqIRZCXhR18Y5r3N4dBgxuJCwTFJRjBns/ahu5\n 8I5PxkxePvGvIPEryJZjLSN83Bn+Meb9eYVkIivHuPzc8W+M5xGO9BW2q\n 54tv2t1SgVmfboN4iCnifkJ6FVXZebdR3V+uqKbVYXdEJhf/7YFWxXkgy\n DqQSCcsRqehiqsUp1hxjRDW/8Ht3YnViGK3R+M7u2DtuTV6n1BwbWuCFl\n H8+7OEJK2CFQW/gVfd+2gLiNl6qxdWl56SQOmZacGn+pX7HtjcXG5Ssuq w==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10819\"; a=\"356511076\"",
            "E=Sophos;i=\"6.02,219,1688454000\"; d=\"scan'208\";a=\"356511076\"",
            "E=McAfee;i=\"6600,9927,10819\"; a=\"854670997\"",
            "E=Sophos;i=\"6.02,219,1688454000\"; d=\"scan'208\";a=\"854670997\""
        ],
        "X-ExtLoop1": "1",
        "From": "Yuying Zhang <yuying.zhang@intel.com>",
        "To": "dev@dpdk.org, qi.z.zhang@intel.com, jingjing.wu@intel.com,\n beilei.xing@intel.com",
        "Cc": "Yuying Zhang <yuying.zhang@intel.com>",
        "Subject": "[PATCH v2 5/8] net/cpfl: set up rte flow skeleton",
        "Date": "Fri,  1 Sep 2023 11:31:55 +0000",
        "Message-Id": "<20230901113158.1654044-6-yuying.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230901113158.1654044-1-yuying.zhang@intel.com>",
        "References": "<20230812075506.361769-1-yuying.zhang@intel.com>\n <20230901113158.1654044-1-yuying.zhang@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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"
    },
    "content": "Set up the rte_flow backend skeleton. Introduce the framework\nto support different engines as rte_flow backend. Bridge rte_flow\ndriver API to flow engines.\n\nSigned-off-by: Yuying Zhang <yuying.zhang@intel.com>\n---\n drivers/net/cpfl/cpfl_ethdev.c |  54 ++++++\n drivers/net/cpfl/cpfl_ethdev.h |   5 +\n drivers/net/cpfl/cpfl_flow.c   | 339 +++++++++++++++++++++++++++++++++\n drivers/net/cpfl/cpfl_flow.h   |  85 +++++++++\n drivers/net/cpfl/meson.build   |   3 +-\n 5 files changed, 485 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/cpfl/cpfl_flow.c\n create mode 100644 drivers/net/cpfl/cpfl_flow.h",
    "diff": "diff --git a/drivers/net/cpfl/cpfl_ethdev.c b/drivers/net/cpfl/cpfl_ethdev.c\nindex 22f3e72894..618a6a0fe2 100644\n--- a/drivers/net/cpfl/cpfl_ethdev.c\n+++ b/drivers/net/cpfl/cpfl_ethdev.c\n@@ -15,6 +15,7 @@\n #include \"cpfl_ethdev.h\"\n #include <ethdev_private.h>\n #include \"cpfl_rxtx.h\"\n+#include \"cpfl_flow.h\"\n \n #define CPFL_REPRESENTOR\t\"representor\"\n #define CPFL_TX_SINGLE_Q\t\"tx_single\"\n@@ -1074,6 +1075,19 @@ cpfl_dev_stop(struct rte_eth_dev *dev)\n \treturn 0;\n }\n \n+static void\n+cpfl_flow_free(struct cpfl_vport *vport)\n+{\n+\tstruct rte_flow *p_flow;\n+\n+\twhile ((p_flow = TAILQ_FIRST(&vport->itf.flow_list))) {\n+\t\tTAILQ_REMOVE(&vport->itf.flow_list, p_flow, next);\n+\t\tif (p_flow->engine->free)\n+\t\t\tp_flow->engine->free(p_flow);\n+\t\trte_free(p_flow);\n+\t}\n+}\n+\n static int\n cpfl_p2p_queue_grps_del(struct idpf_vport *vport)\n {\n@@ -1105,6 +1119,7 @@ cpfl_dev_close(struct rte_eth_dev *dev)\n \tif (!adapter->base.is_rx_singleq && !adapter->base.is_tx_singleq)\n \t\tcpfl_p2p_queue_grps_del(vport);\n \n+\tcpfl_flow_free(cpfl_vport);\n \tidpf_vport_deinit(vport);\n \trte_free(cpfl_vport->p2p_q_chunks_info);\n \n@@ -1117,6 +1132,29 @@ cpfl_dev_close(struct rte_eth_dev *dev)\n \treturn 0;\n }\n \n+static int\n+cpfl_dev_flow_ops_get(struct rte_eth_dev *dev,\n+\t\t      const struct rte_flow_ops **ops)\n+{\n+\tstruct cpfl_itf *itf;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\titf = CPFL_DEV_TO_ITF(dev);\n+\n+\t/* only vport support rte_flow */\n+\tif (itf->type != CPFL_ITF_TYPE_VPORT)\n+\t\treturn -ENOTSUP;\n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+\t*ops = &cpfl_flow_ops;\n+#else\n+\t*ops = NULL;\n+\tPMD_DRV_LOG(NOTICE, \"not support rte_flow, please install json-c library.\");\n+#endif\n+\treturn 0;\n+}\n+\n static int\n cpfl_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,\n \t\t\t    size_t len, uint32_t tx)\n@@ -1318,6 +1356,7 @@ static const struct eth_dev_ops cpfl_eth_dev_ops = {\n \t.xstats_get\t\t\t= cpfl_dev_xstats_get,\n \t.xstats_get_names\t\t= cpfl_dev_xstats_get_names,\n \t.xstats_reset\t\t\t= cpfl_dev_xstats_reset,\n+\t.flow_ops_get\t\t\t= cpfl_dev_flow_ops_get,\n \t.hairpin_cap_get\t\t= cpfl_hairpin_cap_get,\n \t.rx_hairpin_queue_setup\t\t= cpfl_rx_hairpin_queue_setup,\n \t.tx_hairpin_queue_setup\t\t= cpfl_tx_hairpin_queue_setup,\n@@ -2283,6 +2322,13 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *a\n \t\tgoto err_create_ctrl_vport;\n \t}\n \n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+\tret = cpfl_flow_init(adapter);\n+\tif (ret) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to init flow module\");\n+\t\tgoto err_flow_init;\n+\t}\n+#endif\n \tadapter->cur_vports = 0;\n \tadapter->cur_vport_nb = 0;\n \n@@ -2290,6 +2336,10 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *a\n \n \treturn ret;\n \n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+err_flow_init:\n+\tcpfl_ctrl_path_close(adapter);\n+#endif\n err_create_ctrl_vport:\n \trte_free(adapter->vports);\n err_vports_alloc:\n@@ -2446,6 +2496,7 @@ cpfl_dev_vport_init(struct rte_eth_dev *dev, void *init_params)\n \tcpfl_vport->itf.type = CPFL_ITF_TYPE_VPORT;\n \tcpfl_vport->itf.adapter = adapter;\n \tcpfl_vport->itf.data = dev->data;\n+\tTAILQ_INIT(&cpfl_vport->itf.flow_list);\n \tadapter->vports[param->idx] = cpfl_vport;\n \tadapter->cur_vports |= RTE_BIT32(param->devarg_id);\n \tadapter->cur_vport_nb++;\n@@ -2526,6 +2577,9 @@ cpfl_find_adapter_ext(struct rte_pci_device *pci_dev)\n static void\n cpfl_adapter_ext_deinit(struct cpfl_adapter_ext *adapter)\n {\n+#ifdef CPFL_FLOW_JSON_SUPPORT\n+\tcpfl_flow_uninit(adapter);\n+#endif\n \tcpfl_ctrl_path_close(adapter);\n \trte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);\n \tcpfl_vport_map_uninit(adapter);\ndiff --git a/drivers/net/cpfl/cpfl_ethdev.h b/drivers/net/cpfl/cpfl_ethdev.h\nindex 90e71a6550..40a27f8b74 100644\n--- a/drivers/net/cpfl/cpfl_ethdev.h\n+++ b/drivers/net/cpfl/cpfl_ethdev.h\n@@ -143,9 +143,12 @@ enum cpfl_itf_type {\n \tCPFL_ITF_TYPE_REPRESENTOR\n };\n \n+TAILQ_HEAD(cpfl_flow_list, rte_flow);\n+\n struct cpfl_itf {\n \tenum cpfl_itf_type type;\n \tstruct cpfl_adapter_ext *adapter;\n+\tstruct cpfl_flow_list flow_list;\n \tvoid *data;\n };\n \n@@ -195,6 +198,8 @@ struct cpfl_adapter_ext {\n \trte_spinlock_t repr_lock;\n \tstruct rte_hash *repr_whitelist_hash;\n \n+\tstruct cpfl_flow_js_parser *flow_parser;\n+\n \t/* ctrl vport and ctrl queues. */\n \tstruct cpfl_vport ctrl_vport;\n \tuint8_t ctrl_vport_recv_info[IDPF_DFLT_MBX_BUF_SIZE];\ndiff --git a/drivers/net/cpfl/cpfl_flow.c b/drivers/net/cpfl/cpfl_flow.c\nnew file mode 100644\nindex 0000000000..03dd1ffa44\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow.c\n@@ -0,0 +1,339 @@\n+/* SPDX-Lidpfnse-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+#include <rte_flow_driver.h>\n+#include <rte_tailq.h>\n+\n+#include \"cpfl_flow.h\"\n+#include \"cpfl_flow_parser.h\"\n+\n+TAILQ_HEAD(cpfl_flow_engine_list, cpfl_flow_engine);\n+\n+static struct cpfl_flow_engine_list engine_list = TAILQ_HEAD_INITIALIZER(engine_list);\n+\n+void\n+cpfl_flow_engine_register(struct cpfl_flow_engine *engine)\n+{\n+\tTAILQ_INSERT_TAIL(&engine_list, engine, node);\n+}\n+\n+struct cpfl_flow_engine *\n+cpfl_flow_engine_match(struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_attr *attr,\n+\t\t       const struct rte_flow_item pattern[],\n+\t\t       const struct rte_flow_action actions[],\n+\t\t       void **meta)\n+{\n+\tstruct cpfl_flow_engine *engine = NULL;\n+\tvoid *temp;\n+\n+\tRTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {\n+\t\tif (!engine->parse_pattern_action)\n+\t\t\tcontinue;\n+\n+\t\tif (engine->parse_pattern_action(dev, attr, pattern, actions, meta) < 0)\n+\t\t\tcontinue;\n+\t\treturn engine;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+int\n+cpfl_flow_engine_init(struct cpfl_adapter_ext *adapter)\n+{\n+\tstruct cpfl_flow_engine *engine = NULL;\n+\tvoid *temp;\n+\tint ret;\n+\n+\tRTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {\n+\t\tif (!engine->init) {\n+\t\t\tPMD_INIT_LOG(ERR, \"Invalid engine type (%d)\",\n+\t\t\t\t     engine->type);\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\n+\t\tret = engine->init(adapter);\n+\t\tif (ret) {\n+\t\t\tPMD_INIT_LOG(ERR, \"Failed to initialize engine %d\",\n+\t\t\t\t     engine->type);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void\n+cpfl_flow_engine_uninit(struct cpfl_adapter_ext *adapter)\n+{\n+\tstruct cpfl_flow_engine *engine = NULL;\n+\tvoid *temp;\n+\n+\tRTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {\n+\t\tif (engine->uninit)\n+\t\t\tengine->uninit(adapter);\n+\t}\n+}\n+\n+static int\n+cpfl_flow_attr_valid(const struct rte_flow_attr *attr,\n+\t\t     struct rte_flow_error *error)\n+{\n+\tif (attr->priority > CPFL_PREC_MAX) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,\n+\t\t\t\t   attr, \"Only support priority 0-7.\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+cpfl_flow_param_valid(const struct rte_flow_attr *attr,\n+\t\t      const struct rte_flow_item pattern[],\n+\t\t      const struct rte_flow_action actions[],\n+\t\t      struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tif (!pattern) {\n+\t\trte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,\n+\t\t\t\t   NULL, \"NULL pattern.\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tif (!attr) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_ATTR,\n+\t\t\t\t   NULL, \"NULL attribute.\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tret = cpfl_flow_attr_valid(attr, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_ACTION_NUM,\n+\t\t\t\t   NULL, \"NULL action.\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+__cpfl_flow_validate(struct rte_eth_dev *dev,\n+\t\t     const struct rte_flow_attr *attr,\n+\t\t     const struct rte_flow_item pattern[],\n+\t\t     const struct rte_flow_action actions[],\n+\t\t     void **meta,\n+\t\t     struct cpfl_flow_engine **engine,\n+\t\t     struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tret = cpfl_flow_param_valid(attr, pattern, actions, error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t*engine = cpfl_flow_engine_match(dev, attr, pattern, actions, meta);\n+\tif (!*engine) {\n+\t\trte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL, \"No matched engine.\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+cpfl_flow_validate(struct rte_eth_dev *dev,\n+\t\t   const struct rte_flow_attr *attr,\n+\t\t   const struct rte_flow_item pattern[],\n+\t\t   const struct rte_flow_action actions[],\n+\t\t   struct rte_flow_error *error)\n+{\n+\tstruct cpfl_flow_engine *engine = NULL;\n+\tint ret;\n+\n+\tret = __cpfl_flow_validate(dev, attr, pattern, actions, NULL, &engine, error);\n+\n+\treturn ret;\n+}\n+\n+struct rte_flow *\n+cpfl_flow_create(struct rte_eth_dev *dev,\n+\t\t const struct rte_flow_attr *attr,\n+\t\t const struct rte_flow_item pattern[],\n+\t\t const struct rte_flow_action actions[],\n+\t\t struct rte_flow_error *error)\n+{\n+\tstruct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);\n+\tstruct cpfl_flow_engine *engine = NULL;\n+\tstruct rte_flow *flow;\n+\tvoid *meta;\n+\tint ret;\n+\n+\tflow = rte_malloc(NULL, sizeof(struct rte_flow), 0);\n+\tif (!flow) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\t   \"Failed to allocate memory\");\n+\t\treturn NULL;\n+\t}\n+\n+\tret = __cpfl_flow_validate(dev, attr, pattern, actions, &meta, &engine, error);\n+\tif (ret) {\n+\t\trte_free(flow);\n+\t\treturn NULL;\n+\t}\n+\n+\tif (!engine->create) {\n+\t\trte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL, \"No matched flow creation function\");\n+\t\trte_free(flow);\n+\t\treturn NULL;\n+\t}\n+\n+\tret = engine->create(dev, flow, meta, error);\n+\tif (ret) {\n+\t\trte_free(flow);\n+\t\treturn NULL;\n+\t}\n+\n+\tflow->engine = engine;\n+\tTAILQ_INSERT_TAIL(&itf->flow_list, flow, next);\n+\n+\treturn flow;\n+}\n+\n+int\n+cpfl_flow_destroy(struct rte_eth_dev *dev,\n+\t\t  struct rte_flow *flow,\n+\t\t  struct rte_flow_error *error)\n+{\n+\tstruct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);\n+\tint ret = 0;\n+\n+\tif (!flow || !flow->engine || !flow->engine->destroy) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"Invalid flow\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tret = flow->engine->destroy(dev, flow, error);\n+\tif (!ret)\n+\t\tTAILQ_REMOVE(&itf->flow_list, flow, next);\n+\telse\n+\t\tPMD_DRV_LOG(ERR, \"Failed to destroy flow\");\n+\n+\treturn ret;\n+}\n+\n+int\n+cpfl_flow_flush(struct rte_eth_dev *dev,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tstruct cpfl_itf *itf = CPFL_DEV_TO_ITF(dev);\n+\tstruct rte_flow *p_flow;\n+\tvoid *temp;\n+\tint ret = 0;\n+\n+\tRTE_TAILQ_FOREACH_SAFE(p_flow, &itf->flow_list, next, temp) {\n+\t\tret = cpfl_flow_destroy(dev, p_flow, error);\n+\t\tif (ret) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to flush flows\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int\n+cpfl_flow_query(struct rte_eth_dev *dev,\n+\t\tstruct rte_flow *flow,\n+\t\tconst struct rte_flow_action *actions,\n+\t\tvoid *data,\n+\t\tstruct rte_flow_error *error)\n+{\n+\tstruct rte_flow_query_count *count = data;\n+\tint ret = -EINVAL;\n+\n+\tif (!flow || !flow->engine || !flow->engine->query_count) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_HANDLE,\n+\t\t\t\t   NULL, \"Invalid flow\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t\tret = flow->engine->query_count(dev, flow, count, error);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tret = rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION,\n+\t\t\t\t\t\t actions,\n+\t\t\t\t\t\t \"action not supported\");\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+const struct rte_flow_ops cpfl_flow_ops = {\n+\t.validate = cpfl_flow_validate,\n+\t.create = cpfl_flow_create,\n+\t.destroy = cpfl_flow_destroy,\n+\t.flush = cpfl_flow_flush,\n+\t.query = cpfl_flow_query,\n+};\n+\n+int\n+cpfl_flow_init(struct cpfl_adapter_ext *ad)\n+{\n+\tint ret;\n+\n+\tif (ad->devargs.flow_parser[0] == '\\0') {\n+\t\tPMD_INIT_LOG(WARNING, \"flow module is not initialized\");\n+\t\treturn 0;\n+\t}\n+\n+\tret = cpfl_flow_engine_init(ad);\n+\tif (ret) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to init flow engines\");\n+\t\tgoto err;\n+\t}\n+\n+\tret = cpfl_parser_create(&ad->flow_parser, ad->devargs.flow_parser);\n+\tif (ret) {\n+\t\tPMD_DRV_LOG(ERR, \"Failed to create flow parser\");\n+\t\tgoto err;\n+\t}\n+\n+\treturn ret;\n+\n+err:\n+\tcpfl_flow_engine_uninit(ad);\n+\treturn ret;\n+}\n+\n+void\n+cpfl_flow_uninit(struct cpfl_adapter_ext *ad)\n+{\n+\tif (ad->devargs.flow_parser[0] == '\\0')\n+\t\treturn;\n+\n+\tcpfl_parser_destroy(ad->flow_parser);\n+\tcpfl_flow_engine_uninit(ad);\n+}\ndiff --git a/drivers/net/cpfl/cpfl_flow.h b/drivers/net/cpfl/cpfl_flow.h\nnew file mode 100644\nindex 0000000000..8c19b853ca\n--- /dev/null\n+++ b/drivers/net/cpfl/cpfl_flow.h\n@@ -0,0 +1,85 @@\n+/* SPDX-Lidpfnse-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+\n+#ifndef _CPFL_FLOW_H_\n+#define _CPFL_FLOW_H_\n+\n+#include <rte_flow.h>\n+#include \"cpfl_ethdev.h\"\n+\n+#define CPFL_PREC_MAX 7\n+\n+extern const struct rte_flow_ops cpfl_flow_ops;\n+\n+enum cpfl_flow_engine_type {\n+\tCPFL_FLOW_ENGINE_NONE = 0,\n+\tCPFL_FLOW_ENGINE_FXP,\n+};\n+\n+typedef int (*engine_init_t)(struct cpfl_adapter_ext *ad);\n+typedef void (*engine_uninit_t)(struct cpfl_adapter_ext *ad);\n+typedef int (*engine_create_t)(struct rte_eth_dev *dev,\n+\t\t\t       struct rte_flow *flow,\n+\t\t\t       void *meta,\n+\t\t\t       struct rte_flow_error *error);\n+typedef int (*engine_destroy_t)(struct rte_eth_dev *dev,\n+\t\t\t\tstruct rte_flow *flow,\n+\t\t\t\tstruct rte_flow_error *error);\n+typedef int (*engine_query_t)(struct rte_eth_dev *dev,\n+\t\t\t      struct rte_flow *flow,\n+\t\t\t      struct rte_flow_query_count *count,\n+\t\t\t      struct rte_flow_error *error);\n+typedef void (*engine_free_t) (struct rte_flow *flow);\n+typedef int (*engine_parse_pattern_action_t)(struct rte_eth_dev *dev,\n+\t\t\t\t\t     const struct rte_flow_attr *attr,\n+\t\t\t\t\t     const struct rte_flow_item pattern[],\n+\t\t\t\t\t     const struct rte_flow_action actions[],\n+\t\t\t\t\t     void **meta);\n+\n+struct cpfl_flow_engine {\n+\tTAILQ_ENTRY(cpfl_flow_engine) node;\n+\tenum cpfl_flow_engine_type type;\n+\tengine_init_t init;\n+\tengine_uninit_t uninit;\n+\tengine_create_t create;\n+\tengine_destroy_t destroy;\n+\tengine_query_t query_count;\n+\tengine_free_t free;\n+\tengine_parse_pattern_action_t parse_pattern_action;\n+};\n+\n+struct rte_flow {\n+\tTAILQ_ENTRY(rte_flow) next;\n+\tstruct cpfl_flow_engine *engine;\n+\tvoid *rule;\n+};\n+\n+void cpfl_flow_engine_register(struct cpfl_flow_engine *engine);\n+struct cpfl_flow_engine *cpfl_flow_engine_match(struct rte_eth_dev *dev,\n+\t\t\t\t\t\tconst struct rte_flow_attr *attr,\n+\t\t\t\t\t\tconst struct rte_flow_item pattern[],\n+\t\t\t\t\t\tconst struct rte_flow_action actions[],\n+\t\t\t\t\t\tvoid **meta);\n+int cpfl_flow_engine_init(struct cpfl_adapter_ext *adapter);\n+void cpfl_flow_engine_uninit(struct cpfl_adapter_ext *adapter);\n+int cpfl_flow_init(struct cpfl_adapter_ext *ad);\n+void cpfl_flow_uninit(struct cpfl_adapter_ext *ad);\n+struct rte_flow *cpfl_flow_create(struct rte_eth_dev *dev,\n+\t\t\t\t  const struct rte_flow_attr *attr,\n+\t\t\t\t  const struct rte_flow_item pattern[],\n+\t\t\t\t  const struct rte_flow_action actions[],\n+\t\t\t\t  struct rte_flow_error *error);\n+int cpfl_flow_validate(struct rte_eth_dev *dev,\n+\t\t       const struct rte_flow_attr *attr,\n+\t\t       const struct rte_flow_item pattern[],\n+\t\t       const struct rte_flow_action actions[],\n+\t\t       struct rte_flow_error *error);\n+int cpfl_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, struct rte_flow_error *error);\n+int cpfl_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);\n+int cpfl_flow_query(struct rte_eth_dev *dev,\n+\t\t    struct rte_flow *flow,\n+\t\t    const struct rte_flow_action *actions,\n+\t\t    void *data,\n+\t\t    struct rte_flow_error *error);\n+#endif\ndiff --git a/drivers/net/cpfl/meson.build b/drivers/net/cpfl/meson.build\nindex 9a8d25ffae..4951ea1c4a 100644\n--- a/drivers/net/cpfl/meson.build\n+++ b/drivers/net/cpfl/meson.build\n@@ -43,9 +43,10 @@ endif\n js_dep = dependency('json-c', required: false, method : 'pkg-config')\n if js_dep.found()\n     sources += files(\n+        'cpfl_flow.c',\n         'cpfl_flow_parser.c',\n         'cpfl_rules.c',\n     )\n     dpdk_conf.set('CPFL_FLOW_JSON_SUPPORT', true)\n     ext_deps += js_dep\n-endif\n\\ No newline at end of file\n+endif\n",
    "prefixes": [
        "v2",
        "5/8"
    ]
}