]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mptcp: pm: fix backup support in signal endpoints
authorMatthieu Baerts (NGI0) <matttbe@kernel.org>
Fri, 9 Aug 2024 09:09:14 +0000 (11:09 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Aug 2024 03:45:48 +0000 (05:45 +0200)
commit 6834097fc38c5416701c793da94558cea49c0a1f upstream.

There was a support for signal endpoints, but only when the endpoint's
flag was changed during a connection. If an endpoint with the signal and
backup was already present, the MP_JOIN reply was not containing the
backup flag as expected.

That's confusing to have this inconsistent behaviour. On the other hand,
the infrastructure to set the backup flag in the SYN + ACK + MP_JOIN was
already there, it was just never set before. Now when requesting the
local ID from the path-manager, the backup status is also requested.

Note that when the userspace PM is used, the backup flag can be set if
the local address was already used before with a backup flag, e.g. if
the address was announced with the 'backup' flag, or a subflow was
created with the 'backup' flag.

Fixes: 4596a2c1b7f5 ("mptcp: allow creating non-backup subflows")
Cc: stable@vger.kernel.org
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/507
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
[ Conflicts in pm_userspace.c because the context has changed in commit
  1e07938e29c5 ("net: mptcp: rename netlink handlers to
  mptcp_pm_nl_<blah>_{doit,dumpit}") which is not in this version. This
  commit is unrelated to this modification.
  Conflicts in protocol.h because the context has changed in commit
  9ae7846c4b6b ("mptcp: dump addrs in userspace pm list") which is not
  in this version. This commit is unrelated to this modification.
  Conflicts in pm.c because the context has changed in commit
  f40be0db0b76 ("mptcp: unify pm get_flags_and_ifindex_by_id") which is
  not in this version. This commit is unrelated to this modification.
  Conflicts in subflow.c, because the commit 4cf86ae84c71 ("mptcp:
  strict local address ID selection") is not in this version. It is then
  not needed to modify the subflow_chk_local_id() helper, which is not
  in this version.
  Also, in this version, there is no pm_userspace.c, because this PM has
  been added in v5.19, which also causes conflicts in protocol.h, and
  pm_netlink.c. Plus the code in pm.c can be simplified, as there is no
  userspace PM. And the code in pm_netlink.c needs to use
  addresses_equal() instead of mptcp_addresses_equal(), see commit
  4638de5aefe5 ("mptcp: handle local addrs announced by userspace PMs").
  The code in pm_netlink.c also needs to be adapted because the
  pm_nl_get_pernet_from_msk() helper is not in this version, introduced
  later in commit c682bf536cf4 ("mptcp: add pm_nl_pernet helpers"). ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/mptcp/pm.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.h
net/mptcp/subflow.c

index d9790d6fbce9c4b617fdf8eb9f1454a35b75b03e..55e8407bcc2500deac4eb1f2a95b685e788dc094 100644 (file)
@@ -341,6 +341,15 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
        return mptcp_pm_nl_get_local_id(msk, skc);
 }
 
+bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc)
+{
+       struct mptcp_addr_info skc_local;
+
+       mptcp_local_address((struct sock_common *)skc, &skc_local);
+
+       return mptcp_pm_nl_is_backup(msk, &skc_local);
+}
+
 void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
 {
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
index 37e9ff9b99f67d79834c0cbd31aac4173be89e97..1ae164711783f1a27a7fdb6fc95aeac86b94a0b1 100644 (file)
@@ -1014,6 +1014,26 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
        return ret;
 }
 
+bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
+{
+       struct mptcp_pm_addr_entry *entry;
+       struct pm_nl_pernet *pernet;
+       bool backup = false;
+
+       pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
+               if (addresses_equal(&entry->addr, skc, entry->addr.port)) {
+                       backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
+                       break;
+               }
+       }
+       rcu_read_unlock();
+
+       return backup;
+}
+
 void mptcp_pm_nl_data_init(struct mptcp_sock *msk)
 {
        struct mptcp_pm_data *pm = &msk->pm;
index 0f82d75e3d201764a456bf76d77a477a24f36648..234cf918db97fe01591db82cb9ca4fb8733129e7 100644 (file)
@@ -821,6 +821,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb,
 bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
                             struct mptcp_rm_list *rm_list);
 int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
+bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc);
 
 void __init mptcp_pm_nl_init(void);
 void mptcp_pm_nl_data_init(struct mptcp_sock *msk);
@@ -828,6 +829,7 @@ void mptcp_pm_nl_work(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
                                     const struct mptcp_rm_list *rm_list);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
+bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
 unsigned int mptcp_pm_get_add_addr_signal_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_add_addr_accept_max(struct mptcp_sock *msk);
 unsigned int mptcp_pm_get_subflows_max(struct mptcp_sock *msk);
index 90e7a46a6d2f85a524fe6e869c0f9dab56f11730..2f94387f2ade92656cb6e9659e9305f2b359d82f 100644 (file)
@@ -97,6 +97,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)
                return NULL;
        }
        subflow_req->local_id = local_id;
+       subflow_req->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)req);
 
        return msk;
 }