mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net-next] net: lwtunnel: use GFP_KERNEL in build_state paths
@ 2026-11-06 11:40 Max Boone
  2026-11-06 11:46 ` Boone, Max
  2026-11-08 14:21 ` Ido Schimmel
  0 siblings, 2 replies; 3+ messages in thread
From: Max Boone @ 2026-11-06 11:40 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, David Ahern, Ido Schimmel, Justin Iurman,
	Andrea Mayer
  Cc: Donald Sharp, netdev, linux-kernel, bpf, Max Boone,
	Debabrata Banerjee, Nick Hudson

Since 3d25eabbbf67 ("ip_tunnel: Add dst_cache support in lwtunnel_state
of ip tunnel"), build_state runs outside RCU and all its callers can
sleep, but paths still use GFP_ATOMIC.

For dst caches, that limits allocation to populated percpu pages. A
large burst of SRv6 nexthops outruns the refill worker and will fail
with -ENOMEM despite there being free memory:

  percpu: allocation failed, size=40 align=8 atomic=1, atomic alloc
failed, no space left

Batching 20000 RTM_NEWNEXTHOP under QEMU gave 10-109 failures per run
before, none after.

This commit converts the allocations reached through ops->build_state()
and are called after the rcu_read_unlock():

  - ila_build_state(), ioam6_build_state(), rpl_build_state(),
    seg6_build_state(): build_state ops
  - bpf_parse_prog(): only called from bpf_build_state()
  - lwtunnel_state_alloc(): only called from build_state ops (also
    affects mpls, ip/ip6 tunnel, xfrmi and seg6_local)

Signed-off-by: Max Boone <mboone@akamai.com>
Reviewed-by: Debabrata Banerjee <dbanerje@akamai.com>
Reviewed-by: Nick Hudson <nhudson@akamai.com>
---
 net/core/lwt_bpf.c        | 2 +-
 net/core/lwtunnel.c       | 2 +-
 net/ipv6/ila/ila_lwt.c    | 2 +-
 net/ipv6/ioam6_iptunnel.c | 2 +-
 net/ipv6/rpl_iptunnel.c   | 2 +-
 net/ipv6/seg6_iptunnel.c  | 4 ++--
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index da49364ec63d..6d1059ff0c49 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -359,7 +359,7 @@ static int bpf_parse_prog(struct nlattr *attr, struct bpf_lwt_prog *prog,
 	if (!tb[LWT_BPF_PROG_FD] || !tb[LWT_BPF_PROG_NAME])
 		return -EINVAL;
 
-	prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_ATOMIC);
+	prog->name = nla_memdup(tb[LWT_BPF_PROG_NAME], GFP_KERNEL);
 	if (!prog->name)
 		return -ENOMEM;
 
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 8223c44f10c8..f2f4d1ace0e9 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -70,7 +70,7 @@ struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
 {
 	struct lwtunnel_state *lws;
 
-	lws = kzalloc(sizeof(*lws) + encap_len, GFP_ATOMIC);
+	lws = kzalloc(sizeof(*lws) + encap_len, GFP_KERNEL);
 
 	return lws;
 }
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 7bb9edc5c28c..01fd78a232e7 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -228,7 +228,7 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
 		return -ENOMEM;
 
 	ilwt = ila_lwt_lwtunnel(newts);
-	ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+	ret = dst_cache_init(&ilwt->dst_cache, GFP_KERNEL);
 	if (ret) {
 		kfree(newts);
 		return ret;
diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c
index cfb2c41634a0..3093446ad89a 100644
--- a/net/ipv6/ioam6_iptunnel.c
+++ b/net/ipv6/ioam6_iptunnel.c
@@ -166,7 +166,7 @@ static int ioam6_build_state(struct net *net, struct nlattr *nla,
 		return -ENOMEM;
 
 	ilwt = ioam6_lwt_state(lwt);
-	err = dst_cache_init(&ilwt->cache, GFP_ATOMIC);
+	err = dst_cache_init(&ilwt->cache, GFP_KERNEL);
 	if (err)
 		goto free_lwt;
 
diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c
index 4e10adcd70e8..838ede10a79d 100644
--- a/net/ipv6/rpl_iptunnel.c
+++ b/net/ipv6/rpl_iptunnel.c
@@ -102,7 +102,7 @@ static int rpl_build_state(struct net *net, struct nlattr *nla,
 
 	rlwt = rpl_lwt_lwtunnel(newts);
 
-	err = dst_cache_init(&rlwt->cache, GFP_ATOMIC);
+	err = dst_cache_init(&rlwt->cache, GFP_KERNEL);
 	if (err) {
 		kfree(newts);
 		return err;
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 0d39a38a5dd2..7c64680e4632 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -833,11 +833,11 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
 
 	slwt = seg6_lwt_lwtunnel(newts);
 
-	err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC);
+	err = dst_cache_init(&slwt->cache_input, GFP_KERNEL);
 	if (err)
 		goto err_free_newts;
 
-	err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC);
+	err = dst_cache_init(&slwt->cache_output, GFP_KERNEL);
 	if (err)
 		goto err_destroy_input;
 

---
base-commit: 0822d2fe38262e8b55c5ea55c970022bca8dd2a9
change-id: 20261105-build-state-use-gfp-kernel-c3598d190bfb

Best regards,
-- 
Max Boone <mboone@akamai.com>


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-08 14:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 11:40 [PATCH net-next] net: lwtunnel: use GFP_KERNEL in build_state paths Max Boone
2026-11-06 11:46 ` Boone, Max
2026-11-08 14:21 ` Ido Schimmel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®