get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2233029,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2233029/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260505-b4-flowtable-sw-accel-ip6ip-v1-3-9ac39ccc9ea9@kernel.org/",
    "project": {
        "id": 26,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/26/?format=api",
        "name": "Netfilter Development",
        "link_name": "netfilter-devel",
        "list_id": "netfilter-devel.vger.kernel.org",
        "list_email": "netfilter-devel@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260505-b4-flowtable-sw-accel-ip6ip-v1-3-9ac39ccc9ea9@kernel.org>",
    "list_archive_url": null,
    "date": "2026-05-05T14:49:25",
    "name": "[nf-next,3/4] net: netfilter: Add IPv4 over IPv6 tunnel flowtable acceleration",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "c6fd640e3c41e3113bedf8a0d27be348cd00442a",
    "submitter": {
        "id": 76007,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/76007/?format=api",
        "name": "Lorenzo Bianconi",
        "email": "lorenzo@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260505-b4-flowtable-sw-accel-ip6ip-v1-3-9ac39ccc9ea9@kernel.org/mbox/",
    "series": [
        {
            "id": 502850,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/502850/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=502850",
            "date": "2026-05-05T14:49:22",
            "name": "Add IPv4 over IPv6 flowtable SW acceleration",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/502850/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2233029/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2233029/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <netfilter-devel+bounces-12444-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "netfilter-devel@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=ZHPKThhl;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-12444-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"ZHPKThhl\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g91fY5gPlz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 00:51:01 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id B4E3030488C8\n\tfor <incoming@patchwork.ozlabs.org>; Tue,  5 May 2026 14:50:11 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id EB70F480962;\n\tTue,  5 May 2026 14:50:05 +0000 (UTC)",
            "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 7613C480352;\n\tTue,  5 May 2026 14:50:05 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPSA id B4D64C2BCF6;\n\tTue,  5 May 2026 14:50:04 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777992605; cv=none;\n b=LIQddahmPVceIOsL0h2N3YVmYCsZvxBOZiiocpTeJitI0Mw1M0Y6DcP/0+Zoh7TxyzXHy/F8H+ykRCp7tyN1oaRXox+I0eedid0Pz/ymI764McHkCjTZ7mirA70tiajMTzli04SpC6nBpT+VeXz1PEokB2QTlIDs2himNeBr5wU=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777992605; c=relaxed/simple;\n\tbh=NufIRfFbDQZaRSGyfG2ymdDJTGmsa8tSnXmoazf14x8=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=YSA9pkecC5GFvYAHgNugqncZAPWT1ZU/mQg+iJTf+Cdys0MtsGX438AD2rE/y3vuTwsBxbKZhl2A08d/Kgh0PmxeM59dSKvSF7QMEr+AhDNIZ/zp5lJtAWgGn3JSZj0VF+FzhwrZFkgymgS/A4Fnaxe9tpYrDDID0IuqY5dDa+M=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=ZHPKThhl; arc=none smtp.client-ip=10.30.226.201",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1777992605;\n\tbh=NufIRfFbDQZaRSGyfG2ymdDJTGmsa8tSnXmoazf14x8=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=ZHPKThhl4P0SAjIdwJbYusFoEEqKrpOm4XtbWJMwOqG2TWtZzORnGx0zy3zLilWrV\n\t xwx/rroBJf4y2q9wRX8vaPyZS+XHJZ9ACdJCZjFOzrMSsyvmOC2QTHb4sRa+cjAIL1\n\t t7Z9wjKUFoHU+gcAQAfbjgCSTIgDeK79SY8M8roQ2knHGwdsA/Ccsm4PRiu5/jgqvZ\n\t bpjUJfplEtvM/HahhEBAfdixr+1jCRsgixdCB65Au5JIaAHEtIwsw7TNdtxIccVHfq\n\t yjz+EBPrbFdGRdD2eOBPn2ghnf0ecVXW/kRc0lIcgLduMl76L/EVymI3oyeH/Adjc9\n\t aDIkVZOWXCKlg==",
        "From": "Lorenzo Bianconi <lorenzo@kernel.org>",
        "Date": "Tue, 05 May 2026 16:49:25 +0200",
        "Subject": "[PATCH nf-next 3/4] net: netfilter: Add IPv4 over IPv6 tunnel\n flowtable acceleration",
        "Precedence": "bulk",
        "X-Mailing-List": "netfilter-devel@vger.kernel.org",
        "List-Id": "<netfilter-devel.vger.kernel.org>",
        "List-Subscribe": "<mailto:netfilter-devel+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:netfilter-devel+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "\n <20260505-b4-flowtable-sw-accel-ip6ip-v1-3-9ac39ccc9ea9@kernel.org>",
        "References": "\n <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>",
        "In-Reply-To": "\n <20260505-b4-flowtable-sw-accel-ip6ip-v1-0-9ac39ccc9ea9@kernel.org>",
        "To": "Andrew Lunn <andrew+netdev@lunn.ch>,\n \"David S. Miller\" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>,\n Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,\n Felix Fietkau <nbd@nbd.name>, Matthias Brugger <matthias.bgg@gmail.com>,\n AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>,\n Simon Horman <horms@kernel.org>, David Ahern <dsahern@kernel.org>,\n Ido Schimmel <idosch@nvidia.com>, Pablo Neira Ayuso <pablo@netfilter.org>,\n Florian Westphal <fw@strlen.de>, Phil Sutter <phil@nwl.cc>,\n Shuah Khan <shuah@kernel.org>",
        "Cc": "linux-arm-kernel@lists.infradead.org,\n linux-mediatek@lists.infradead.org, netdev@vger.kernel.org,\n netfilter-devel@vger.kernel.org, coreteam@netfilter.org,\n linux-kselftest@vger.kernel.org, Lorenzo Bianconi <lorenzo@kernel.org>",
        "X-Mailer": "b4 0.14.3"
    },
    "content": "Introduce sw flowtable acceleration for the TX/RX paths of\nIPv4 over IPv6 tunnels, relying on the netfilter flowtable\ninfrastructure.\nThe feature can be tested with a forwarding scenario between two\nNICs (eth0 and eth1), where an IPv4 over IPv6 tunnel is used to\nreach a remote site via eth1 as the underlay device:\n\n    ETH0 -- TUN0 <==> ETH1 -- [IP network] -- TUN1 (192.168.100.2)\n\n[IP configuration]\n\n6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000\n    link/ether 00:00:22:33:11:55 brd ff:ff:ff:ff:ff:ff\n    inet 192.168.0.2/24 scope global eth0\n       valid_lft forever preferred_lft forever\n7: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000\n    link/ether 00:11:22:33:11:55 brd ff:ff:ff:ff:ff:ff\n    inet6 2001:db8:2::1/64 scope global nodad\n       valid_lft forever preferred_lft forever\n8: tun0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000\n    link/tunnel6 2001:db8:2::1 peer 2001:db8:2::2 permaddr ce9c:2940:7dcc::\n    inet 192.168.100.1/24 scope global tun0\n       valid_lft forever preferred_lft forever\n\n$ ip route show\ndefault via 192.168.100.2 dev tun0\n192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2\n192.168.100.0/24 dev tun0 proto kernel scope link src 192.168.100.1\n\n$ ip -6 route show\n2001:db8:2::/64 dev eth1 proto kernel metric 256 pref medium\ndefault via 2002:db8:1::2 dev tun0 metric 1024 pref medium\n\n$ nft list ruleset\ntable inet filter {\n    flowtable ft {\n        hook ingress priority filter\n        devices = { eth0, eth1 }\n    }\n\n    chain forward {\n        type filter hook forward priority filter; policy accept;\n        meta l4proto { tcp, udp } flow add @ft\n    }\n}\n\nWhen reproducing this scenario using veth interfaces, the following\nresults were observed:\n\n- TCP stream received from IPv4 over IPv6 tunnel:\n  - net-next (baseline):                ~126 Gbps\n  - net-next + IP6IP flowtable support: ~140 Gbps\n\n- TCP stream transmitted to IPv4 over IPv6 tunnel:\n  - net-next (baseline):                ~127 Gbps\n  - net-next + IP6IP flowtable support: ~141 Gbps\n\nSigned-off-by: Lorenzo Bianconi <lorenzo@kernel.org>\n---\n net/netfilter/nf_flow_table_core.c |  14 ++--\n net/netfilter/nf_flow_table_ip.c   | 127 +++++++++++++++++++++++++++----------\n net/netfilter/nf_flow_table_path.c |   6 +-\n 3 files changed, 107 insertions(+), 40 deletions(-)",
    "diff": "diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c\nindex 2c4140e6f53c..53fea3da0747 100644\n--- a/net/netfilter/nf_flow_table_core.c\n+++ b/net/netfilter/nf_flow_table_core.c\n@@ -76,9 +76,11 @@ struct flow_offload *flow_offload_alloc(struct nf_conn *ct)\n }\n EXPORT_SYMBOL_GPL(flow_offload_alloc);\n \n-static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)\n+static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple,\n+\t\t\t\t   u8 tun_encap_proto)\n {\n-\tif (flow_tuple->l3proto == NFPROTO_IPV6)\n+\tif (flow_tuple->l3proto == NFPROTO_IPV6 ||\n+\t    tun_encap_proto == NFPROTO_IPV6)\n \t\treturn rt6_get_cookie(dst_rt6_info(flow_tuple->dst_cache));\n \n \treturn 0;\n@@ -134,10 +136,14 @@ static int flow_offload_fill_route(struct flow_offload *flow,\n \t\tdst_release(dst);\n \t\tbreak;\n \tcase FLOW_OFFLOAD_XMIT_XFRM:\n-\tcase FLOW_OFFLOAD_XMIT_NEIGH:\n+\tcase FLOW_OFFLOAD_XMIT_NEIGH: {\n+\t\tu8 encap_proto = route->tuple[!dir].in.tun.encap_proto;\n+\n \t\tflow_tuple->ifidx = route->tuple[dir].out.ifindex;\n \t\tflow_tuple->dst_cache = dst;\n-\t\tflow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);\n+\t\tflow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple,\n+\t\t\t\t\t\t\t\t encap_proto);\n+\t\t}\n \t\tbreak;\n \tdefault:\n \t\tWARN_ON_ONCE(1);\ndiff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c\nindex 9efd76b57847..70d7b5a200e2 100644\n--- a/net/netfilter/nf_flow_table_ip.c\n+++ b/net/netfilter/nf_flow_table_ip.c\n@@ -191,27 +191,27 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,\n \t\tbreak;\n \t}\n \n-\tswitch (inner_proto) {\n-\tcase htons(ETH_P_IP):\n-\t\tiph = (struct iphdr *)(skb_network_header(skb) + offset);\n-\t\tif (ctx->tun.proto == IPPROTO_IPIP) {\n+\tif (ctx->tun.proto == IPPROTO_IPIP || ctx->tun.proto == IPPROTO_IPV6) {\n+\t\tswitch (inner_proto) {\n+\t\tcase htons(ETH_P_IP):\n+\t\t\tiph = (struct iphdr *)(skb_network_header(skb) +\n+\t\t\t\t\t       offset);\n \t\t\ttuple->tun.dst_v4.s_addr = iph->daddr;\n \t\t\ttuple->tun.src_v4.s_addr = iph->saddr;\n-\t\t\ttuple->tun.l3_proto = IPPROTO_IPIP;\n+\t\t\ttuple->tun.l3_proto = ctx->tun.proto;\n \t\t\ttuple->tun.encap_proto = AF_INET;\n-\t\t}\n-\t\tbreak;\n-\tcase htons(ETH_P_IPV6):\n-\t\tip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);\n-\t\tif (ctx->tun.proto == IPPROTO_IPV6) {\n+\t\t\tbreak;\n+\t\tcase htons(ETH_P_IPV6):\n+\t\t\tip6h = (struct ipv6hdr *)(skb_network_header(skb) +\n+\t\t\t\t\t\t  offset);\n \t\t\ttuple->tun.dst_v6 = ip6h->daddr;\n \t\t\ttuple->tun.src_v6 = ip6h->saddr;\n-\t\t\ttuple->tun.l3_proto = IPPROTO_IPV6;\n+\t\t\ttuple->tun.l3_proto = ctx->tun.proto;\n \t\t\ttuple->tun.encap_proto = AF_INET6;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n \t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n \t}\n }\n \n@@ -367,9 +367,9 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,\n \tif (hdrlen < 0)\n \t\treturn false;\n \n-\tif (nexthdr == IPPROTO_IPV6) {\n+\tif (nexthdr == IPPROTO_IPIP || nexthdr == IPPROTO_IPV6) {\n \t\tctx->tun.hdr_size = hdrlen;\n-\t\tctx->tun.proto = IPPROTO_IPV6;\n+\t\tctx->tun.proto = nexthdr;\n \t}\n \tctx->offset += ctx->tun.hdr_size;\n \n@@ -388,6 +388,10 @@ static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,\n \n \tskb_pull(skb, ctx->tun.hdr_size);\n \tskb_reset_network_header(skb);\n+\tif (ctx->tun.proto == IPPROTO_IPIP)\n+\t\tskb->protocol = htons(ETH_P_IP);\n+\telse\n+\t\tskb->protocol = htons(ETH_P_IPV6);\n }\n \n static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,\n@@ -650,18 +654,29 @@ static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,\n \t\t\t\t      struct in6_addr **ip6_daddr,\n \t\t\t\t      int encap_limit)\n {\n-\tstruct ipv6hdr *ip6h = (struct ipv6hdr *)skb_network_header(skb);\n-\tu8 hop_limit = ip6h->hop_limit, proto = IPPROTO_IPV6;\n \tstruct rtable *rt = dst_rtable(tuple->dst_cache);\n-\t__u8 dsfield = ipv6_get_dsfield(ip6h);\n+\tu8 hop_limit, proto = tuple->tun.l3_proto;\n \tstruct flowi6 fl6 = {\n \t\t.daddr = tuple->tun.src_v6,\n \t\t.saddr = tuple->tun.dst_v6,\n \t\t.flowi6_proto = proto,\n \t};\n+\tstruct ipv6hdr *ip6h;\n+\t__u8 dsfield;\n \tint err, mtu;\n \tu32 headroom;\n \n+\tif (tuple->tun.l3_proto == IPPROTO_IPIP) {\n+\t\tstruct iphdr *iph = (struct iphdr *)skb_network_header(skb);\n+\n+\t\tdsfield = ipv4_get_dsfield(iph);\n+\t\thop_limit = iph->ttl;\n+\t} else {\n+\t\tip6h = (struct ipv6hdr *)skb_network_header(skb);\n+\t\tdsfield = ipv6_get_dsfield(ip6h);\n+\t\thop_limit = ip6h->hop_limit;\n+\t}\n+\n \terr = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6);\n \tif (err)\n \t\treturn err;\n@@ -697,12 +712,13 @@ static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,\n \n \t\thopt = skb_push(skb, ipv6_optlen(opt.ops.dst1opt));\n \t\tmemcpy(hopt, opt.ops.dst1opt, ipv6_optlen(opt.ops.dst1opt));\n-\t\thopt->nexthdr = IPPROTO_IPV6;\n+\t\thopt->nexthdr = proto;\n \t\tproto = NEXTHDR_DEST;\n \t}\n \n \tskb_push(skb, sizeof(*ip6h));\n \tskb_reset_network_header(skb);\n+\tskb->protocol = htons(ETH_P_IPV6);\n \n \tip6h = ipv6_hdr(skb);\n \tip6_flow_hdr(ip6h, dsfield,\n@@ -767,6 +783,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,\n \t\t.in\t= state->in,\n \t};\n \tstruct nf_flow_xmit xmit = {};\n+\tstruct in6_addr *ip6_daddr;\n \tstruct flow_offload *flow;\n \tstruct neighbour *neigh;\n \tstruct rtable *rt;\n@@ -796,28 +813,50 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,\n \tother_tuple = &flow->tuplehash[!dir].tuple;\n \tip_daddr = other_tuple->src_v4.s_addr;\n \n-\tif (nf_flow_tunnel_v4_push(state->net, skb, other_tuple, &ip_daddr) < 0)\n+\tif (other_tuple->tun.encap_proto == AF_INET6) {\n+\t\tif (nf_flow_tunnel_v6_push(state->net, skb, other_tuple,\n+\t\t\t\t\t   &ip6_daddr,\n+\t\t\t\t\t   IPV6_DEFAULT_TNL_ENCAP_LIMIT) < 0)\n+\t\t\treturn NF_DROP;\n+\t} else if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple,\n+\t\t\t\t\t  &ip_daddr) < 0) {\n \t\treturn NF_DROP;\n+\t}\n \n \tif (nf_flow_encap_push(skb, other_tuple) < 0)\n \t\treturn NF_DROP;\n \n \tswitch (tuplehash->tuple.xmit_type) {\n-\tcase FLOW_OFFLOAD_XMIT_NEIGH:\n-\t\trt = dst_rtable(tuplehash->tuple.dst_cache);\n+\tcase FLOW_OFFLOAD_XMIT_NEIGH: {\n+\t\tstruct dst_entry *dst;\n+\n \t\txmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);\n \t\tif (!xmit.outdev) {\n \t\t\tflow_offload_teardown(flow);\n \t\t\treturn NF_DROP;\n \t\t}\n-\t\tneigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, ip_daddr));\n+\t\tif (other_tuple->tun.encap_proto == AF_INET6 ||\n+\t\t    ctx.tun.proto == IPPROTO_IPV6) {\n+\t\t\tstruct rt6_info *rt6;\n+\n+\t\t\trt6 = dst_rt6_info(tuplehash->tuple.dst_cache);\n+\t\t\tneigh = ip_neigh_gw6(rt6->dst.dev,\n+\t\t\t\t\t     rt6_nexthop(rt6, ip6_daddr));\n+\t\t\tdst = &rt6->dst;\n+\t\t} else {\n+\t\t\trt = dst_rtable(tuplehash->tuple.dst_cache);\n+\t\t\tneigh = ip_neigh_gw4(rt->dst.dev,\n+\t\t\t\t\t     rt_nexthop(rt, ip_daddr));\n+\t\t\tdst = &rt->dst;\n+\t\t}\n \t\tif (IS_ERR(neigh)) {\n \t\t\tflow_offload_teardown(flow);\n \t\t\treturn NF_DROP;\n \t\t}\n \t\txmit.dest = neigh->ha;\n-\t\tskb_dst_set_noref(skb, &rt->dst);\n+\t\tskb_dst_set_noref(skb, dst);\n \t\tbreak;\n+\t}\n \tcase FLOW_OFFLOAD_XMIT_DIRECT:\n \t\txmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);\n \t\tif (!xmit.outdev) {\n@@ -1068,8 +1107,12 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,\n \tif (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IPV6)))\n \t\treturn NULL;\n \n-\tif (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)\n+\tif (ctx->tun.proto == IPPROTO_IPIP) {\n+\t\tif (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)\n+\t\t\treturn NULL;\n+\t} else if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0) {\n \t\treturn NULL;\n+\t}\n \n \treturn flow_offload_lookup(flow_table, &tuple);\n }\n@@ -1097,8 +1140,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,\n \tif (tuplehash == NULL)\n \t\treturn NF_ACCEPT;\n \n-\tret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb,\n-\t\t\t\t\t   encap_limit);\n+\tif (ctx.tun.proto == IPPROTO_IPIP)\n+\t\tret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);\n+\telse\n+\t\tret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash,\n+\t\t\t\t\t\t   skb, encap_limit);\n \tif (ret < 0)\n \t\treturn NF_DROP;\n \telse if (ret == 0)\n@@ -1125,21 +1171,38 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,\n \t\treturn NF_DROP;\n \n \tswitch (tuplehash->tuple.xmit_type) {\n-\tcase FLOW_OFFLOAD_XMIT_NEIGH:\n-\t\trt = dst_rt6_info(tuplehash->tuple.dst_cache);\n+\tcase FLOW_OFFLOAD_XMIT_NEIGH: {\n+\t\tstruct dst_entry *dst;\n+\n \t\txmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);\n \t\tif (!xmit.outdev) {\n \t\t\tflow_offload_teardown(flow);\n \t\t\treturn NF_DROP;\n \t\t}\n-\t\tneigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, ip6_daddr));\n+\t\tif (other_tuple->tun.encap_proto == AF_INET ||\n+\t\t    ctx.tun.proto == IPPROTO_IPIP) {\n+\t\t\t__be32 ip_daddr = other_tuple->src_v4.s_addr;\n+\t\t\tstruct rtable *rt4;\n+\n+\t\t\tskb->protocol = htons(ETH_P_IP);\n+\t\t\trt4 = dst_rtable(tuplehash->tuple.dst_cache);\n+\t\t\tneigh = ip_neigh_gw4(rt4->dst.dev,\n+\t\t\t\t\t     rt_nexthop(rt4, ip_daddr));\n+\t\t\tdst = &rt4->dst;\n+\t\t} else {\n+\t\t\trt = dst_rt6_info(tuplehash->tuple.dst_cache);\n+\t\t\tneigh = ip_neigh_gw6(rt->dst.dev,\n+\t\t\t\t\t     rt6_nexthop(rt, ip6_daddr));\n+\t\t\tdst = &rt->dst;\n+\t\t}\n \t\tif (IS_ERR(neigh)) {\n \t\t\tflow_offload_teardown(flow);\n \t\t\treturn NF_DROP;\n \t\t}\n \t\txmit.dest = neigh->ha;\n-\t\tskb_dst_set_noref(skb, &rt->dst);\n+\t\tskb_dst_set_noref(skb, dst);\n \t\tbreak;\n+\t}\n \tcase FLOW_OFFLOAD_XMIT_DIRECT:\n \t\txmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);\n \t\tif (!xmit.outdev) {\ndiff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c\nindex 5a5774d9b6f5..74b6f5ea35f9 100644\n--- a/net/netfilter/nf_flow_table_path.c\n+++ b/net/netfilter/nf_flow_table_path.c\n@@ -209,12 +209,11 @@ static int nft_flow_tunnel_update_route(const struct nft_pktinfo *pkt,\n \tstruct dst_entry *tun_dst = NULL;\n \tstruct flowi fl = {};\n \n-\tswitch (nft_pf(pkt)) {\n+\tswitch (tun->encap_proto) {\n \tcase NFPROTO_IPV4:\n \t\tfl.u.ip4.daddr = tun->dst_v4.s_addr;\n \t\tfl.u.ip4.saddr = tun->src_v4.s_addr;\n \t\tfl.u.ip4.flowi4_iif = nft_in(pkt)->ifindex;\n-\t\tfl.u.ip4.flowi4_dscp = ip4h_dscp(ip_hdr(pkt->skb));\n \t\tfl.u.ip4.flowi4_mark = pkt->skb->mark;\n \t\tfl.u.ip4.flowi4_flags = FLOWI_FLAG_ANYSRC;\n \t\tbreak;\n@@ -222,13 +221,12 @@ static int nft_flow_tunnel_update_route(const struct nft_pktinfo *pkt,\n \t\tfl.u.ip6.daddr = tun->dst_v6;\n \t\tfl.u.ip6.saddr = tun->src_v6;\n \t\tfl.u.ip6.flowi6_iif = nft_in(pkt)->ifindex;\n-\t\tfl.u.ip6.flowlabel = ip6_flowinfo(ipv6_hdr(pkt->skb));\n \t\tfl.u.ip6.flowi6_mark = pkt->skb->mark;\n \t\tfl.u.ip6.flowi6_flags = FLOWI_FLAG_ANYSRC;\n \t\tbreak;\n \t}\n \n-\tnf_route(nft_net(pkt), &tun_dst, &fl, false, nft_pf(pkt));\n+\tnf_route(nft_net(pkt), &tun_dst, &fl, false, tun->encap_proto);\n \tif (!tun_dst)\n \t\treturn -ENOENT;\n \n",
    "prefixes": [
        "nf-next",
        "3/4"
    ]
}