Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mptcp: remote addresses fullmesh

This patch added and managed a new per endpoint flag, named
MPTCP_PM_ADDR_FLAG_FULLMESH.

In mptcp_pm_create_subflow_or_signal_addr(), if such flag is set, instead
of:
remote_address((struct sock_common *)sk, &remote);
fill a temporary allocated array of all known remote address. After
releaseing the pm lock loop on such array and create a subflow for each
remote address from the given local.

Note that the we could still use an array even for non 'fullmesh'
endpoint: with a single entry corresponding to the primary MPC subflow
remote address.

Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@xiaomi.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Geliang Tang and committed by
David S. Miller
2843ff6f ee285257

+56 -4
+1
include/uapi/linux/mptcp.h
··· 73 73 #define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) 74 74 #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) 75 75 #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) 76 + #define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3) 76 77 77 78 enum { 78 79 MPTCP_PM_CMD_UNSPEC,
+55 -4
net/mptcp/pm_netlink.c
··· 410 410 } 411 411 } 412 412 413 + static bool lookup_address_in_vec(struct mptcp_addr_info *addrs, unsigned int nr, 414 + struct mptcp_addr_info *addr) 415 + { 416 + int i; 417 + 418 + for (i = 0; i < nr; i++) { 419 + if (addresses_equal(&addrs[i], addr, addr->port)) 420 + return true; 421 + } 422 + 423 + return false; 424 + } 425 + 426 + /* Fill all the remote addresses into the array addrs[], 427 + * and return the array size. 428 + */ 429 + static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, bool fullmesh, 430 + struct mptcp_addr_info *addrs) 431 + { 432 + struct sock *sk = (struct sock *)msk, *ssk; 433 + struct mptcp_subflow_context *subflow; 434 + struct mptcp_addr_info remote = { 0 }; 435 + unsigned int subflows_max; 436 + int i = 0; 437 + 438 + subflows_max = mptcp_pm_get_subflows_max(msk); 439 + 440 + /* Non-fullmesh endpoint, fill in the single entry 441 + * corresponding to the primary MPC subflow remote address 442 + */ 443 + if (!fullmesh) { 444 + remote_address((struct sock_common *)sk, &remote); 445 + msk->pm.subflows++; 446 + addrs[i++] = remote; 447 + } else { 448 + mptcp_for_each_subflow(msk, subflow) { 449 + ssk = mptcp_subflow_tcp_sock(subflow); 450 + remote_address((struct sock_common *)ssk, &remote); 451 + if (!lookup_address_in_vec(addrs, i, &remote) && 452 + msk->pm.subflows < subflows_max) { 453 + msk->pm.subflows++; 454 + addrs[i++] = remote; 455 + } 456 + } 457 + } 458 + 459 + return i; 460 + } 461 + 413 462 static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) 414 463 { 415 464 struct sock *sk = (struct sock *)msk; ··· 504 455 !READ_ONCE(msk->pm.remote_deny_join_id0)) { 505 456 local = select_local_address(pernet, msk); 506 457 if (local) { 507 - struct mptcp_addr_info remote = { 0 }; 458 + bool fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH); 459 + struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX]; 460 + int i, nr; 508 461 509 462 msk->pm.local_addr_used++; 510 - msk->pm.subflows++; 511 463 check_work_pending(msk); 512 - remote_address((struct sock_common *)sk, &remote); 464 + nr = fill_remote_addresses_vec(msk, fullmesh, addrs); 513 465 spin_unlock_bh(&msk->pm.lock); 514 - __mptcp_subflow_connect(sk, &local->addr, &remote); 466 + for (i = 0; i < nr; i++) 467 + __mptcp_subflow_connect(sk, &local->addr, &addrs[i]); 515 468 spin_lock_bh(&msk->pm.lock); 516 469 return; 517 470 }