]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Oct 2025 08:05:22 +0000 (10:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Oct 2025 08:05:22 +0000 (10:05 +0200)
added patches:
mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch

queue-6.6/mptcp-pm-in-kernel-usable-client-side-with-c-flag.patch [new file with mode: 0644]
queue-6.6/series

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 (file)
index 0000000..baf05e7
--- /dev/null
@@ -0,0 +1,184 @@
+From 4b1ff850e0c1aacc23e923ed22989b827b9808f9 Mon Sep 17 00:00:00 2001
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Thu, 25 Sep 2025 12:32:36 +0200
+Subject: mptcp: pm: in-kernel: usable client side with C-flag
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+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 <geliang@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20250925-net-next-mptcp-c-flag-laminar-v1-1-ad126cc47c6b@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ 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) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
index 2a91e8bb8934e91188805d370035a54605715fb9..6f7c96df797e79d00043876036bf78b18167c50c 100644 (file)
@@ -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