[PATCH nf-next v2 2/4] netfilter: flowtable: promote a flow offloaded in one direction only
flat view
COOLING6d
From: Julius Bairaktaris <hidden>
Date: 2026-10-04 17:16:33
Also in:
linux-kselftest, 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
The next patch offloads TCP flows without a reply in the original direction only. Keep the reply direction of such a flow on the classic path until the connection is assured, then offload it too, as act_ct does for UDP. The XDP flowtable lookup does not return that reply tuple either. Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris <redacted> --- net/netfilter/nf_flow_table_bpf.c | 4 ++++ net/netfilter/nf_flow_table_ip.c | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/net/netfilter/nf_flow_table_bpf.c b/net/netfilter/nf_flow_table_bpf.c
index cbd5b97a6329..7070bc600db1 100644
--- a/net/netfilter/nf_flow_table_bpf.c
+++ b/net/netfilter/nf_flow_table_bpf.c@@ -50,6 +50,10 @@ bpf_xdp_flow_tuple_lookup(struct net_device *dev, nf_flow = container_of(tuplehash, struct flow_offload, tuplehash[tuplehash->tuple.dir]); + if (tuplehash->tuple.dir == FLOW_OFFLOAD_DIR_REPLY && + !test_bit(NF_FLOW_HW_BIDIRECTIONAL, &nf_flow->flags)) + return ERR_PTR(-ENOENT); + flow_offload_refresh(nf_flow_table, nf_flow, false); return tuplehash;
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index c8c29a9a1684..289fe6c9e4f5 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c@@ -465,6 +465,26 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx, return flow_offload_lookup(flow_table, &tuple); } +/* The reply direction of a flow offloaded in one direction only stays on the + * classic path so that conntrack sees it. Once the connection is assured, that + * direction is offloaded too. + */ +static bool nf_flow_reply_unoffloaded(struct nf_flowtable *flow_table, + struct flow_offload *flow, + enum flow_offload_tuple_dir dir) +{ + if (dir != FLOW_OFFLOAD_DIR_REPLY || + test_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags)) + return false; + + if (test_bit(IPS_ASSURED_BIT, &flow->ct->status)) { + set_bit(NF_FLOW_HW_BIDIRECTIONAL, &flow->flags); + flow_offload_refresh(flow_table, flow, true); + } + + return true; +} + static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx, struct nf_flowtable *flow_table, struct flow_offload_tuple_rhash *tuplehash,
@@ -478,6 +498,9 @@ static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx, dir = tuplehash->tuple.dir; flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + if (nf_flow_reply_unoffloaded(flow_table, flow, dir)) + return 0; + mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; if (flow->tuplehash[!dir].tuple.tun_num) mtu -= sizeof(*iph);
@@ -1074,6 +1097,9 @@ static int nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx, dir = tuplehash->tuple.dir; flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + if (nf_flow_reply_unoffloaded(flow_table, flow, dir)) + return 0; + mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; if (flow->tuplehash[!dir].tuple.tun_num) mtu -= sizeof(*ip6h);
--
2.53.0