get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 127903,
    "url": "http://patches.dpdk.org/api/patches/127903/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230601195538.8265-31-ivan.malov@arknetworks.am/",
    "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": "<20230601195538.8265-31-ivan.malov@arknetworks.am>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230601195538.8265-31-ivan.malov@arknetworks.am",
    "date": "2023-06-01T19:55:34",
    "name": "[30/34] net/sfc: support indirect count action in transfer flows",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2c2b930931ba5aee8098325a96f2a02db5f38376",
    "submitter": {
        "id": 2962,
        "url": "http://patches.dpdk.org/api/people/2962/?format=api",
        "name": "Ivan Malov",
        "email": "ivan.malov@arknetworks.am"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230601195538.8265-31-ivan.malov@arknetworks.am/mbox/",
    "series": [
        {
            "id": 28307,
            "url": "http://patches.dpdk.org/api/series/28307/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=28307",
            "date": "2023-06-01T19:55:04",
            "name": "net/sfc: support HW conntrack assistance",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/28307/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/127903/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/127903/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 56A1C42C07;\n\tThu,  1 Jun 2023 21:58:59 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 268214300F;\n\tThu,  1 Jun 2023 21:56:19 +0200 (CEST)",
            "from agw.arknetworks.am (agw.arknetworks.am [79.141.165.80])\n by mails.dpdk.org (Postfix) with ESMTP id 9E00B42D86\n for <dev@dpdk.org>; Thu,  1 Jun 2023 21:55:57 +0200 (CEST)",
            "from localhost.localdomain (unknown [78.109.69.146])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by agw.arknetworks.am (Postfix) with ESMTPSA id 30C19E1283;\n Thu,  1 Jun 2023 23:55:57 +0400 (+04)"
        ],
        "From": "Ivan Malov <ivan.malov@arknetworks.am>",
        "To": "dev@dpdk.org",
        "Cc": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,\n Ferruh Yigit <ferruh.yigit@amd.com>, Andy Moreton <amoreton@xilinx.com>",
        "Subject": "[PATCH 30/34] net/sfc: support indirect count action in transfer\n flows",
        "Date": "Thu,  1 Jun 2023 23:55:34 +0400",
        "Message-Id": "<20230601195538.8265-31-ivan.malov@arknetworks.am>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20230601195538.8265-1-ivan.malov@arknetworks.am>",
        "References": "<20230601195538.8265-1-ivan.malov@arknetworks.am>",
        "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": "Indirect count action is useful to applications that\nneed to gather aggregated statistics for many flows.\n\nSigned-off-by: Ivan Malov <ivan.malov@arknetworks.am>\nReviewed-by: Andy Moreton <amoreton@xilinx.com>\n---\n doc/guides/nics/features/sfc.ini |   1 +\n doc/guides/nics/sfc_efx.rst      |   2 +\n drivers/net/sfc/sfc.h            |   1 +\n drivers/net/sfc/sfc_flow.c       | 126 +++++++++++++++++++++++\n drivers/net/sfc/sfc_flow.h       |  14 +++\n drivers/net/sfc/sfc_mae.c        | 167 ++++++++++++++++++++++++++++++-\n drivers/net/sfc/sfc_mae.h        |  15 +++\n 7 files changed, 325 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini\nindex 19d4935ce6..15a97ce8cd 100644\n--- a/doc/guides/nics/features/sfc.ini\n+++ b/doc/guides/nics/features/sfc.ini\n@@ -62,6 +62,7 @@ count                = Y\n dec_ttl              = Y\n drop                 = Y\n flag                 = Y\n+indirect             = P\n jump                 = P\n mark                 = Y\n of_dec_nw_ttl        = Y\ndiff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst\nindex 6e974c3720..ba82b02093 100644\n--- a/doc/guides/nics/sfc_efx.rst\n+++ b/doc/guides/nics/sfc_efx.rst\n@@ -306,6 +306,8 @@ Supported actions (***transfer*** rules):\n \n - COUNT\n \n+- INDIRECT\n+\n - DROP\n \n Validating flow rules depends on the firmware variant.\ndiff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h\nindex 6b301aad60..f84a21009e 100644\n--- a/drivers/net/sfc/sfc.h\n+++ b/drivers/net/sfc/sfc.h\n@@ -248,6 +248,7 @@ struct sfc_adapter {\n \tstruct sfc_tbls\t\t\thw_tables;\n \tstruct sfc_repr_proxy\t\trepr_proxy;\n \n+\tstruct sfc_flow_indir_actions\tflow_indir_actions;\n \tstruct sfc_flow_list\t\tflow_list;\n \n \tunsigned int\t\t\trxq_max;\ndiff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c\nindex 6f366c1b06..283f672d6d 100644\n--- a/drivers/net/sfc/sfc_flow.c\n+++ b/drivers/net/sfc/sfc_flow.c\n@@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,\n \treturn 0;\n }\n \n+static struct rte_flow_action_handle *\n+sfc_flow_action_handle_create(struct rte_eth_dev *dev,\n+\t\t\t      const struct rte_flow_indir_action_conf *conf,\n+\t\t\t      const struct rte_flow_action *action,\n+\t\t\t      struct rte_flow_error *error)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct rte_flow_action_handle *handle;\n+\tint ret;\n+\n+\tif (!conf->transfer) {\n+\t\trte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t   \"non-transfer domain does not support indirect actions\");\n+\t\treturn NULL;\n+\t}\n+\n+\tif (conf->ingress || conf->egress) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t   NULL, \"cannot combine ingress/egress with transfer\");\n+\t\treturn NULL;\n+\t}\n+\n+\thandle = rte_zmalloc(\"sfc_rte_flow_action_handle\", sizeof(*handle), 0);\n+\tif (handle == NULL) {\n+\t\trte_flow_error_set(error, ENOMEM,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t   \"failed to allocate memory\");\n+\t\treturn NULL;\n+\t}\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tret = sfc_mae_indir_action_create(sa, action, handle, error);\n+\tif (ret != 0) {\n+\t\tsfc_adapter_unlock(sa);\n+\t\trte_free(handle);\n+\t\treturn NULL;\n+\t}\n+\n+\tTAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);\n+\n+\thandle->transfer = (bool)conf->transfer;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn handle;\n+}\n+\n+static int\n+sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,\n+\t\t\t       struct rte_flow_action_handle *handle,\n+\t\t\t       struct rte_flow_error *error)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct rte_flow_action_handle *entry;\n+\tint rc = EINVAL;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tTAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {\n+\t\tif (entry != handle)\n+\t\t\tcontinue;\n+\n+\t\tif (entry->transfer) {\n+\t\t\trc = sfc_mae_indir_action_destroy(sa, handle,\n+\t\t\t\t\t\t\t  error);\n+\t\t\tif (rc != 0)\n+\t\t\t\tgoto exit;\n+\t\t} else {\n+\t\t\tSFC_ASSERT(B_FALSE);\n+\t\t}\n+\n+\t\tTAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);\n+\t\trte_free(entry);\n+\t\tgoto exit;\n+\t}\n+\n+\trc = rte_flow_error_set(error, ENOENT,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"indirect action handle not found\");\n+\n+exit:\n+\tsfc_adapter_unlock(sa);\n+\treturn rc;\n+}\n+\n+static int\n+sfc_flow_action_handle_query(struct rte_eth_dev *dev,\n+\t\t\t     const struct rte_flow_action_handle *handle,\n+\t\t\t     void *data, struct rte_flow_error *error)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct rte_flow_action_handle *entry;\n+\tint rc = EINVAL;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tTAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {\n+\t\tif (entry != handle)\n+\t\t\tcontinue;\n+\n+\t\tif (entry->transfer) {\n+\t\t\trc = sfc_mae_indir_action_query(sa, handle,\n+\t\t\t\t\t\t\tdata, error);\n+\t\t} else {\n+\t\t\tSFC_ASSERT(B_FALSE);\n+\t\t}\n+\n+\t\tgoto exit;\n+\t}\n+\n+\trc = rte_flow_error_set(error, ENOENT,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"indirect action handle not found\");\n+\n+exit:\n+\tsfc_adapter_unlock(sa);\n+\treturn rc;\n+}\n+\n const struct rte_flow_ops sfc_flow_ops = {\n \t.validate = sfc_flow_validate,\n \t.create = sfc_flow_create,\n@@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = {\n \t.flush = sfc_flow_flush,\n \t.query = sfc_flow_query,\n \t.isolate = sfc_flow_isolate,\n+\t.action_handle_create = sfc_flow_action_handle_create,\n+\t.action_handle_destroy = sfc_flow_action_handle_destroy,\n+\t.action_handle_query = sfc_flow_action_handle_query,\n \t.tunnel_decap_set = sfc_ft_decap_set,\n \t.tunnel_match = sfc_ft_match,\n \t.tunnel_action_decap_release = sfc_ft_action_decap_release,\n@@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa)\n {\n \tSFC_ASSERT(sfc_adapter_is_locked(sa));\n \n+\tTAILQ_INIT(&sa->flow_indir_actions);\n \tTAILQ_INIT(&sa->flow_list);\n }\n \ndiff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h\nindex 8f706fc589..af94d0654a 100644\n--- a/drivers/net/sfc/sfc_flow.h\n+++ b/drivers/net/sfc/sfc_flow.h\n@@ -88,6 +88,20 @@ struct sfc_flow_spec_mae {\n \tsfc_mae_conntrack_key_t\t\tct_key;\n };\n \n+/* PMD-specific definition of the opaque type from rte_flow.h */\n+struct rte_flow_action_handle {\n+\tTAILQ_ENTRY(rte_flow_action_handle)\tentries;\n+\n+\tbool\t\t\t\t\ttransfer;\n+\tenum rte_flow_action_type\t\ttype;\n+\n+\tunion {\n+\t\tstruct sfc_mae_counter\t\t*counter;\n+\t};\n+};\n+\n+TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle);\n+\n /* Flow specification */\n struct sfc_flow_spec {\n \t/* Flow specification type (engine-based) */\ndiff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex d44e066493..9851690f58 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -4005,6 +4005,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,\n \treturn rc;\n }\n \n+static int\n+sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa,\n+\t\t\t\t   const struct rte_flow_action_handle *handle,\n+\t\t\t\t   enum sfc_ft_rule_type ft_rule_type,\n+\t\t\t\t   struct sfc_mae_aset_ctx *ctx,\n+\t\t\t\t   struct rte_flow_error *error)\n+{\n+\tstruct rte_flow_action_handle *entry;\n+\tint rc;\n+\n+\tTAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {\n+\t\tif (entry == handle) {\n+\t\t\tsfc_dbg(sa, \"attaching to indirect_action=%p\", entry);\n+\n+\t\t\tswitch (entry->type) {\n+\t\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\t\t\tif (ft_rule_type != SFC_FT_RULE_NONE) {\n+\t\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"cannot use indirect count action in tunnel model\");\n+\t\t\t\t}\n+\n+\t\t\t\tif (ctx->counter != NULL) {\n+\t\t\t\t\treturn rte_flow_error_set(error, EINVAL,\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"cannot have multiple actions COUNT in one flow\");\n+\t\t\t\t}\n+\n+\t\t\t\trc = efx_mae_action_set_populate_count(ctx->spec);\n+\t\t\t\tif (rc != 0) {\n+\t\t\t\t\treturn rte_flow_error_set(error, rc,\n+\t\t\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t \"failed to add COUNT to MAE action set\");\n+\t\t\t\t}\n+\n+\t\t\t\tctx->counter = entry->counter;\n+\t\t\t\t++(ctx->counter->refcnt);\n+\t\t\t\tbreak;\n+\t\t\tdefault:\n+\t\t\t\tSFC_ASSERT(B_FALSE);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn rte_flow_error_set(error, ENOENT,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"indirect action handle not found\");\n+}\n+\n static int\n sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,\n \t\t\t\tconst struct rte_flow_action_vf *vf_conf,\n@@ -4143,6 +4195,7 @@ static const char * const action_names[] = {\n \t[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = \"OF_SET_VLAN_PCP\",\n \t[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = \"VXLAN_ENCAP\",\n \t[RTE_FLOW_ACTION_TYPE_COUNT] = \"COUNT\",\n+\t[RTE_FLOW_ACTION_TYPE_INDIRECT] = \"INDIRECT\",\n \t[RTE_FLOW_ACTION_TYPE_FLAG] = \"FLAG\",\n \t[RTE_FLOW_ACTION_TYPE_MARK] = \"MARK\",\n \t[RTE_FLOW_ACTION_TYPE_PF] = \"PF\",\n@@ -4258,6 +4311,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,\n \t\trc = sfc_mae_rule_parse_action_count(sa, action->conf,\n \t\t\t\t\t\t     counterp, spec_ptr);\n \t\tbreak;\n+\tcase RTE_FLOW_ACTION_TYPE_INDIRECT:\n+\t\tSFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,\n+\t\t\t\t       bundle->actions_mask);\n+\t\trc = sfc_mae_rule_parse_action_indirect(sa, action->conf,\n+\t\t\t\t\t\t\tspec_mae->ft_rule_type,\n+\t\t\t\t\t\t\tctx, error);\n+\t\tcustom_error = B_TRUE;\n+\t\tbreak;\n \tcase RTE_FLOW_ACTION_TYPE_FLAG:\n \t\tSFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,\n \t\t\t\t       bundle->actions_mask);\n@@ -4813,7 +4874,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa,\n \tstruct sfc_mae_counter *counter;\n \tint rc;\n \n-\tif (action_rule == NULL || action_rule->action_set->counter == NULL) {\n+\tif (action_rule == NULL || action_rule->action_set == NULL ||\n+\t    action_rule->action_set->counter == NULL ||\n+\t    action_rule->action_set->counter->indirect) {\n \t\treturn rte_flow_error_set(error, EINVAL,\n \t\t\tRTE_FLOW_ERROR_TYPE_ACTION, action,\n \t\t\t\"Queried flow rule does not have count actions\");\n@@ -4924,3 +4987,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)\n \tsfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);\n \tsfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);\n }\n+\n+int\n+sfc_mae_indir_action_create(struct sfc_adapter *sa,\n+\t\t\t    const struct rte_flow_action *action,\n+\t\t\t    struct rte_flow_action_handle *handle,\n+\t\t\t    struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\tSFC_ASSERT(handle != NULL);\n+\n+\tswitch (action->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\tret = sfc_mae_rule_parse_action_count(sa, action->conf,\n+\t\t\t\t\t\t      &handle->counter, NULL);\n+\t\tif (ret == 0)\n+\t\t\thandle->counter->indirect = true;\n+\t\tbreak;\n+\tdefault:\n+\t\tret = ENOTSUP;\n+\t}\n+\n+\tif (ret != 0) {\n+\t\treturn rte_flow_error_set(error, ret,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"failed to parse indirect action to mae object\");\n+\t}\n+\n+\thandle->type = action->type;\n+\n+\treturn 0;\n+}\n+\n+int\n+sfc_mae_indir_action_destroy(struct sfc_adapter *sa,\n+\t\t\t     const struct rte_flow_action_handle *handle,\n+\t\t\t     struct rte_flow_error *error)\n+{\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\tSFC_ASSERT(handle != NULL);\n+\n+\tswitch (handle->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\tif (handle->counter->refcnt != 1)\n+\t\t\tgoto fail;\n+\n+\t\tsfc_mae_counter_del(sa, handle->counter);\n+\t\tbreak;\n+\tdefault:\n+\t\tSFC_ASSERT(B_FALSE);\n+\t\tbreak;\n+\t}\n+\n+\treturn 0;\n+\n+fail:\n+\treturn rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t  NULL, \"indirect action is still in use\");\n+}\n+\n+int\n+sfc_mae_indir_action_query(struct sfc_adapter *sa,\n+\t\t\t   const struct rte_flow_action_handle *handle,\n+\t\t\t   void *data, struct rte_flow_error *error)\n+{\n+\tint ret;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\tSFC_ASSERT(handle != NULL);\n+\n+\tswitch (handle->type) {\n+\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n+\t\tSFC_ASSERT(handle->counter != NULL);\n+\n+\t\tif (handle->counter->fw_rsrc.refcnt == 0)\n+\t\t\tgoto fail_not_in_use;\n+\n+\t\tret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,\n+\t\t\t\t\t  handle->counter, data);\n+\t\tif (ret != 0)\n+\t\t\tgoto fail_counter_get;\n+\n+\t\tbreak;\n+\tdefault:\n+\t\tgoto fail_unsup;\n+\t}\n+\n+\treturn 0;\n+\n+fail_not_in_use:\n+\treturn rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t  NULL, \"indirect action is not in use\");\n+\n+fail_counter_get:\n+\treturn rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t  NULL, \"failed to collect indirect action COUNT data\");\n+\n+fail_unsup:\n+\treturn rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t  NULL, \"indirect action of this type cannot be queried\");\n+}\ndiff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex c73ce0a5e6..e7b7d3a35e 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -84,6 +84,8 @@ struct sfc_mae_counter {\n \tstruct sfc_ft_ctx\t\t*ft_ctx;\n \n \tstruct sfc_mae_fw_rsrc\t\tfw_rsrc;\n+\n+\tbool\t\t\t\tindirect;\n };\n \n TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);\n@@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);\n int sfc_mae_switchdev_init(struct sfc_adapter *sa);\n void sfc_mae_switchdev_fini(struct sfc_adapter *sa);\n \n+int sfc_mae_indir_action_create(struct sfc_adapter *sa,\n+\t\t\t\tconst struct rte_flow_action *action,\n+\t\t\t\tstruct rte_flow_action_handle *handle,\n+\t\t\t\tstruct rte_flow_error *error);\n+\n+int sfc_mae_indir_action_destroy(struct sfc_adapter *sa,\n+\t\t\t\t const struct rte_flow_action_handle *handle,\n+\t\t\t\t struct rte_flow_error *error);\n+\n+int sfc_mae_indir_action_query(struct sfc_adapter *sa,\n+\t\t\t       const struct rte_flow_action_handle *handle,\n+\t\t\t       void *data, struct rte_flow_error *error);\n+\n #ifdef __cplusplus\n }\n #endif\n",
    "prefixes": [
        "30/34"
    ]
}