Re: [PATCH net] net: fix __this_cpu_add() in preemptible code in dev_xmit_recursion_inc/dec

Eric Dumazet
2026-04-09T07:18:45Z

On Wed, Apr 8, 2026 at 8:54 PM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
> dev_xmit_recursion_inc/dec() use __this_cpu_inc/dec() which requires
> 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@linux.dev>
> ---
> 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

This seems wrong.

The migrate_disable() should happen before dev_recursion_level().