[PATCH nf-next v2 5/6] net: netfilter: nf_flow_table: refactor MTU check for tunnel offload
Lorenzo Bianconi <[email protected]>
| Newsgroups | gmane.linux.network,gmane.comp.security.firewalls.netfilter.devel |
|---|---|
| Message-ID | <20260907-nf-flowtable-sw-accel-ip6ip-sit-preliminary-v2-5-7c6ac1750725@oss.qualcomm.com> |
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 <[email protected]> --- 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