From: Greg Kroah-Hartman Date: Fri, 17 Oct 2025 08:05:22 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v5.15.195~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d58fa422730c234e5c56da39789bb6527bc1fe1d;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch --- diff --git a/queue-6.6/mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch b/queue-6.6/mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch new file mode 100644 index 0000000000..baf05e7717 --- /dev/null +++ b/queue-6.6/mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch @@ -0,0 +1,184 @@ +From 4b1ff850e0c1aacc23e923ed22989b827b9808f9 Mon Sep 17 00:00:00 2001 +From: "Matthieu Baerts (NGI0)" +Date: Thu, 25 Sep 2025 12:32:36 +0200 +Subject: mptcp: pm: in-kernel: usable client side with C-flag + +From: Matthieu Baerts (NGI0) + +commit 4b1ff850e0c1aacc23e923ed22989b827b9808f9 upstream. + +When servers set the C-flag in their MP_CAPABLE to tell clients not to +create subflows to the initial address and port, clients will likely not +use their other endpoints. That's because the in-kernel path-manager +uses the 'subflow' endpoints to create subflows only to the initial +address and port. + +If the limits have not been modified to accept ADD_ADDR, the client +doesn't try to establish new subflows. If the limits accept ADD_ADDR, +the routing routes will be used to select the source IP. + +The C-flag is typically set when the server is operating behind a legacy +Layer 4 load balancer, or using anycast IP address. Clients having their +different 'subflow' endpoints setup, don't end up creating multiple +subflows as expected, and causing some deployment issues. + +A special case is then added here: when servers set the C-flag in the +MPC and directly sends an ADD_ADDR, this single ADD_ADDR is accepted. +The 'subflows' endpoints will then be used with this new remote IP and +port. This exception is only allowed when the ADD_ADDR is sent +immediately after the 3WHS, and makes the client switching to the 'fully +established' mode. After that, 'select_local_address()' will not be able +to find any subflows, because 'id_avail_bitmap' will be filled in +mptcp_pm_create_subflow_or_signal_addr(), when switching to 'fully +established' mode. + +Fixes: df377be38725 ("mptcp: add deny_join_id0 in mptcp_options_received") +Cc: stable@vger.kernel.org +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/536 +Reviewed-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20250925-net-next-mptcp-c-flag-laminar-v1-1-ad126cc47c6b@kernel.org +Signed-off-by: Jakub Kicinski +[ Conflict in pm.c, because commit 498d7d8b75f1 ("mptcp: pm: remove + '_nl' from mptcp_pm_nl_is_init_remote_addr") renamed an helper in the + context, and it is not in this version. The same new code can be + applied at the same place. + Conflict in pm_kernel.c, because the modified code has been moved from + pm_netlink.c to pm_kernel.c in commit 8617e85e04bd ("mptcp: pm: split + in-kernel PM specific code"), which is not in this version. The + resolution is easy: simply by applying the patch where 'pm_kernel.c' + has been replaced 'pm_netlink.c'. + Conflict in pm_netlink.c, because commit b83fbca1b4c9 ("mptcp: pm: + reduce entries iterations on connect") is not in this version. Instead + of using the 'locals' variable (struct mptcp_pm_local *) from the new + version and embedding a "struct mptcp_addr_info", we can simply + continue to use the 'addrs' variable (struct mptcp_addr_info *). + Conflict in protocol.h, because commit af3dc0ad3167 ("mptcp: Remove + unused declaration mptcp_sockopt_sync()") is not in this version and + it removed one line in the context. The resolution is easy because the + new function can still be added at the same place. ] +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm.c | 7 ++++-- + net/mptcp/pm_netlink.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- + net/mptcp/protocol.h | 8 +++++++ + 3 files changed, 64 insertions(+), 3 deletions(-) + +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -227,9 +227,12 @@ void mptcp_pm_add_addr_received(const st + } else { + __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); + } +- /* id0 should not have a different address */ ++ /* - id0 should not have a different address ++ * - special case for C-flag: linked to fill_local_addresses_vec() ++ */ + } else if ((addr->id == 0 && !mptcp_pm_nl_is_init_remote_addr(msk, addr)) || +- (addr->id > 0 && !READ_ONCE(pm->accept_addr))) { ++ (addr->id > 0 && !READ_ONCE(pm->accept_addr) && ++ !mptcp_pm_add_addr_c_flag_case(msk))) { + mptcp_pm_announce_addr(msk, addr, true); + mptcp_pm_add_addr_send_ack(msk); + } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) { +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -675,10 +675,12 @@ static unsigned int fill_local_addresses + struct mptcp_addr_info mpc_addr; + struct pm_nl_pernet *pernet; + unsigned int subflows_max; ++ bool c_flag_case; + int i = 0; + + pernet = pm_nl_get_pernet_from_msk(msk); + subflows_max = mptcp_pm_get_subflows_max(msk); ++ c_flag_case = remote->id && mptcp_pm_add_addr_c_flag_case(msk); + + mptcp_local_address((struct sock_common *)msk, &mpc_addr); + +@@ -691,11 +693,26 @@ static unsigned int fill_local_addresses + continue; + + if (msk->pm.subflows < subflows_max) { ++ bool is_id0; ++ + msk->pm.subflows++; + addrs[i] = entry->addr; + ++ is_id0 = mptcp_addresses_equal(&entry->addr, ++ &mpc_addr, ++ entry->addr.port); ++ ++ if (c_flag_case && ++ (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)) { ++ __clear_bit(addrs[i].id, ++ msk->pm.id_avail_bitmap); ++ ++ if (!is_id0) ++ msk->pm.local_addr_used++; ++ } ++ + /* Special case for ID0: set the correct ID */ +- if (mptcp_addresses_equal(&entry->addr, &mpc_addr, entry->addr.port)) ++ if (is_id0) + addrs[i].id = 0; + + i++; +@@ -703,6 +720,39 @@ static unsigned int fill_local_addresses + } + rcu_read_unlock(); + ++ /* Special case: peer sets the C flag, accept one ADD_ADDR if default ++ * limits are used -- accepting no ADD_ADDR -- and use subflow endpoints ++ */ ++ if (!i && c_flag_case) { ++ unsigned int local_addr_max = mptcp_pm_get_local_addr_max(msk); ++ ++ while (msk->pm.local_addr_used < local_addr_max && ++ msk->pm.subflows < subflows_max) { ++ struct mptcp_pm_addr_entry local; ++ ++ if (!select_local_address(pernet, msk, &local)) ++ break; ++ ++ __clear_bit(local.addr.id, msk->pm.id_avail_bitmap); ++ ++ if (!mptcp_pm_addr_families_match(sk, &local.addr, ++ remote)) ++ continue; ++ ++ if (mptcp_addresses_equal(&local.addr, &mpc_addr, ++ local.addr.port)) ++ continue; ++ ++ addrs[i] = local.addr; ++ ++ msk->pm.local_addr_used++; ++ msk->pm.subflows++; ++ i++; ++ } ++ ++ return i; ++ } ++ + /* If the array is empty, fill in the single + * 'IPADDRANY' local address + */ +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -1080,6 +1080,14 @@ static inline void mptcp_pm_close_subflo + spin_unlock_bh(&msk->pm.lock); + } + ++static inline bool mptcp_pm_add_addr_c_flag_case(struct mptcp_sock *msk) ++{ ++ return READ_ONCE(msk->pm.remote_deny_join_id0) && ++ msk->pm.local_addr_used == 0 && ++ mptcp_pm_get_add_addr_accept_max(msk) == 0 && ++ msk->pm.subflows < mptcp_pm_get_subflows_max(msk); ++} ++ + void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk); + void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk); + diff --git a/queue-6.6/series b/queue-6.6/series index 2a91e8bb89..6f7c96df79 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -188,3 +188,4 @@ s390-bpf-describe-the-frame-using-a-struct-instead-of-constants.patch s390-bpf-write-back-tail-call-counter-for-bpf_pseudo_call.patch s390-bpf-write-back-tail-call-counter-for-bpf_tramp_f_call_orig.patch selftests-mm-skip-soft-dirty-tests-when-config_mem_soft_dirty-is-disabled.patch +mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch