From nobody Thu Nov 27 13:59:29 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 97F4F2FB610; Sat, 1 Nov 2025 17:57:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019832; cv=none; b=UZjiRsUlM+hFKz8Qb9ySc8Xp21PFVCKX5BSsogpoQp7TI9u0E6u29fT95z5Jh6KWHTxBOKwCT/0H9MWmU1Negs278Dx5siWEEaWQ1I60TXR557zm+ZzvbQschYRs/wM62yl7CF6v/xpv4Dj2V9xlVbtkELDsJ0UhMgh2VIomKqg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019832; c=relaxed/simple; bh=Vla5Q77FG456x0fXBCmps8Q8V1m829UbW1rFyOYi7zk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OYdpSdPskbtA+qpUcvmCbMqsFiOZNW3fw5tuHRYH9TttnC1SYbSWzxZY4FwCg93Y9qcwomk6Rs3ohtyYOdpGlXQxRK4KUmaBw+sM8K6kwPD0g9FBrXZFNyleNarOsSWsUvrVaNSgYWQYFcyVtjJYcVBrnQ8Qp0/1QreK6dT3vCo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rauTwZ4J; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rauTwZ4J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 045F6C116C6; Sat, 1 Nov 2025 17:57:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762019832; bh=Vla5Q77FG456x0fXBCmps8Q8V1m829UbW1rFyOYi7zk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rauTwZ4JZj1/4H9hu+TYOPwuN0gMuUBt2aKkFBnRkxo/wIVGMwI7cdbgoaebRC8bb OnZxahOBwvLwHKDVYboNyhsTRQP9khIKMGqVknUcncJ7H38PZp25otJmE64nu6FUO6 q7P5k+PGiVpvywOEf2S9xSBvSpe9t3PIh3RTWI742eKFPC8IVSQYf5wq6xDTVvuYNH a+csMis3HOGV0TxF6k4eJKPLXaKmPhBtbUKM+xAQ7VI0w4KsA4kPAgJJHxjO+nmLuo YO7DxY05IjaHCWX/D7eRckuOaEh8IgO+81GjPWPQxuQksqigFaKBEHmwyX6R/OWyJc NrqbVuRgWjG0Q== From: "Matthieu Baerts (NGI0)" Date: Sat, 01 Nov 2025 18:56:51 +0100 Subject: [PATCH net-next 1/4] mptcp: pm: in-kernel: record fullmesh endp nb Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-1-b4166772d6bb@kernel.org> References: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> In-Reply-To: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=5303; i=matttbe@kernel.org; h=from:subject:message-id; bh=Vla5Q77FG456x0fXBCmps8Q8V1m829UbW1rFyOYi7zk=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGDLZPN8wa5ifO6W6t7QgI/vw7xNGT1ID+I9x6KeHXlqX+ S1o+fKwjlIWBjEuBlkxRRbptsj8mc+reEu8/Cxg5rAygQxh4OIUgImwX2D4Kx2y2+HsN+5tGs/7 F7nOfbw8//HS3pX/bO20Zba9MyiqtGf4H+ZzamNwHN9j60MOmXZPFx53fetgcHRtq1F94KzTzQe 6WQE= X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 Instead of iterating over all endpoints, under RCU read lock, just to check if one of them as the fullmesh flag, we can keep a counter of fullmesh endpoint, similar to what is done with the other flags. This counter is now checked, before iterating over all endpoints. Similar to the other counters, this new one is also exposed. A userspace app can then know when it is being used in a fullmesh mode, with potentially (too) many subflows. Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) --- include/uapi/linux/mptcp.h | 3 ++- net/mptcp/pm_kernel.c | 38 +++++++++++++++++++++++++++++++++++--- net/mptcp/protocol.h | 1 + net/mptcp/sockopt.c | 2 ++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h index 87cfab874e24..04eea6d1d0a9 100644 --- a/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h @@ -70,7 +70,8 @@ struct mptcp_info { __u64 mptcpi_bytes_acked; __u8 mptcpi_subflows_total; __u8 mptcpi_endp_laminar_max; - __u8 reserved[2]; + __u8 mptcpi_endp_fullmesh_max; + __u8 reserved; __u32 mptcpi_last_data_sent; __u32 mptcpi_last_data_recv; __u32 mptcpi_last_ack_recv; diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c index 2ae95476dba3..e2918c68ff02 100644 --- a/net/mptcp/pm_kernel.c +++ b/net/mptcp/pm_kernel.c @@ -22,6 +22,7 @@ struct pm_nl_pernet { u8 endp_signal_max; u8 endp_subflow_max; u8 endp_laminar_max; + u8 endp_fullmesh_max; u8 limit_add_addr_accepted; u8 limit_extra_subflows; u8 next_id; @@ -70,6 +71,14 @@ u8 mptcp_pm_get_endp_laminar_max(const struct mptcp_sock= *msk) } EXPORT_SYMBOL_GPL(mptcp_pm_get_endp_laminar_max); =20 +u8 mptcp_pm_get_endp_fullmesh_max(const struct mptcp_sock *msk) +{ + struct pm_nl_pernet *pernet =3D pm_nl_get_pernet_from_msk(msk); + + return READ_ONCE(pernet->endp_fullmesh_max); +} +EXPORT_SYMBOL_GPL(mptcp_pm_get_endp_fullmesh_max); + u8 mptcp_pm_get_limit_add_addr_accepted(const struct mptcp_sock *msk) { struct pm_nl_pernet *pernet =3D pm_nl_get_pernet_from_msk(msk); @@ -603,9 +612,12 @@ fill_local_addresses_vec(struct mptcp_sock *msk, struc= t mptcp_addr_info *remote, int i; =20 /* If there is at least one MPTCP endpoint with a fullmesh flag */ - i =3D fill_local_addresses_vec_fullmesh(msk, remote, locals, c_flag_case); - if (i) - return i; + if (mptcp_pm_get_endp_fullmesh_max(msk)) { + i =3D fill_local_addresses_vec_fullmesh(msk, remote, locals, + c_flag_case); + if (i) + return i; + } =20 /* If there is at least one MPTCP endpoint with a laminar flag */ if (mptcp_pm_get_endp_laminar_max(msk)) @@ -790,6 +802,10 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm= _nl_pernet *pernet, addr_max =3D pernet->endp_laminar_max; WRITE_ONCE(pernet->endp_laminar_max, addr_max + 1); } + if (entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) { + addr_max =3D pernet->endp_fullmesh_max; + WRITE_ONCE(pernet->endp_fullmesh_max, addr_max + 1); + } =20 pernet->endpoints++; if (!entry->addr.port) @@ -1187,6 +1203,10 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, s= truct genl_info *info) addr_max =3D pernet->endp_laminar_max; WRITE_ONCE(pernet->endp_laminar_max, addr_max - 1); } + if (entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) { + addr_max =3D pernet->endp_fullmesh_max; + WRITE_ONCE(pernet->endp_fullmesh_max, addr_max - 1); + } =20 pernet->endpoints--; list_del_rcu(&entry->list); @@ -1502,6 +1522,18 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry= *local, changed =3D (local->flags ^ entry->flags) & mask; entry->flags =3D (entry->flags & ~mask) | (local->flags & mask); *local =3D *entry; + + if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH) { + u8 addr_max =3D pernet->endp_fullmesh_max; + + if (entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) + addr_max++; + else + addr_max--; + + WRITE_ONCE(pernet->endp_fullmesh_max, addr_max); + } + spin_unlock_bh(&pernet->lock); =20 mptcp_pm_nl_set_flags_all(net, local, changed); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 379a88e14e8d..9a3429175758 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1183,6 +1183,7 @@ void __mptcp_pm_kernel_worker(struct mptcp_sock *msk); u8 mptcp_pm_get_endp_signal_max(const struct mptcp_sock *msk); u8 mptcp_pm_get_endp_subflow_max(const struct mptcp_sock *msk); u8 mptcp_pm_get_endp_laminar_max(const struct mptcp_sock *msk); +u8 mptcp_pm_get_endp_fullmesh_max(const struct mptcp_sock *msk); u8 mptcp_pm_get_limit_add_addr_accepted(const struct mptcp_sock *msk); u8 mptcp_pm_get_limit_extra_subflows(const struct mptcp_sock *msk); =20 diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index a28a48385885..de90a2897d2d 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -982,6 +982,8 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struc= t mptcp_info *info) mptcp_pm_get_endp_subflow_max(msk); info->mptcpi_endp_laminar_max =3D mptcp_pm_get_endp_laminar_max(msk); + info->mptcpi_endp_fullmesh_max =3D + mptcp_pm_get_endp_fullmesh_max(msk); } =20 if (__mptcp_check_fallback(msk)) --=20 2.51.0 From nobody Thu Nov 27 13:59:29 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 47ACA2FBE1B; Sat, 1 Nov 2025 17:57:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019835; cv=none; b=QLlItASY2BbOmQRw+bg6m2ojz3WGgX/GlWknK2rENV0dEhGDYO0fd0J4rT+WV9DRgov9xqI6vmry2nPf4Ol0qe9q3tDhtrgDA/DraSRSTbIQpz566yPFer5WSQr9lLAvdCxsvUGsNe60FwNNgwZWRFsmYpEouXoWEdaYWiJeJoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019835; c=relaxed/simple; bh=FJL2HPrgfIL22xuRMCxFhchP9t64Srg/5u4D4oykfAA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fh9KNPof6+pWrK8oSPLiVENgRHIbk6lFRocKsKnnbT2HzKwJbVvC3kcxwl9bzllcvpsYK0eRfr4TM5QvD5mlme1fJKhULimp6YdM5X89pWjWqPza076FcFp7pJnsHwUxSlFLHZr5ao4ms7Tskneux9HkAk3hTXnbO+4rO0TKVg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LtXrg/Ph; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LtXrg/Ph" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8D50AC4CEFB; Sat, 1 Nov 2025 17:57:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762019834; bh=FJL2HPrgfIL22xuRMCxFhchP9t64Srg/5u4D4oykfAA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LtXrg/PhUmaPeudO0vhduZUnOlrzA2CwiIVKaHDUGtqjjWrQSySEQ4GjnMtrA/34p GVXk13HCeMBaJbJDWpv7h8PRiNRFuxX0HeyxGsoR1GgDVNp7j1LtZt7mqP1t6cXRsi alL0YuyFjt3tD5117BYJ7fGcdqhW9G+W2Lk5v3ObvsSPo4+Zwo5wapiPVCortrKPxq MdDyltMM7bW1Q+5/B92/NP/sVLswl24M9p9JorKZSAcOhxYIGsMQkK5nqLsPyM/jAt j6CnECOVktAC7JCRtb/nBToeFdMLlFubGxk3UrB7LMqry5jXRxtJVp8djwLOgVJM6F abaeLOToM8xMQ== From: "Matthieu Baerts (NGI0)" Date: Sat, 01 Nov 2025 18:56:52 +0100 Subject: [PATCH net-next 2/4] mptcp: pm: in kernel: only use fullmesh endp if any Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-2-b4166772d6bb@kernel.org> References: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> In-Reply-To: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2545; i=matttbe@kernel.org; h=from:subject:message-id; bh=FJL2HPrgfIL22xuRMCxFhchP9t64Srg/5u4D4oykfAA=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGDLZPN+tr1RjfnUv9W2XrU+3RrXz4g8GuyaXXQtetKFo9 c2ijSZCHaUsDGJcDLJiiizSbZH5M59X8ZZ4+VnAzGFlAhnCwMUpABPxYWT4H/pozr69FufWxFTL vZY69v/1tlyW81Y+bE7+r7OCXqeXujMynMr82nqA5zyLwvzF+9YF/WwQZeyL1s8MPPrnzMYoKde NrAA= X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 Our documentation is saying that the in-kernel PM is only using fullmesh endpoints to establish subflows to announced addresses when at least one endpoint has a fullmesh flag. But this was not totally correct: only fullmesh endpoints were used if at least one endpoint *from the same address family as the received ADD_ADDR* has the fullmesh flag. This is confusing, and it seems clearer not to have differences depending on the address family. So, now, when at least one MPTCP endpoint has a fullmesh flag, the local addresses are picked from all fullmesh endpoints, which might be 0 if there are no endpoints for the correct address family. One selftest needs to be adapted for this behaviour change. Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) --- net/mptcp/pm_kernel.c | 10 +++------- tools/testing/selftests/net/mptcp/mptcp_join.sh | 6 +++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c index e2918c68ff02..e50721c670d0 100644 --- a/net/mptcp/pm_kernel.c +++ b/net/mptcp/pm_kernel.c @@ -609,15 +609,11 @@ fill_local_addresses_vec(struct mptcp_sock *msk, stru= ct mptcp_addr_info *remote, struct mptcp_pm_local *locals) { bool c_flag_case =3D remote->id && mptcp_pm_add_addr_c_flag_case(msk); - int i; =20 /* If there is at least one MPTCP endpoint with a fullmesh flag */ - if (mptcp_pm_get_endp_fullmesh_max(msk)) { - i =3D fill_local_addresses_vec_fullmesh(msk, remote, locals, - c_flag_case); - if (i) - return i; - } + if (mptcp_pm_get_endp_fullmesh_max(msk)) + return fill_local_addresses_vec_fullmesh(msk, remote, locals, + c_flag_case); =20 /* If there is at least one MPTCP endpoint with a laminar flag */ if (mptcp_pm_get_endp_laminar_max(msk)) diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testin= g/selftests/net/mptcp/mptcp_join.sh index 78a1aa4ecff2..e7a498dd5a46 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -2952,7 +2952,11 @@ mixed_tests() pm_nl_add_endpoint $ns1 10.0.1.1 flags signal speed=3Dslow \ run_tests $ns1 $ns2 dead:beef:2::1 - chk_join_nr 1 1 1 + if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_fullmesh_max$"; then + chk_join_nr 0 0 0 + else + chk_join_nr 1 1 1 + fi fi =20 # fullmesh still tries to create all the possibly subflows with --=20 2.51.0 From nobody Thu Nov 27 13:59:29 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 BD0DE2FD1BA; Sat, 1 Nov 2025 17:57:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019837; cv=none; b=oZejTx9iWr3MdFE8stJ/Gqanh1a83vt82R2SllbteabKmk4pAySp5sn6OUcMdr29Gw98xWjo3yTYXjV6ZSPjyqFO/6DfwlrusArNt4gPXi4W+WXrzZ5d0qui/8NZuh9s9fdlujJ6wTo9kK8+naVyziY3n6SpswD41riIb7wicwI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019837; c=relaxed/simple; bh=4FJjDaN/bzVx1rmeRAMy6ePFb5sfpEyCI2M2+OEJJcc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GtlMz3F6PPKyxxjSX1lUp2ZfnohZKiC3mtKXO9X88xRiymDs8Qd802Q7mg//LAKIqxs4w1ht8LZcAZAQcQ3KF7lzbqV5+Kq6hBpu/x5ng0w85xNIgnEDcdu3qqkFXGTpu3T4xt7yqgdSxoreBfL9Z6/Oh0L7iEpWAFDApNdBNLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RN9fnZT2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RN9fnZT2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 21260C4CEF1; Sat, 1 Nov 2025 17:57:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762019837; bh=4FJjDaN/bzVx1rmeRAMy6ePFb5sfpEyCI2M2+OEJJcc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RN9fnZT2ECi3EqvGKkB5hqVcmQjfuxgZNt7vSK/zKp401KRWPxlBrVQ7UppPR5HSO qo4LySLgtJFAqhKIy6aYziZVxYdcptedhZFaMd2pRF6dAwg4hldaoReTrq0NiWHkMd 6GRpaDPDFb7+EELWm/yevNbUDjhkABMixggwQyb5wyp0nStXTWF7QTse8rQA+K5ddh 8nTH9ZvebhY3kMn15OHtGbkyk3mFIFHpvVLpVPjRKWQGqJQ2W+vIF9ByiWDwfF4adl rSRHV0ZBkyr3q3ZwrPc1FL3135IZO5KpXQ7BfzHG4V/0rfIEHWOvK3KF5zVz7Q7MuF 5LXE4N4Gkc97w== From: "Matthieu Baerts (NGI0)" Date: Sat, 01 Nov 2025 18:56:53 +0100 Subject: [PATCH net-next 3/4] selftests: mptcp: join: do_transfer: reduce code dup Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-3-b4166772d6bb@kernel.org> References: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> In-Reply-To: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3151; i=matttbe@kernel.org; h=from:subject:message-id; bh=4FJjDaN/bzVx1rmeRAMy6ePFb5sfpEyCI2M2+OEJJcc=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGDLZPD9wmZ83yUmYGSt+Za3eljtrtzlcOuWbNH1OmtBT4 4h9J3KMO0pZGMS4GGTFFFmk2yLzZz6v4i3x8rOAmcPKBDKEgYtTACZy9wQjw33LZe+YtriwvHv6 TvNy/gxv/wYvubffWGP/e2+rfW0ld5Lhv8OlLw1V2y8GNTxiPhiSXrqxz+bcLf7D0aIu6tY7eWd zcwMA X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 The same extra long commands are present twice, with small differences: the variable for the stdin file is different. Use new dedicated variables in one command to avoid this code duplication. Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) --- tools/testing/selftests/net/mptcp/mptcp_join.sh | 30 +++++++++------------= ---- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testin= g/selftests/net/mptcp/mptcp_join.sh index e7a498dd5a46..4c9ee094381e 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -951,6 +951,8 @@ do_transfer() local FAILING_LINKS=3D${FAILING_LINKS:-""} local fastclose=3D${fastclose:-""} local speed=3D${speed:-"fast"} + local listener_in=3D"${sin}" + local connector_in=3D"${cin}" port=3D$(get_port) =20 :> "$cout" @@ -999,16 +1001,12 @@ do_transfer() =20 extra_srv_args=3D"$extra_args $extra_srv_args" if [ "$test_linkfail" -gt 1 ];then - timeout ${timeout_test} \ - ip netns exec ${listener_ns} \ - ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - $extra_srv_args "::" < "$sinfail" > "$sout" & - else - timeout ${timeout_test} \ - ip netns exec ${listener_ns} \ - ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - $extra_srv_args "::" < "$sin" > "$sout" & + listener_in=3D"${sinfail}" fi + timeout ${timeout_test} \ + ip netns exec ${listener_ns} \ + ./mptcp_connect -t ${timeout_poll} -l -p ${port} -s ${srv_proto} \ + ${extra_srv_args} "::" < "${listener_in}" > "${sout}" & local spid=3D$! =20 mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" @@ -1020,6 +1018,7 @@ do_transfer() ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ $extra_cl_args $connect_addr < "$cin" > "$cout" & elif [ "$test_linkfail" -eq 1 ] || [ "$test_linkfail" -eq 2 ];then + connector_in=3D"${cinsent}" ( cat "$cinfail" ; sleep 2; link_failure $listener_ns ; cat "$cinfail" )= | \ tee "$cinsent" | \ timeout ${timeout_test} \ @@ -1027,6 +1026,7 @@ do_transfer() ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ $extra_cl_args $connect_addr > "$cout" & else + connector_in=3D"${cinsent}" tee "$cinsent" < "$cinfail" | \ timeout ${timeout_test} \ ip netns exec ${connector_ns} \ @@ -1057,17 +1057,9 @@ do_transfer() return 1 fi =20 - if [ "$test_linkfail" -gt 1 ];then - check_transfer $sinfail $cout "file received by client" $trunc_size - else - check_transfer $sin $cout "file received by client" $trunc_size - fi + check_transfer $listener_in $cout "file received by client" $trunc_size retc=3D$? - if [ "$test_linkfail" -eq 0 ];then - check_transfer $cin $sout "file received by server" $trunc_size - else - check_transfer $cinsent $sout "file received by server" $trunc_size - fi + check_transfer $connector_in $sout "file received by server" $trunc_size rets=3D$? =20 [ $retc -eq 0 ] && [ $rets -eq 0 ] --=20 2.51.0 From nobody Thu Nov 27 13:59:29 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 054512FD691; Sat, 1 Nov 2025 17:57:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019840; cv=none; b=rnzuWhcEJlTXcwO3obxoZLVJ7X7ze4gE0++eVVRih33c5K2GEd0LfElYuE2/zJ022mKPT/xgFgDPUwbFvhgAG7Ag5kum84t/0mXAaa2lsjwGkl5BdqqNMQe89wilWax/5NqFWEVVdj9ALu83kBM/xVKZqJOHXjExwCGtiAOJL6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762019840; c=relaxed/simple; bh=in42XnovMXeVQqZbDa2ZCxwTuNrF6sz8oX+pUPjugkw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ls3FFqH7Ff9dDEwYrQD4MEsefQtMrVraj0j0jpmwndJ0DcEOnzaXMScacWsV0xdU4lj6OniGwGe5HRM0qqGJNRHXL1tPWHg32SKK8NyvLKgrGAmSEmc4i3SlIUFXZYqOVm0ekHfhDFubwsnF4dBoErOgAFoIR7wlZkqNsyIaTgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TX09LgCR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TX09LgCR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A97E0C4CEFB; Sat, 1 Nov 2025 17:57:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1762019839; bh=in42XnovMXeVQqZbDa2ZCxwTuNrF6sz8oX+pUPjugkw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TX09LgCRjL//NZFSuJbnsLprNO+I4shNwhohXNpiHNEgaz1ziN1C4Dp4EQw4Uripk +Nt5hppo/IGz3pADXkxV1WHKbIv+P4t9w3Zvevcc/lb/JNMEeyIoY0PGpHxBjZRVMw hghF1l2PD3i5CGxMfI2orTgogWLoTInXQD4JJOLIYw92KsFHmbm71fUKswtRoWpk0m NXcPc+27K4FMDV/LClP2ojNvD66FNN2CqrDisISQwnWSWZIPQnWk+dfoXjLUHLE6JC WFFL2nPt6nPEKD13Mzr9YRkeIzmApceKfeFqbTMyUKAChEAOtRQqp8LvVxcSzEuvNp RpMXYypMZ8tTg== From: "Matthieu Baerts (NGI0)" Date: Sat, 01 Nov 2025 18:56:54 +0100 Subject: [PATCH net-next 4/4] selftests: mptcp: join: validate extra bind cases Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-4-b4166772d6bb@kernel.org> References: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> In-Reply-To: <20251101-net-next-mptcp-fm-endp-nb-bind-v1-0-b4166772d6bb@kernel.org> To: Mat Martineau , Geliang Tang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Shuah Khan Cc: netdev@vger.kernel.org, mptcp@lists.linux.dev, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, "Matthieu Baerts (NGI0)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8916; i=matttbe@kernel.org; h=from:subject:message-id; bh=in42XnovMXeVQqZbDa2ZCxwTuNrF6sz8oX+pUPjugkw=; b=owGbwMvMwCVWo/Th0Gd3rumMp9WSGDLZPD9NL2n4+3/P2bTGmSW2iSsdF577tuioynFHs4/SX 1l8rP8Wd5SyMIhxMciKKbJIt0Xmz3xexVvi5WcBM4eVCWQIAxenAEzEfjLDf1++rFVNsjH6SxdK 7574ff/VnCVPnp3nrHsSlTsjIKz51TWGf/pcIietnnzaL1sU/8bMfv31mHt3/wqx8m8Lsrh9SHn 3UQ4A X-Developer-Key: i=matttbe@kernel.org; a=openpgp; fpr=E8CB85F76877057A6E27F77AF6B7824F4269A073 By design, an MPTCP connection will not accept extra subflows where no MPTCP listening sockets can accept such requests. In other words, it means that if the 'server' listens on a specific address / device, it cannot accept MP_JOIN sent to a different address / device. Except if there is another MPTCP listening socket accepting them. This is what the new tests are validating: - Forcing a bind on the main v4/v6 address, and checking that MP_JOIN to announced addresses are not accepted. - Also forcing a bind on the main v4/v6 address, but before, another listening socket is created to accept additional subflows. Note that 'mptcpize run nc -l' -- or something else only doing: socket(MPTCP), bind(), listen(0) -- would be enough, but here mptcp_connect is reused not to depend on another tool just for that. - Same as the previous one, but using v6 link-local addresses: this is a bit particular because it is required to specify the outgoing network interface when connecting to a link-local address announced by the other peer. When using the routing rules, this doesn't work (the outgoing interface is not known) ; but it does work with a 'laminar' endpoint having a specified interface. Note that extra small modifications are needed for these tests to work: - mptcp_connect's check_getpeername_connect() check should strip the specified interface when comparing addresses. - With IPv6 link-local addresses, it is required to wait for them to be ready (no longer in 'tentative' mode) before using them, otherwise the bind() will not be allowed. Link: https://github.com/multipath-tcp/mptcp_net-next/issues/591 Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) --- tools/testing/selftests/net/mptcp/mptcp_connect.c | 10 +- tools/testing/selftests/net/mptcp/mptcp_join.sh | 153 ++++++++++++++++++= +++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/test= ing/selftests/net/mptcp/mptcp_connect.c index b148cadb96d0..c030b08a7195 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -1064,6 +1064,8 @@ static void check_getpeername_connect(int fd) socklen_t salen =3D sizeof(ss); char a[INET6_ADDRSTRLEN]; char b[INET6_ADDRSTRLEN]; + const char *iface; + size_t len; =20 if (getpeername(fd, (struct sockaddr *)&ss, &salen) < 0) { perror("getpeername"); @@ -1073,7 +1075,13 @@ static void check_getpeername_connect(int fd) xgetnameinfo((struct sockaddr *)&ss, salen, a, sizeof(a), b, sizeof(b)); =20 - if (strcmp(cfg_host, a) || strcmp(cfg_port, b)) + iface =3D strchr(cfg_host, '%'); + if (iface) + len =3D iface - cfg_host; + else + len =3D strlen(cfg_host) + 1; + + if (strncmp(cfg_host, a, len) || strcmp(cfg_port, b)) fprintf(stderr, "%s: %s vs %s, %s vs %s\n", __func__, cfg_host, a, cfg_port, b); } diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testin= g/selftests/net/mptcp/mptcp_join.sh index 4c9ee094381e..4faf58fecc94 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -62,6 +62,7 @@ unset sflags unset fastclose unset fullmesh unset speed +unset bind_addr unset join_syn_rej unset join_csum_ns1 unset join_csum_ns2 @@ -645,6 +646,27 @@ wait_mpj() done } =20 +wait_ll_ready() +{ + local ns=3D"${1}" + + local i + for i in $(seq 50); do + ip -n "${ns}" -6 addr show scope link | grep "inet6 fe80" | + grep -qw "tentative" || break + sleep 0.1 + done +} + +get_ll_addr() +{ + local ns=3D"${1}" + local iface=3D"${2}" + + ip -n "${ns}" -6 addr show dev "${iface}" scope link | + grep "inet6 fe80" | sed 's#.*\(fe80::.*\)/.*#\1#' +} + kill_events_pids() { mptcp_lib_kill_wait $evts_ns1_pid @@ -951,6 +973,7 @@ do_transfer() local FAILING_LINKS=3D${FAILING_LINKS:-""} local fastclose=3D${fastclose:-""} local speed=3D${speed:-"fast"} + local bind_addr=3D${bind_addr:-"::"} local listener_in=3D"${sin}" local connector_in=3D"${cin}" port=3D$(get_port) @@ -1006,7 +1029,7 @@ do_transfer() timeout ${timeout_test} \ ip netns exec ${listener_ns} \ ./mptcp_connect -t ${timeout_poll} -l -p ${port} -s ${srv_proto} \ - ${extra_srv_args} "::" < "${listener_in}" > "${sout}" & + ${extra_srv_args} "${bind_addr}" < "${listener_in}" > "${sout}" & local spid=3D$! =20 mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" @@ -3229,6 +3252,133 @@ add_addr_ports_tests() fi } =20 +bind_tests() +{ + # bind to one address should not allow extra subflows to other addresses + if reset "bind main address v4, no join v4"; then + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + bind_addr=3D"10.0.1.1" \ + run_tests $ns1 $ns2 10.0.1.1 + join_syn_tx=3D1 \ + chk_join_nr 0 0 0 + chk_add_nr 1 1 + fi + + # bind to one address should not allow extra subflows to other addresses + if reset "bind main address v6, no join v6"; then + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal + bind_addr=3D"dead:beef:1::1" \ + run_tests $ns1 $ns2 dead:beef:1::1 + join_syn_tx=3D1 \ + chk_join_nr 0 0 0 + chk_add_nr 1 1 + fi + + # multiple binds to allow extra subflows to other addresses + if reset "multiple bind to allow joins v4"; then + local extra_bind + + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + + # Launching another app listening on a different address + # Note: it could be a totally different app, e.g. nc, socat, ... + ip netns exec ${ns1} ./mptcp_connect -l -t -1 -p "$(get_port)" \ + -s MPTCP 10.0.2.1 & + extra_bind=3D$! + + bind_addr=3D"10.0.1.1" \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 + + kill ${extra_bind} + fi + + # multiple binds to allow extra subflows to other addresses + if reset "multiple bind to allow joins v6"; then + local extra_bind + + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal + + # Launching another app listening on a different address + # Note: it could be a totally different app, e.g. nc, socat, ... + ip netns exec ${ns1} ./mptcp_connect -l -t -1 -p "$(get_port)" \ + -s MPTCP dead:beef:2::1 & + extra_bind=3D$! + + bind_addr=3D"dead:beef:1::1" \ + run_tests $ns1 $ns2 dead:beef:1::1 + chk_join_nr 1 1 1 + chk_add_nr 1 1 + + kill ${extra_bind} + fi + + # multiple binds to allow extra subflows to other addresses: v6 LL case + if reset "multiple bind to allow joins v6 link-local routing"; then + local extra_bind ns1ll1 ns1ll2 + + ns1ll1=3D"$(get_ll_addr $ns1 ns1eth1)" + ns1ll2=3D"$(get_ll_addr $ns1 ns1eth2)" + + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 "${ns1ll2}" flags signal + + wait_ll_ready $ns1 # to be able to bind + wait_ll_ready $ns2 # also needed to bind on the client side + ip netns exec ${ns1} ./mptcp_connect -l -t -1 -p "$(get_port)" \ + -s MPTCP "${ns1ll2}%ns1eth2" & + extra_bind=3D$! + + bind_addr=3D"${ns1ll1}%ns1eth1" \ + run_tests $ns1 $ns2 "${ns1ll1}%ns2eth1" + # it is not possible to connect to the announced LL addr without + # specifying the outgoing interface. + join_connect_err=3D1 \ + chk_join_nr 0 0 0 + chk_add_nr 1 1 + + kill ${extra_bind} + fi + + # multiple binds to allow extra subflows to v6 LL addresses: laminar + if reset "multiple bind to allow joins v6 link-local laminar" && + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; t= hen + local extra_bind ns1ll1 ns1ll2 ns2ll2 + + ns1ll1=3D"$(get_ll_addr $ns1 ns1eth1)" + ns1ll2=3D"$(get_ll_addr $ns1 ns1eth2)" + ns2ll2=3D"$(get_ll_addr $ns2 ns2eth2)" + + pm_nl_set_limits $ns1 0 2 + pm_nl_set_limits $ns2 2 2 + pm_nl_add_endpoint $ns1 "${ns1ll2}" flags signal + pm_nl_add_endpoint $ns2 "${ns2ll2}" flags laminar dev ns2eth2 + + wait_ll_ready $ns1 # to be able to bind + wait_ll_ready $ns2 # also needed to bind on the client side + ip netns exec ${ns1} ./mptcp_connect -l -t -1 -p "$(get_port)" \ + -s MPTCP "${ns1ll2}%ns1eth2" & + extra_bind=3D$! + + bind_addr=3D"${ns1ll1}%ns1eth1" \ + run_tests $ns1 $ns2 "${ns1ll1}%ns2eth1" + chk_join_nr 1 1 1 + chk_add_nr 1 1 + + kill ${extra_bind} + fi +} + syncookies_tests() { # single subflow, syncookies @@ -4183,6 +4333,7 @@ all_tests_sorted=3D( M@mixed_tests b@backup_tests p@add_addr_ports_tests + B@bind_tests k@syncookies_tests S@checksum_tests d@deny_join_id0_tests --=20 2.51.0