6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Abdul Wasey The 6.12.y backport of upstream commit 1bba3f219c5e ("mptcp: do not fallback when OoO is present") put the out-of-order queue check in __mptcp_finish_join() instead of __mptcp_try_fallback(). So the fix itself is missing, as fallback still happens with OoO data queued. Worse, the passive side now refuses every MP_JOIN while its OoO queue is not empty, which is the normal state of a connection already sending data over more than one subflow. The joining subflow is reset, so such a connection can't add a new path, and a path that comes back after an outage can't rejoin while data is in flight. Move the check to __mptcp_try_fallback(), as upstream does. Tested on 6.12.113 in netns: 6 connections (5 uploading) over two paths, then a third endpoint added mid-transfer. Without this patch only the idle connection gets a subflow on the new path and the other 5 joins are reset. With it, all 6 join. Same result in 3 of 3 runs each. Fixes: aab400cf8e35 ("mptcp: do not fallback when OoO is present") Signed-off-by: Abdul Wasey Signed-off-by: Sasha Levin --- net/mptcp/protocol.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -74,6 +74,13 @@ bool __mptcp_try_fallback(struct mptcp_s if (__mptcp_check_fallback(msk)) return true; + /* The caller possibly is not holding the msk socket lock, but + * in the fallback case only the current subflow is touching + * the OoO queue. + */ + if (!RB_EMPTY_ROOT(&msk->out_of_order_queue)) + return false; + spin_lock_bh(&msk->fallback_lock); if (!msk->allow_infinite_fallback) { spin_unlock_bh(&msk->fallback_lock); @@ -943,13 +950,6 @@ static bool __mptcp_finish_join(struct m if (sk->sk_state != TCP_ESTABLISHED) return false; - /* The caller possibly is not holding the msk socket lock, but - * in the fallback case only the current subflow is touching - * the OoO queue. - */ - if (!RB_EMPTY_ROOT(&msk->out_of_order_queue)) - return false; - spin_lock_bh(&msk->fallback_lock); if (!msk->allow_subflows) { spin_unlock_bh(&msk->fallback_lock);