get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 100023,
    "url": "http://patches.dpdk.org/api/patches/100023/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20210929205730.775-4-ivan.malov@oktetlabs.ru/",
    "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": "<20210929205730.775-4-ivan.malov@oktetlabs.ru>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210929205730.775-4-ivan.malov@oktetlabs.ru",
    "date": "2021-09-29T20:57:23",
    "name": "[03/10] net/sfc: support JUMP flows in tunnel offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2f679577024261203b98d206dde85da717fbb5d2",
    "submitter": {
        "id": 869,
        "url": "http://patches.dpdk.org/api/people/869/?format=api",
        "name": "Ivan Malov",
        "email": "Ivan.Malov@oktetlabs.ru"
    },
    "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/20210929205730.775-4-ivan.malov@oktetlabs.ru/mbox/",
    "series": [
        {
            "id": 19272,
            "url": "http://patches.dpdk.org/api/series/19272/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=19272",
            "date": "2021-09-29T20:57:20",
            "name": "net/sfc: add support for tunnel offload",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/19272/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/100023/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/100023/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 0D2A4A0032;\n\tWed, 29 Sep 2021 22:58:03 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E225041109;\n\tWed, 29 Sep 2021 22:57:48 +0200 (CEST)",
            "from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113])\n by mails.dpdk.org (Postfix) with ESMTP id 24E02410EE\n for <dev@dpdk.org>; Wed, 29 Sep 2021 22:57:45 +0200 (CEST)",
            "from localhost.localdomain (unknown [5.144.122.192])\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 shelob.oktetlabs.ru (Postfix) with ESMTPSA id CAF0F7F553;\n Wed, 29 Sep 2021 23:57:44 +0300 (MSK)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru CAF0F7F553",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=simple/simple; d=oktetlabs.ru;\n s=default; t=1632949064;\n bh=tgcp9Ml3rKJz4djm1/bhq0oiTqt/AM9MdUjfO0FbApY=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References;\n b=VN1f23IqZLj5kBSD7UMoa3W+Uke77QbNJxc+Qh2dWtWM7a4iaQUFFt3MGu2faKJQ9\n yU/dU9fm9dTOa0rUZCF1zo5WUGonqNuYaQG2Ca+DlId9LnRABUx7jPF7vWl59nntIa\n 4hml5cYTQMkY+tn8RpGOFxejbUAU/pfTyAaz7+JA=",
        "From": "Ivan Malov <ivan.malov@oktetlabs.ru>",
        "To": "dev@dpdk.org",
        "Cc": "Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>",
        "Date": "Wed, 29 Sep 2021 23:57:23 +0300",
        "Message-Id": "<20210929205730.775-4-ivan.malov@oktetlabs.ru>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20210929205730.775-1-ivan.malov@oktetlabs.ru>",
        "References": "<20210929205730.775-1-ivan.malov@oktetlabs.ru>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH 03/10] net/sfc: support JUMP flows in tunnel\n offload",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "JUMP is an in-house term for so-called \"tunnel_set\" flows. On parsing,\nthey are identified by virtue of actions MARK (PMD-internal) and JUMP.\nThe action MARK associates a given flow with its tunnel context.\n\nSuch a flow is represented by a MAE outer rule (OR) which has its\nrecirculation ID set. This ID is also associated with the tunnel\ncontext. The OR is supposed to set this ID in 8 high bits of\nRx mark in matching packets. It also counts the packets.\n\nPackets that hit the OR but miss in action rule (AR) table,\nshould go to MAE admin PF (that is, to DPDK) by default.\n\nSupport for the use of action COUNT in JUMP\nflows will be introduced by later patches.\n\nSigned-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>\nReviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>\n---\n drivers/net/sfc/sfc.h             |   3 +\n drivers/net/sfc/sfc_flow.c        |  35 ++++++-\n drivers/net/sfc/sfc_flow.h        |  12 +++\n drivers/net/sfc/sfc_flow_tunnel.c | 116 ++++++++++++++++++++++\n drivers/net/sfc/sfc_flow_tunnel.h |  31 ++++++\n drivers/net/sfc/sfc_mae.c         | 156 +++++++++++++++++++++++-------\n drivers/net/sfc/sfc_mae.h         |   2 +\n 7 files changed, 319 insertions(+), 36 deletions(-)",
    "diff": "diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h\nindex 2812d76cbb..35b776f443 100644\n--- a/drivers/net/sfc/sfc.h\n+++ b/drivers/net/sfc/sfc.h\n@@ -27,6 +27,7 @@\n #include \"sfc_debug.h\"\n #include \"sfc_log.h\"\n #include \"sfc_filter.h\"\n+#include \"sfc_flow_tunnel.h\"\n #include \"sfc_sriov.h\"\n #include \"sfc_mae.h\"\n #include \"sfc_dp.h\"\n@@ -258,6 +259,8 @@ struct sfc_adapter {\n \tstruct sfc_intr\t\t\tintr;\n \tstruct sfc_port\t\t\tport;\n \tstruct sfc_sw_xstats\t\tsw_xstats;\n+\t/* Registry of tunnel offload contexts */\n+\tstruct sfc_flow_tunnel\t\tflow_tunnels[SFC_FT_MAX_NTUNNELS];\n \tstruct sfc_filter\t\tfilter;\n \tstruct sfc_mae\t\t\tmae;\n \ndiff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c\nindex 7510cbb95b..fe726afc9c 100644\n--- a/drivers/net/sfc/sfc_flow.c\n+++ b/drivers/net/sfc/sfc_flow.c\n@@ -2547,15 +2547,46 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,\n \tstruct sfc_flow_spec_mae *spec_mae = &spec->mae;\n \tint rc;\n \n+\t/*\n+\t * If the flow is meant to be a JUMP rule in tunnel offload,\n+\t * preparse its actions and save its properties in spec_mae.\n+\t */\n+\trc = sfc_flow_tunnel_detect_jump_rule(sa, actions, spec_mae, error);\n+\tif (rc != 0)\n+\t\tgoto fail;\n+\n \trc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);\n \tif (rc != 0)\n-\t\treturn rc;\n+\t\tgoto fail;\n+\n+\tif (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {\n+\t\t/*\n+\t\t * This flow is represented solely by the outer rule.\n+\t\t * It is supposed to mark and count matching packets.\n+\t\t */\n+\t\tgoto skip_action_rule;\n+\t}\n \n \trc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);\n \tif (rc != 0)\n-\t\treturn rc;\n+\t\tgoto fail;\n+\n+skip_action_rule:\n+\tif (spec_mae->ft != NULL) {\n+\t\tif (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)\n+\t\t\tspec_mae->ft->jump_rule_is_set = B_TRUE;\n+\n+\t\t++(spec_mae->ft->refcnt);\n+\t}\n \n \treturn 0;\n+\n+fail:\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 = NULL;\n+\n+\treturn rc;\n }\n \n static int\ndiff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h\nindex 3435d53ba4..ada3d563ad 100644\n--- a/drivers/net/sfc/sfc_flow.h\n+++ b/drivers/net/sfc/sfc_flow.h\n@@ -63,8 +63,20 @@ struct sfc_flow_spec_filter {\n \tstruct sfc_flow_rss rss_conf;\n };\n \n+/* Indicates the role of a given flow in tunnel offload */\n+enum sfc_flow_tunnel_rule_type {\n+\t/* The flow has nothing to do with tunnel offload */\n+\tSFC_FT_RULE_NONE = 0,\n+\t/* The flow represents a JUMP rule */\n+\tSFC_FT_RULE_JUMP,\n+};\n+\n /* MAE-specific flow specification */\n struct sfc_flow_spec_mae {\n+\t/* FLow Tunnel (FT) rule type (or NONE) */\n+\tenum sfc_flow_tunnel_rule_type\tft_rule_type;\n+\t/* Flow Tunnel (FT) context (or NULL) */\n+\tstruct sfc_flow_tunnel\t\t*ft;\n \t/* Desired priority level */\n \tunsigned int\t\t\tpriority;\n \t/* Outer rule registry entry */\ndiff --git a/drivers/net/sfc/sfc_flow_tunnel.c b/drivers/net/sfc/sfc_flow_tunnel.c\nindex 06b4a27a65..b03c90c9a4 100644\n--- a/drivers/net/sfc/sfc_flow_tunnel.c\n+++ b/drivers/net/sfc/sfc_flow_tunnel.c\n@@ -7,6 +7,7 @@\n #include <stdint.h>\n \n #include \"sfc.h\"\n+#include \"sfc_flow.h\"\n #include \"sfc_dp_rx.h\"\n #include \"sfc_flow_tunnel.h\"\n #include \"sfc_mae.h\"\n@@ -27,3 +28,118 @@ sfc_flow_tunnel_is_active(struct sfc_adapter *sa)\n \n \treturn ((sa->negotiated_rx_meta & RTE_ETH_RX_META_TUNNEL_ID) != 0);\n }\n+\n+struct sfc_flow_tunnel *\n+sfc_flow_tunnel_pick(struct sfc_adapter *sa, uint32_t ft_mark)\n+{\n+\tuint32_t tunnel_mark = SFC_FT_GET_TUNNEL_MARK(ft_mark);\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tif (tunnel_mark != SFC_FT_TUNNEL_MARK_INVALID) {\n+\t\tsfc_ft_id_t ft_id = SFC_FT_TUNNEL_MARK_TO_ID(tunnel_mark);\n+\t\tstruct sfc_flow_tunnel *ft = &sa->flow_tunnels[ft_id];\n+\n+\t\tft->id = ft_id;\n+\n+\t\treturn ft;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+int\n+sfc_flow_tunnel_detect_jump_rule(struct sfc_adapter *sa,\n+\t\t\t\t const struct rte_flow_action *actions,\n+\t\t\t\t struct sfc_flow_spec_mae *spec,\n+\t\t\t\t struct rte_flow_error *error)\n+{\n+\tconst struct rte_flow_action_mark *action_mark = NULL;\n+\tconst struct rte_flow_action_jump *action_jump = NULL;\n+\tstruct sfc_flow_tunnel *ft;\n+\tuint32_t ft_mark = 0;\n+\tint rc = 0;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tif (!sfc_flow_tunnel_is_active(sa)) {\n+\t\t/* Tunnel-related actions (if any) will be turned down later. */\n+\t\treturn 0;\n+\t}\n+\n+\tif (actions == NULL) {\n+\t\trte_flow_error_set(error, EINVAL,\n+\t\t\t\t   RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,\n+\t\t\t\t   \"NULL actions\");\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {\n+\t\tif (actions->type == RTE_FLOW_ACTION_TYPE_VOID)\n+\t\t\tcontinue;\n+\n+\t\tif (actions->conf == NULL) {\n+\t\t\trc = EINVAL;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tswitch (actions->type) {\n+\t\tcase RTE_FLOW_ACTION_TYPE_MARK:\n+\t\t\tif (action_mark == NULL) {\n+\t\t\t\taction_mark = actions->conf;\n+\t\t\t\tft_mark = action_mark->id;\n+\t\t\t} else {\n+\t\t\t\trc = EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n+\t\t\tif (action_jump == NULL) {\n+\t\t\t\taction_jump = actions->conf;\n+\t\t\t\tif (action_jump->group != 0)\n+\t\t\t\t\trc = EINVAL;\n+\t\t\t} else {\n+\t\t\t\trc = EINVAL;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\trc = ENOTSUP;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tft = sfc_flow_tunnel_pick(sa, ft_mark);\n+\tif (ft != NULL && action_jump != 0) {\n+\t\tsfc_dbg(sa, \"tunnel offload: JUMP: detected\");\n+\n+\t\tif (rc != 0) {\n+\t\t\t/* The loop above might have spotted wrong actions. */\n+\t\t\tsfc_err(sa, \"tunnel offload: JUMP: invalid actions: %s\",\n+\t\t\t\tstrerror(rc));\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\tif (ft->refcnt == 0) {\n+\t\t\tsfc_err(sa, \"tunnel offload: JUMP: tunnel=%u does not exist\",\n+\t\t\t\tft->id);\n+\t\t\trc = ENOENT;\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\tif (ft->jump_rule_is_set) {\n+\t\t\tsfc_err(sa, \"tunnel offload: JUMP: already exists in tunnel=%u\",\n+\t\t\t\tft->id);\n+\t\t\trc = EEXIST;\n+\t\t\tgoto fail;\n+\t\t}\n+\n+\t\tspec->ft_rule_type = SFC_FT_RULE_JUMP;\n+\t\tspec->ft = ft;\n+\t}\n+\n+\treturn 0;\n+\n+fail:\n+\treturn rte_flow_error_set(error, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: JUMP: preparsing failed\");\n+}\ndiff --git a/drivers/net/sfc/sfc_flow_tunnel.h b/drivers/net/sfc/sfc_flow_tunnel.h\nindex fec891fdad..6a81b29438 100644\n--- a/drivers/net/sfc/sfc_flow_tunnel.h\n+++ b/drivers/net/sfc/sfc_flow_tunnel.h\n@@ -10,6 +10,8 @@\n #include <stdbool.h>\n #include <stdint.h>\n \n+#include \"efx.h\"\n+\n #ifdef __cplusplus\n extern \"C\" {\n #endif\n@@ -26,12 +28,41 @@ typedef uint8_t sfc_ft_id_t;\n #define SFC_FT_USER_MARK_MASK \\\n \tRTE_LEN2MASK(SFC_FT_USER_MARK_BITS, uint32_t)\n \n+#define SFC_FT_GET_TUNNEL_MARK(_mark) \\\n+\t((_mark) >> SFC_FT_USER_MARK_BITS)\n+\n+#define SFC_FT_TUNNEL_MARK_INVALID\t(0)\n+\n+#define SFC_FT_TUNNEL_MARK_TO_ID(_tunnel_mark) \\\n+\t((_tunnel_mark) - 1)\n+\n+#define SFC_FT_ID_TO_TUNNEL_MARK(_id) \\\n+\t((_id) + 1)\n+\n+#define SFC_FT_MAX_NTUNNELS \\\n+\t(RTE_LEN2MASK(SFC_FT_TUNNEL_MARK_BITS, uint8_t) - 1)\n+\n+struct sfc_flow_tunnel {\n+\tbool\t\t\t\tjump_rule_is_set;\n+\tefx_tunnel_protocol_t\t\tencap_type;\n+\tunsigned int\t\t\trefcnt;\n+\tsfc_ft_id_t\t\t\tid;\n+};\n+\n struct sfc_adapter;\n \n bool sfc_flow_tunnel_is_supported(struct sfc_adapter *sa);\n \n bool sfc_flow_tunnel_is_active(struct sfc_adapter *sa);\n \n+struct sfc_flow_tunnel *sfc_flow_tunnel_pick(struct sfc_adapter *sa,\n+\t\t\t\t\t     uint32_t ft_mark);\n+\n+int sfc_flow_tunnel_detect_jump_rule(struct sfc_adapter *sa,\n+\t\t\t\t     const struct rte_flow_action *actions,\n+\t\t\t\t     struct sfc_flow_spec_mae *spec,\n+\t\t\t\t     struct rte_flow_error *error);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c\nindex 2b80492e59..57a999d895 100644\n--- a/drivers/net/sfc/sfc_mae.c\n+++ b/drivers/net/sfc/sfc_mae.c\n@@ -269,6 +269,9 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,\n \t\t}\n \t}\n \n+\tif (match_spec_action == NULL)\n+\t\tgoto skip_action_rule;\n+\n \trc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,\n \t\t\t\t\t\t  &fw_rsrc->rule_id);\n \tif (rc != 0) {\n@@ -283,6 +286,7 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,\n \t\treturn rc;\n \t}\n \n+skip_action_rule:\n \tif (fw_rsrc->refcnt == 0) {\n \t\tsfc_dbg(sa, \"enabled outer_rule=%p: OR_ID=0x%08x\",\n \t\t\trule, fw_rsrc->rule_id.id);\n@@ -806,6 +810,14 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,\n \n \tspec_mae = &spec->mae;\n \n+\tif (spec_mae->ft != NULL) {\n+\t\tif (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)\n+\t\t\tspec_mae->ft->jump_rule_is_set = B_FALSE;\n+\n+\t\tSFC_ASSERT(spec_mae->ft->refcnt != 0);\n+\t\t--(spec_mae->ft->refcnt);\n+\t}\n+\n \tSFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);\n \n \tif (spec_mae->outer_rule != NULL)\n@@ -2146,6 +2158,16 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,\n \tctx->match_spec_outer = NULL;\n \n no_or_id:\n+\tswitch (ctx->ft_rule_type) {\n+\tcase SFC_FT_RULE_NONE:\n+\t\tbreak;\n+\tcase SFC_FT_RULE_JUMP:\n+\t\t/* No action rule */\n+\t\treturn 0;\n+\tdefault:\n+\t\tSFC_ASSERT(B_FALSE);\n+\t}\n+\n \t/*\n \t * In MAE, lookup sequence comprises outer parse, outer rule lookup,\n \t * inner parse (when some outer rule is hit) and action rule lookup.\n@@ -2183,6 +2205,7 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,\n \t\t\t      struct rte_flow_error *error)\n {\n \tstruct sfc_mae *mae = &sa->mae;\n+\tuint8_t recirc_id = 0;\n \tint rc;\n \n \tif (pattern == NULL) {\n@@ -2222,34 +2245,71 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,\n \t\tbreak;\n \t}\n \n-\tif (pattern->type == RTE_FLOW_ITEM_TYPE_END)\n-\t\treturn 0;\n+\tswitch (ctx->ft_rule_type) {\n+\tcase SFC_FT_RULE_NONE:\n+\t\tif (pattern->type == RTE_FLOW_ITEM_TYPE_END)\n+\t\t\treturn 0;\n+\t\tbreak;\n+\tcase SFC_FT_RULE_JUMP:\n+\t\tif (pattern->type != RTE_FLOW_ITEM_TYPE_END) {\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n+\t\t\t\t\t\t  pattern, \"tunnel offload: JUMP: invalid item\");\n+\t\t}\n+\t\tctx->encap_type = ctx->ft->encap_type;\n+\t\tbreak;\n+\tdefault:\n+\t\tSFC_ASSERT(B_FALSE);\n+\t\tbreak;\n+\t}\n \n \tif ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) {\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t  pattern, \"Unsupported tunnel item\");\n+\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t  \"OR: unsupported tunnel type\");\n \t}\n \n-\tif (ctx->priority >= mae->nb_outer_rule_prios_max) {\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,\n-\t\t\t\t\t  NULL, \"Unsupported priority level\");\n-\t}\n+\tswitch (ctx->ft_rule_type) {\n+\tcase SFC_FT_RULE_JUMP:\n+\t\trecirc_id = SFC_FT_ID_TO_TUNNEL_MARK(ctx->ft->id);\n+\t\t/* FALLTHROUGH */\n+\tcase SFC_FT_RULE_NONE:\n+\t\tif (ctx->priority >= mae->nb_outer_rule_prios_max) {\n+\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,\n+\t\t\t\t\tNULL, \"OR: unsupported priority level\");\n+\t\t}\n \n-\trc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_OUTER, ctx->priority,\n-\t\t\t\t     &ctx->match_spec_outer);\n-\tif (rc != 0) {\n-\t\treturn rte_flow_error_set(error, rc,\n-\t\t\tRTE_FLOW_ERROR_TYPE_ITEM, pattern,\n-\t\t\t\"Failed to initialise outer rule match specification\");\n-\t}\n+\t\trc = efx_mae_match_spec_init(sa->nic,\n+\t\t\t\t\t     EFX_MAE_RULE_OUTER, ctx->priority,\n+\t\t\t\t\t     &ctx->match_spec_outer);\n+\t\tif (rc != 0) {\n+\t\t\treturn rte_flow_error_set(error, rc,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"OR: failed to initialise the match specification\");\n+\t\t}\n+\n+\t\t/*\n+\t\t * Outermost items comprise a match\n+\t\t * specification of type OUTER.\n+\t\t */\n+\t\tctx->match_spec = ctx->match_spec_outer;\n \n-\t/* Outermost items comprise a match specification of type OUTER. */\n-\tctx->match_spec = ctx->match_spec_outer;\n+\t\t/* Outermost items use \"ENC\" EFX MAE field IDs. */\n+\t\tctx->field_ids_remap = field_ids_remap_to_encap;\n \n-\t/* Outermost items use \"ENC\" EFX MAE field IDs. */\n-\tctx->field_ids_remap = field_ids_remap_to_encap;\n+\t\trc = efx_mae_outer_rule_recirc_id_set(ctx->match_spec,\n+\t\t\t\t\t\t      recirc_id);\n+\t\tif (rc != 0) {\n+\t\t\treturn rte_flow_error_set(error, rc,\n+\t\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\t\"OR: failed to initialise RECIRC_ID\");\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tSFC_ASSERT(B_FALSE);\n+\t\tbreak;\n+\t}\n \n \treturn 0;\n }\n@@ -2276,17 +2336,29 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \tint rc;\n \n \tmemset(&ctx_mae, 0, sizeof(ctx_mae));\n+\tctx_mae.ft_rule_type = spec->ft_rule_type;\n \tctx_mae.priority = spec->priority;\n+\tctx_mae.ft = spec->ft;\n \tctx_mae.sa = sa;\n \n-\trc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,\n-\t\t\t\t     spec->priority,\n-\t\t\t\t     &ctx_mae.match_spec_action);\n-\tif (rc != 0) {\n-\t\trc = rte_flow_error_set(error, rc,\n-\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\"Failed to initialise action rule match specification\");\n-\t\tgoto fail_init_match_spec_action;\n+\tswitch (ctx_mae.ft_rule_type) {\n+\tcase SFC_FT_RULE_JUMP:\n+\t\t/* No action rule */\n+\t\tbreak;\n+\tcase SFC_FT_RULE_NONE:\n+\t\trc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,\n+\t\t\t\t\t     spec->priority,\n+\t\t\t\t\t     &ctx_mae.match_spec_action);\n+\t\tif (rc != 0) {\n+\t\t\trc = rte_flow_error_set(error, rc,\n+\t\t\t\tRTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t\"AR: failed to initialise the match specification\");\n+\t\t\tgoto fail_init_match_spec_action;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tSFC_ASSERT(B_FALSE);\n+\t\tbreak;\n \t}\n \n \t/*\n@@ -2320,7 +2392,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \tif (rc != 0)\n \t\tgoto fail_process_outer;\n \n-\tif (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {\n+\tif (ctx_mae.match_spec_action != NULL &&\n+\t    !efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {\n \t\trc = rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\tRTE_FLOW_ERROR_TYPE_ITEM, NULL,\n \t\t\t\t\t\"Inconsistent pattern\");\n@@ -2338,7 +2411,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,\n \tsfc_mae_rule_encap_parse_fini(sa, &ctx_mae);\n \n fail_encap_parse_init:\n-\tefx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);\n+\tif (ctx_mae.match_spec_action != NULL)\n+\t\tefx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);\n \n fail_init_match_spec_action:\n \treturn rc;\n@@ -3254,6 +3328,9 @@ sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,\n {\n \tconst struct rte_flow *entry;\n \n+\tif (spec->match_spec == NULL)\n+\t\treturn 0;\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@@ -3325,11 +3402,10 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,\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 = &action_set->fw_rsrc;\n+\tstruct sfc_mae_fw_rsrc *fw_rsrc;\n \tint rc;\n \n \tSFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);\n-\tSFC_ASSERT(action_set != NULL);\n \n \tif (outer_rule != NULL) {\n \t\trc = sfc_mae_outer_rule_enable(sa, outer_rule,\n@@ -3338,6 +3414,11 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,\n \t\t\tgoto fail_outer_rule_enable;\n \t}\n \n+\tif (action_set == NULL) {\n+\t\tsfc_dbg(sa, \"enabled flow=%p (no AR)\", flow);\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@@ -3351,6 +3432,8 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,\n \t\t}\n \t}\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@@ -3384,8 +3467,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,\n \tstruct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;\n \tint rc;\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-\tSFC_ASSERT(action_set != NULL);\n \n \trc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);\n \tif (rc != 0) {\n@@ -3398,6 +3485,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,\n \n \tsfc_mae_action_set_disable(sa, action_set);\n \n+skip_action_rule:\n \tif (outer_rule != NULL)\n \t\tsfc_mae_outer_rule_disable(sa, outer_rule);\n \n@@ -3416,7 +3504,7 @@ sfc_mae_query_counter(struct sfc_adapter *sa,\n \tunsigned int i;\n \tint rc;\n \n-\tif (action_set->n_counters == 0) {\n+\tif (action_set == NULL || 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\");\ndiff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h\nindex 7e3b6a7a97..907e292dd1 100644\n--- a/drivers/net/sfc/sfc_mae.h\n+++ b/drivers/net/sfc/sfc_mae.h\n@@ -285,9 +285,11 @@ struct sfc_mae_parse_ctx {\n \tsize_t\t\t\t\ttunnel_def_mask_size;\n \tconst void\t\t\t*tunnel_def_mask;\n \tbool\t\t\t\tmatch_mport_set;\n+\tenum sfc_flow_tunnel_rule_type\tft_rule_type;\n \tstruct sfc_mae_pattern_data\tpattern_data;\n \tefx_tunnel_protocol_t\t\tencap_type;\n \tunsigned int\t\t\tpriority;\n+\tstruct sfc_flow_tunnel\t\t*ft;\n };\n \n int sfc_mae_attach(struct sfc_adapter *sa);\n",
    "prefixes": [
        "03/10"
    ]
}