get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 128309,
    "url": "http://patches.dpdk.org/api/patches/128309/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230607130245.8048-21-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": "<20230607130245.8048-21-ivan.malov@arknetworks.am>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230607130245.8048-21-ivan.malov@arknetworks.am",
    "date": "2023-06-07T13:02:31",
    "name": "[v4,20/34] net/sfc: turn MAE flow action rules into shareable resources",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "878ebc548f1ea87c54fff1192915dbd6786693e8",
    "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/20230607130245.8048-21-ivan.malov@arknetworks.am/mbox/",
    "series": [
        {
            "id": 28390,
            "url": "http://patches.dpdk.org/api/series/28390/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=28390",
            "date": "2023-06-07T13:02:11",
            "name": "net/sfc: support HW conntrack assistance",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/28390/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/128309/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/128309/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 C423742C4D;\n\tWed,  7 Jun 2023 15:05:50 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9C8A042DCC;\n\tWed,  7 Jun 2023 15:03:12 +0200 (CEST)",
            "from agw.arknetworks.am (agw.arknetworks.am [79.141.165.80])\n by mails.dpdk.org (Postfix) with ESMTP id 45B7142D51\n for <dev@dpdk.org>; Wed,  7 Jun 2023 15:02:58 +0200 (CEST)",
            "from localhost.localdomain (unknown [78.109.69.83])\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 C354BE1253;\n Wed,  7 Jun 2023 17:02: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 v4 20/34] net/sfc: turn MAE flow action rules into shareable\n resources",
        "Date": "Wed,  7 Jun 2023 17:02:31 +0400",
        "Message-Id": "<20230607130245.8048-21-ivan.malov@arknetworks.am>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20230607130245.8048-1-ivan.malov@arknetworks.am>",
        "References": "<20230601195538.8265-1-ivan.malov@arknetworks.am>\n <20230607130245.8048-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": "Later patches of the series provide support for HW conntrack\nassistance. With the new feature, multiple flows that differ\nin the 5-tuple match fields but are otherwise identical will\nbe able to share all FW-allocatable objects except for those\nof the conntrack table. That will boost flow engine capacity.\n\nTo prepare for that, action rules of the match-action engine\nhave to be turned into shareable objects, from SW standpoint.\n\nSigned-off-by: Ivan Malov <ivan.malov@arknetworks.am>\nReviewed-by: Andy Moreton <amoreton@xilinx.com>\n---\n drivers/net/sfc/sfc_flow.c |   4 +-\n drivers/net/sfc/sfc_flow.h |  13 +-\n drivers/net/sfc/sfc_mae.c  | 362 +++++++++++++++++++++++++++----------\n drivers/net/sfc/sfc_mae.h  |  13 ++\n 4 files changed, 287 insertions(+), 105 deletions(-)",
    "diff": "diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c\nindex 6dfbbfd022..0abeabfbf2 100644\n--- a/drivers/net/sfc/sfc_flow.c\n+++ b/drivers/net/sfc/sfc_flow.c\n@@ -1294,9 +1294,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,\n \t\t}\n \t\tspec->type = SFC_FLOW_SPEC_MAE;\n \t\tspec_mae->priority = attr->priority;\n-\t\tspec_mae->match_spec = NULL;\n-\t\tspec_mae->action_set = NULL;\n-\t\tspec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\t\tspec_mae->action_rule = NULL;\n \t}\n \n \treturn 0;\ndiff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h\nindex ec5e29f257..10c73d012f 100644\n--- a/drivers/net/sfc/sfc_flow.h\n+++ b/drivers/net/sfc/sfc_flow.h\n@@ -75,14 +75,13 @@ struct sfc_flow_spec_mae {\n \tstruct sfc_ft_ctx\t\t*ft_ctx;\n \t/* Desired priority level */\n \tunsigned int\t\t\tpriority;\n-\t/* Outer rule registry entry */\n+\t/*\n+\t * Outer rule registry entry (points to below action_rule->outer_rule\n+\t * when action_rule is not NULL; self-sufficient entry otherwise)\n+\t */\n \tstruct sfc_mae_outer_rule\t*outer_rule;\n-\t/* EFX match specification */\n-\tefx_mae_match_spec_t\t\t*match_spec;\n-\t/* Action set registry entry */\n-\tstruct sfc_mae_action_set\t*action_set;\n-\t/* Firmware-allocated rule ID */\n-\tefx_mae_rule_id_t\t\trule_id;\n+\t/* Action rule registry entry */\n+\tstruct sfc_mae_action_rule\t*action_rule;\n };\n \n /* Flow specification */\ndiff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex 624be53269..addcad2843 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -204,6 +204,7 @@ sfc_mae_attach(struct sfc_adapter *sa)\n \tTAILQ_INIT(&mae->mac_addrs);\n \tTAILQ_INIT(&mae->encap_headers);\n \tTAILQ_INIT(&mae->action_sets);\n+\tTAILQ_INIT(&mae->action_rules);\n \n \tif (encp->enc_mae_admin)\n \t\tmae->status = SFC_MAE_STATUS_ADMIN;\n@@ -1172,6 +1173,200 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,\n \t--(fw_rsrc->refcnt);\n }\n \n+struct sfc_mae_action_rule_ctx {\n+\tstruct sfc_mae_outer_rule\t*outer_rule;\n+\tstruct sfc_mae_action_set\t*action_set;\n+\tefx_mae_match_spec_t\t\t*match_spec;\n+};\n+\n+static int\n+sfc_mae_action_rule_attach(struct sfc_adapter *sa,\n+\t\t\t   const struct sfc_mae_action_rule_ctx *ctx,\n+\t\t\t   struct sfc_mae_action_rule **rulep,\n+\t\t\t   __rte_unused struct rte_flow_error *error)\n+{\n+\tstruct sfc_mae_action_rule *rule;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\t/*\n+\t * It is assumed that the caller of this helper has already properly\n+\t * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when\n+\t * ctx->outer_rule refers to a currently active outer rule) or\n+\t * on 0xffffffff / 0xffffffff, so that specs compare correctly.\n+\t */\n+\tTAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {\n+\t\tif (rule->outer_rule != ctx->outer_rule ||\n+\t\t    rule->action_set != ctx->action_set)\n+\t\t\tcontinue;\n+\n+\t\tif (efx_mae_match_specs_equal(rule->match_spec,\n+\t\t\t\t\t      ctx->match_spec)) {\n+\t\t\tsfc_dbg(sa, \"attaching to action_rule=%p\", rule);\n+\t\t\t++(rule->refcnt);\n+\t\t\t*rulep = rule;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * No need to set RTE error, as this\n+\t * code should be handled gracefully.\n+\t */\n+\treturn -ENOENT;\n+}\n+\n+static int\n+sfc_mae_action_rule_add(struct sfc_adapter *sa,\n+\t\t\tconst struct sfc_mae_action_rule_ctx *ctx,\n+\t\t\tstruct sfc_mae_action_rule **rulep)\n+{\n+\tstruct sfc_mae_action_rule *rule;\n+\tstruct sfc_mae *mae = &sa->mae;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\trule = rte_zmalloc(\"sfc_mae_action_rule\", sizeof(*rule), 0);\n+\tif (rule == NULL)\n+\t\treturn ENOMEM;\n+\n+\trule->refcnt = 1;\n+\trule->outer_rule = ctx->outer_rule;\n+\trule->action_set = ctx->action_set;\n+\trule->match_spec = ctx->match_spec;\n+\n+\trule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\n+\tTAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);\n+\n+\t*rulep = rule;\n+\n+\tsfc_dbg(sa, \"added action_rule=%p\", rule);\n+\n+\treturn 0;\n+}\n+\n+static void\n+sfc_mae_action_rule_del(struct sfc_adapter *sa,\n+\t\t\tstruct sfc_mae_action_rule *rule)\n+{\n+\tstruct sfc_mae *mae = &sa->mae;\n+\tif (rule == NULL)\n+\t\treturn;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\tSFC_ASSERT(rule->refcnt != 0);\n+\n+\t--(rule->refcnt);\n+\n+\tif (rule->refcnt != 0)\n+\t\treturn;\n+\n+\tif (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||\n+\t    rule->fw_rsrc.refcnt != 0) {\n+\t\tsfc_err(sa, \"deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u\",\n+\t\t\trule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);\n+\t}\n+\n+\tefx_mae_match_spec_fini(sa->nic, rule->match_spec);\n+\tsfc_mae_action_set_del(sa, rule->action_set);\n+\tsfc_mae_outer_rule_del(sa, rule->outer_rule);\n+\n+\tTAILQ_REMOVE(&mae->action_rules, rule, entries);\n+\trte_free(rule);\n+\n+\tsfc_dbg(sa, \"deleted action_rule=%p\", rule);\n+}\n+\n+static int\n+sfc_mae_action_rule_enable(struct sfc_adapter *sa,\n+\t\t\t   struct sfc_mae_action_rule *rule)\n+{\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n+\tint rc;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tfw_rsrc = &rule->fw_rsrc;\n+\n+\tif (fw_rsrc->refcnt != 0)\n+\t\tgoto success;\n+\n+\trc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);\n+\tif (rc != 0)\n+\t\tgoto fail_outer_rule_enable;\n+\n+\trc = sfc_mae_action_set_enable(sa, rule->action_set);\n+\tif (rc != 0)\n+\t\tgoto fail_action_set_enable;\n+\n+\trc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, NULL,\n+\t\t\t\t\t&rule->action_set->fw_rsrc.aset_id,\n+\t\t\t\t\t&fw_rsrc->rule_id);\n+\tif (rc != 0) {\n+\t\tsfc_err(sa, \"failed to enable action_rule=%p: %s\",\n+\t\t\trule, strerror(rc));\n+\t\tgoto fail_action_rule_insert;\n+\t}\n+\n+success:\n+\tif (fw_rsrc->refcnt == 0) {\n+\t\tsfc_dbg(sa, \"enabled action_rule=%p: AR_ID=0x%08x\",\n+\t\t\trule, fw_rsrc->rule_id.id);\n+\t}\n+\n+\t++(fw_rsrc->refcnt);\n+\n+\treturn 0;\n+\n+fail_action_rule_insert:\n+\tsfc_mae_action_set_disable(sa, rule->action_set);\n+\n+fail_action_set_enable:\n+\tsfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);\n+\n+fail_outer_rule_enable:\n+\treturn rc;\n+}\n+static void\n+sfc_mae_action_rule_disable(struct sfc_adapter *sa,\n+\t\t\t    struct sfc_mae_action_rule *rule)\n+{\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n+\tint rc;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tfw_rsrc = &rule->fw_rsrc;\n+\n+\tif (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||\n+\t    fw_rsrc->refcnt == 0) {\n+\t\tsfc_err(sa, \"failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u\",\n+\t\t\trule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);\n+\t\treturn;\n+\t}\n+\n+\tif (fw_rsrc->refcnt == 1) {\n+\t\trc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);\n+\t\tif (rc == 0) {\n+\t\t\tsfc_dbg(sa, \"disabled action_rule=%p with AR_ID=0x%08x\",\n+\t\t\t\trule, fw_rsrc->rule_id.id);\n+\t\t} else {\n+\t\t\tsfc_err(sa, \"failed to disable action_rule=%p with AR_ID=0x%08x: %s\",\n+\t\t\t\trule, fw_rsrc->rule_id.id, strerror(rc));\n+\t\t}\n+\n+\t\tfw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;\n+\n+\t\tsfc_mae_action_set_disable(sa, rule->action_set);\n+\n+\t\tsfc_mae_outer_rule_disable(sa, rule->outer_rule,\n+\t\t\t\t\t   rule->match_spec);\n+\t}\n+\n+\t--(fw_rsrc->refcnt);\n+}\n+\n void\n sfc_mae_flow_cleanup(struct sfc_adapter *sa,\n \t\t     struct rte_flow *flow)\n@@ -1191,13 +1386,7 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,\n \t\t--(spec_mae->ft_ctx->refcnt);\n \t}\n \n-\tSFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);\n-\n-\tsfc_mae_outer_rule_del(sa, spec_mae->outer_rule);\n-\tsfc_mae_action_set_del(sa, spec_mae->action_set);\n-\n-\tif (spec_mae->match_spec != NULL)\n-\t\tefx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);\n+\tsfc_mae_action_rule_del(sa, spec_mae->action_rule);\n }\n \n static int\n@@ -2781,9 +2970,11 @@ static int\n sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \t\t\t   const struct rte_flow_item pattern[],\n \t\t\t   struct rte_flow *flow,\n+\t\t\t   struct sfc_mae_action_rule_ctx *action_rule_ctx,\n \t\t\t   struct rte_flow_error *error)\n {\n \tstruct sfc_flow_spec_mae *spec = &flow->spec.mae;\n+\tstruct sfc_mae_outer_rule **outer_rulep;\n \tstruct sfc_mae_parse_ctx ctx_mae;\n \tunsigned int priority_shift = 0;\n \tstruct sfc_flow_parse_ctx ctx;\n@@ -2796,6 +2987,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \tctx_mae.ft_ctx = spec->ft_ctx;\n \tctx_mae.sa = sa;\n \n+\touter_rulep = &action_rule_ctx->outer_rule;\n+\n \tswitch (ctx_mae.ft_rule_type) {\n \tcase SFC_FT_RULE_TUNNEL:\n \t\t/*\n@@ -2872,7 +3065,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \tif (rc != 0)\n \t\tgoto fail_process_pattern_data;\n \n-\trc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);\n+\trc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);\n \tif (rc != 0)\n \t\tgoto fail_process_outer;\n \n@@ -2884,7 +3077,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \t\tgoto fail_validate_match_spec_action;\n \t}\n \n-\tspec->match_spec = ctx_mae.match_spec_action;\n+\taction_rule_ctx->match_spec = ctx_mae.match_spec_action;\n \n \treturn 0;\n \n@@ -3806,6 +3999,7 @@ static int\n sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\t\t   const struct rte_flow_action actions[],\n \t\t\t   struct rte_flow *flow,\n+\t\t\t   struct sfc_mae_action_rule_ctx *action_rule_ctx,\n \t\t\t   struct rte_flow_error *error)\n {\n \tstruct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;\n@@ -3927,8 +4121,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\tgoto fail_check_fate_action;\n \t}\n \n-\tspec_mae->action_set = sfc_mae_action_set_attach(sa, &ctx);\n-\tif (spec_mae->action_set != NULL) {\n+\taction_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);\n+\tif (action_rule_ctx->action_set != NULL) {\n \t\tsfc_mae_mac_addr_del(sa, ctx.src_mac);\n \t\tsfc_mae_mac_addr_del(sa, ctx.dst_mac);\n \t\tsfc_mae_encap_header_del(sa, ctx.encap_header);\n@@ -3936,7 +4130,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,\n \t\treturn 0;\n \t}\n \n-\trc = sfc_mae_action_set_add(sa, actions, &ctx, &spec_mae->action_set);\n+\trc = sfc_mae_action_set_add(sa, actions, &ctx,\n+\t\t\t\t    &action_rule_ctx->action_set);\n \tif (rc != 0)\n \t\tgoto fail_action_set_add;\n \n@@ -3972,6 +4167,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],\n {\n \tstruct sfc_flow_spec *spec = &flow->spec;\n \tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n+\tstruct sfc_mae_action_rule_ctx ctx = {};\n \tint rc;\n \n \t/*\n@@ -3982,7 +4178,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],\n \tif (rc != 0)\n \t\tgoto fail;\n \n-\trc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);\n+\trc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);\n \tif (rc != 0)\n \t\tgoto fail;\n \n@@ -3998,10 +4194,30 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],\n \t\t */\n \t}\n \n-\trc = sfc_mae_rule_parse_actions(sa, actions, flow, error);\n+\tspec_mae->outer_rule = ctx.outer_rule;\n+\n+\trc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);\n \tif (rc != 0)\n \t\tgoto fail;\n \n+\trc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,\n+\t\t\t\t\terror);\n+\tif (rc == 0) {\n+\t\tefx_mae_match_spec_fini(sa->nic, ctx.match_spec);\n+\t\tsfc_mae_action_set_del(sa, ctx.action_set);\n+\t\tsfc_mae_outer_rule_del(sa, ctx.outer_rule);\n+\t} else if (rc == -ENOENT) {\n+\t\trc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);\n+\t\tif (rc != 0) {\n+\t\t\trc = rte_flow_error_set(error, rc,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n+\t\t\t\t\tNULL, \"AR: failed to add the entry\");\n+\t\t\tgoto fail;\n+\t\t}\n+\t} else {\n+\t\tgoto fail;\n+\t}\n+\n \tif (spec_mae->ft_ctx != NULL) {\n \t\tif (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)\n \t\t\tspec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;\n@@ -4012,6 +4228,12 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],\n \treturn 0;\n \n fail:\n+\tif (ctx.match_spec != NULL)\n+\t\tefx_mae_match_spec_fini(sa->nic, ctx.match_spec);\n+\n+\tsfc_mae_action_set_del(sa, ctx.action_set);\n+\tsfc_mae_outer_rule_del(sa, ctx.outer_rule);\n+\n \t/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */\n \tspec_mae->ft_rule_type = SFC_FT_RULE_NONE;\n \tspec_mae->ft_ctx = NULL;\n@@ -4071,30 +4293,27 @@ sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,\n \n static int\n sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,\n-\t\t\t\t struct sfc_flow_spec_mae *spec)\n+\t\t\t\t struct sfc_mae_action_rule *rule)\n {\n-\tconst struct rte_flow *entry;\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;\n+\tconst struct sfc_mae_action_rule *entry;\n+\tstruct sfc_mae *mae = &sa->mae;\n \n-\tif (spec->match_spec == NULL)\n+\tif (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {\n+\t\t/* An active rule is reused. Its class is known to be valid. */\n \t\treturn 0;\n+\t}\n \n-\tTAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {\n-\t\tconst struct sfc_flow_spec *entry_spec = &entry->spec;\n-\t\tconst struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;\n-\t\tconst efx_mae_match_spec_t *left = es_mae->match_spec;\n-\t\tconst efx_mae_match_spec_t *right = spec->match_spec;\n+\tTAILQ_FOREACH_REVERSE(entry, &mae->action_rules,\n+\t\t\t      sfc_mae_action_rules, entries) {\n+\t\tconst efx_mae_match_spec_t *left = entry->match_spec;\n+\t\tconst efx_mae_match_spec_t *right = rule->match_spec;\n \n-\t\tswitch (entry_spec->type) {\n-\t\tcase SFC_FLOW_SPEC_FILTER:\n-\t\t\t/* Ignore VNIC-level flows */\n-\t\t\tbreak;\n-\t\tcase SFC_FLOW_SPEC_MAE:\n-\t\t\tif (sfc_mae_rules_class_cmp(sa, left, right))\n-\t\t\t\treturn 0;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tSFC_ASSERT(false);\n-\t\t}\n+\t\tif (entry == rule)\n+\t\t\tcontinue;\n+\n+\t\tif (sfc_mae_rules_class_cmp(sa, left, right))\n+\t\t\treturn 0;\n \t}\n \n \tsfc_info(sa, \"for now, the HW doesn't support rule validation, and HW \"\n@@ -4124,6 +4343,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,\n {\n \tstruct sfc_flow_spec *spec = &flow->spec;\n \tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n+\tstruct sfc_mae_action_rule *action_rule = spec_mae->action_rule;\n \tstruct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;\n \tint rc;\n \n@@ -4136,7 +4356,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,\n \tif (rc != 0)\n \t\treturn rc;\n \n-\treturn sfc_mae_action_rule_class_verify(sa, spec_mae);\n+\treturn sfc_mae_action_rule_class_verify(sa, action_rule);\n }\n \n int\n@@ -4145,55 +4365,22 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,\n {\n \tstruct sfc_flow_spec *spec = &flow->spec;\n \tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n-\tstruct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;\n-\tstruct sfc_mae_action_set *action_set = spec_mae->action_set;\n-\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n+\tstruct sfc_mae_action_rule *action_rule = spec_mae->action_rule;\n \tint rc;\n \n-\tSFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);\n-\n-\tif (outer_rule != NULL) {\n-\t\trc = sfc_mae_outer_rule_enable(sa, outer_rule,\n-\t\t\t\t\t       spec_mae->match_spec);\n-\t\tif (rc != 0)\n-\t\t\tgoto fail_outer_rule_enable;\n-\t}\n-\n \tif (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {\n \t\tspec_mae->ft_ctx->reset_tunnel_hit_counter =\n \t\t\tspec_mae->ft_ctx->switch_hit_counter;\n \t}\n \n-\tif (action_set == NULL) {\n-\t\tsfc_dbg(sa, \"enabled flow=%p (no AR)\", flow);\n+\tif (action_rule == NULL)\n \t\treturn 0;\n-\t}\n-\n-\trc = sfc_mae_action_set_enable(sa, action_set);\n-\tif (rc != 0)\n-\t\tgoto fail_action_set_enable;\n-\n-\tfw_rsrc = &action_set->fw_rsrc;\n \n-\trc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,\n-\t\t\t\t\tNULL, &fw_rsrc->aset_id,\n-\t\t\t\t\t&spec_mae->rule_id);\n+\trc = sfc_mae_action_rule_enable(sa, action_rule);\n \tif (rc != 0)\n-\t\tgoto fail_action_rule_insert;\n-\n-\tsfc_dbg(sa, \"enabled flow=%p: AR_ID=0x%08x\",\n-\t\tflow, spec_mae->rule_id.id);\n+\t\treturn rc;\n \n \treturn 0;\n-\n-fail_action_rule_insert:\n-\tsfc_mae_action_set_disable(sa, action_set);\n-\n-fail_action_set_enable:\n-\tsfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);\n-\n-fail_outer_rule_enable:\n-\treturn rc;\n }\n \n int\n@@ -4202,30 +4389,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,\n {\n \tstruct sfc_flow_spec *spec = &flow->spec;\n \tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n-\tstruct sfc_mae_action_set *action_set = spec_mae->action_set;\n-\tstruct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;\n-\tint rc;\n+\tstruct sfc_mae_action_rule *action_rule = spec_mae->action_rule;\n \n-\tif (action_set == NULL) {\n-\t\tsfc_dbg(sa, \"disabled flow=%p (no AR)\", flow);\n-\t\tgoto skip_action_rule;\n-\t}\n-\n-\tSFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);\n-\n-\trc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);\n-\tif (rc != 0) {\n-\t\tsfc_err(sa, \"failed to disable flow=%p with AR_ID=0x%08x: %s\",\n-\t\t\tflow, spec_mae->rule_id.id, strerror(rc));\n-\t}\n-\tsfc_dbg(sa, \"disabled flow=%p with AR_ID=0x%08x\",\n-\t\tflow, spec_mae->rule_id.id);\n-\tspec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;\n-\n-\tsfc_mae_action_set_disable(sa, action_set);\n+\tif (action_rule == NULL)\n+\t\treturn 0;\n \n-skip_action_rule:\n-\tsfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);\n+\tsfc_mae_action_rule_disable(sa, action_rule);\n \n \treturn 0;\n }\n@@ -4237,17 +4406,20 @@ sfc_mae_query_counter(struct sfc_adapter *sa,\n \t\t      struct rte_flow_query_count *data,\n \t\t      struct rte_flow_error *error)\n {\n-\tstruct sfc_mae_action_set *action_set = spec->action_set;\n+\tconst struct sfc_mae_action_rule *action_rule = spec->action_rule;\n \tconst struct rte_flow_action_count *conf = action->conf;\n+\tstruct sfc_mae_action_set *action_set;\n \tunsigned int i;\n \tint rc;\n \n-\tif (action_set == NULL || action_set->n_counters == 0) {\n+\tif (action_rule == NULL || action_rule->action_set->n_counters == 0) {\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 \t}\n \n+\taction_set = action_rule->action_set;\n+\n \tfor (i = 0; i < action_set->n_counters; i++) {\n \t\t/*\n \t\t * Get the first available counter of the flow rule if\ndiff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex 1d937c9b5b..cbe190075c 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -97,6 +97,17 @@ struct sfc_mae_action_set {\n \n TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);\n \n+/** Action rule registry entry */\n+struct sfc_mae_action_rule {\n+\tTAILQ_ENTRY(sfc_mae_action_rule)\tentries;\n+\tstruct sfc_mae_outer_rule\t\t*outer_rule;\n+\tstruct sfc_mae_action_set\t\t*action_set;\n+\tefx_mae_match_spec_t\t\t\t*match_spec;\n+\tstruct sfc_mae_fw_rsrc\t\t\tfw_rsrc;\n+\tunsigned int\t\t\t\trefcnt;\n+};\n+TAILQ_HEAD(sfc_mae_action_rules, sfc_mae_action_rule);\n+\n /** Options for MAE support status */\n enum sfc_mae_status {\n \tSFC_MAE_STATUS_UNKNOWN = 0,\n@@ -201,6 +212,8 @@ struct sfc_mae {\n \tstruct sfc_mae_mac_addrs\tmac_addrs;\n \t/** Action set registry */\n \tstruct sfc_mae_action_sets\taction_sets;\n+\t/** Action rule registry */\n+\tstruct sfc_mae_action_rules\taction_rules;\n \t/** Encap. header bounce buffer */\n \tstruct sfc_mae_bounce_eh\tbounce_eh;\n \t/** Flag indicating whether counter-only RxQ is running */\n",
    "prefixes": [
        "v4",
        "20/34"
    ]
}