* [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration
@ 2026-10-29 13:35 Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 1/8] net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching Lorenzo Bianconi
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Similar to IPIP and IP6I6 tunnels, introduce sw acceleration for IPv4 over
IPv6 and SIT tunnels in the netfilter flowtable infrastructure.
---
Lorenzo Bianconi (8):
net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching
net: netfilter: nf_flow_table: refactor MTU check for tunnel offload
net: ip6_tunnel: add IPv4 over IPv6 flowtable tunnel offload
net: netfilter: nf_flow_table: use tunnel encap proto for route lookup
net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
selftests: netfilter: nft_flowtable.sh: add IPv4 over IPv6 flowtable selftest
net: netfilter: add SIT tunnel flowtable acceleration
selftests: netfilter: nft_flowtable.sh: add SIT flowtable selftest
net/ipv6/ip6_tunnel.c | 11 +-
net/ipv6/sit.c | 59 +++++++++
net/netfilter/nf_flow_table_core.c | 18 ++-
net/netfilter/nf_flow_table_ip.c | 133 ++++++++++++++++-----
tools/testing/selftests/net/netfilter/config | 1 +
.../selftests/net/netfilter/nft_flowtable.sh | 86 ++++++++++++-
6 files changed, 269 insertions(+), 39 deletions(-)
---
base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
change-id: 20261029-flowtable-sw-accel-ip6ip-sit-f3393772880e
Best regards,
--
Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH nf-next 1/8] net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 2/8] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload Lorenzo Bianconi
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Allow the flowtable to parse IPv4-in-IPv6 and IPv6-in-IPv4 tunnels by
accepting both IPPROTO_IPIP and IPPROTO_IPV6 as the inner protocol when
walking the outer header in nf_flow_ip4_tunnel_proto() and
nf_flow_ip6_tunnel_proto(). This is a preliminary patch to support IPv4
over IPv6 and SIT tunnel flowtable offload.
Please note IPv4 over IPv6 and SIT tunnel flowtable offloading is not
enabled yet.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/netfilter/nf_flow_table_ip.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 19cafae748ab..e07fa9327eb7 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -328,7 +328,7 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
if (iph->ttl <= 1)
return false;
- if (iph->protocol == IPPROTO_IPIP) {
+ if (iph->protocol == IPPROTO_IPIP || iph->protocol == IPPROTO_IPV6) {
ctx->tun.inner_proto = iph->protocol;
ctx->tun.hdr_size = size;
ctx->offset += ctx->tun.hdr_size;
@@ -353,7 +353,7 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
if (ipv6_ext_hdr(ip6h->nexthdr))
return false;
- if (ip6h->nexthdr == IPPROTO_IPV6) {
+ if (ip6h->nexthdr == IPPROTO_IPIP || ip6h->nexthdr == IPPROTO_IPV6) {
ctx->tun.inner_proto = ip6h->nexthdr;
ctx->tun.hdr_size = sizeof(*ip6h);
ctx->offset += ctx->tun.hdr_size;
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 2/8] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 1/8] net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 3/8] net: ip6_tunnel: add IPv4 over IPv6 flowtable " Lorenzo Bianconi
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Introduce nf_flow_offload_check_mtu() helper and use the encapsulated
protocol (tun.encap_proto) to compute the tunnel overhead instead of
relying on tun_num, so the correct inner header size (IPv4 vs IPv6) is
accounted for. Use it in both the IPv4 and IPv6 forward paths.
This is a preliminary patch to support IPv4 over IPv6 and SIT flowtable
tunnel offload.
Please note IPv4 over IPv6 and SIT tunnel flowtable offloading is not
enabled yet.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/netfilter/nf_flow_table_ip.c | 41 ++++++++++++++++++++++++++++------------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index e07fa9327eb7..902b9b595677 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -472,6 +472,31 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
return flow_offload_lookup(flow_table, &tuple);
}
+static int nf_flow_offload_check_mtu(struct nf_flowtable_ctx *ctx,
+ struct flow_offload *flow,
+ enum flow_offload_tuple_dir dir,
+ struct sk_buff *skb)
+{
+ unsigned int mtu;
+
+ mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset;
+ switch (flow->tuplehash[!dir].tuple.tun.encap_proto) {
+ case AF_INET:
+ mtu -= sizeof(struct iphdr);
+ break;
+ case AF_INET6:
+ mtu -= sizeof(struct ipv6hdr);
+ break;
+ default:
+ break;
+ }
+
+ if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
+ return -EINVAL;
+
+ return 0;
+}
+
static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx,
struct nf_flowtable *flow_table,
struct flow_offload_tuple_rhash *tuplehash,
@@ -479,17 +504,13 @@ static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx,
{
enum flow_offload_tuple_dir dir;
struct flow_offload *flow;
- unsigned int thoff, mtu;
+ unsigned int thoff;
struct iphdr *iph;
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset;
- if (flow->tuplehash[!dir].tuple.tun_num)
- mtu -= sizeof(*iph);
-
- if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
+ if (nf_flow_offload_check_mtu(ctx, flow, dir, skb))
return 0;
iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset);
@@ -1108,17 +1129,13 @@ static int nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx,
{
enum flow_offload_tuple_dir dir;
struct flow_offload *flow;
- unsigned int thoff, mtu;
struct ipv6hdr *ip6h;
+ unsigned int thoff;
dir = tuplehash->tuple.dir;
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
- mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset;
- if (flow->tuplehash[!dir].tuple.tun_num)
- mtu -= sizeof(*ip6h);
-
- if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
+ if (nf_flow_offload_check_mtu(ctx, flow, dir, skb))
return 0;
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset);
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 3/8] net: ip6_tunnel: add IPv4 over IPv6 flowtable tunnel offload
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 1/8] net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 2/8] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 4/8] net: netfilter: nf_flow_table: use tunnel encap proto for route lookup Lorenzo Bianconi
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Allow ip6_tnl_fill_forward_path() to set the inner protocol for IPv4
packets (IPPROTO_IPIP) in addition to IPv6 (IPPROTO_IPV6), so that the
flowtable can offload IPv4-in-IPv6 tunnels.
Return -EOPNOTSUPP for any other ethertype.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/ipv6/ip6_tunnel.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 64a184bca467..9ae14977c900 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1844,8 +1844,16 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
struct flowi6 fl6;
int err;
- if (ctx->ether_type != cpu_to_be16(ETH_P_IPV6))
+ switch (ctx->ether_type) {
+ case cpu_to_be16(ETH_P_IP):
+ path->tun.inner_proto = IPPROTO_IPIP;
+ break;
+ case cpu_to_be16(ETH_P_IPV6):
+ path->tun.inner_proto = IPPROTO_IPV6;
+ break;
+ default:
return -EOPNOTSUPP;
+ }
if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS |
IP6_TNL_F_USE_ORIG_FLOWLABEL |
@@ -1867,7 +1875,6 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
path->type = DEV_PATH_TUN;
path->tun.src_v6 = fl6.saddr;
path->tun.dst_v6 = fl6.daddr;
- path->tun.inner_proto = IPPROTO_IPV6;
path->tun.encap_proto = AF_INET6;
path->tun.dst = dst;
path->dev = ctx->dev;
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 4/8] net: netfilter: nf_flow_table: use tunnel encap proto for route lookup
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
` (2 preceding siblings ...)
2026-10-29 13:35 ` [PATCH nf-next 3/8] net: ip6_tunnel: add IPv4 over IPv6 flowtable " Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration Lorenzo Bianconi
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
For IP tunnels, resolve the MTU and the dst cookie against the tunnel's
inner IP protocol (tun.encap_proto) instead of the flow's l3proto, so
the correct header size and route cookie are used when the flow is
carried over a tunnel.
This is a preliminary patch to support IPv4 over IPv6 and SIT tunnel
flowtable offload.
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/netfilter/nf_flow_table_core.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 0d72dc8ae47a..aa8e3f42b23f 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -76,9 +76,10 @@ struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
}
EXPORT_SYMBOL_GPL(flow_offload_alloc);
-static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
+static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple,
+ u8 l3_proto)
{
- if (flow_tuple->l3proto == NFPROTO_IPV6)
+ if (l3_proto == NFPROTO_IPV6)
return rt6_get_cookie(dst_rt6_info(flow_tuple->dst_cache));
return 0;
@@ -100,9 +101,15 @@ static int flow_offload_fill_route(struct flow_offload *flow,
{
struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
struct dst_entry *dst = nft_route_dst_fetch(route, dir);
+ u8 l3_proto = flow_tuple->l3proto;
int i, j = 0;
- switch (flow_tuple->l3proto) {
+ if (route->tuple[!dir].in.tun.encap_proto) {
+ /* For IP tunnels we need to consider tunnel IP protocol. */
+ l3_proto = route->tuple[!dir].in.tun.encap_proto;
+ }
+
+ switch (l3_proto) {
case NFPROTO_IPV4:
flow_tuple->mtu = ip_dst_mtu_maybe_forward(dst, true);
break;
@@ -130,7 +137,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
if (route->tuple[!dir].in.num_tuns) {
flow_tuple->dst_cache = dst;
flow_tuple->dst_cookie =
- flow_offload_dst_cookie(flow_tuple);
+ flow_offload_dst_cookie(flow_tuple, l3_proto);
} else {
dst_release(dst);
}
@@ -144,7 +151,8 @@ static int flow_offload_fill_route(struct flow_offload *flow,
case FLOW_OFFLOAD_XMIT_NEIGH:
flow_tuple->ifidx = route->tuple[dir].out.ifindex;
flow_tuple->dst_cache = dst;
- flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
+ flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple,
+ l3_proto);
break;
default:
WARN_ON_ONCE(1);
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
` (3 preceding siblings ...)
2026-10-29 13:35 ` [PATCH nf-next 4/8] net: netfilter: nf_flow_table: use tunnel encap proto for route lookup Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-30 4:33 ` kernel test robot
2026-10-29 13:35 ` [PATCH nf-next 6/8] selftests: netfilter: nft_flowtable.sh: add IPv4 over IPv6 flowtable selftest Lorenzo Bianconi
` (2 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Introduce sw flowtable acceleration for the TX/RX paths of
IPv4 over IPv6 tunnels, relying on the netfilter flowtable
infrastructure.
The feature can be tested with a forwarding scenario between two
NICs (eth0 and eth1), where an IPv4 over IPv6 tunnel is used to
reach a remote site via eth1 as the underlay device:
ETH0 -- TUN0 <==> ETH1 -- [IP network] -- TUN1 (2001:db8:2::2)
[IP configuration]
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:00:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/24 scope global eth0
valid_lft forever preferred_lft forever
7: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:11:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet6 2001:db8:2::1/64 scope global nodad
valid_lft forever preferred_lft forever
8: tun0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/tunnel6 2001:db8:2::1 peer 2001:db8:2::2 permaddr ce9c:2940:7dcc::
inet 192.168.100.1/24 scope global tun0
valid_lft forever preferred_lft forever
$ ip route show
default via 192.168.100.2 dev tun0
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.2
192.168.100.0/24 dev tun0 proto kernel scope link src 192.168.100.1
$ ip -6 route show
2001:db8:2::/64 dev eth1 proto kernel metric 256 pref medium
$ nft list ruleset
table inet filter {
flowtable ft {
hook ingress priority filter
devices = { eth0, eth1 }
}
chain forward {
type filter hook forward priority filter; policy accept;
meta l4proto { tcp, udp } flow add @ft
}
}
When reproducing this scenario using veth interfaces, the following
results were observed:
- TCP stream received from IPv4 over IPv6 tunnel:
- net-next (baseline): ~126 Gbps
- net-next + IP6IP flowtable support: ~138 Gbps
- TCP stream transmitted to IPv4 over IPv6 tunnel:
- net-next (baseline): ~127 Gbps
- net-next + IP6IP flowtable support: ~140 Gbps
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/netfilter/nf_flow_table_ip.c | 66 ++++++++++++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 902b9b595677..0ffa6470c46d 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -856,7 +856,8 @@ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
return NF_STOLEN;
}
-static int nf_flow_queue_xmit4(struct sk_buff *skb,
+static int nf_flow_queue_xmit4(struct nf_flowtable_ctx *ctx,
+ struct sk_buff *skb,
struct flow_offload_tuple_rhash *tuplehash,
const struct nf_hook_state *state)
{
@@ -886,14 +887,29 @@ static int nf_flow_queue_xmit4(struct sk_buff *skb,
return NF_DROP;
switch (tuplehash->tuple.xmit_type) {
- case FLOW_OFFLOAD_XMIT_NEIGH:
- rt = dst_rtable(tuplehash->tuple.dst_cache);
+ case FLOW_OFFLOAD_XMIT_NEIGH: {
+ struct dst_entry *dst;
+
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
if (!xmit.outdev) {
flow_offload_teardown(flow);
return NF_DROP;
}
- neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, ip_addr->ip));
+ if (other_tuple->tun.encap_proto ?
+ other_tuple->tun.encap_proto == AF_INET6 :
+ ctx->tun.inner_proto == IPPROTO_IPV6) {
+ struct rt6_info *rt6;
+
+ rt6 = dst_rt6_info(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw6(rt6->dst.dev,
+ rt6_nexthop(rt6, &ip_addr->in6));
+ dst = &rt6->dst;
+ } else {
+ rt = dst_rtable(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw4(rt->dst.dev,
+ rt_nexthop(rt, ip_addr->ip));
+ dst = &rt->dst;
+ }
if (IS_ERR(neigh)) {
flow_offload_teardown(flow);
return NF_DROP;
@@ -902,6 +918,7 @@ static int nf_flow_queue_xmit4(struct sk_buff *skb,
skb_dst_drop(skb);
skb_dst_set_noref(skb, &rt->dst);
break;
+ }
case FLOW_OFFLOAD_XMIT_DIRECT:
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
if (!xmit.outdev) {
@@ -948,7 +965,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
else if (ret == 0)
return NF_ACCEPT;
- return nf_flow_queue_xmit4(skb, tuplehash, state);
+ return nf_flow_queue_xmit4(&ctx, skb, tuplehash, state);
}
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
@@ -1175,13 +1192,18 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
+ if (ctx->tun.inner_proto == IPPROTO_IPIP) {
+ if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
+ return NULL;
+ } else if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0) {
return NULL;
+ }
return flow_offload_lookup(flow_table, &tuple);
}
-static int nf_flow_queue_xmit6(struct sk_buff *skb,
+static int nf_flow_queue_xmit6(struct nf_flowtable_ctx *ctx,
+ struct sk_buff *skb,
struct flow_offload_tuple_rhash *tuplehash,
const struct nf_hook_state *state)
{
@@ -1211,14 +1233,29 @@ static int nf_flow_queue_xmit6(struct sk_buff *skb,
return NF_DROP;
switch (tuplehash->tuple.xmit_type) {
- case FLOW_OFFLOAD_XMIT_NEIGH:
- rt = dst_rt6_info(tuplehash->tuple.dst_cache);
+ case FLOW_OFFLOAD_XMIT_NEIGH: {
+ struct dst_entry *dst;
+
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
if (!xmit.outdev) {
flow_offload_teardown(flow);
return NF_DROP;
}
- neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, &ip_addr->in6));
+ if (other_tuple->tun.encap_proto ?
+ other_tuple->tun.encap_proto == AF_INET :
+ ctx->tun.inner_proto == IPPROTO_IPIP) {
+ struct rtable *rt4;
+
+ rt4 = dst_rtable(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw4(rt4->dst.dev,
+ rt_nexthop(rt4, ip_addr->ip));
+ dst = &rt4->dst;
+ } else {
+ rt = dst_rt6_info(tuplehash->tuple.dst_cache);
+ neigh = ip_neigh_gw6(rt->dst.dev,
+ rt6_nexthop(rt, &ip_addr->in6));
+ dst = &rt->dst;
+ }
if (IS_ERR(neigh)) {
flow_offload_teardown(flow);
return NF_DROP;
@@ -1227,6 +1264,7 @@ static int nf_flow_queue_xmit6(struct sk_buff *skb,
skb_dst_drop(skb);
skb_dst_set_noref(skb, &rt->dst);
break;
+ }
case FLOW_OFFLOAD_XMIT_DIRECT:
xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
if (!xmit.outdev) {
@@ -1267,12 +1305,16 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
if (!tuplehash)
return NF_ACCEPT;
- ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
+ if (ctx.tun.inner_proto == IPPROTO_IPIP)
+ ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
+ else
+ ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash,
+ skb);
if (ret < 0)
return NF_DROP;
else if (ret == 0)
return NF_ACCEPT;
- return nf_flow_queue_xmit6(skb, tuplehash, state);
+ return nf_flow_queue_xmit6(&ctx, skb, tuplehash, state);
}
EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 6/8] selftests: netfilter: nft_flowtable.sh: add IPv4 over IPv6 flowtable selftest
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
` (4 preceding siblings ...)
2026-10-29 13:35 ` [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 7/8] net: netfilter: add SIT tunnel flowtable acceleration Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 8/8] selftests: netfilter: nft_flowtable.sh: add SIT flowtable selftest Lorenzo Bianconi
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Similar to IPIP and IP6IP6, introduce specific selftest for IPv4 over IPv6
flowtable sw acceleration in nft_flowtable.sh
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
.../selftests/net/netfilter/nft_flowtable.sh | 33 +++++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/net/netfilter/nft_flowtable.sh b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
index 449c518bd947..dcbae9a3d92b 100755
--- a/tools/testing/selftests/net/netfilter/nft_flowtable.sh
+++ b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
@@ -579,9 +579,8 @@ if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 ""; then
ip netns exec "$nsr1" nft list ruleset
fi
-# IPIP tunnel test:
-# Add IPIP tunnel interfaces and check flowtable acceleration.
-test_ipip() {
+# IP tunnel tests:
+test_ip_tnls() {
if ! ip -net "$nsr1" link add name tun0 type ipip \
local 192.168.10.1 remote 192.168.10.2 >/dev/null;then
echo "SKIP: could not add ipip tunnel"
@@ -594,7 +593,9 @@ ip netns exec "$nsr1" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
ip -net "$nsr1" link add name tun6 type ip6tnl local fee1:2::1 remote fee1:2::2 encaplimit none
ip -net "$nsr1" link set tun6 up
+ip -net "$nsr1" addr add 192.168.210.1/24 dev tun6
ip -net "$nsr1" addr add fee1:3::1/64 dev tun6 nodad
+ip netns exec "$nsr1" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun0 type ipip local 192.168.10.2 remote 192.168.10.1
ip -net "$nsr2" link set tun0 up
@@ -603,7 +604,9 @@ ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun6 type ip6tnl local fee1:2::2 remote fee1:2::1 encaplimit none || ret=1
ip -net "$nsr2" link set tun6 up
+ip -net "$nsr2" addr add 192.168.210.2/24 dev tun6
ip -net "$nsr2" addr add fee1:3::2/64 dev tun6 nodad
+ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
ip -net "$nsr1" route change default via 192.168.100.2
ip -net "$nsr2" route change default via 192.168.100.1
@@ -640,6 +643,15 @@ else
ret=1
fi
+ip -net "$nsr1" route change default via 192.168.210.2
+ip -net "$nsr2" route change default via 192.168.210.1
+
+if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP4IP6 tunnel"; then
+ echo "FAIL: flow offload for ns1/ns2 with IP4IP6 tunnel" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Create vlan tagged devices for IPIP traffic.
ip -net "$nsr1" link add link veth1 name veth1.10 type vlan id 10
ip -net "$nsr1" link set veth1.10 up
@@ -661,7 +673,9 @@ ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0.10 a
ip -net "$nsr1" link add name tun6.10 type ip6tnl local fee1:4::1 remote fee1:4::2 encaplimit none
ip -net "$nsr1" link set tun6.10 up
+ip -net "$nsr1" addr add 192.168.220.1/24 dev tun6.10
ip -net "$nsr1" addr add fee1:5::1/64 dev tun6.10 nodad
+ip netns exec "$nsr1" sysctl net.ipv4.conf.tun6/10.forwarding=1 > /dev/null
ip -6 -net "$nsr1" route delete default
ip -6 -net "$nsr1" route add default via fee1:5::2
ip netns exec "$nsr1" nft -a insert rule inet filter forward \
@@ -682,7 +696,9 @@ ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0/10.forwarding=1 > /dev/null
ip -net "$nsr2" link add name tun6.10 type ip6tnl local fee1:4::2 remote fee1:4::1 encaplimit none || ret=1
ip -net "$nsr2" link set tun6.10 up
+ip -net "$nsr2" addr add 192.168.220.2/24 dev tun6.10
ip -net "$nsr2" addr add fee1:5::2/64 dev tun6.10 nodad
+ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6/10.forwarding=1 > /dev/null
ip -6 -net "$nsr2" route delete default
ip -6 -net "$nsr2" route add default via fee1:5::1
@@ -700,6 +716,15 @@ else
ret=1
fi
+ip -net "$nsr1" route change default via 192.168.220.2
+ip -net "$nsr2" route change default via 192.168.220.1
+
+if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP4IP6 tunnel over vlan"; then
+ echo "FAIL: flow offload for ns1/ns2 with IP4IP6 tunnel over vlan" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Restore the previous configuration
ip -net "$nsr1" route change default via 192.168.10.2
ip -net "$nsr2" route change default via 192.168.10.1
@@ -847,7 +872,7 @@ ip -net "$nsr1" addr add dead:1::1/64 dev veth0 nodad
ip -net "$nsr1" link set up dev veth0
}
-test_ipip
+test_ip_tnls
test_bridge
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 7/8] net: netfilter: add SIT tunnel flowtable acceleration
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
` (5 preceding siblings ...)
2026-10-29 13:35 ` [PATCH nf-next 6/8] selftests: netfilter: nft_flowtable.sh: add IPv4 over IPv6 flowtable selftest Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 8/8] selftests: netfilter: nft_flowtable.sh: add SIT flowtable selftest Lorenzo Bianconi
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Introduce sw flowtable acceleration for the TX/RX paths of
SIT tunnels, relying on the netfilter flowtable infrastructure.
The feature can be tested with a forwarding scenario between two
NICs (eth0 and eth1), where a SIT tunnel is used to reach a remote
site via eth1 as the underlay device:
ETH0 -- TUN0 <==> ETH1 -- [IP network] -- TUN1 (192.168.2.2)
[IP configuration]
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:00:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet6 2001:db8:1::2/64 scope global nodad
valid_lft forever preferred_lft forever
7: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:11:22:33:11:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.2.1/24 scope global eth1
valid_lft forever preferred_lft forever
8: tun0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/sit 192.168.2.1 peer 192.168.2.2
inet6 2001:db8:200::1/64 scope global nodad
valid_lft forever preferred_lft forever
$ ip route show
192.168.2.0/24 dev eth1 proto kernel scope link src 192.168.2.1
$ ip -6 route show
2001:db8:1::/64 dev eth0 proto kernel metric 256 pref medium
2001:db8:200::/64 dev tun0 proto kernel metric 256 pref medium
default via 2001:db8:200::2 dev tun0 metric 1024 pref medium
$ nft list ruleset
table inet filter {
flowtable ft {
hook ingress priority filter
devices = { eth0, eth1 }
}
chain forward {
type filter hook forward priority filter; policy accept;
meta l4proto { tcp, udp } flow add @ft
}
}
When reproducing this scenario using veth interfaces, the following
results were observed:
- TCP stream received from SIT tunnel:
- net-next (baseline): ~118 Gbps
- net-next + SIT flowtable support: ~148 Gbps
- TCP stream transmitted to SIT tunnel:
- net-next (baseline): ~131 Gbps
- net-next + SIT flowtable support: ~147 Gbps
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
net/ipv6/sit.c | 59 ++++++++++++++++++++++++++++++++++++++++
net/netfilter/nf_flow_table_ip.c | 22 +++++++++++++--
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index a7ec800216ad..ed66358ab644 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -29,6 +29,7 @@
#include <linux/icmp.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/inetdevice.h>
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
#include <linux/if_ether.h>
@@ -1483,6 +1484,63 @@ ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p,
}
}
+static int ipip6_tunnel_fill_forward_path(struct net_device_path_ctx *ctx,
+ struct net_device_path *path)
+{
+ struct ip_tunnel *tunnel = netdev_priv(ctx->dev);
+ const struct iphdr *tiph = &tunnel->parms.iph;
+ struct rtable *rt;
+
+ /* NBMA tunnels (ISATAP, 6to4, 6rd) resolve the outer destination
+ * per-packet from the inner IPv6 address; not offloadable.
+ */
+ if (ctx->dev->priv_flags & IFF_ISATAP)
+ return -EOPNOTSUPP;
+
+ if (!tiph->daddr)
+ return -EOPNOTSUPP;
+
+ /* FOU/GUE encapsulation is handled in the slow path by
+ * ip_tunnel_encap(); the fast path only pushes a plain
+ * IPv4 header and would skip the UDP encapsulation.
+ */
+ if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
+ return -EOPNOTSUPP;
+
+ rt = ip_route_output(dev_net(ctx->dev), tiph->daddr, tiph->saddr,
+ inet_dsfield_to_dscp(tiph->tos),
+ tunnel->parms.link, RT_SCOPE_UNIVERSE);
+ if (IS_ERR(rt))
+ return PTR_ERR(rt);
+
+ path->type = DEV_PATH_TUN;
+ if (tiph->saddr)
+ path->tun.src_v4.s_addr = tiph->saddr;
+ else
+ path->tun.src_v4.s_addr = inet_select_addr(rt->dst.dev,
+ tiph->daddr,
+ RT_SCOPE_UNIVERSE);
+ path->tun.dst_v4.s_addr = tiph->daddr;
+ path->tun.encap_proto = AF_INET;
+ path->dev = ctx->dev;
+ path->tun.dst = &rt->dst;
+
+ switch (ctx->ether_type) {
+ case cpu_to_be16(ETH_P_IP):
+ path->tun.inner_proto = IPPROTO_IPIP;
+ break;
+ case cpu_to_be16(ETH_P_IPV6):
+ path->tun.inner_proto = IPPROTO_IPV6;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ ctx->dev = rt->dst.dev;
+
+ return 0;
+}
+
static int
ipip6_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
void __user *data, int cmd)
@@ -1533,6 +1591,7 @@ static const struct net_device_ops ipip6_netdev_ops = {
.ndo_siocdevprivate = ipip6_tunnel_siocdevprivate,
.ndo_get_iflink = ipip6_get_iflink,
.ndo_tunnel_ctl = ipip6_tunnel_ctl,
+ .ndo_fill_forward_path = ipip6_tunnel_fill_forward_path,
};
static void ipip6_dev_free(struct net_device *dev)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 0ffa6470c46d..876e3e87ef87 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -158,6 +158,16 @@ struct nf_flowtable_ctx {
} tun;
};
+static int nf_flow_tuple_ipv6(struct nf_flowtable_ctx *ctx,
+ struct sk_buff *skb,
+ struct flow_offload_tuple *tuple);
+
+static int
+nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx,
+ struct nf_flowtable *flow_table,
+ struct flow_offload_tuple_rhash *tuplehash,
+ struct sk_buff *skb);
+
static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
struct sk_buff *skb,
struct flow_offload_tuple *tuple)
@@ -466,8 +476,12 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
+ if (ctx->tun.inner_proto == IPPROTO_IPV6) {
+ if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
+ return NULL;
+ } else if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0) {
return NULL;
+ }
return flow_offload_lookup(flow_table, &tuple);
}
@@ -959,7 +973,11 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
if (!tuplehash)
return NF_ACCEPT;
- ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
+ if (ctx.tun.inner_proto == IPPROTO_IPV6)
+ ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash,
+ skb);
+ else
+ ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
if (ret < 0)
return NF_DROP;
else if (ret == 0)
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH nf-next 8/8] selftests: netfilter: nft_flowtable.sh: add SIT flowtable selftest
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
` (6 preceding siblings ...)
2026-10-29 13:35 ` [PATCH nf-next 7/8] net: netfilter: add SIT tunnel flowtable acceleration Lorenzo Bianconi
@ 2026-10-29 13:35 ` Lorenzo Bianconi
7 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-29 13:35 UTC (permalink / raw)
To: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan
Cc: netfilter-devel, coreteam, netdev, linux-kselftest,
Lorenzo Bianconi
Similar to IPIP, IP6IP6 and IPv4 over IPv6, introduce specific selftest
for SIT flowtable sw acceleration in nft_flowtable.sh.
Also add tunnel-specific flow-add rules for sit1 and sit1.10 so that
check_counters() properly verifies offload occurred, and restore IPv6
default routes at cleanup to prevent tunnel routes leaking to subsequent
tests (e.g. IPsec).
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
tools/testing/selftests/net/netfilter/config | 1 +
.../selftests/net/netfilter/nft_flowtable.sh | 53 ++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/tools/testing/selftests/net/netfilter/config b/tools/testing/selftests/net/netfilter/config
index 629b2b29ed1a..930374aabec1 100644
--- a/tools/testing/selftests/net/netfilter/config
+++ b/tools/testing/selftests/net/netfilter/config
@@ -35,6 +35,7 @@ CONFIG_IP_SCTP=m
CONFIG_IPV6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_SIT=m
CONFIG_IP_VS=m
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_RR=m
diff --git a/tools/testing/selftests/net/netfilter/nft_flowtable.sh b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
index dcbae9a3d92b..3a393c8deab9 100755
--- a/tools/testing/selftests/net/netfilter/nft_flowtable.sh
+++ b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
@@ -597,6 +597,10 @@ ip -net "$nsr1" addr add 192.168.210.1/24 dev tun6
ip -net "$nsr1" addr add fee1:3::1/64 dev tun6 nodad
ip netns exec "$nsr1" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
+ip -net "$nsr1" link add name sit1 type sit local 192.168.10.1 remote 192.168.10.2 ttl 255
+ip -net "$nsr1" link set sit1 up
+ip -net "$nsr1" addr add fe01:3::1/64 dev sit1 nodad
+
ip -net "$nsr2" link add name tun0 type ipip local 192.168.10.2 remote 192.168.10.1
ip -net "$nsr2" link set tun0 up
ip -net "$nsr2" addr add 192.168.100.2/24 dev tun0
@@ -608,6 +612,10 @@ ip -net "$nsr2" addr add 192.168.210.2/24 dev tun6
ip -net "$nsr2" addr add fee1:3::2/64 dev tun6 nodad
ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6.forwarding=1 > /dev/null
+ip -net "$nsr2" link add name sit1 type sit local 192.168.10.2 remote 192.168.10.1 ttl 255
+ip -net "$nsr2" link set sit1 up
+ip -net "$nsr2" addr add fe01:3::2/64 dev sit1 nodad
+
ip -net "$nsr1" route change default via 192.168.100.2
ip -net "$nsr2" route change default via 192.168.100.1
@@ -626,6 +634,9 @@ ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0 acce
ip netns exec "$nsr1" nft -a insert rule inet filter forward \
'meta oif tun6 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept'
ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun6 accept'
+ip netns exec "$nsr1" nft -a insert rule inet filter forward \
+ 'meta oif sit1 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept'
+ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif sit1 accept'
ip netns exec "$nsr1" nft -a insert rule inet filter forward \
'meta oif "veth0" tcp sport 12345 ct mark set 1 flow add @f1 counter name routed_repl accept'
@@ -652,6 +663,19 @@ if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP4IP6 tunnel"; then
ret=1
fi
+ip -6 -net "$nsr1" route delete default
+ip -6 -net "$nsr1" route add default via fe01:3::2
+ip -6 -net "$nsr2" route delete default
+ip -6 -net "$nsr2" route add default via fe01:3::1
+
+if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then
+ check_counters "flow offload for ns1/ns2 SIT tunnel"
+else
+ echo "FAIL: flow offload for ns1/ns2 with SIT tunnel" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Create vlan tagged devices for IPIP traffic.
ip -net "$nsr1" link add link veth1 name veth1.10 type vlan id 10
ip -net "$nsr1" link set veth1.10 up
@@ -682,6 +706,13 @@ ip netns exec "$nsr1" nft -a insert rule inet filter forward \
'meta oif tun6.10 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept'
ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun6.10 accept'
+ip -net "$nsr1" link add name sit1.10 type sit local 192.168.20.1 remote 192.168.20.2 ttl 255
+ip -net "$nsr1" link set sit1.10 up
+ip -net "$nsr1" addr add fe01:5::1/64 dev sit1.10 nodad
+ip netns exec "$nsr1" nft -a insert rule inet filter forward \
+ 'meta oif sit1.10 tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept'
+ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif sit1.10 accept'
+
ip -net "$nsr2" link add link veth0 name veth0.10 type vlan id 10
ip -net "$nsr2" link set veth0.10 up
ip -net "$nsr2" addr add 192.168.20.2/24 dev veth0.10
@@ -699,6 +730,11 @@ ip -net "$nsr2" link set tun6.10 up
ip -net "$nsr2" addr add 192.168.220.2/24 dev tun6.10
ip -net "$nsr2" addr add fee1:5::2/64 dev tun6.10 nodad
ip netns exec "$nsr2" sysctl net.ipv4.conf.tun6/10.forwarding=1 > /dev/null
+
+ip -net "$nsr2" link add name sit1.10 type sit local 192.168.20.2 remote 192.168.20.1 ttl 255
+ip -net "$nsr2" link set sit1.10 up
+ip -net "$nsr2" addr add fe01:5::2/64 dev sit1.10 nodad
+
ip -6 -net "$nsr2" route delete default
ip -6 -net "$nsr2" route add default via fee1:5::1
@@ -725,11 +761,28 @@ if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IP4IP6 tunnel over vlan"; then
ret=1
fi
+ip -6 -net "$nsr1" route delete default
+ip -6 -net "$nsr1" route add default via fe01:5::2
+ip -6 -net "$nsr2" route delete default
+ip -6 -net "$nsr2" route add default via fe01:5::1
+
+if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then
+ check_counters "flow offload for ns1/ns2 SIT tunnel over vlan"
+else
+ echo "FAIL: flow offload for ns1/ns2 with SIT tunnel over vlan" 1>&2
+ ip netns exec "$nsr1" nft list ruleset
+ ret=1
+fi
+
# Restore the previous configuration
ip -net "$nsr1" route change default via 192.168.10.2
ip -net "$nsr2" route change default via 192.168.10.1
ip -net "$ns2" route del default via 10.0.2.1
ip -6 -net "$ns2" route del default via dead:2::1
+ip -6 -net "$nsr1" route delete default
+ip -6 -net "$nsr1" route add default via fee1:2::2
+ip -6 -net "$nsr2" route delete default
+ip -6 -net "$nsr2" route add default via fee1:2::1
}
# Another test:
--
2.56.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
2026-10-29 13:35 ` [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration Lorenzo Bianconi
@ 2026-10-30 4:33 ` kernel test robot
2026-10-30 8:20 ` Lorenzo Bianconi
0 siblings, 1 reply; 11+ messages in thread
From: kernel test robot @ 2026-10-30 4:33 UTC (permalink / raw)
To: Lorenzo Bianconi, Pablo Neira Ayuso, Florian Westphal,
Phil Sutter, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Ahern, Ido Schimmel, Shuah Khan
Cc: oe-kbuild-all, netdev, netfilter-devel, coreteam, linux-kselftest,
Lorenzo Bianconi
Hi Lorenzo,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 734bef548a96e8774d6eef5dfa2026c6edc4e80b]
url: https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Bianconi/net-netfilter-nf_flow_table-recognize-IPv4-IPv6-in-tunnel-proto-matching/20261029-143512
base: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
patch link: https://lore.kernel.org/r/20261029-flowtable-sw-accel-ip6ip-sit-v1-5-6a17c54f9fb7%40oss.qualcomm.com
patch subject: [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
config: m68k-defconfig (https://download.01.org/0day-ci/archive/20261030/202610301255.BRNUBmqH-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261030/202610301255.BRNUBmqH-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202610301255.BRNUBmqH-lkp@intel.com/
All warnings (new ones prefixed by >>):
net/netfilter/nf_flow_table_ip.c: In function 'nf_flow_queue_xmit4':
>> net/netfilter/nf_flow_table_ip.c:891:35: warning: variable 'dst' set but not used [-Wunused-but-set-variable=]
891 | struct dst_entry *dst;
| ^~~
net/netfilter/nf_flow_table_ip.c: In function 'nf_flow_queue_xmit6':
net/netfilter/nf_flow_table_ip.c:1237:35: warning: variable 'dst' set but not used [-Wunused-but-set-variable=]
1237 | struct dst_entry *dst;
| ^~~
vim +/dst +891 net/netfilter/nf_flow_table_ip.c
858
859 static int nf_flow_queue_xmit4(struct nf_flowtable_ctx *ctx,
860 struct sk_buff *skb,
861 struct flow_offload_tuple_rhash *tuplehash,
862 const struct nf_hook_state *state)
863 {
864 struct flow_offload_tuple *other_tuple;
865 enum flow_offload_tuple_dir dir;
866 struct nf_flow_xmit xmit = {};
867 union nf_inet_addr *ip_addr;
868 struct flow_offload *flow;
869 struct neighbour *neigh;
870 struct rtable *rt;
871
872 if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
873 rt = dst_rtable(tuplehash->tuple.dst_cache);
874 memset(skb->cb, 0, sizeof(struct inet_skb_parm));
875 IPCB(skb)->iif = skb->dev->ifindex;
876 IPCB(skb)->flags = IPSKB_FORWARDED;
877 return nf_flow_xmit_xfrm(skb, state, &rt->dst);
878 }
879
880 dir = tuplehash->tuple.dir;
881 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
882 other_tuple = &flow->tuplehash[!dir].tuple;
883 ip_addr = (union nf_inet_addr *)&other_tuple->src_v4;
884
885 if (nf_flow_tunnel_push(state->net, skb, other_tuple,
886 tuplehash->tuple.dst_cache, &ip_addr) < 0)
887 return NF_DROP;
888
889 switch (tuplehash->tuple.xmit_type) {
890 case FLOW_OFFLOAD_XMIT_NEIGH: {
> 891 struct dst_entry *dst;
892
893 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
894 if (!xmit.outdev) {
895 flow_offload_teardown(flow);
896 return NF_DROP;
897 }
898 if (other_tuple->tun.encap_proto ?
899 other_tuple->tun.encap_proto == AF_INET6 :
900 ctx->tun.inner_proto == IPPROTO_IPV6) {
901 struct rt6_info *rt6;
902
903 rt6 = dst_rt6_info(tuplehash->tuple.dst_cache);
904 neigh = ip_neigh_gw6(rt6->dst.dev,
905 rt6_nexthop(rt6, &ip_addr->in6));
906 dst = &rt6->dst;
907 } else {
908 rt = dst_rtable(tuplehash->tuple.dst_cache);
909 neigh = ip_neigh_gw4(rt->dst.dev,
910 rt_nexthop(rt, ip_addr->ip));
911 dst = &rt->dst;
912 }
913 if (IS_ERR(neigh)) {
914 flow_offload_teardown(flow);
915 return NF_DROP;
916 }
917 xmit.dest = neigh->ha;
918 skb_dst_drop(skb);
919 skb_dst_set_noref(skb, &rt->dst);
920 break;
921 }
922 case FLOW_OFFLOAD_XMIT_DIRECT:
923 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
924 if (!xmit.outdev) {
925 flow_offload_teardown(flow);
926 return NF_DROP;
927 }
928 xmit.dest = tuplehash->tuple.out.h_dest;
929 xmit.source = tuplehash->tuple.out.h_source;
930 break;
931 default:
932 WARN_ON_ONCE(1);
933 return NF_DROP;
934 }
935 xmit.tuple = other_tuple;
936 xmit.needs_gso_segment = tuplehash->tuple.needs_gso_segment;
937
938 return nf_flow_queue_xmit(state->net, skb, &xmit);
939 }
940
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
2026-10-30 4:33 ` kernel test robot
@ 2026-10-30 8:20 ` Lorenzo Bianconi
0 siblings, 0 replies; 11+ messages in thread
From: Lorenzo Bianconi @ 2026-10-30 8:20 UTC (permalink / raw)
To: kernel test robot
Cc: Pablo Neira Ayuso, Florian Westphal, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Ido Schimmel, Shuah Khan, oe-kbuild-all, netdev,
netfilter-devel, coreteam, linux-kselftest
[-- Attachment #1: Type: text/plain, Size: 5246 bytes --]
> Hi Lorenzo,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on 734bef548a96e8774d6eef5dfa2026c6edc4e80b]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Bianconi/net-netfilter-nf_flow_table-recognize-IPv4-IPv6-in-tunnel-proto-matching/20261029-143512
> base: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
> patch link: https://lore.kernel.org/r/20261029-flowtable-sw-accel-ip6ip-sit-v1-5-6a17c54f9fb7%40oss.qualcomm.com
> patch subject: [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration
> config: m68k-defconfig (https://download.01.org/0day-ci/archive/20261030/202610301255.BRNUBmqH-lkp@intel.com/config)
> compiler: m68k-linux-gcc (GCC) 16.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261030/202610301255.BRNUBmqH-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202610301255.BRNUBmqH-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> net/netfilter/nf_flow_table_ip.c: In function 'nf_flow_queue_xmit4':
> >> net/netfilter/nf_flow_table_ip.c:891:35: warning: variable 'dst' set but not used [-Wunused-but-set-variable=]
> 891 | struct dst_entry *dst;
> | ^~~
> net/netfilter/nf_flow_table_ip.c: In function 'nf_flow_queue_xmit6':
> net/netfilter/nf_flow_table_ip.c:1237:35: warning: variable 'dst' set but not used [-Wunused-but-set-variable=]
> 1237 | struct dst_entry *dst;
> | ^~~
ack, I will fix it in v2.
Regards,
Lorenzo
>
>
> vim +/dst +891 net/netfilter/nf_flow_table_ip.c
>
> 858
> 859 static int nf_flow_queue_xmit4(struct nf_flowtable_ctx *ctx,
> 860 struct sk_buff *skb,
> 861 struct flow_offload_tuple_rhash *tuplehash,
> 862 const struct nf_hook_state *state)
> 863 {
> 864 struct flow_offload_tuple *other_tuple;
> 865 enum flow_offload_tuple_dir dir;
> 866 struct nf_flow_xmit xmit = {};
> 867 union nf_inet_addr *ip_addr;
> 868 struct flow_offload *flow;
> 869 struct neighbour *neigh;
> 870 struct rtable *rt;
> 871
> 872 if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
> 873 rt = dst_rtable(tuplehash->tuple.dst_cache);
> 874 memset(skb->cb, 0, sizeof(struct inet_skb_parm));
> 875 IPCB(skb)->iif = skb->dev->ifindex;
> 876 IPCB(skb)->flags = IPSKB_FORWARDED;
> 877 return nf_flow_xmit_xfrm(skb, state, &rt->dst);
> 878 }
> 879
> 880 dir = tuplehash->tuple.dir;
> 881 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
> 882 other_tuple = &flow->tuplehash[!dir].tuple;
> 883 ip_addr = (union nf_inet_addr *)&other_tuple->src_v4;
> 884
> 885 if (nf_flow_tunnel_push(state->net, skb, other_tuple,
> 886 tuplehash->tuple.dst_cache, &ip_addr) < 0)
> 887 return NF_DROP;
> 888
> 889 switch (tuplehash->tuple.xmit_type) {
> 890 case FLOW_OFFLOAD_XMIT_NEIGH: {
> > 891 struct dst_entry *dst;
> 892
> 893 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
> 894 if (!xmit.outdev) {
> 895 flow_offload_teardown(flow);
> 896 return NF_DROP;
> 897 }
> 898 if (other_tuple->tun.encap_proto ?
> 899 other_tuple->tun.encap_proto == AF_INET6 :
> 900 ctx->tun.inner_proto == IPPROTO_IPV6) {
> 901 struct rt6_info *rt6;
> 902
> 903 rt6 = dst_rt6_info(tuplehash->tuple.dst_cache);
> 904 neigh = ip_neigh_gw6(rt6->dst.dev,
> 905 rt6_nexthop(rt6, &ip_addr->in6));
> 906 dst = &rt6->dst;
> 907 } else {
> 908 rt = dst_rtable(tuplehash->tuple.dst_cache);
> 909 neigh = ip_neigh_gw4(rt->dst.dev,
> 910 rt_nexthop(rt, ip_addr->ip));
> 911 dst = &rt->dst;
> 912 }
> 913 if (IS_ERR(neigh)) {
> 914 flow_offload_teardown(flow);
> 915 return NF_DROP;
> 916 }
> 917 xmit.dest = neigh->ha;
> 918 skb_dst_drop(skb);
> 919 skb_dst_set_noref(skb, &rt->dst);
> 920 break;
> 921 }
> 922 case FLOW_OFFLOAD_XMIT_DIRECT:
> 923 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
> 924 if (!xmit.outdev) {
> 925 flow_offload_teardown(flow);
> 926 return NF_DROP;
> 927 }
> 928 xmit.dest = tuplehash->tuple.out.h_dest;
> 929 xmit.source = tuplehash->tuple.out.h_source;
> 930 break;
> 931 default:
> 932 WARN_ON_ONCE(1);
> 933 return NF_DROP;
> 934 }
> 935 xmit.tuple = other_tuple;
> 936 xmit.needs_gso_segment = tuplehash->tuple.needs_gso_segment;
> 937
> 938 return nf_flow_queue_xmit(state->net, skb, &xmit);
> 939 }
> 940
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-30 8:20 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 13:35 [PATCH nf-next 0/8] Add IPv4 over IPv6 and SIT flowtable SW acceleration Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 1/8] net: netfilter: nf_flow_table: recognize IPv4/IPv6 in tunnel proto matching Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 2/8] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 3/8] net: ip6_tunnel: add IPv4 over IPv6 flowtable " Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 4/8] net: netfilter: nf_flow_table: use tunnel encap proto for route lookup Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 5/8] net: netfilter: add IPv4 over IPv6 tunnel flowtable acceleration Lorenzo Bianconi
2026-10-30 4:33 ` kernel test robot
2026-10-30 8:20 ` Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 6/8] selftests: netfilter: nft_flowtable.sh: add IPv4 over IPv6 flowtable selftest Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 7/8] net: netfilter: add SIT tunnel flowtable acceleration Lorenzo Bianconi
2026-10-29 13:35 ` [PATCH nf-next 8/8] selftests: netfilter: nft_flowtable.sh: add SIT flowtable selftest Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox