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

Jiayuan Chen
2026-04-09T07:50:50Z

On 4/9/26 3:18 PM, Eric Dumazet wrote:
> 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().

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