* [PATCH nf-next] netfilter: nf_nat: skip the xfrm re-lookup without outbound policies
@ 2026-11-11 8:44 Antonio Quartulli
0 siblings, 0 replies; only message in thread
From: Antonio Quartulli @ 2026-11-11 8:44 UTC (permalink / raw)
To: pablo, fw
Cc: Antonio Quartulli, phil, steffen.klassert, herbert, davem,
edumazet, kuba, pabeni, horms, netfilter-devel, coreteam, netdev
nf_xfrm_me_harder() decodes the session and redoes the xfrm lookup for
every packet whose source or ports NAT changed, even when there is no
policy that could match. The session decode alone is a sizeable part of
the NAT path.
Skip it when there is no outbound policy, global or per socket, the
default outbound policy accepts and the dst is not a bundle: the lookup
would return the same route. xfrm_route_forward() takes the same
shortcut for forwarded packets.
This is the common case for masquerading routers built with
CONFIG_XFRM that never use IPsec. Forwarding a 1400-byte packet through
conntrack and masquerade (x86, qemu -icount) drops from 7533 to 7091
instructions for UDP (-5.9%) and from 7835 to 7395 for TCP (-5.6%).
With an outbound policy installed the full path still runs, and a
block policy matching only the masqueraded flow still drops it.
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
---
net/netfilter/nf_nat_proto.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c
index 64b9bac228ea..69849d805984 100644
--- a/net/netfilter/nf_nat_proto.c
+++ b/net/netfilter/nf_nat_proto.c
@@ -600,12 +600,25 @@ nf_nat_ipv4_pre_routing(void *priv, struct sk_buff *skb,
#ifdef CONFIG_XFRM
static int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
{
+ const struct netns_xfrm *xfrm = &net->xfrm;
struct sock *sk = skb->sk;
struct dst_entry *dst;
unsigned int hh_len;
struct flowi fl;
int err;
+ /* Without any outbound policy, global or per socket, and with the
+ * default outbound policy accepting, the lookup below cannot change
+ * the route unless the dst is already a bundle: skip it, and the
+ * session decode it needs.
+ */
+ if (!READ_ONCE(xfrm->policy_count[XFRM_POLICY_OUT]) &&
+ !READ_ONCE(xfrm->policy_count[XFRM_POLICY_MAX + XFRM_POLICY_OUT]) &&
+ READ_ONCE(xfrm->policy_default[XFRM_POLICY_OUT]) ==
+ XFRM_USERPOLICY_ACCEPT &&
+ !skb_dst(skb)->xfrm)
+ return 0;
+
err = xfrm_decode_session(net, skb, &fl, family);
if (err < 0)
return err;
--
2.56.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-11 8:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-11 8:44 [PATCH nf-next] netfilter: nf_nat: skip the xfrm re-lookup without outbound policies Antonio Quartulli
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox