[PATCH nf-next v2 5/6] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload
From: Lorenzo Bianconi <hidden>
Date: 2026-09-07 07:34:18
Also in:
netfilter-devel
Subsystem:
netfilter, networking [general], the rest · Maintainers:
Pablo Neira Ayuso, Florian Westphal, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
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 <redacted> --- 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 1b9360d54dfc..96dbdadba4e7 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);
@@ -1075,17 +1096,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.55.0