Re: [PATCH net] net: fix __this_cpu_add() in preemptible code in dev_xmit_recursion_inc/dec
From: Jiayuan Chen
Date: Thu Apr 09 2026 - 03:53:58 EST
On 4/9/26 3:18 PM, Eric Dumazet wrote:
On Wed, Apr 8, 2026 at 8:54 PM Jiayuan Chen <jiayuan.chen@xxxxxxxxx> wrote:
dev_xmit_recursion_inc/dec() use __this_cpu_inc/dec() which requiresThis seems wrong.
migration to be disabled. However, some callers like SCTP's UDP
encapsulation path invoke iptunnel_xmit() from process context without
disabling BH or preemption:
sctp_inet_connect -> __sctp_connect -> sctp_do_sm ->
sctp_outq_flush -> sctp_packet_transmit -> sctp_v4_xmit ->
udp_tunnel_xmit_skb -> iptunnel_xmit -> dev_xmit_recursion_inc
This triggers the following warning on PREEMPT(full) kernels:
Fix this by adding migrate_disable/enable() around the __this_cpu
operations in dev_xmit_recursion_inc/dec() to ensure the per-cpu
variable is accessed on the same CPU throughout the inc/dec pair.
Fixes: 6f1a9140ecda ("net: add xmit recursion limit to tunnel xmit functions")
Signed-off-by: Jiayuan Chen <jiayuan.chen@xxxxxxxxx>
---
include/linux/netdevice.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7ca01eb3f7d2..6b1cd5380d70 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3591,14 +3591,19 @@ static inline bool dev_xmit_recursion(void)
XMIT_RECURSION_LIMIT);
}
+/* Non PREEMPT_RT version: inc and dec must run on the same CPU,
+ * migrate_disable is sufficient.
+ */
static inline void dev_xmit_recursion_inc(void)
{
+ migrate_disable();
__this_cpu_inc(softnet_data.xmit.recursion);
}
static inline void dev_xmit_recursion_dec(void)
{
__this_cpu_dec(softnet_data.xmit.recursion);
+ migrate_enable();
}
#else
static inline int dev_recursion_level(void)
--
2.43.0
The migrate_disable() should happen before dev_recursion_level().
Thanks
I checked all callers of dev_xmit_recursion_inc(). Most are fine.
The only problematic ones are iptunnel_xmit() and ip6tunnel_xmit(),
I think adding guard(migrate)() at the top of both functions is enough