Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mptcp: clear scheduled subflows on retransmit

When __mptcp_retrans() kicks-in, it schedules one or more subflows for
retransmission, but such subflows could be actually left alone if there
is no more data to retransmit and/or in case of concurrent fallback.

Scheduled subflows could be processed much later in time, i.e. when new
data will be transmitted, leading to bad subflow selection.

Explicitly clear all scheduled subflows before leaving the
retransmission function.

Fixes: ee2708aedad0 ("mptcp: use get_retrans wrapper")
Cc: stable@vger.kernel.org
Reported-by: Filip Pokryvka <fpokryvk@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20251125-net-mptcp-clear-sched-rtx-v1-1-1cea4ad2165f@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Paolo Abeni and committed by
Jakub Kicinski
27fd0286 da62abaa

+11 -2
+11 -2
net/mptcp/protocol.c
··· 2665 2665 } 2666 2666 2667 2667 if (!mptcp_send_head(sk)) 2668 - return; 2668 + goto clear_scheduled; 2669 2669 2670 2670 goto reset_timer; 2671 2671 } ··· 2696 2696 if (__mptcp_check_fallback(msk)) { 2697 2697 spin_unlock_bh(&msk->fallback_lock); 2698 2698 release_sock(ssk); 2699 - return; 2699 + goto clear_scheduled; 2700 2700 } 2701 2701 2702 2702 while (info.sent < info.limit) { ··· 2728 2728 2729 2729 if (!mptcp_rtx_timer_pending(sk)) 2730 2730 mptcp_reset_rtx_timer(sk); 2731 + 2732 + clear_scheduled: 2733 + /* If no rtx data was available or in case of fallback, there 2734 + * could be left-over scheduled subflows; clear them all 2735 + * or later xmit could use bad ones 2736 + */ 2737 + mptcp_for_each_subflow(msk, subflow) 2738 + if (READ_ONCE(subflow->scheduled)) 2739 + mptcp_subflow_set_scheduled(subflow, false); 2731 2740 } 2732 2741 2733 2742 /* schedule the timeout timer for the relevant event: either close timeout