]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mptcp: pm: in-kernel: record fullmesh endp nb
authorMatthieu Baerts (NGI0) <matttbe@kernel.org>
Sat, 1 Nov 2025 17:56:51 +0000 (18:56 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 5 Nov 2025 01:15:06 +0000 (17:15 -0800)
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 <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20251101-net-next-mptcp-fm-endp-nb-bind-v1-1-b4166772d6bb@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/uapi/linux/mptcp.h
net/mptcp/pm_kernel.c
net/mptcp/protocol.h
net/mptcp/sockopt.c

index 87cfab874e2415d88c98f17e5562b0440feafaab..04eea6d1d0a9bc01b426c70190f92c5619970db7 100644 (file)
@@ -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;
index 2ae95476dba35e00f88ae83ca64ee2bd1eef5cb6..e2918c68ff023becfde3ee132403060b30ffd219 100644 (file)
@@ -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);
 
+u8 mptcp_pm_get_endp_fullmesh_max(const struct mptcp_sock *msk)
+{
+       struct pm_nl_pernet *pernet = 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 = pm_nl_get_pernet_from_msk(msk);
@@ -603,9 +612,12 @@ fill_local_addresses_vec(struct mptcp_sock *msk, struct mptcp_addr_info *remote,
        int i;
 
        /* If there is at least one MPTCP endpoint with a fullmesh flag */
-       i = fill_local_addresses_vec_fullmesh(msk, remote, locals, c_flag_case);
-       if (i)
-               return i;
+       if (mptcp_pm_get_endp_fullmesh_max(msk)) {
+               i = fill_local_addresses_vec_fullmesh(msk, remote, locals,
+                                                     c_flag_case);
+               if (i)
+                       return i;
+       }
 
        /* If there is at least one MPTCP endpoint with a laminar flag */
        if (mptcp_pm_get_endp_laminar_max(msk))
@@ -790,6 +802,10 @@ find_next:
                addr_max = pernet->endp_laminar_max;
                WRITE_ONCE(pernet->endp_laminar_max, addr_max + 1);
        }
+       if (entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
+               addr_max = pernet->endp_fullmesh_max;
+               WRITE_ONCE(pernet->endp_fullmesh_max, addr_max + 1);
+       }
 
        pernet->endpoints++;
        if (!entry->addr.port)
@@ -1187,6 +1203,10 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info)
                addr_max = pernet->endp_laminar_max;
                WRITE_ONCE(pernet->endp_laminar_max, addr_max - 1);
        }
+       if (entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
+               addr_max = pernet->endp_fullmesh_max;
+               WRITE_ONCE(pernet->endp_fullmesh_max, addr_max - 1);
+       }
 
        pernet->endpoints--;
        list_del_rcu(&entry->list);
@@ -1502,6 +1522,18 @@ int mptcp_pm_nl_set_flags(struct mptcp_pm_addr_entry *local,
        changed = (local->flags ^ entry->flags) & mask;
        entry->flags = (entry->flags & ~mask) | (local->flags & mask);
        *local = *entry;
+
+       if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH) {
+               u8 addr_max = 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);
 
        mptcp_pm_nl_set_flags_all(net, local, changed);
index 379a88e14e8d2549e54a103da1ed758c4bae9bb9..9a342917575853346a571d9fc18d71d8b73b0b65 100644 (file)
@@ -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);
 
index a28a483858852b49966b904a2f0dd44d8d118b5e..de90a2897d2d8f88202b3d6066a82db9ef8d537e 100644 (file)
@@ -982,6 +982,8 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
                        mptcp_pm_get_endp_subflow_max(msk);
                info->mptcpi_endp_laminar_max =
                        mptcp_pm_get_endp_laminar_max(msk);
+               info->mptcpi_endp_fullmesh_max =
+                       mptcp_pm_get_endp_fullmesh_max(msk);
        }
 
        if (__mptcp_check_fallback(msk))