get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132404,
    "url": "http://patches.dpdk.org/api/patches/132404/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230908160552.148060-4-yuying.zhang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230908160552.148060-4-yuying.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230908160552.148060-4-yuying.zhang@intel.com",
    "date": "2023-09-08T16:05:46",
    "name": "[v10,3/9] net/cpfl: set up flow offloading skeleton",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2d6ea491857ffe9c5b326a2e284a0fb13473f74e",
    "submitter": {
        "id": 1844,
        "url": "http://patches.dpdk.org/api/people/1844/?format=api",
        "name": "Zhang, Yuying",
        "email": "yuying.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "http://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230908160552.148060-4-yuying.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 29766,
            "url": "http://patches.dpdk.org/api/series/29766/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29766",
            "date": "2023-09-08T16:05:43",
            "name": "add rte flow support for cpfl",
            "version": 10,
            "mbox": "http://patches.dpdk.org/series/29766/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/132404/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/132404/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 96A7342338;\n\tMon,  9 Oct 2023 10:02:37 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 8B94E4067C;\n\tMon,  9 Oct 2023 10:02:21 +0200 (CEST)",
            "from mgamail.intel.com (mgamail.intel.com [134.134.136.126])\n by mails.dpdk.org (Postfix) with ESMTP id 4D5224067C\n for <dev@dpdk.org>; Mon,  9 Oct 2023 10:02:19 +0200 (CEST)",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Oct 2023 01:02:18 -0700",
            "from dpdk-pengyuan-mev.sh.intel.com ([10.67.119.132])\n by orsmga005.jf.intel.com with ESMTP; 09 Oct 2023 01:02:16 -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=1696838539; x=1728374539;\n h=from:to:subject:date:message-id:in-reply-to:references:\n mime-version:content-transfer-encoding;\n bh=wvHs+GKuU8UCw4LTcwJG9oFLvsp94NElrqe3kIzWfLA=;\n b=Z0SLz3fLKlajeMixW1o+yctTLu6Jy/qh+qhR30n8BE6cOBPbK2YRvRzJ\n frDtXZDMTZBNkvV+o4DszAfh3zUPiJy0aE6jYPbHsS6svDkAzNRaeus5f\n t2diLU4ynt0zjI0aSD6E8OTEFh4mwccJ2BGmgs14tT0aZSwTqsE+VlUn6\n djzabFbZvke9L0Q7yWez9HYOQHM3pifU6IxEFfQFnkkIxpebV5uFMDwKg\n rsFu5j/Tsxhvr7Lp26OWa+/ToU+OwvpYohVz6awGRU9jOWCRltbReUsgF\n aL6ltL+OnEkqKMDTvx9nl/xviagWFMze6+z7Lsxlz35Yn4OZixvfI9XxW A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6600,9927,10857\"; a=\"369155057\"",
            "E=Sophos;i=\"6.03,209,1694761200\"; d=\"scan'208\";a=\"369155057\"",
            "E=McAfee;i=\"6600,9927,10857\"; a=\"926675830\"",
            "E=Sophos;i=\"6.03,209,1694761200\"; d=\"scan'208\";a=\"926675830\""
        ],
        "X-ExtLoop1": "1",
        "From": "\"Zhang, Yuying\" <yuying.zhang@intel.com>",
        "To": "yuying.zhang@intel.com, dev@dpdk.org, qi.z.zhang@intel.com,\n jingjing.wu@intel.com, beilei.xing@intel.com",
        "Subject": "[PATCH v10 3/9] net/cpfl: set up flow offloading skeleton",
        "Date": "Fri,  8 Sep 2023 16:05:46 +0000",
        "Message-Id": "<20230908160552.148060-4-yuying.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20230908160552.148060-1-yuying.zhang@intel.com>",
        "References": "<20230928084458.2333663-1-yuying.zhang@intel.com>\n <20230908160552.148060-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": "From: Yuying Zhang <yuying.zhang@intel.com>\n\nSet 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>\nAcked-by: Qi Zhang <qi.z.zhang@intel.com>\n---\n drivers/net/cpfl/cpfl_ethdev.c |  53 ++++++\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   |   1 +\n 5 files changed, 483 insertions(+)\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 1745f703c8..c350728861 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 RTE_HAS_JANSSON\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@@ -2021,6 +2060,13 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *a\n \t\tgoto err_vports_alloc;\n \t}\n \n+#ifdef RTE_HAS_JANSSON\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@@ -2028,6 +2074,9 @@ cpfl_adapter_ext_init(struct rte_pci_device *pci_dev, struct cpfl_adapter_ext *a\n \n \treturn ret;\n \n+#ifdef RTE_HAS_JANSSON\n+err_flow_init:\n+#endif\n err_vports_alloc:\n \trte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);\n \tcpfl_repr_allowlist_uninit(adapter);\n@@ -2182,6 +2231,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@@ -2262,6 +2312,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 RTE_HAS_JANSSON\n+\tcpfl_flow_uninit(adapter);\n+#endif\n \trte_eal_alarm_cancel(cpfl_dev_alarm_handler, adapter);\n \tcpfl_vport_map_uninit(adapter);\n \tidpf_adapter_deinit(&adapter->base);\ndiff --git a/drivers/net/cpfl/cpfl_ethdev.h b/drivers/net/cpfl/cpfl_ethdev.h\nindex 383dbd14c6..69bf32cfbd 100644\n--- a/drivers/net/cpfl/cpfl_ethdev.h\n+++ b/drivers/net/cpfl/cpfl_ethdev.h\n@@ -140,9 +140,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@@ -206,6 +209,8 @@ struct cpfl_adapter_ext {\n \trte_spinlock_t repr_lock;\n \tstruct rte_hash *repr_allowlist_hash;\n \n+\tstruct cpfl_flow_js_parser *flow_parser;\n+\n \tstruct cpfl_metadata meta;\n };\n \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 d767818eb7..f5654d5b0e 100644\n--- a/drivers/net/cpfl/meson.build\n+++ b/drivers/net/cpfl/meson.build\n@@ -41,6 +41,7 @@ endif\n \n if dpdk_conf.has('RTE_HAS_JANSSON')\n     sources += files(\n+\t    'cpfl_flow.c',\n             'cpfl_flow_parser.c',\n     )\n     ext_deps += jansson_dep\n",
    "prefixes": [
        "v10",
        "3/9"
    ]
}