mptcp: more accurate MPC endpoint tracking
authorPaolo Abeni <pabeni@redhat.com>
Mon, 11 Jul 2022 19:16:32 +0000 (12:16 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 13 Jul 2022 01:37:20 +0000 (18:37 -0700)
Currently the id accounting for the ID 0 subflow is not correct:
at creation time we mark (correctly) as unavailable the endpoint
id corresponding the MPC subflow source address, while at subflow
removal time set as available the id 0.

With this change we track explicitly the endpoint id corresponding
to the MPC subflow so that we can mark it as available at removal time.
Additionally this allow deleting the initial subflow via the NL PM
specifying the corresponding endpoint id.

Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/pm_netlink.c
net/mptcp/protocol.h

index b767a33..291b5da 100644 (file)
@@ -549,6 +549,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
                entry = __lookup_addr(pernet, &mpc_addr, false);
                if (entry) {
                        __clear_bit(entry->addr.id, msk->pm.id_avail_bitmap);
+                       msk->mpc_endpoint_id = entry->addr.id;
                        backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
                }
                rcu_read_unlock();
@@ -764,6 +765,11 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
        return -EINVAL;
 }
 
+static bool mptcp_local_id_match(const struct mptcp_sock *msk, u8 local_id, u8 id)
+{
+       return local_id == id || (!local_id && msk->mpc_endpoint_id == id);
+}
+
 static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
                                           const struct mptcp_rm_list *rm_list,
                                           enum linux_mptcp_mib_field rm_type)
@@ -787,6 +793,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
                return;
 
        for (i = 0; i < rm_list->nr; i++) {
+               u8 rm_id = rm_list->ids[i];
                bool removed = false;
 
                list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
@@ -794,15 +801,15 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
                        int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
                        u8 id = subflow->local_id;
 
-                       if (rm_type == MPTCP_MIB_RMADDR)
-                               id = subflow->remote_id;
-
-                       if (rm_list->ids[i] != id)
+                       if (rm_type == MPTCP_MIB_RMADDR && subflow->remote_id != rm_id)
+                               continue;
+                       if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id))
                                continue;
 
-                       pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u",
+                       pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u",
                                 rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
-                                i, rm_list->ids[i], subflow->local_id, subflow->remote_id);
+                                i, rm_id, subflow->local_id, subflow->remote_id,
+                                msk->mpc_endpoint_id);
                        spin_unlock_bh(&msk->pm.lock);
                        mptcp_subflow_shutdown(sk, ssk, how);
 
@@ -814,7 +821,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
                        __MPTCP_INC_STATS(sock_net(sk), rm_type);
                }
                if (rm_type == MPTCP_MIB_RMSUBFLOW)
-                       __set_bit(rm_list->ids[i], msk->pm.id_avail_bitmap);
+                       __set_bit(rm_id ? rm_id : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap);
                if (!removed)
                        continue;
 
index e38b861..5d6043c 100644 (file)
@@ -282,6 +282,7 @@ struct mptcp_sock {
        bool            use_64bit_ack; /* Set when we received a 64-bit DSN */
        bool            csum_enabled;
        bool            allow_infinite_fallback;
+       u8              mpc_endpoint_id;
        u8              recvmsg_inq:1,
                        cork:1,
                        nodelay:1;