get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 100026,
    "url": "https://patches.dpdk.org/api/patches/100026/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210929205730.775-7-ivan.malov@oktetlabs.ru/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210929205730.775-7-ivan.malov@oktetlabs.ru>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210929205730.775-7-ivan.malov@oktetlabs.ru",
    "date": "2021-09-29T20:57:26",
    "name": "[06/10] net/sfc: implement control path operations in tunnel offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "b3291992ca84efff2a225556b9e35760e4111651",
    "submitter": {
        "id": 869,
        "url": "https://patches.dpdk.org/api/people/869/?format=api",
        "name": "Ivan Malov",
        "email": "Ivan.Malov@oktetlabs.ru"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210929205730.775-7-ivan.malov@oktetlabs.ru/mbox/",
    "series": [
        {
            "id": 19272,
            "url": "https://patches.dpdk.org/api/series/19272/?format=api",
            "web_url": "https://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": "https://patches.dpdk.org/series/19272/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/100026/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/100026/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 031C0A0032;\n\tWed, 29 Sep 2021 22:58:25 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C1F1141142;\n\tWed, 29 Sep 2021 22:57:53 +0200 (CEST)",
            "from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113])\n by mails.dpdk.org (Postfix) with ESMTP id E7A93410EE\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 8F2667F6D5;\n Wed, 29 Sep 2021 23:57:45 +0300 (MSK)"
        ],
        "DKIM-Filter": "OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru 8F2667F6D5",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=simple/simple; d=oktetlabs.ru;\n s=default; t=1632949065;\n bh=Edq0zT95StPv7UQHppqoKThQYklQinck9GxNYneodfs=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References;\n b=Eyo7SmC0fUFEOH8+Jy1y0C8ni8lf2dBTJypUUFcjVS+/XSkdj7bicHghk0unV+b9K\n M/M5BChwYEleM6R0VhxtWeDmYEE5u86Fv8mBXCM9S2gmlaHoCEITWofL3z77KrCQFk\n 7FN9vvC3hImb6Uz1oN4EdPk6IS6QZf+bg23SR1A0=",
        "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:26 +0300",
        "Message-Id": "<20210929205730.775-7-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 06/10] net/sfc: implement control path operations\n in tunnel 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": "Support generic callbacks which callers will invoke to get\nPMD-specific actions and items used to produce JUMP and\nGROUP flows and to detect tunnel information.\n\nSigned-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>\nReviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>\n---\n drivers/net/sfc/sfc_dp.c          |  48 +++++\n drivers/net/sfc/sfc_dp.h          |   9 +\n drivers/net/sfc/sfc_ef100_rx.c    |  12 ++\n drivers/net/sfc/sfc_flow.c        |   5 +\n drivers/net/sfc/sfc_flow_tunnel.c | 316 ++++++++++++++++++++++++++++++\n drivers/net/sfc/sfc_flow_tunnel.h |  37 ++++\n 6 files changed, 427 insertions(+)",
    "diff": "diff --git a/drivers/net/sfc/sfc_dp.c b/drivers/net/sfc/sfc_dp.c\nindex 24ed0898c8..509c95890d 100644\n--- a/drivers/net/sfc/sfc_dp.c\n+++ b/drivers/net/sfc/sfc_dp.c\n@@ -12,6 +12,7 @@\n #include <errno.h>\n \n #include <rte_log.h>\n+#include <rte_mbuf_dyn.h>\n \n #include \"sfc_dp.h\"\n #include \"sfc_log.h\"\n@@ -77,3 +78,50 @@ sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry)\n \n \treturn 0;\n }\n+\n+int sfc_dp_ft_id_offset = -1;\n+uint64_t sfc_dp_ft_id_valid;\n+\n+int\n+sfc_dp_ft_id_register(void)\n+{\n+\tstatic const struct rte_mbuf_dynfield ft_id = {\n+\t\t.name = \"rte_net_sfc_dynfield_ft_id\",\n+\t\t.size = sizeof(uint8_t),\n+\t\t.align = __alignof__(uint8_t),\n+\t};\n+\tstatic const struct rte_mbuf_dynflag ft_id_valid = {\n+\t\t.name = \"rte_net_sfc_dynflag_ft_id_valid\",\n+\t};\n+\n+\tint field_offset;\n+\tint flag;\n+\n+\tSFC_GENERIC_LOG(INFO, \"%s() entry\", __func__);\n+\n+\tif (sfc_dp_ft_id_valid != 0) {\n+\t\tSFC_GENERIC_LOG(INFO, \"%s() already registered\", __func__);\n+\t\treturn 0;\n+\t}\n+\n+\tfield_offset = rte_mbuf_dynfield_register(&ft_id);\n+\tif (field_offset < 0) {\n+\t\tSFC_GENERIC_LOG(ERR, \"%s() failed to register ft_id dynfield\",\n+\t\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\n+\tflag = rte_mbuf_dynflag_register(&ft_id_valid);\n+\tif (flag < 0) {\n+\t\tSFC_GENERIC_LOG(ERR, \"%s() failed to register ft_id dynflag\",\n+\t\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\n+\tsfc_dp_ft_id_offset = field_offset;\n+\tsfc_dp_ft_id_valid = UINT64_C(1) << flag;\n+\n+\tSFC_GENERIC_LOG(INFO, \"%s() done\", __func__);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/sfc/sfc_dp.h b/drivers/net/sfc/sfc_dp.h\nindex 7fd8f34b0f..b27420d4fc 100644\n--- a/drivers/net/sfc/sfc_dp.h\n+++ b/drivers/net/sfc/sfc_dp.h\n@@ -126,6 +126,15 @@ struct sfc_dp *sfc_dp_find_by_caps(struct sfc_dp_list *head,\n \t\t\t\t   unsigned int avail_caps);\n int sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry);\n \n+/** Dynamically registered mbuf \"ft_id\" validity flag (as a bitmask). */\n+extern uint64_t sfc_dp_ft_id_valid;\n+\n+/** Dynamically registered mbuf field \"ft_id\" (mbuf byte offset). */\n+extern int sfc_dp_ft_id_offset;\n+\n+/** Register dynamic mbuf field \"ft_id\" and its validity flag. */\n+int sfc_dp_ft_id_register(void);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/drivers/net/sfc/sfc_ef100_rx.c b/drivers/net/sfc/sfc_ef100_rx.c\nindex 3219c972db..a4f4500d74 100644\n--- a/drivers/net/sfc/sfc_ef100_rx.c\n+++ b/drivers/net/sfc/sfc_ef100_rx.c\n@@ -422,6 +422,7 @@ sfc_ef100_rx_prefix_to_offloads(const struct sfc_ef100_rxq *rxq,\n \t}\n \n \tif (rxq->flags & SFC_EF100_RXQ_USER_MARK) {\n+\t\tuint8_t tunnel_mark;\n \t\tuint32_t user_mark;\n \t\tuint32_t mark;\n \n@@ -434,6 +435,17 @@ sfc_ef100_rx_prefix_to_offloads(const struct sfc_ef100_rxq *rxq,\n \t\t\tol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;\n \t\t\tm->hash.fdir.hi = user_mark;\n \t\t}\n+\n+\t\ttunnel_mark = SFC_FT_GET_TUNNEL_MARK(mark);\n+\t\tif (tunnel_mark != SFC_FT_TUNNEL_MARK_INVALID) {\n+\t\t\tsfc_ft_id_t ft_id;\n+\n+\t\t\tft_id = SFC_FT_TUNNEL_MARK_TO_ID(tunnel_mark);\n+\n+\t\t\tol_flags |= sfc_dp_ft_id_valid;\n+\t\t\t*RTE_MBUF_DYNFIELD(m, sfc_dp_ft_id_offset,\n+\t\t\t\t\t   sfc_ft_id_t *) = ft_id;\n+\t\t}\n \t}\n \n \tm->ol_flags = ol_flags;\ndiff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c\nindex fe726afc9c..c3e75bae84 100644\n--- a/drivers/net/sfc/sfc_flow.c\n+++ b/drivers/net/sfc/sfc_flow.c\n@@ -2926,6 +2926,11 @@ 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.tunnel_decap_set = sfc_flow_tunnel_decap_set,\n+\t.tunnel_match = sfc_flow_tunnel_match,\n+\t.tunnel_action_decap_release = sfc_flow_tunnel_action_decap_release,\n+\t.tunnel_item_release = sfc_flow_tunnel_item_release,\n+\t.get_restore_info = sfc_flow_tunnel_get_restore_info,\n };\n \n void\ndiff --git a/drivers/net/sfc/sfc_flow_tunnel.c b/drivers/net/sfc/sfc_flow_tunnel.c\nindex b03c90c9a4..2de401148e 100644\n--- a/drivers/net/sfc/sfc_flow_tunnel.c\n+++ b/drivers/net/sfc/sfc_flow_tunnel.c\n@@ -6,7 +6,10 @@\n #include <stdbool.h>\n #include <stdint.h>\n \n+#include <rte_flow.h>\n+\n #include \"sfc.h\"\n+#include \"sfc_dp.h\"\n #include \"sfc_flow.h\"\n #include \"sfc_dp_rx.h\"\n #include \"sfc_flow_tunnel.h\"\n@@ -143,3 +146,316 @@ sfc_flow_tunnel_detect_jump_rule(struct sfc_adapter *sa,\n \t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n \t\t\t\t  \"tunnel offload: JUMP: preparsing failed\");\n }\n+\n+static int\n+sfc_flow_tunnel_attach(struct sfc_adapter *sa,\n+\t\t       struct rte_flow_tunnel *tunnel,\n+\t\t       struct sfc_flow_tunnel **ftp)\n+{\n+\tstruct sfc_flow_tunnel *ft;\n+\tconst char *ft_status;\n+\tint ft_id_free = -1;\n+\tsfc_ft_id_t ft_id;\n+\tint rc;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\trc = sfc_dp_ft_id_register();\n+\tif (rc != 0)\n+\t\treturn rc;\n+\n+\tif (tunnel->type != RTE_FLOW_ITEM_TYPE_VXLAN) {\n+\t\tsfc_err(sa, \"tunnel offload: unsupported tunnel (encapsulation) type\");\n+\t\treturn ENOTSUP;\n+\t}\n+\n+\tfor (ft_id = 0; ft_id < SFC_FT_MAX_NTUNNELS; ++ft_id) {\n+\t\tft = &sa->flow_tunnels[ft_id];\n+\n+\t\tif (ft->refcnt == 0) {\n+\t\t\tif (ft_id_free == -1)\n+\t\t\t\tft_id_free = ft_id;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (memcmp(tunnel, &ft->rte_tunnel, sizeof(*tunnel)) == 0) {\n+\t\t\tft_status = \"existing\";\n+\t\t\tgoto attach;\n+\t\t}\n+\t}\n+\n+\tif (ft_id_free == -1) {\n+\t\tsfc_err(sa, \"tunnel offload: no free slot for the new tunnel\");\n+\t\treturn ENOBUFS;\n+\t}\n+\n+\tft_id = ft_id_free;\n+\tft = &sa->flow_tunnels[ft_id];\n+\n+\tmemcpy(&ft->rte_tunnel, tunnel, sizeof(*tunnel));\n+\n+\tft->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;\n+\n+\tft->action_mark.id = SFC_FT_ID_TO_MARK(ft_id_free);\n+\tft->action.type = RTE_FLOW_ACTION_TYPE_MARK;\n+\tft->action.conf = &ft->action_mark;\n+\n+\tft->item.type = RTE_FLOW_ITEM_TYPE_MARK;\n+\tft->item_mark_v.id = ft->action_mark.id;\n+\tft->item.spec = &ft->item_mark_v;\n+\tft->item.mask = &ft->item_mark_m;\n+\tft->item_mark_m.id = UINT32_MAX;\n+\n+\tft->jump_rule_is_set = B_FALSE;\n+\n+\tft->refcnt = 0;\n+\n+\tft_status = \"newly added\";\n+\n+attach:\n+\tsfc_dbg(sa, \"tunnel offload: attaching to %s tunnel=%u\",\n+\t\tft_status, ft_id);\n+\n+\t++(ft->refcnt);\n+\t*ftp = ft;\n+\n+\treturn 0;\n+}\n+\n+static int\n+sfc_flow_tunnel_detach(struct sfc_adapter *sa,\n+\t\t       uint32_t ft_mark)\n+{\n+\tstruct sfc_flow_tunnel *ft;\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tft = sfc_flow_tunnel_pick(sa, ft_mark);\n+\tif (ft == NULL) {\n+\t\tsfc_err(sa, \"tunnel offload: invalid tunnel\");\n+\t\treturn EINVAL;\n+\t}\n+\n+\tif (ft->refcnt == 0) {\n+\t\tsfc_err(sa, \"tunnel offload: tunnel=%u does not exist\", ft->id);\n+\t\treturn ENOENT;\n+\t}\n+\n+\t--(ft->refcnt);\n+\n+\treturn 0;\n+}\n+\n+int\n+sfc_flow_tunnel_decap_set(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_flow_tunnel *tunnel,\n+\t\t\t  struct rte_flow_action **pmd_actions,\n+\t\t\t  uint32_t *num_of_actions,\n+\t\t\t  struct rte_flow_error *err)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct sfc_flow_tunnel *ft;\n+\tint rc;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tif (!sfc_flow_tunnel_is_active(sa)) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail;\n+\t}\n+\n+\trc = sfc_flow_tunnel_attach(sa, tunnel, &ft);\n+\tif (rc != 0)\n+\t\tgoto fail;\n+\n+\t*pmd_actions = &ft->action;\n+\t*num_of_actions = 1;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail:\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn rte_flow_error_set(err, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: decap_set failed\");\n+}\n+\n+int\n+sfc_flow_tunnel_match(struct rte_eth_dev *dev,\n+\t\t      struct rte_flow_tunnel *tunnel,\n+\t\t      struct rte_flow_item **pmd_items,\n+\t\t      uint32_t *num_of_items,\n+\t\t      struct rte_flow_error *err)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tstruct sfc_flow_tunnel *ft;\n+\tint rc;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tif (!sfc_flow_tunnel_is_active(sa)) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail;\n+\t}\n+\n+\trc = sfc_flow_tunnel_attach(sa, tunnel, &ft);\n+\tif (rc != 0)\n+\t\tgoto fail;\n+\n+\t*pmd_items = &ft->item;\n+\t*num_of_items = 1;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail:\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn rte_flow_error_set(err, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: tunnel_match failed\");\n+}\n+\n+int\n+sfc_flow_tunnel_item_release(struct rte_eth_dev *dev,\n+\t\t\t     struct rte_flow_item *pmd_items,\n+\t\t\t     uint32_t num_items,\n+\t\t\t     struct rte_flow_error *err)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tconst struct rte_flow_item_mark *item_mark;\n+\tstruct rte_flow_item *item = pmd_items;\n+\tint rc;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tif (!sfc_flow_tunnel_is_active(sa)) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail;\n+\t}\n+\n+\tif (num_items != 1 || item == NULL || item->spec == NULL ||\n+\t    item->type != RTE_FLOW_ITEM_TYPE_MARK) {\n+\t\tsfc_err(sa, \"tunnel offload: item_release: wrong input\");\n+\t\trc = EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\titem_mark = item->spec;\n+\n+\trc = sfc_flow_tunnel_detach(sa, item_mark->id);\n+\tif (rc != 0)\n+\t\tgoto fail;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail:\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn rte_flow_error_set(err, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: item_release failed\");\n+}\n+\n+int\n+sfc_flow_tunnel_action_decap_release(struct rte_eth_dev *dev,\n+\t\t\t\t     struct rte_flow_action *pmd_actions,\n+\t\t\t\t     uint32_t num_actions,\n+\t\t\t\t     struct rte_flow_error *err)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tconst struct rte_flow_action_mark *action_mark;\n+\tstruct rte_flow_action *action = pmd_actions;\n+\tint rc;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tif (!sfc_flow_tunnel_is_active(sa)) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail;\n+\t}\n+\n+\tif (num_actions != 1 || action == NULL || action->conf == NULL ||\n+\t    action->type != RTE_FLOW_ACTION_TYPE_MARK) {\n+\t\tsfc_err(sa, \"tunnel offload: action_decap_release: wrong input\");\n+\t\trc = EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\taction_mark = action->conf;\n+\n+\trc = sfc_flow_tunnel_detach(sa, action_mark->id);\n+\tif (rc != 0)\n+\t\tgoto fail;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail:\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn rte_flow_error_set(err, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: item_release failed\");\n+}\n+\n+int\n+sfc_flow_tunnel_get_restore_info(struct rte_eth_dev *dev,\n+\t\t\t\t struct rte_mbuf *m,\n+\t\t\t\t struct rte_flow_restore_info *info,\n+\t\t\t\t struct rte_flow_error *err)\n+{\n+\tstruct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);\n+\tconst struct sfc_flow_tunnel *ft;\n+\tsfc_ft_id_t ft_id;\n+\tint rc;\n+\n+\tsfc_adapter_lock(sa);\n+\n+\tif ((m->ol_flags & sfc_dp_ft_id_valid) == 0) {\n+\t\tsfc_dbg(sa, \"tunnel offload: get_restore_info: no tunnel mark in the packet\");\n+\t\trc = EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\tft_id = *RTE_MBUF_DYNFIELD(m, sfc_dp_ft_id_offset, sfc_ft_id_t *);\n+\tft = &sa->flow_tunnels[ft_id];\n+\n+\tif (ft->refcnt == 0) {\n+\t\tsfc_err(sa, \"tunnel offload: get_restore_info: tunnel=%u does not exist\",\n+\t\t\tft_id);\n+\t\trc = ENOENT;\n+\t\tgoto fail;\n+\t}\n+\n+\tmemcpy(&info->tunnel, &ft->rte_tunnel, sizeof(info->tunnel));\n+\n+\t/*\n+\t * The packet still has encapsulation header; JUMP rules never\n+\t * strip it. Therefore, set RTE_FLOW_RESTORE_INFO_ENCAPSULATED.\n+\t */\n+\tinfo->flags = RTE_FLOW_RESTORE_INFO_ENCAPSULATED |\n+\t\t      RTE_FLOW_RESTORE_INFO_GROUP_ID |\n+\t\t      RTE_FLOW_RESTORE_INFO_TUNNEL;\n+\n+\tinfo->group_id = 0;\n+\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn 0;\n+\n+fail:\n+\tsfc_adapter_unlock(sa);\n+\n+\treturn rte_flow_error_set(err, rc,\n+\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n+\t\t\t\t  \"tunnel offload: get_restore_info failed\");\n+}\ndiff --git a/drivers/net/sfc/sfc_flow_tunnel.h b/drivers/net/sfc/sfc_flow_tunnel.h\nindex 27a8fa5ae7..573585ca80 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 <rte_flow.h>\n+\n #include \"efx.h\"\n \n #ifdef __cplusplus\n@@ -51,8 +53,16 @@ typedef uint8_t sfc_ft_id_t;\n struct sfc_flow_tunnel {\n \tbool\t\t\t\tjump_rule_is_set;\n \tefx_tunnel_protocol_t\t\tencap_type;\n+\tstruct rte_flow_tunnel\t\trte_tunnel;\n \tunsigned int\t\t\trefcnt;\n \tsfc_ft_id_t\t\t\tid;\n+\n+\tstruct rte_flow_action_mark\taction_mark;\n+\tstruct rte_flow_action\t\taction;\n+\n+\tstruct rte_flow_item_mark\titem_mark_v;\n+\tstruct rte_flow_item_mark\titem_mark_m;\n+\tstruct rte_flow_item\t\titem;\n };\n \n struct sfc_adapter;\n@@ -69,6 +79,33 @@ int sfc_flow_tunnel_detect_jump_rule(struct sfc_adapter *sa,\n \t\t\t\t     struct sfc_flow_spec_mae *spec,\n \t\t\t\t     struct rte_flow_error *error);\n \n+int sfc_flow_tunnel_decap_set(struct rte_eth_dev *dev,\n+\t\t\t      struct rte_flow_tunnel *tunnel,\n+\t\t\t      struct rte_flow_action **pmd_actions,\n+\t\t\t      uint32_t *num_of_actions,\n+\t\t\t      struct rte_flow_error *err);\n+\n+int sfc_flow_tunnel_match(struct rte_eth_dev *dev,\n+\t\t\t  struct rte_flow_tunnel *tunnel,\n+\t\t\t  struct rte_flow_item **pmd_items,\n+\t\t\t  uint32_t *num_of_items,\n+\t\t\t  struct rte_flow_error *err);\n+\n+int sfc_flow_tunnel_item_release(struct rte_eth_dev *dev,\n+\t\t\t\t struct rte_flow_item *pmd_items,\n+\t\t\t\t uint32_t num_items,\n+\t\t\t\t struct rte_flow_error *err);\n+\n+int sfc_flow_tunnel_action_decap_release(struct rte_eth_dev *dev,\n+\t\t\t\t\t struct rte_flow_action *pmd_actions,\n+\t\t\t\t\t uint32_t num_actions,\n+\t\t\t\t\t struct rte_flow_error *err);\n+\n+int sfc_flow_tunnel_get_restore_info(struct rte_eth_dev *dev,\n+\t\t\t\t     struct rte_mbuf *m,\n+\t\t\t\t     struct rte_flow_restore_info *info,\n+\t\t\t\t     struct rte_flow_error *err);\n+\n #ifdef __cplusplus\n }\n #endif\n",
    "prefixes": [
        "06/10"
    ]
}