Skip to content

Commit

Permalink
mptcp: fix duplicate subflow creation
Browse files Browse the repository at this point in the history
Fullmesh endpoints could end-up unexpectedly generating duplicate
subflows - same local and remote addresses - when multiple incoming
ADD_ADDR are processed before the PM creates the subflow for the local
endpoints.

Address the issue explicitly checking for duplicates at subflow
creation time.

To avoid a quadratic computational complexity, track the unavailable
remote address ids in a temporary bitmap and initialize such bitmap
with the remote ids of all the existing subflows matching the local
address currently processed.

The above allows additionally replacing the existing code checking
for duplicate entry in the current set with a simple bit test
operation.

Fixes: 2843ff6 ("mptcp: remote addresses fullmesh")
Closes: multipath-tcp/mptcp_net-next#435
Signed-off-by: Paolo Abeni <[email protected]>
  • Loading branch information
Paolo Abeni authored and intel-lab-lkp committed Feb 5, 2024
1 parent 93dbd80 commit a784c42
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions net/mptcp/pm_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,6 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
}
}

static bool lookup_address_in_vec(const struct mptcp_addr_info *addrs, unsigned int nr,
const struct mptcp_addr_info *addr)
{
int i;

for (i = 0; i < nr; i++) {
if (addrs[i].id == addr->id)
return true;
}

return false;
}

/* Fill all the remote addresses into the array addrs[],
* and return the array size.
*/
Expand Down Expand Up @@ -440,18 +427,34 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk,
msk->pm.subflows++;
addrs[i++] = remote;
} else {
DECLARE_BITMAP(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);

/* Forbit creation of new subflows matching existing
* ones, possibly already created by incoming ADD_ADDR
*/
bitmap_zero(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);
mptcp_for_each_subflow(msk, subflow)
if (READ_ONCE(subflow->local_id) == local->id)
__set_bit(subflow->remote_id, unavail_id);

mptcp_for_each_subflow(msk, subflow) {
ssk = mptcp_subflow_tcp_sock(subflow);
remote_address((struct sock_common *)ssk, &addrs[i]);
addrs[i].id = READ_ONCE(subflow->remote_id);
if (deny_id0 && !addrs[i].id)
continue;

if (test_bit(addrs[i].id, unavail_id))
continue;

if (!mptcp_pm_addr_families_match(sk, local, &addrs[i]))
continue;

if (!lookup_address_in_vec(addrs, i, &addrs[i]) &&
msk->pm.subflows < subflows_max) {
if (msk->pm.subflows < subflows_max) {
/* forbit creating multiple address towards
* this id
*/
__set_bit(addrs[i].id, unavail_id);
msk->pm.subflows++;
i++;
}
Expand Down

0 comments on commit a784c42

Please sign in to comment.