From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F39D3093C1; Fri, 7 Aug 2026 13:50:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110638; cv=none; b=tBbr2fPsFfGL2NXnSzGWSXE8wSDEWvGymjzCroOQ58oyRXcv7RQVBVXKZG+RsW0VneMRLo1xEM/Au4A10FNJZcOR/s4xo6LJh9Rynq7Xsw15a9s2xmheZiHEVAtqPlqYgEmG3vDwBRGWbmy040T+mkRhckFyLsBhwoEqLfO4WK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110638; c=relaxed/simple; bh=xgbDvt3zHrOT/WEpa4DxGPpBdeTpvPW3YwmpCoAcXwc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hFvCQl+snp54xtO/eyfHhGqSNwfxpNOBSMc9vmVWcrxNi56Y23tXTxwaUaUAVIAvn99i+vLt11YHJYlzr+yQ+ePQAIFJmvzwdO1/7uJEsfKMFV5HYg5Zo+jNJQi7qHVfxNhC0ovw08Mxf/RdyuaKxtbZ5HEqk9HmbWSPlrCiDYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bdUZ4v/y; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bdUZ4v/y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D0891F00AC4; Fri, 7 Aug 2026 13:50:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110628; bh=zNW9O7nDJJOhUaPlcVjrSfdovfBpd4bywmlp83qFXH0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=bdUZ4v/yeen0wKe/pDDB9Xd+V+LzOOdbDXD2y9woyFClskYoy6kSuDRk8VISGgIS1 1b7pnmW+cdfGyAcZ2ximbBRe6vPWo8xvimQwJtR5o0i/Mw6LiTw0GbUagJzQ2C/nLW f67DMQGdVbhIQRhvxmWJ2BABSIBcQ2yO/e6uXbvLCiVnD5kZxem7jqkaT0Hw/Ix8fl wf5PW0Tf6ETuQ+ORxGsJ/sEnr1guWT5tXKaj68ysPxZdoZTY09LaHBAGam+mLHyTnt htyFk2xbvI9rkW5iZTPpPYUQIixATdmMH7pGcvFaI2ywEZz2LAp5BkOeDfklE6Kbvv nJcaSiRRDxyNA== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:01 +0200 Subject: [PATCH net-next v3 1/7] mptcp: move the retrans loop to a separate helper Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-1-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" , Gang Yan X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3211; i=matttbe@kernel.org; h=from:subject:message-id; bh=Kw+kqm2msX44Ibf3PD2H8S4HiigbLbQchXMlKvR2/9M=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH80qeh/18cXjFU8fhm768vfM2uVbe00YbUSYBVQ6x D1DpoYFd5SyMIhxMciKKbJIt0Xmz3xexVvi5WcBM4eVCWQIAxenAEzkXxAjw6ywhzvbJ/Kuk/tV wHVfJ2XFjfKtVTp6p/3YP5Y/Xn8i4hcjw60TSz4V36pXXSDEb3etMrCNQTOl6LfRwTNLP27pbRb 5wQ0A X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni This is a cleanup in order to make the next patch simpler. No functional change intended. Tested-by: Gang Yan Tested-by: Geliang Tang Acked-by: Geliang Tang Signed-off-by: Paolo Abeni Signed-off-by: Matthieu Baerts (NGI0) --- net/mptcp/protocol.c | 74 ++++++++++++++++++++++++++++++------------------= ---- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 7c8180d8d5ef..a21b10a8c5d3 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2791,41 +2791,14 @@ static void mptcp_check_fastclose(struct mptcp_sock= *msk) sk_error_report(sk); } =20 -static void __mptcp_retrans(struct sock *sk) +/* Retransmit the specified data fragment on all the selected subflows. */ +static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *d= frag) { struct mptcp_sendmsg_info info =3D { .data_lock_held =3D true, }; struct mptcp_sock *msk =3D mptcp_sk(sk); struct mptcp_subflow_context *subflow; - struct mptcp_data_frag *dfrag; struct sock *ssk; - int ret, err; - u16 len =3D 0; - - mptcp_clean_una_wakeup(sk); - - /* first check ssk: need to kick "stale" logic */ - err =3D mptcp_sched_get_retrans(msk); - dfrag =3D mptcp_rtx_head(sk); - if (!dfrag) { - if (mptcp_data_fin_enabled(msk)) { - struct inet_connection_sock *icsk =3D inet_csk(sk); - - WRITE_ONCE(icsk->icsk_retransmits, - icsk->icsk_retransmits + 1); - mptcp_set_datafin_timeout(sk); - mptcp_send_ack(msk); - - goto reset_timer; - } - - if (!mptcp_send_head(sk)) - goto clear_scheduled; - - goto reset_timer; - } - - if (err) - goto reset_timer; + int ret, len =3D 0; =20 mptcp_for_each_subflow(msk, subflow) { if (READ_ONCE(subflow->scheduled)) { @@ -2853,7 +2826,7 @@ static void __mptcp_retrans(struct sock *sk) !msk->allow_subflows) { spin_unlock_bh(&msk->fallback_lock); release_sock(ssk); - goto clear_scheduled; + return -1; } =20 while (info.sent < info.limit) { @@ -2876,6 +2849,45 @@ static void __mptcp_retrans(struct sock *sk) release_sock(ssk); } } + return len; +} + +static void __mptcp_retrans(struct sock *sk) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct mptcp_subflow_context *subflow; + struct mptcp_data_frag *dfrag; + int err, len; + + mptcp_clean_una_wakeup(sk); + + /* first check ssk: need to kick "stale" logic */ + err =3D mptcp_sched_get_retrans(msk); + dfrag =3D mptcp_rtx_head(sk); + if (!dfrag) { + if (mptcp_data_fin_enabled(msk)) { + struct inet_connection_sock *icsk =3D inet_csk(sk); + + WRITE_ONCE(icsk->icsk_retransmits, + icsk->icsk_retransmits + 1); + mptcp_set_datafin_timeout(sk); + mptcp_send_ack(msk); + + goto reset_timer; + } + + if (!mptcp_send_head(sk)) + goto clear_scheduled; + + goto reset_timer; + } + + if (err) + goto reset_timer; + + len =3D __mptcp_push_retrans(sk, dfrag); + if (len < 0) + goto clear_scheduled; =20 msk->bytes_retrans +=3D len; dfrag->already_sent =3D max(dfrag->already_sent, len); --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63A7730C361; Fri, 7 Aug 2026 13:50:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110636; cv=none; b=cb6Win0eaNzhqAed3kWzItcNtVnNo5X53NyyEuM4xOSLaho6G+2zkz0fRBPVjLm1K4gx/EDfH2aAvSR12pfQRUBwK81/hNqmvfZp2gVUa+hWht1AHJ01fCg5CNWTIVOxXilSRt8WMyF90hssiFhpIbBuqGX4LT0GSI/v64c9xkY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110636; c=relaxed/simple; bh=M2/xXFhSck3zpMfTAf/pdsHgWlGGCN4mOSI5yWc8T9Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kLjbnOH1H98uvWSlQ2h9CB+tELl9i8gPNCeFBWCq5VHrlosMrQIPX4rU3Z9jWB/KI6CzjOs2OTqtMq2EH2aE+A6o08r2UYqYIkxPL7TJpYj5y7AwnpG//MzDvxhd7dadlbYL3uhrfOR4pBoacQkVqACGg8KzE+RhfQATGkLX6kE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Lnx/WHm6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Lnx/WHm6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3D3C1F00ACF; Fri, 7 Aug 2026 13:50:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110630; bh=5zq4q3uMOzNcIPWzdwEPiuJjkkUoTqIJKHTpTDR/5Fs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Lnx/WHm6HZ66IqDf8PkQg1eRrUYssW2EG30Y5VaEelIkZuJ8/SRO3YURho0HCQY2y 4nB+hjjJ2gDZibbpSLzUjEXIPjD6aZ9ImURPujuwXPenpmajN5vc2DH3BMz6joYDMs EU8ETgOCcfaB0Nnj9Qtqgqxj8j5yzLgsk1hgiEgX+p4s1WR/DS7fc6LYQTGWo4iMCU SFINgDjClyT7u6YvjVwUcXMFB8OWSyanEgcuSVq2O5rkdNz6DLzF5gxUcdGFL3yeyq DC5k+EXPZgnLEuxTAVuotr5bNZrqPi1Yid9FnZZ31KGJvDiL+G52x4FDQZIwwFdKPO j3QeMSnH9wFPQ== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:02 +0200 Subject: [PATCH net-next v3 2/7] mptcp: move the stale logic out of retrans scheduler Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-2-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5969; i=matttbe@kernel.org; h=from:subject:message-id; bh=3Nq+TArMeCH5AiTwTu2VJ+qfvcmkzXJJf9dbYOKdvHk=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH83e4vCr/9Ppvza2X22LOp0tHW5v3vqkiWXnb1OFl 5/ENkev6ChhYRDjYpAVU2SRbovMn/m8irfEy88CZg4rE8gQBi5OAZjIm3cMP06ILf77ieOHf6/Z ggkv/BP+PVLlXRRQoLxf7yFvjNCmVYwMPZFutT90d8lMae5PS1p44EnXy4nH9+Wdy9wQHj+9sOQ TNwA= X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni This allow separating the stale logic invocation and the retrans scheduler, and will simplify the next patch. It's also a cleaner design as the retrans scheduler has currently too many side effects. As a possible downside, the retrans work will now traverse the subflows list additional times; that does not matter much, as this is slowpath. While at it, pick more accurate names for the involved helpers and explicitly note that the per subflow stale data is under msk socket lock protection. The scheduler and the stale logic may observe different subflow statues, as no subflow lock is acquired. This is intentional and not harmful, worst case leading to slower retransmissions. Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) --- v3: new --- net/mptcp/pm.c | 41 +++++++++++++++++++++++++++-------------- net/mptcp/protocol.c | 4 ++-- net/mptcp/protocol.h | 11 +++++++---- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 64a1236aabee..d1f73c3e39fa 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -1065,7 +1065,8 @@ bool mptcp_pm_is_backup(struct mptcp_sock *msk, struc= t sock_common *skc) return mptcp_pm_nl_is_backup(msk, &skc_local); } =20 -static void mptcp_pm_subflows_chk_stale(const struct mptcp_sock *msk, stru= ct sock *ssk) +static void +mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk) { struct mptcp_subflow_context *iter, *subflow =3D mptcp_subflow_ctx(ssk); struct sock *sk =3D (struct sock *)msk; @@ -1102,22 +1103,34 @@ static void mptcp_pm_subflows_chk_stale(const struc= t mptcp_sock *msk, struct soc } } =20 -void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock = *ssk) +void mptcp_pm_chk_stale(const struct mptcp_sock *msk) { - struct mptcp_subflow_context *subflow =3D mptcp_subflow_ctx(ssk); - u32 rcv_tstamp =3D READ_ONCE(tcp_sk(ssk)->rcv_tstamp); + struct mptcp_subflow_context *subflow; =20 - /* keep track of rtx periods with no progress */ - if (!subflow->stale_count) { - subflow->stale_rcv_tstamp =3D rcv_tstamp; - subflow->stale_count++; - } else if (subflow->stale_rcv_tstamp =3D=3D rcv_tstamp) { - if (subflow->stale_count < U8_MAX) + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + u32 rcv_tstamp; + + if (!__mptcp_subflow_active(subflow)) + continue; + + /* No data outstanding at TCP level? not stale */ + if (tcp_rtx_and_write_queues_empty(ssk)) + continue; + + /* keep track of rtx periods with no progress */ + rcv_tstamp =3D READ_ONCE(tcp_sk(ssk)->rcv_tstamp); + if (!subflow->stale_count) { + subflow->stale_rcv_tstamp =3D rcv_tstamp; subflow->stale_count++; - mptcp_pm_subflows_chk_stale(msk, ssk); - } else { - subflow->stale_count =3D 0; - mptcp_subflow_set_active(subflow); + } else if (subflow->stale_rcv_tstamp =3D=3D rcv_tstamp) { + if (subflow->stale_count < U8_MAX) + subflow->stale_count++; + mptcp_pm_subflow_chk_stale(msk, ssk); + } else { + subflow->stale_count =3D 0; + mptcp_subflow_set_active(subflow); + } } } =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index a21b10a8c5d3..88167edc6598 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2469,7 +2469,6 @@ struct sock *mptcp_subflow_get_retrans(struct mptcp_s= ock *msk) =20 /* still data outstanding at TCP level? skip this */ if (!tcp_rtx_and_write_queues_empty(ssk)) { - mptcp_pm_subflow_chk_stale(msk, ssk); min_stale_count =3D min_t(int, min_stale_count, subflow->stale_count); continue; } @@ -2859,9 +2858,10 @@ static void __mptcp_retrans(struct sock *sk) struct mptcp_data_frag *dfrag; int err, len; =20 + mptcp_pm_chk_stale(msk); + mptcp_clean_una_wakeup(sk); =20 - /* first check ssk: need to kick "stale" logic */ err =3D mptcp_sched_get_retrans(msk); dfrag =3D mptcp_rtx_head(sk); if (!dfrag) { diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 1b80f2d6ec5a..b3af3462bdd1 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -580,12 +580,11 @@ struct mptcp_subflow_context { remote_key_valid : 1, /* received the peer key from */ disposable : 1, /* ctx can be free at ulp release time */ closing : 1, /* must not pass rx data to msk anymore */ - stale : 1, /* unable to snd/rcv data, do not use for xmit */ valid_csum_seen : 1, /* at least one csum validated */ is_mptfo : 1, /* subflow is doing TFO */ close_event_done : 1, /* has done the post-closed part */ mpc_drop : 1, /* the MPC option has been dropped in a rtx */ - __unused : 8; + __unused : 9; bool data_avail; bool scheduled; bool pm_listener; /* a listener managed by the kernel PM? */ @@ -604,7 +603,11 @@ struct mptcp_subflow_context { u8 reset_seen:1; u8 reset_transient:1; u8 reset_reason:4; - u8 stale_count; + u8 stale_count; /* Protected by the msk socket lock */ + u8 stale; /* Protected by the msk socket lock, + * if set the subflow is unable to snd/rcv + * data, the schedule should skip it + */ =20 u32 subflow_id; =20 @@ -1103,7 +1106,7 @@ int mptcp_pm_parse_entry(struct nlattr *attr, struct = genl_info *info, bool mptcp_pm_addr_families_match(const struct sock *sk, const struct mptcp_addr_info *loc, const struct mptcp_addr_info *rem); -void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock = *ssk); +void mptcp_pm_chk_stale(const struct mptcp_sock *msk); void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ss= k, int server_side); void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock = *ssk); bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk); --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2943326ED3E; Fri, 7 Aug 2026 13:50:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110647; cv=none; b=dUztHCOVcTMK+q94b3Z77fsl4d/HqY/kwFfREVQ/k8KRBIjahAoh6WC/fj1hg7y/Ca2J+1nmrGZZexaV48lJJdEDpDxZUflmQOTevt5vzRWEX2kt9jEjluhGv76l5/OaZobqnTYFIC8hDEiN+r5wPODhM/wt3F2YBBaON9uuM20= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110647; c=relaxed/simple; bh=xaWz6CyMMKxzOd0Swe/VxKb9+yYIgz2OvTEbTi2CkpU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HMPTlSrSScb5fTolRpvzGwJj6Gtrb0cQUhnVpbdwTGT3SAz9tRr9blrzL2OPjr4w/DuLDhPmlF72A1AgJtK9MwuUHXb0ooiVr/sc97lO5IikE9m9ld44HJqjrUroNvB41umbY5qviJ4zj5XNwgLAPNKiyrbcmLcT4QrY9PEUqLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mqa1GSRr; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mqa1GSRr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 112631F00ADE; Fri, 7 Aug 2026 13:50:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110633; bh=X07P8JJsNfMLTWtLg406EQpUen9p5lYWpitcQ6F19C8=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=mqa1GSRrRXDHPZk/cY8AYORnqG+6cQf9+bwtpQ/8dQKSObtgqKFwmjUzYySOixyrZ toZcxkaq+1q3HAfqzkjQ6xU370Lu1VbOARkgMz3dbnNbO+MI39qoH2L4J91VzTij7D xIIeMbd8dYkcHglbWMZjRHezeELdf0v8CfrMv5aBu9LhsXw0uaHv4dxFot2yIqU/EH XCoiMx5j8HbMBcEXRH7ow9Wg0+pmLZbgTY58TNqS3bdKAwu7R9GGmm2Y9Kj3lwno9z s3TuT2bCBblX5dX3psdU5MqG5be4GyNjiXvAHxJYscCwBg1vWBUIqZXs1ZfTc53mGE KbsGtuPgamhYQ== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:03 +0200 Subject: [PATCH net-next v3 3/7] mptcp: let the retrans scheduler do its job Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-3-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" , Gang Yan X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6071; i=matttbe@kernel.org; h=from:subject:message-id; bh=7M+rqCWJUFFm+ZsElpBS0Crbt8K0xeAdxFY7DIckIT0=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH83RczZeFn6U64btKc6m8Ely77t2bJgWfWja5fz6b 2rPamtDOkpZGMS4GGTFFFmk2yLzZz6v4i3x8rOAmcPKBDKEgYtTACby6T0jwymeL3UCO8RX73T9 cWaSFZ+r7Ek+y/19Tr7tM+9LroxgM2L4K/hPaPt+nsi8HczX74m3KzVe6jXs7BC5KJn55N2vdCM BDgA= X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni Currently the MPTCP core enforces that when MPTCP-level retrans timer fires, at most a single dfrag is retransmitted. In some corner-cases, it may be necessary to retransmit multiple dfrags, and the MPTCP socket will need to wait multiple retrans timeout to accomplish that. Remove the mentioned constraint, allowing to transmit multiple dfrags per retrans period, as long as the scheduler keeps selecting subflows for retransmissions and pending data is available in the rtx queue. The default scheduler will transmit a dfrag per available subflow. Tested-by: Gang Yan Tested-by: Geliang Tang Acked-by: Geliang Tang Signed-off-by: Paolo Abeni Signed-off-by: Matthieu Baerts (NGI0) --- v3: - Many cleanups, since the stale logic is invoked only once outside the main loop. --- net/mptcp/protocol.c | 106 ++++++++++++++++++++++++++++++++++++-----------= ---- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 88167edc6598..09cd3c1f3cdb 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1142,13 +1142,6 @@ static void __mptcp_clean_una_wakeup(struct sock *sk) mptcp_write_space(sk); } =20 -static void mptcp_clean_una_wakeup(struct sock *sk) -{ - mptcp_data_lock(sk); - __mptcp_clean_una_wakeup(sk); - mptcp_data_unlock(sk); -} - static void mptcp_enter_memory_pressure(struct sock *sk) { struct mptcp_subflow_context *subflow; @@ -2790,8 +2783,12 @@ static void mptcp_check_fastclose(struct mptcp_sock = *msk) sk_error_report(sk); } =20 -/* Retransmit the specified data fragment on all the selected subflows. */ -static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *d= frag) +/* + * Retransmit the specified data fragment on all the selected subflows, + * starting from the specified sequence + */ +static int __mptcp_push_retrans(struct sock *sk, struct mptcp_data_frag *d= frag, + u64 sent_seq) { struct mptcp_sendmsg_info info =3D { .data_lock_held =3D true, }; struct mptcp_sock *msk =3D mptcp_sk(sk); @@ -2801,6 +2798,7 @@ static int __mptcp_push_retrans(struct sock *sk, stru= ct mptcp_data_frag *dfrag) =20 mptcp_for_each_subflow(msk, subflow) { if (READ_ONCE(subflow->scheduled)) { + u16 offset =3D sent_seq - dfrag->data_seq; u16 copied =3D 0; =20 mptcp_subflow_set_scheduled(subflow, false); @@ -2810,7 +2808,7 @@ static int __mptcp_push_retrans(struct sock *sk, stru= ct mptcp_data_frag *dfrag) lock_sock(ssk); =20 /* limit retransmission to the bytes already sent on some subflows */ - info.sent =3D 0; + info.sent =3D offset; info.limit =3D READ_ONCE(msk->csum_enabled) ? dfrag->data_len : dfrag->already_sent; =20 @@ -2856,15 +2854,78 @@ static void __mptcp_retrans(struct sock *sk) struct mptcp_sock *msk =3D mptcp_sk(sk); struct mptcp_subflow_context *subflow; struct mptcp_data_frag *dfrag; + u64 retrans_seq, sent_seq; + bool need_retrans; int err, len; =20 mptcp_pm_chk_stale(msk); =20 - mptcp_clean_una_wakeup(sk); - - err =3D mptcp_sched_get_retrans(msk); + /* Get an updated and consistent rtx queue status. */ + mptcp_data_lock(sk); + __mptcp_clean_una_wakeup(sk); + retrans_seq =3D msk->snd_una; dfrag =3D mptcp_rtx_head(sk); - if (!dfrag) { + need_retrans =3D !!dfrag; + mptcp_data_unlock(sk); + + for (;;) { + bool already_acked; + + err =3D mptcp_sched_get_retrans(msk); + if (err) + break; + + /* `already_sent` can be 0 for `dfrag` belonging to the RTX + * queue due to __mptcp_retransmit_pending_data(). + */ + if (!dfrag || !dfrag->already_sent) + break; + + /* Can fail only in case of fallback. */ + len =3D __mptcp_push_retrans(sk, dfrag, retrans_seq); + if (len < 0) + goto clear_scheduled; + + retrans_seq +=3D len; + msk->bytes_retrans +=3D len; + dfrag->already_sent =3D max_t(u16, dfrag->already_sent, + retrans_seq - dfrag->data_seq); + + /* With csum enabled, retransmission can send new data. */ + sent_seq =3D dfrag->already_sent + dfrag->data_seq; + if (after64(sent_seq, msk->snd_nxt)) + WRITE_ONCE(msk->snd_nxt, sent_seq); + + /* Attempt the next fragment only if the current one is + * completely retransmitted. + */ + if (before64(retrans_seq, dfrag->data_seq + dfrag->data_len)) + break; + + dfrag =3D list_is_last(&dfrag->list, &msk->rtx_queue) ? + NULL : list_next_entry(dfrag, list); + if (!dfrag) + break; + + /* Incoming acks can move snd_una after the current dfrag + * across loop iterations, if so start again from RTX head. + */ + mptcp_data_lock(sk); + already_acked =3D !before64(msk->snd_una, dfrag->data_seq + + dfrag->already_sent); + if (already_acked) { + __mptcp_clean_una_wakeup(sk); + retrans_seq =3D msk->snd_una; + dfrag =3D mptcp_rtx_head(sk); + need_retrans =3D !!dfrag; + } else if (after64(msk->snd_una, retrans_seq)) { + retrans_seq =3D msk->snd_una; + } + mptcp_data_unlock(sk); + } + + /* Attempt data-fin retransmission only when the RTX queue is empty. */ + if (!need_retrans) { if (mptcp_data_fin_enabled(msk)) { struct inet_connection_sock *icsk =3D inet_csk(sk); =20 @@ -2872,30 +2933,13 @@ static void __mptcp_retrans(struct sock *sk) icsk->icsk_retransmits + 1); mptcp_set_datafin_timeout(sk); mptcp_send_ack(msk); - goto reset_timer; } =20 if (!mptcp_send_head(sk)) goto clear_scheduled; - - goto reset_timer; } =20 - if (err) - goto reset_timer; - - len =3D __mptcp_push_retrans(sk, dfrag); - if (len < 0) - goto clear_scheduled; - - msk->bytes_retrans +=3D len; - dfrag->already_sent =3D max(dfrag->already_sent, len); - - /* With csum enabled retransmission can send new data. */ - if (after64(dfrag->already_sent + dfrag->data_seq, msk->snd_nxt)) - WRITE_ONCE(msk->snd_nxt, dfrag->already_sent + dfrag->data_seq); - reset_timer: mptcp_check_and_set_pending(sk); =20 --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C940F1A680E; Fri, 7 Aug 2026 13:50:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110646; cv=none; b=Tf+Kk5SalIQrpo1hrstzNk+q/Uynh3AaOnI1WsHCzYiN/wcDjJVymEwo45mnxWKSQabvrLcy2ZJntSiOHtJ6zRQfo2cZy1XRfFlfZ7EAucZ57AqMkh9hQH20RopuIXY+aeyMYKRE4z4P2TFfmvbf9NEpc5/9NpYW9CudKot4NX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110646; c=relaxed/simple; bh=xXbe9KM0R1FPpoF7uqBwLCbyzCw//JO/HJwcZUALB5o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fHObBiq3QODP9jchh/jCa/b1vgNWDgKTi9mR9JKTgY548Z3BIy9+pk9a67EkdyoP4tycAFBMgRP3yOj5jvOSwdGXloHJXfPN3cGlBbr1jHtaCsvsEXgA9mgCP7bX+1iWNNqjfVQ3DN+lXa7NyDK10pJ0svqJ4o3N3owXVvVHIsc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HJSnpX+J; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HJSnpX+J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6790D1F00ADF; Fri, 7 Aug 2026 13:50:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110635; bh=3Vg4ZBTK8EICstEJx6hBbT9srnzcGKNDXlH6HZAELBA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=HJSnpX+J3ay99hkW2+v0FN/5B0OCgO0TxK0AbOimfKsIBNSCJ1ufhM/fKG3zQXsjc prIb1i8OZ5mu8Za0Av3hZ7BrxHdUxkM9w5aQO84m8ovkEvD0PKdKL1M+9ER+gbIoZT f4r1n8vIXBRNJfmxiihBEXUi/UTuWBFTHb2HCc4h8QMe+0KKeGvUfRizVQ8UuU8A+D x9a5dTqCQXls2LDJiRX5r4mDfTuXIVloNeiY6DUQtRWt/Z13hORbUHvEzsQcCQNYUT sSjC8jpLhLzPtS0B+ru9C0P3Tqqv94GVhj5Sh/sHPJOt6pb2hrdjm+s39OlH9eqVLQ uKIfQIOwTDMBA== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:04 +0200 Subject: [PATCH net-next v3 4/7] mptcp: explicitly drop over memory limits Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-4-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7160; i=matttbe@kernel.org; h=from:subject:message-id; bh=9Ivb2sQePeKn04xop488JA4iBD50hNuL9sI1rE/g7tk=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH82dmHY39NTcU77++/RsD1TPbbhjVlVw/9et4gnaJ /23H13V3FHKwiDGxSArpsgi3RaZP/N5FW+Jl58FzBxWJpAhDFycAjCRu3sYGdqYwqq0lnaf3ho2 i6XnC/vJqvsSGRfYGGRWvnzycPmi0IuMDB3ZLWkHHmedzjcU0FGq9T0Xef/Fo94lArvZYvxP/HV k4gIA X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni Currently the enforcement of the rcvbuf constraint is implemented when moving the skbs into the msk receive or OoO queue, keeping the incoming skbs in the subflow queue when over limits. Under significant memory pressure the above can cause permanent data transfer stalls, as the skb needed to make forward progress can be stuck in a subflow queue. Over memory limits, drop the incoming skb, relying on MPTCP-level retransmissions. Note that fallback socket must perform the limit before the skb reaches the subflow-level queue, as dropping an in-sequence already acked skb would break the stream. This is not a complete fix for the stall issue, as the drop strategy needs refinements that will come in the next patches. Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) --- v2: - mib: typo: "constrains" -> "constraints". - mptcp_over_limit: more than 0-win: retrans, dup or old acks. - mptcp_over_limit: bump LINUX_MIB_TCPRCVQDROP. - Note: Sashiko might point to a possible forward-allocated memory leak: this is a temp leak, and releasing additionally allocated fwd memory in the error path will be fix in a patch for -net. v3: - refine mptcp_over_limit() to check separately backlog and rcvbuf - do not drop rst (with data) --- net/mptcp/mib.c | 2 ++ net/mptcp/mib.h | 2 ++ net/mptcp/options.c | 32 +++++++++++++++++++++++++++++--- net/mptcp/protocol.c | 31 +++++++++++++++++++++++-------- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index f23fda0c55a7..ef65e2df709f 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -85,6 +85,8 @@ static const struct snmp_mib mptcp_snmp_list[] =3D { SNMP_MIB_ITEM("SimultConnectFallback", MPTCP_MIB_SIMULTCONNFALLBACK), SNMP_MIB_ITEM("FallbackFailed", MPTCP_MIB_FALLBACKFAILED), SNMP_MIB_ITEM("WinProbe", MPTCP_MIB_WINPROBE), + SNMP_MIB_ITEM("BacklogDrop", MPTCP_MIB_BACKLOGDROP), + SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED), }; =20 /* mptcp_mib_alloc - allocate percpu mib counters diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 812218b5ed2b..9271205f682e 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -88,6 +88,8 @@ enum linux_mptcp_mib_field { MPTCP_MIB_SIMULTCONNFALLBACK, /* Simultaneous connect */ MPTCP_MIB_FALLBACKFAILED, /* Can't fallback due to msk status */ MPTCP_MIB_WINPROBE, /* MPTCP-level zero window probe */ + MPTCP_MIB_BACKLOGDROP, /* Backlog over memory limit */ + MPTCP_MIB_RCVPRUNED, /* Dropped due to memory constraints */ __MPTCP_MIB_MAX }; =20 diff --git a/net/mptcp/options.c b/net/mptcp/options.c index 1057d500577b..b8318e030138 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -1190,8 +1190,34 @@ static bool add_addr_hmac_valid(struct mptcp_sock *m= sk, return hmac =3D=3D mp_opt->ahmac; } =20 -/* Return false in case of error (or subflow has been reset), - * else return true. +static bool mptcp_over_limit(struct sock *sk, struct sock *ssk, + const struct sk_buff *skb) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + u32 rcvbuf =3D READ_ONCE(sk->sk_rcvbuf); + + if (likely((u32)sk_rmem_alloc_get(sk) <=3D rcvbuf && + READ_ONCE(msk->backlog_len) <=3D rcvbuf)) + return false; + + /* Avoid silently dropping pure acks, fin, rst or already-acked segm. */ + if (TCP_SKB_CB(skb)->seq =3D=3D TCP_SKB_CB(skb)->end_seq || + TCP_SKB_CB(skb)->tcp_flags & (TCPHDR_FIN | TCPHDR_RST) || + !after(TCP_SKB_CB(skb)->end_seq, tcp_sk(ssk)->rcv_nxt)) + return false; + + /* Dropped due to memory constraints, schedule an ack. */ + inet_csk(ssk)->icsk_ack.pending |=3D ICSK_ACK_NOMEM | ICSK_ACK_NOW; + inet_csk_schedule_ack(ssk); + + /* Plain TCP (fallback) and skb is dropped before the TCP recv queue. */ + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVQDROP); + + return true; +} + +/* Return false when the caller must drop the packet, i.e. in case of erro= r, + * subflow has been reset, or over memory limits. */ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) { @@ -1217,7 +1243,7 @@ bool mptcp_incoming_options(struct sock *sk, struct s= k_buff *skb) =20 __mptcp_data_acked(subflow->conn); mptcp_data_unlock(subflow->conn); - return true; + return !mptcp_over_limit(subflow->conn, sk, skb); } =20 mptcp_get_options(skb, &mp_opt); diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 09cd3c1f3cdb..cfb77a32518a 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -387,6 +387,16 @@ static bool __mptcp_move_skb(struct sock *sk, struct s= k_buff *skb) =20 mptcp_borrow_fwdmem(sk, skb); =20 + /* Can't drop packets for fallback socket this late, or the stream + * will break. + */ + if (unlikely(sk_rmem_alloc_get(sk) > READ_ONCE(sk->sk_rcvbuf)) && + !__mptcp_check_fallback(msk)) { + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); + mptcp_drop(sk, skb); + return false; + } + if (MPTCP_SKB_CB(skb)->map_seq =3D=3D msk->ack_seq) { /* in sequence */ msk->bytes_received +=3D copy_len; @@ -681,6 +691,7 @@ static void __mptcp_add_backlog(struct sock *sk, struct sk_buff *tail =3D NULL; struct sock *ssk =3D skb->sk; bool fragstolen; + u64 limit; int delta; =20 if (unlikely(sk->sk_state =3D=3D TCP_CLOSE)) { @@ -688,6 +699,16 @@ static void __mptcp_add_backlog(struct sock *sk, return; } =20 + /* Similar additional allowance as plain TCP. */ + limit =3D READ_ONCE(sk->sk_rcvbuf); + limit +=3D (limit >> 1) + 64 * 1024; + limit =3D min_t(u64, limit, UINT_MAX); + if (msk->backlog_len > limit && !__mptcp_check_fallback(msk)) { + __MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_BACKLOGDROP); + kfree_skb_reason(skb, SKB_DROP_REASON_SOCKET_BACKLOG); + return; + } + /* Try to coalesce with the last skb in our backlog */ if (!list_empty(&msk->backlog_list)) tail =3D list_last_entry(&msk->backlog_list, struct sk_buff, list); @@ -759,7 +780,7 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp= _sock *msk, =20 mptcp_init_skb(ssk, skb, offset, len); =20 - if (own_msk && sk_rmem_alloc_get(sk) < sk->sk_rcvbuf) { + if (own_msk) { mptcp_subflow_lend_fwdmem(subflow, skb); ret |=3D __mptcp_move_skb(sk, skb); } else { @@ -2210,10 +2231,6 @@ static bool __mptcp_move_skbs(struct sock *sk, struc= t list_head *skbs, u32 *delt =20 *delta =3D 0; while (1) { - /* If the msk recvbuf is full stop, don't drop */ - if (sk_rmem_alloc_get(sk) > sk->sk_rcvbuf) - break; - prefetch(skb->next); list_del(&skb->list); *delta +=3D skb->truesize; @@ -2241,9 +2258,7 @@ static bool mptcp_can_spool_backlog(struct sock *sk, = struct list_head *skbs) DEBUG_NET_WARN_ON_ONCE(msk->backlog_unaccounted && sk->sk_socket && mem_cgroup_from_sk(sk)); =20 - /* Don't spool the backlog if the rcvbuf is full. */ - if (list_empty(&msk->backlog_list) || - sk_rmem_alloc_get(sk) > sk->sk_rcvbuf) + if (list_empty(&msk->backlog_list)) return false; =20 INIT_LIST_HEAD(skbs); --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7C75305664; Fri, 7 Aug 2026 13:50:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110645; cv=none; b=LIHIvE6RcJMexzgy4uzdrMxzXHh1/lWJa7wfqKULiJYtCT4ggYApMGkpTvrZFvunp+GeJP2TLYzSOUNb6xVRKDWklgyLD9lE7YAZ+3jsCkYEsSKrlogL2swEv5e7afrPMCwpbZvcBQscFKEfoFJjR0/nFCUipZzyIPHJKQdQFMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110645; c=relaxed/simple; bh=ALznjQGtvoVBcalJJYwM8tV/AS3Bp4YJ4oVXijUXRTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lYLtM8Dh2DiAxUGMqbPKnWPe1pd8q5Q55DA+tNhrZ4Tu7I2GdXeoY2+y+FQvzIzA+gPDKJYgU/A+P0017il3b6uh7PmR58wVD8fPNFXDPICHPaG8HDc3vHrHHNy6aMIE+ri6HuiadjOjWsqlp25nGYTLzNZGT1gRyXTgnknhegQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KFZJqFuV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KFZJqFuV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 987E31F0155B; Fri, 7 Aug 2026 13:50:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110637; bh=4fQDsfPXPmXQvaEjhBOAK4eluE7WFeO4u3lOgWyfu2k=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=KFZJqFuVnYEP38WE3WZNVpxhxlHGlGMp0ONOgntWlG0RiRnF/B/UsFQSOYym8yN7M UkJ2L0S4cbQGnvHGcr15dQnpNVtK99PptzBmMhnYvJsJswThqtKvqOcQ79WJVMfYLV HCuzDqENg8vRv/tC4U91B5zbw93cdyl9aFa4CY72fPp7pbzn3G3a2AtdpJ1Ls65orb owr7UAWpBslQzbir30XpQ+mzMGjcKdN9eIDM3LM8kvcbI557jaoxiQOcRJLOfA/E0P Tt1FWjtpfV2OzMivpc43JoKhQI5nqeqxOynKtSN2RFupYLsbH/SilzsDSTcAfyHGKS okAzBjXW+RCxA== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:05 +0200 Subject: [PATCH net-next v3 5/7] mptcp: enforce hard limit on backlog flushing Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-5-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2868; i=matttbe@kernel.org; h=from:subject:message-id; bh=nO7DO4LcT9hCk2u8lAWi1GUEiA1x94V/H3xv1e2WLkM=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH837fPzqm443DU1Buf3z2Fb1zq0NXvFz93k3gU+aK W0qVRwpHaUsDGJcDLJiiizSbZH5M59X8ZZ4+VnAzGFlAhnCwMUpABNZt4WRYcIzAduYrrP8lWHv raec2PY3nuVo2EolT2Xx3A1TPB6VvGNkaEz2XXRPyX3Zip+WOd8faHvpqNa9fRUjElTM9WR2aXw 7FwA= X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni Currently a wild producer could keep the backlog flushing operation spinning for an unbound time. Since the previous patch, the amount of data present in the backlog is hard-limited. Move the backlog len update at the end of the flush loop to prevent it spinning forever. Also, no need to splice back the remaining skbs list into the backlog, as such list is always empty after each backlog processing loop. Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) --- net/mptcp/protocol.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index cfb77a32518a..d96fbdc34dbb 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2229,7 +2229,6 @@ static bool __mptcp_move_skbs(struct sock *sk, struct= list_head *skbs, u32 *delt struct mptcp_sock *msk =3D mptcp_sk(sk); bool moved =3D false; =20 - *delta =3D 0; while (1) { prefetch(skb->next); list_del(&skb->list); @@ -2266,20 +2265,12 @@ static bool mptcp_can_spool_backlog(struct sock *sk= , struct list_head *skbs) return true; } =20 -static void mptcp_backlog_spooled(struct sock *sk, u32 moved, - struct list_head *skbs) -{ - struct mptcp_sock *msk =3D mptcp_sk(sk); - - WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved); - list_splice(skbs, &msk->backlog_list); -} - static bool mptcp_move_skbs(struct sock *sk) { + struct mptcp_sock *msk =3D mptcp_sk(sk); struct list_head skbs; bool enqueued =3D false; - u32 moved; + u32 moved =3D 0; =20 mptcp_data_lock(sk); while (mptcp_can_spool_backlog(sk, &skbs)) { @@ -2287,8 +2278,8 @@ static bool mptcp_move_skbs(struct sock *sk) enqueued |=3D __mptcp_move_skbs(sk, &skbs, &moved); =20 mptcp_data_lock(sk); - mptcp_backlog_spooled(sk, moved, &skbs); } + WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved); mptcp_data_unlock(sk); =20 if (enqueued && mptcp_epollin_ready(sk)) @@ -3747,12 +3738,12 @@ static void mptcp_release_cb(struct sock *sk) __must_hold(&sk->sk_lock.slock) { struct mptcp_sock *msk =3D mptcp_sk(sk); + u32 moved =3D 0; =20 for (;;) { unsigned long flags =3D (msk->cb_flags & MPTCP_FLAGS_PROCESS_CTX_NEED); struct list_head join_list, skbs; bool spool_bl; - u32 moved; =20 spool_bl =3D mptcp_can_spool_backlog(sk, &skbs); if (!flags && !spool_bl) @@ -3785,9 +3776,9 @@ static void mptcp_release_cb(struct sock *sk) =20 cond_resched(); spin_lock_bh(&sk->sk_lock.slock); - if (spool_bl) - mptcp_backlog_spooled(sk, moved, &skbs); } + if (moved) + WRITE_ONCE(msk->backlog_len, msk->backlog_len - moved); =20 if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) __mptcp_clean_una_wakeup(sk); --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F21F830FF36; Fri, 7 Aug 2026 13:50:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110647; cv=none; b=u7/OEiKmD7PCO/3r9GZYdBtixhSp9x+DqjcI9/CCj+lEDCX7MwzNutrjjFMtBXiR6oIS4dz2ls9naE8tXIrJCuMLmlABNSJ15T1Lmp1v0pL04yoXb62458lpbF+YKBdxEgYtGEajksuKlaW6MzZ5yLozhUc8Zu+lJkBdv26ZLe0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110647; c=relaxed/simple; bh=1eiyJsGpZHXVZ4bb74ikO4gDWjHoZGmKm4vMNppG+U0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SN39Akq78+vOfVyT8g618uRUVXAyOca/FW8pOCX9MuUubP0E9Gfj4Pvfa/KpPvdfBtpdlWYoUYhZDnegYV02yzhHeR5wXCfBth/slFtdeLxqLo4kbiyHfCc8rzX2AWLYpjELXGq4boTHl927uvFlkZdsZ6ARF7GHhG95C2wfxwo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KEPTZ2u6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KEPTZ2u6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C948B1F00A3F; Fri, 7 Aug 2026 13:50:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110639; bh=bTTBL9ZnohPensATpDZ27YbIQmHvsuAQwXU3J5quaLc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=KEPTZ2u6cipf1/m0JPnYnwnUj64eUM3aVP/4WYD2NDt0qYrRlo+w411zFMBu/2yyK WojOblDQPCBEB7lLx9xNHSrY/blsF/PETKet6IhJee1XgYMFPOGw34gakcBp6DCfoZ DnN2ZWxZmCa6WXrAzWFExbbKoJ/U0QdY3osOhoSc3AN/gTz4fkF3V2K/595laADKTW FvH3lKVkBQKO2ixK8Wp9Q+qcyZZdMq+1svhubD9mB9AxmoxOIh/Jr+GxIoHJhr3d0F 9kdlhqxhJEB6mFYAiBXXxiG/SuFUX48ueNQQs7ANTDwTfa0bubO4PpBACN+HtSP0Sp +3OBOcYfoT0HA== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:06 +0200 Subject: [PATCH net-next v3 6/7] mptcp: avoid code duplication in __mptcp_move_skb() Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-6-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2367; i=matttbe@kernel.org; h=from:subject:message-id; bh=397Kd7gjPDDLnPSX5yVPxXg++ui+5efdW+wfQQ/dn8I=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH807/HPLfIWItAtb9h59ryB6JfXV1wCvqnqh1K2Zw gWTzq6f0FHKwiDGxSArpsgi3RaZP/N5FW+Jl58FzBxWJpAhDFycAjCRhHSG/4kLVi+5bztXq3e1 w/Jtk+7eePCmbKr1sfV77JRYubqq+A4zMsx8LPd+ioCCVGLo77+HFkUd89ylXXpC9PH6VZaiRzp /buQEAA== X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni Alike TCP, MPTCP handles in-sequence packets and partially overlapping ones in a very similar way: we can use the same path to handle both, avoiding some code duplication. This will also make the next patch simpler. Signed-off-by: Paolo Abeni Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) --- v3: new --- net/mptcp/protocol.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index d96fbdc34dbb..63f2c18bc01f 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -399,6 +399,7 @@ static bool __mptcp_move_skb(struct sock *sk, struct sk= _buff *skb) =20 if (MPTCP_SKB_CB(skb)->map_seq =3D=3D msk->ack_seq) { /* in sequence */ +insert: msk->bytes_received +=3D copy_len; WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len); tail =3D skb_peek_tail(&sk->sk_receive_queue); @@ -413,26 +414,20 @@ static bool __mptcp_move_skb(struct sock *sk, struct = sk_buff *skb) return false; } =20 - /* Completely old data? */ - if (!after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) { - MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); - mptcp_drop(sk, skb); - return false; + /* Partial packet */ + if (after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) { + copy_len =3D MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq; + MPTCP_SKB_CB(skb)->offset +=3D msk->ack_seq - + MPTCP_SKB_CB(skb)->map_seq; + MPTCP_SKB_CB(skb)->map_seq +=3D msk->ack_seq - + MPTCP_SKB_CB(skb)->map_seq; + goto insert; } =20 - /* Partial packet: map_seq < ack_seq < end_seq. - * Skip the already-acked bytes and enqueue the new data. - */ - copy_len =3D MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq; - MPTCP_SKB_CB(skb)->offset +=3D msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq; - MPTCP_SKB_CB(skb)->map_seq +=3D msk->ack_seq - - MPTCP_SKB_CB(skb)->map_seq; - msk->bytes_received +=3D copy_len; - WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len); - - skb_set_owner_r(skb, sk); - __skb_queue_tail(&sk->sk_receive_queue, skb); - return true; + /* Completely old data */ + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA); + mptcp_drop(sk, skb); + return false; } =20 static void mptcp_stop_rtx_timer(struct sock *sk) --=20 2.53.0 From nobody Sat Aug 15 20:32:24 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9BFAA30E0E9; Fri, 7 Aug 2026 13:50:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110652; cv=none; b=h2RfGKI9GS31QGjwszZZvf1lomK6VZgWbizTgCIkdQQY0hWu5AJ/3fXC4EB8DNemqNRoCGKTnw40wq/USBzAoNtSsVlAmEnFeigeLwejm8PMzd9/rJ1bBSqA2jOgKOa0DHa8Za5Z7LFIn8bt7zWlYzQJ+++lcl1XHfYRXfyWrq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786110652; c=relaxed/simple; bh=lUkBtkqx0K2qkY5bwN2OdiEBPUwziZTeHLobcsOpFk4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SQiwjFzuTTF6FAfb41elPwfselAbNGO6LN+SZA5btDddlt6hWAHPeK9kIWIeLDZ37yCRlqKGrz4NnNvjvWRc73o063u0puErxhWksWyhd0KVzsm8rI8en0/voymzTcxRfm9gMych4Tnw7jyTQ5wIr1I+DCDZU83Xi/9ZMpgfF5g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XR6Y9fDk; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XR6Y9fDk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0640C1F00ACA; Fri, 7 Aug 2026 13:50:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786110642; bh=Hp8FSiOxKfQHeeC+JtYjdyoMvW0eZ8MoTAl8tlSx1hg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=XR6Y9fDkpVf+iujxTEiwkS5KPecMzgosMxK6rLB9TLqiO29s+kAOJRx7vzjOQdIBf 4qtfp80hhadAicKPf391ooEekfOlyerLxdh0A/2HbWglr+5KmLmE4bjazXh7qMge6z ZdNH9Lxr2a5Z4+muwm5ttoRy+GUQrbjCy1NWP41jvRATt/HUkOzIjOuqAyTmzMkZOP /OnmyPz8iCzWUrNCCOvKPasBQHYCKsWuzIOYT3YMXsO80UqHtN/jO7cYNFoflfMvZU iHf9IkM9sGxkaTtd51/mXzoWn6m34Y2cpcyEi/TdafjZL4dLQKfZr0XKez91gdkiHo FZ/41Vmw7Zrsw== From: "Matthieu Baerts (NGI0)" Date: Fri, 07 Aug 2026 15:49:07 +0200 Subject: [PATCH net-next v3 7/7] mptcp: implemented OoO queue pruning Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260807-net-next-mptcp-oooq-pruning-v3-7-dbc1eb853cc3@kernel.org> References: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> In-Reply-To: <20260807-net-next-mptcp-oooq-pruning-v3-0-dbc1eb853cc3@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, "Matthieu Baerts (NGI0)" , Gang Yan X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4979; i=matttbe@kernel.org; h=from:subject:message-id; bh=D17M8n5T3NEzzAe7GBb53KDyX6iU9Q4IORwBahYPUVs=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGLJKH83vS0nJzOX6bbSnZOmB86/vZFws/rL0XX+fS0rXs WQZ9lNmHaUsDGJcDLJiiizSbZH5M59X8ZZ4+VnAzGFlAhnCwMUpABP5XMjwT99PbbqDlg77qt+G PCt4uuW3HT5wr+ed2dKo47v09yQvt2L4X1tZUB2c3LrZoCdCg1l5y/KwtVNerws8tM3k0NuFPXu 28gAA X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 From: Paolo Abeni When moving incoming skbs in the msk receive queue and the latter is above limits, prune it as needed quite alike what TCP is doing at the subflow level. The main difference relies in the stop condition: since MPTCP does not perform collapsing, it's better off dropping the bare minimum to fit the (newer) incoming packet. Signed-off-by: Paolo Abeni Tested-by: Gang Yan Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) --- v2: - Uniform the new counter with the other OFO ones. v3: - prune only for new data - reorganize the code to follow more closely TCP --- net/mptcp/mib.c | 1 + net/mptcp/mib.h | 1 + net/mptcp/protocol.c | 81 +++++++++++++++++++++++++++++++++++++++++++++---= ---- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index ef65e2df709f..2569385bab7c 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -87,6 +87,7 @@ static const struct snmp_mib mptcp_snmp_list[] =3D { SNMP_MIB_ITEM("WinProbe", MPTCP_MIB_WINPROBE), SNMP_MIB_ITEM("BacklogDrop", MPTCP_MIB_BACKLOGDROP), SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED), + SNMP_MIB_ITEM("OFOPruned", MPTCP_MIB_OFOPRUNED), }; =20 /* mptcp_mib_alloc - allocate percpu mib counters diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 9271205f682e..3a3425e258a7 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -90,6 +90,7 @@ enum linux_mptcp_mib_field { MPTCP_MIB_WINPROBE, /* MPTCP-level zero window probe */ MPTCP_MIB_BACKLOGDROP, /* Backlog over memory limit */ MPTCP_MIB_RCVPRUNED, /* Dropped due to memory constraints */ + MPTCP_MIB_OFOPRUNED, /* MPTCP-level OoO queue pruned */ __MPTCP_MIB_MAX }; =20 diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 63f2c18bc01f..ec874d2ead6a 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -242,6 +242,65 @@ static bool mptcp_rcvbuf_grow(struct sock *sk, u32 new= val) return false; } =20 +/* "Inspired" from the TCP version; main difference: stop as soon as the M= PTCP + * socket is under memory limit. + */ +static void mptcp_prune_ofo_queue(struct sock *sk, + const struct sk_buff *in_skb) +{ + struct mptcp_sock *msk =3D mptcp_sk(sk); + struct rb_node *node, *prev; + bool pruned =3D false; + u64 mem; + + if (RB_EMPTY_ROOT(&msk->out_of_order_queue)) + return; + + node =3D &msk->ooo_last_skb->rbnode; + + do { + struct sk_buff *skb =3D rb_to_skb(node); + + /* Stop pruning if the incoming skb would land in OoO tail. */ + if (after64(MPTCP_SKB_CB(in_skb)->map_seq, + MPTCP_SKB_CB(skb)->map_seq)) + break; + + pruned =3D true; + prev =3D rb_prev(node); + rb_erase(node, &msk->out_of_order_queue); + mptcp_drop(sk, skb); + msk->ooo_last_skb =3D rb_to_skb(prev); + + mem =3D (unsigned int)sk_rmem_alloc_get(sk); + if (mem <=3D sk->sk_rcvbuf) + break; + + node =3D prev; + } while (node); + + if (pruned) + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_OFOPRUNED); +} + +/* The stack can't drop packets for fallback socket at the msk level, or t= he + * stream will break. + */ +static bool mptcp_can_ingest(const struct sock *sk) +{ + return unlikely(sk_rmem_alloc_get(sk) <=3D READ_ONCE(sk->sk_rcvbuf)) || + __mptcp_check_fallback(mptcp_sk(sk)); +} + +static bool mptcp_try_rmem_schedule(struct sock *sk, const struct sk_buff = *skb) +{ + if (!mptcp_can_ingest(sk)) { + mptcp_prune_ofo_queue(sk, skb); + return mptcp_can_ingest(sk); + } + return true; +} + /* "inspired" by tcp_data_queue_ofo(), main differences: * - use mptcp seqs * - don't cope with sacks @@ -253,6 +312,12 @@ static void mptcp_data_queue_ofo(struct mptcp_sock *ms= k, struct sk_buff *skb) u64 seq, end_seq, max_seq; struct sk_buff *skb1; =20 + if (!mptcp_try_rmem_schedule(sk, skb)) { + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); + mptcp_drop(sk, skb); + return; + } + seq =3D MPTCP_SKB_CB(skb)->map_seq; end_seq =3D MPTCP_SKB_CB(skb)->end_seq; max_seq =3D atomic64_read(&msk->rcv_wnd_sent); @@ -387,19 +452,15 @@ static bool __mptcp_move_skb(struct sock *sk, struct = sk_buff *skb) =20 mptcp_borrow_fwdmem(sk, skb); =20 - /* Can't drop packets for fallback socket this late, or the stream - * will break. - */ - if (unlikely(sk_rmem_alloc_get(sk) > READ_ONCE(sk->sk_rcvbuf)) && - !__mptcp_check_fallback(msk)) { - MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); - mptcp_drop(sk, skb); - return false; - } - if (MPTCP_SKB_CB(skb)->map_seq =3D=3D msk->ack_seq) { /* in sequence */ insert: + if (!mptcp_try_rmem_schedule(sk, skb)) { + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RCVPRUNED); + mptcp_drop(sk, skb); + return false; + } + msk->bytes_received +=3D copy_len; WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len); tail =3D skb_peek_tail(&sk->sk_receive_queue); --=20 2.53.0