* [PATCH nf,v2 1/3] netfilter: flowtable: use dst in this direction when pushing IPIP header
@ 2026-06-30 9:40 Pablo Neira Ayuso
2026-06-30 9:40 ` [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support Pablo Neira Ayuso
2026-06-30 9:40 ` [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit Pablo Neira Ayuso
0 siblings, 2 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-30 9:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo, chzhengyang2023
When pushing the IPIP header, the route of the other direction is used
to calculate the headroom, use the route in this direction. Accessing
the other tuple to set the IP source and destination is fine because
this tuple does not provide such information to avoid storing redundant
information. However, this tuple already provides the dst for this
direction, this went unnoticed because this bug affects headroom and
iph->frag_off only at this stage.
Fixes: d30301ba4b07 ("netfilter: flowtable: Add IPIP tx sw acceleration")
Fixes: 93cf357fa797 ("netfilter: flowtable: Add IP6IP6 tx sw acceleration")
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes
net/netfilter/nf_flow_table_ip.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 29e93ac1e2e4..089f2bc19972 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -590,10 +590,10 @@ static int nf_flow_pppoe_push(struct sk_buff *skb, u16 id,
static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
struct flow_offload_tuple *tuple,
- __be32 *ip_daddr)
+ struct dst_entry *dst, __be32 *ip_daddr)
{
struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
- struct rtable *rt = dst_rtable(tuple->dst_cache);
+ struct rtable *rt = dst_rtable(dst);
u8 tos = iph->tos, ttl = iph->ttl;
__be16 frag_off = iph->frag_off;
u32 headroom = sizeof(*iph);
@@ -636,21 +636,22 @@ static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
static int nf_flow_tunnel_v4_push(struct net *net, struct sk_buff *skb,
struct flow_offload_tuple *tuple,
- __be32 *ip_daddr)
+ struct dst_entry *dst, __be32 *ip_daddr)
{
if (tuple->tun_num)
- return nf_flow_tunnel_ipip_push(net, skb, tuple, ip_daddr);
+ return nf_flow_tunnel_ipip_push(net, skb, tuple, dst, ip_daddr);
return 0;
}
static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,
struct flow_offload_tuple *tuple,
+ struct dst_entry *dst,
struct in6_addr **ip6_daddr)
{
struct ipv6hdr *ip6h = (struct ipv6hdr *)skb_network_header(skb);
- struct rtable *rt = dst_rtable(tuple->dst_cache);
__u8 dsfield = ipv6_get_dsfield(ip6h);
+ struct rtable *rt = dst_rtable(dst);
struct flowi6 fl6 = {
.daddr = tuple->tun.src_v6,
.saddr = tuple->tun.dst_v6,
@@ -696,10 +697,11 @@ static int nf_flow_tunnel_ip6ip6_push(struct net *net, struct sk_buff *skb,
static int nf_flow_tunnel_v6_push(struct net *net, struct sk_buff *skb,
struct flow_offload_tuple *tuple,
+ struct dst_entry *dst,
struct in6_addr **ip6_daddr)
{
if (tuple->tun_num)
- return nf_flow_tunnel_ip6ip6_push(net, skb, tuple, ip6_daddr);
+ return nf_flow_tunnel_ip6ip6_push(net, skb, tuple, dst, ip6_daddr);
return 0;
}
@@ -842,7 +844,8 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
other_tuple = &flow->tuplehash[!dir].tuple;
ip_daddr = other_tuple->src_v4.s_addr;
- if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple, &ip_daddr) < 0)
+ if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple,
+ tuplehash->tuple.dst_cache, &ip_daddr) < 0)
return NF_DROP;
switch (tuplehash->tuple.xmit_type) {
@@ -1158,6 +1161,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
ip6_daddr = &other_tuple->src_v6;
if (nf_flow_tunnel_v6_push(state->net, skb, other_tuple,
+ tuplehash->tuple.dst_cache,
&ip6_daddr) < 0)
return NF_DROP;
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support
2026-06-30 9:40 [PATCH nf,v2 1/3] netfilter: flowtable: use dst in this direction when pushing IPIP header Pablo Neira Ayuso
@ 2026-06-30 9:40 ` Pablo Neira Ayuso
2026-06-30 10:18 ` Lorenzo Bianconi
2026-06-30 9:40 ` [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit Pablo Neira Ayuso
1 sibling, 1 reply; 5+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-30 9:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo, chzhengyang2023
No driver supports for IPIP tunnels yet, give up early on setting up the
hardware offload for this scenario.
This patch adds a stub that can be enhanced to add more configuration
that are currently not supported. As of now, the offload work is
enqueued to the worker, then ignored if the hardware offload
configuration is not supported.
Check the NF_FLOW_HW flag to know if this entry was already tried once
to be offloaded so this is not retried on refresh when unsupported. Move
NF_FLOW_HW flag check to nf_flow_offload_add(). If this NF_FLOW_HW flag
is unset the _del and _stats variants are never called.
This can be updated later on to skip hardware offload work to be queued
in case hardware offload does not support it.
Fixes: d98103575dcd ("netfilter: flowtable: Add IP6IP6 rx sw acceleration")
Fixes: ab427db17885 ("netfilter: flowtable: Add IPIP rx sw acceleration")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Reported-by: Zhengyang Chen <chzhengyang2023@lzu.edu.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: - set NF_FLOW_HW flag from nf_flow_offload_add(), after checking if it is supported.
- call nf_flow_offload_refresh() only if NF_FLOW_HW is set on.
include/net/netfilter/nf_flow_table.h | 2 ++
net/netfilter/nf_flow_table_core.c | 7 +++----
net/netfilter/nf_flow_table_offload.c | 22 ++++++++++++++++++++--
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index 7b23b245a5a8..dc5c9b48e65a 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -357,6 +357,8 @@ static inline int nf_flow_register_bpf(void)
void nf_flow_offload_add(struct nf_flowtable *flowtable,
struct flow_offload *flow);
+void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
+ struct flow_offload *flow);
void nf_flow_offload_del(struct nf_flowtable *flowtable,
struct flow_offload *flow);
void nf_flow_offload_stats(struct nf_flowtable *flowtable,
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 99c5b9d671a0..d06ce0848b68 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -345,10 +345,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
nf_ct_refresh(flow->ct, NF_CT_DAY);
- if (nf_flowtable_hw_offload(flow_table)) {
- __set_bit(NF_FLOW_HW, &flow->flags);
+ if (nf_flowtable_hw_offload(flow_table))
nf_flow_offload_add(flow_table, flow);
- }
return 0;
}
@@ -369,7 +367,8 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
test_bit(NF_FLOW_CLOSING, &flow->flags))
return;
- nf_flow_offload_add(flow_table, flow);
+ if (test_bit(NF_FLOW_HW, &flow->flags))
+ nf_flow_offload_refresh(flow_table, flow);
}
EXPORT_SYMBOL_GPL(flow_offload_refresh);
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index 002ec15d988b..d26874f1b15f 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -1101,9 +1101,17 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable,
return offload;
}
+static bool nf_flow_offload_unsupported(struct flow_offload *flow)
+{
+ if (flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.tun_num ||
+ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.tun_num)
+ return true;
-void nf_flow_offload_add(struct nf_flowtable *flowtable,
- struct flow_offload *flow)
+ return false;
+}
+
+void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
+ struct flow_offload *flow)
{
struct flow_offload_work *offload;
@@ -1114,6 +1122,16 @@ void nf_flow_offload_add(struct nf_flowtable *flowtable,
flow_offload_queue_work(offload);
}
+void nf_flow_offload_add(struct nf_flowtable *flowtable,
+ struct flow_offload *flow)
+{
+ if (nf_flow_offload_unsupported(flow))
+ return;
+
+ __set_bit(NF_FLOW_HW, &flow->flags);
+ nf_flow_offload_refresh(flowtable, flow);
+}
+
void nf_flow_offload_del(struct nf_flowtable *flowtable,
struct flow_offload *flow)
{
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit
2026-06-30 9:40 [PATCH nf,v2 1/3] netfilter: flowtable: use dst in this direction when pushing IPIP header Pablo Neira Ayuso
2026-06-30 9:40 ` [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support Pablo Neira Ayuso
@ 2026-06-30 9:40 ` Pablo Neira Ayuso
2026-06-30 10:19 ` Lorenzo Bianconi
1 sibling, 1 reply; 5+ messages in thread
From: Pablo Neira Ayuso @ 2026-06-30 9:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo, chzhengyang2023
The combination of IPIP tunnel with direct xmit, eg. bridge device,
breaks because no dst_entry is provided to check the skb headroom and to
set the iph->frag_off field. This leads to invalid dst usage and can
trigger a crash in the tunnel transmit path.
Fix this by moving dst_cache and dst_cookie out of the runtime union so
that they can be shared by neighbour, xfrm, and direct tunnel flows.
For FLOW_OFFLOAD_XMIT_DIRECT tuples carrying tunnel metadata, preserve
route state in these shared fields and release it through the common
dst release path.
Since dst_entry is now available to the three supported xmit modes and
dst_release() already deals with NULL dst, remove the xmit type check
in nft_flow_dst_release(). Moreover, skip the check if the dst entry
is NULL in nf_flow_dst_check() which is now the case for the direct
xmit case.
Based on patch from Rein Wei <n05ec@lzu.edu.cn>.
Fixes: d30301ba4b07 ("netfilter: flowtable: Add IPIP tx sw acceleration")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Reported-by: Zhengyang Chen <chzhengyang2023@lzu.edu.cn>
Reported-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: - reorder dst_cookie and dst_cache to fix a 4-byte hole in struct
- remove unnecessary zeroing on dst_cookie and dst_cache, struct is already zeroed at init
Both updates per Lorenzo Bianconi's comment.
include/net/netfilter/nf_flow_table.h | 5 +++--
net/netfilter/nf_flow_table_core.c | 12 ++++++++----
net/netfilter/nf_flow_table_ip.c | 3 +--
3 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index dc5c9b48e65a..ce414118962f 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -155,11 +155,12 @@ struct flow_offload_tuple {
tun_num:2,
in_vlan_ingress:2;
u16 mtu;
+ u32 dst_cookie;
+ struct dst_entry *dst_cache;
+
union {
struct {
- struct dst_entry *dst_cache;
u32 ifidx;
- u32 dst_cookie;
};
struct {
u32 ifidx;
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index d06ce0848b68..2a829b5e8240 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -127,12 +127,18 @@ static int flow_offload_fill_route(struct flow_offload *flow,
switch (route->tuple[dir].xmit_type) {
case FLOW_OFFLOAD_XMIT_DIRECT:
+ if (flow_tuple->tun_num) {
+ flow_tuple->dst_cache = dst;
+ flow_tuple->dst_cookie =
+ flow_offload_dst_cookie(flow_tuple);
+ }
memcpy(flow_tuple->out.h_dest, route->tuple[dir].out.h_dest,
ETH_ALEN);
memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source,
ETH_ALEN);
flow_tuple->out.ifidx = route->tuple[dir].out.ifindex;
- dst_release(dst);
+ if (!flow_tuple->tun_num)
+ dst_release(dst);
break;
case FLOW_OFFLOAD_XMIT_XFRM:
case FLOW_OFFLOAD_XMIT_NEIGH:
@@ -152,9 +158,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
static void nft_flow_dst_release(struct flow_offload *flow,
enum flow_offload_tuple_dir dir)
{
- if (flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
- flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)
- dst_release(flow->tuplehash[dir].tuple.dst_cache);
+ dst_release(flow->tuplehash[dir].tuple.dst_cache);
}
void flow_offload_route_init(struct flow_offload *flow,
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 089f2bc19972..0b78decce8a9 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -299,8 +299,7 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple)
{
- if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH &&
- tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM)
+ if (!tuple->dst_cache)
return true;
return dst_check(tuple->dst_cache, tuple->dst_cookie);
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support
2026-06-30 9:40 ` [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support Pablo Neira Ayuso
@ 2026-06-30 10:18 ` Lorenzo Bianconi
0 siblings, 0 replies; 5+ messages in thread
From: Lorenzo Bianconi @ 2026-06-30 10:18 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, chzhengyang2023
[-- Attachment #1: Type: text/plain, Size: 4587 bytes --]
> No driver supports for IPIP tunnels yet, give up early on setting up the
> hardware offload for this scenario.
>
> This patch adds a stub that can be enhanced to add more configuration
> that are currently not supported. As of now, the offload work is
> enqueued to the worker, then ignored if the hardware offload
> configuration is not supported.
>
> Check the NF_FLOW_HW flag to know if this entry was already tried once
> to be offloaded so this is not retried on refresh when unsupported. Move
> NF_FLOW_HW flag check to nf_flow_offload_add(). If this NF_FLOW_HW flag
> is unset the _del and _stats variants are never called.
>
> This can be updated later on to skip hardware offload work to be queued
> in case hardware offload does not support it.
>
> Fixes: d98103575dcd ("netfilter: flowtable: Add IP6IP6 rx sw acceleration")
> Fixes: ab427db17885 ("netfilter: flowtable: Add IPIP rx sw acceleration")
> Reported-by: Yuan Tan <yuantan098@gmail.com>
> Reported-by: Xin Liu <bird@lzu.edu.cn>
> Reported-by: Zhengyang Chen <chzhengyang2023@lzu.edu.cn>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> v2: - set NF_FLOW_HW flag from nf_flow_offload_add(), after checking if it is supported.
> - call nf_flow_offload_refresh() only if NF_FLOW_HW is set on.
>
> include/net/netfilter/nf_flow_table.h | 2 ++
> net/netfilter/nf_flow_table_core.c | 7 +++----
> net/netfilter/nf_flow_table_offload.c | 22 ++++++++++++++++++++--
> 3 files changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
> index 7b23b245a5a8..dc5c9b48e65a 100644
> --- a/include/net/netfilter/nf_flow_table.h
> +++ b/include/net/netfilter/nf_flow_table.h
> @@ -357,6 +357,8 @@ static inline int nf_flow_register_bpf(void)
>
> void nf_flow_offload_add(struct nf_flowtable *flowtable,
> struct flow_offload *flow);
> +void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
> + struct flow_offload *flow);
> void nf_flow_offload_del(struct nf_flowtable *flowtable,
> struct flow_offload *flow);
> void nf_flow_offload_stats(struct nf_flowtable *flowtable,
> diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
> index 99c5b9d671a0..d06ce0848b68 100644
> --- a/net/netfilter/nf_flow_table_core.c
> +++ b/net/netfilter/nf_flow_table_core.c
> @@ -345,10 +345,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
>
> nf_ct_refresh(flow->ct, NF_CT_DAY);
>
> - if (nf_flowtable_hw_offload(flow_table)) {
> - __set_bit(NF_FLOW_HW, &flow->flags);
> + if (nf_flowtable_hw_offload(flow_table))
> nf_flow_offload_add(flow_table, flow);
> - }
>
> return 0;
> }
> @@ -369,7 +367,8 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
> test_bit(NF_FLOW_CLOSING, &flow->flags))
> return;
>
> - nf_flow_offload_add(flow_table, flow);
> + if (test_bit(NF_FLOW_HW, &flow->flags))
> + nf_flow_offload_refresh(flow_table, flow);
> }
> EXPORT_SYMBOL_GPL(flow_offload_refresh);
>
> diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
> index 002ec15d988b..d26874f1b15f 100644
> --- a/net/netfilter/nf_flow_table_offload.c
> +++ b/net/netfilter/nf_flow_table_offload.c
> @@ -1101,9 +1101,17 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable,
> return offload;
> }
>
> +static bool nf_flow_offload_unsupported(struct flow_offload *flow)
> +{
> + if (flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.tun_num ||
> + flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.tun_num)
> + return true;
>
> -void nf_flow_offload_add(struct nf_flowtable *flowtable,
> - struct flow_offload *flow)
> + return false;
> +}
> +
> +void nf_flow_offload_refresh(struct nf_flowtable *flowtable,
> + struct flow_offload *flow)
> {
> struct flow_offload_work *offload;
>
> @@ -1114,6 +1122,16 @@ void nf_flow_offload_add(struct nf_flowtable *flowtable,
> flow_offload_queue_work(offload);
> }
>
> +void nf_flow_offload_add(struct nf_flowtable *flowtable,
> + struct flow_offload *flow)
> +{
> + if (nf_flow_offload_unsupported(flow))
> + return;
> +
> + __set_bit(NF_FLOW_HW, &flow->flags);
> + nf_flow_offload_refresh(flowtable, flow);
> +}
> +
> void nf_flow_offload_del(struct nf_flowtable *flowtable,
> struct flow_offload *flow)
> {
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit
2026-06-30 9:40 ` [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit Pablo Neira Ayuso
@ 2026-06-30 10:19 ` Lorenzo Bianconi
0 siblings, 0 replies; 5+ messages in thread
From: Lorenzo Bianconi @ 2026-06-30 10:19 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, chzhengyang2023
[-- Attachment #1: Type: text/plain, Size: 4477 bytes --]
> The combination of IPIP tunnel with direct xmit, eg. bridge device,
> breaks because no dst_entry is provided to check the skb headroom and to
> set the iph->frag_off field. This leads to invalid dst usage and can
> trigger a crash in the tunnel transmit path.
>
> Fix this by moving dst_cache and dst_cookie out of the runtime union so
> that they can be shared by neighbour, xfrm, and direct tunnel flows.
> For FLOW_OFFLOAD_XMIT_DIRECT tuples carrying tunnel metadata, preserve
> route state in these shared fields and release it through the common
> dst release path.
>
> Since dst_entry is now available to the three supported xmit modes and
> dst_release() already deals with NULL dst, remove the xmit type check
> in nft_flow_dst_release(). Moreover, skip the check if the dst entry
> is NULL in nf_flow_dst_check() which is now the case for the direct
> xmit case.
>
> Based on patch from Rein Wei <n05ec@lzu.edu.cn>.
>
> Fixes: d30301ba4b07 ("netfilter: flowtable: Add IPIP tx sw acceleration")
> Reported-by: Yuan Tan <yuantan098@gmail.com>
> Reported-by: Xin Liu <bird@lzu.edu.cn>
> Reported-by: Zhengyang Chen <chzhengyang2023@lzu.edu.cn>
> Reported-by: Ren Wei <n05ec@lzu.edu.cn>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> v2: - reorder dst_cookie and dst_cache to fix a 4-byte hole in struct
> - remove unnecessary zeroing on dst_cookie and dst_cache, struct is already zeroed at init
> Both updates per Lorenzo Bianconi's comment.
>
> include/net/netfilter/nf_flow_table.h | 5 +++--
> net/netfilter/nf_flow_table_core.c | 12 ++++++++----
> net/netfilter/nf_flow_table_ip.c | 3 +--
> 3 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
> index dc5c9b48e65a..ce414118962f 100644
> --- a/include/net/netfilter/nf_flow_table.h
> +++ b/include/net/netfilter/nf_flow_table.h
> @@ -155,11 +155,12 @@ struct flow_offload_tuple {
> tun_num:2,
> in_vlan_ingress:2;
> u16 mtu;
> + u32 dst_cookie;
> + struct dst_entry *dst_cache;
> +
> union {
> struct {
> - struct dst_entry *dst_cache;
> u32 ifidx;
> - u32 dst_cookie;
> };
> struct {
> u32 ifidx;
> diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
> index d06ce0848b68..2a829b5e8240 100644
> --- a/net/netfilter/nf_flow_table_core.c
> +++ b/net/netfilter/nf_flow_table_core.c
> @@ -127,12 +127,18 @@ static int flow_offload_fill_route(struct flow_offload *flow,
>
> switch (route->tuple[dir].xmit_type) {
> case FLOW_OFFLOAD_XMIT_DIRECT:
> + if (flow_tuple->tun_num) {
> + flow_tuple->dst_cache = dst;
> + flow_tuple->dst_cookie =
> + flow_offload_dst_cookie(flow_tuple);
> + }
> memcpy(flow_tuple->out.h_dest, route->tuple[dir].out.h_dest,
> ETH_ALEN);
> memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source,
> ETH_ALEN);
> flow_tuple->out.ifidx = route->tuple[dir].out.ifindex;
> - dst_release(dst);
> + if (!flow_tuple->tun_num)
> + dst_release(dst);
> break;
> case FLOW_OFFLOAD_XMIT_XFRM:
> case FLOW_OFFLOAD_XMIT_NEIGH:
> @@ -152,9 +158,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
> static void nft_flow_dst_release(struct flow_offload *flow,
> enum flow_offload_tuple_dir dir)
> {
> - if (flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
> - flow->tuplehash[dir].tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)
> - dst_release(flow->tuplehash[dir].tuple.dst_cache);
> + dst_release(flow->tuplehash[dir].tuple.dst_cache);
> }
>
> void flow_offload_route_init(struct flow_offload *flow,
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index 089f2bc19972..0b78decce8a9 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -299,8 +299,7 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
>
> static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple)
> {
> - if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH &&
> - tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM)
> + if (!tuple->dst_cache)
> return true;
>
> return dst_check(tuple->dst_cache, tuple->dst_cookie);
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-30 10:19 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-30 9:40 [PATCH nf,v2 1/3] netfilter: flowtable: use dst in this direction when pushing IPIP header Pablo Neira Ayuso
2026-06-30 9:40 ` [PATCH nf,v2 2/3] netfilter: flowtable: IPIP tunnel hardware offload is not yet support Pablo Neira Ayuso
2026-06-30 10:18 ` Lorenzo Bianconi
2026-06-30 9:40 ` [PATCH nf,v2 3/3] netfilter: flowtable: support IPIP tunnel with direct xmit Pablo Neira Ayuso
2026-06-30 10:19 ` Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox