Skip to content

Commit b666a65

Browse files
author
Paolo Abeni
committed
Merge branch 'mptcp-more-fixes-for-the-in-kernel-pm'
Matthieu Baerts says: ==================== mptcp: more fixes for the in-kernel PM Here is a new batch of fixes for the MPTCP in-kernel path-manager: Patch 1 ensures the address ID is set to 0 when the path-manager sends an ADD_ADDR for the address of the initial subflow. The same fix is applied when a new subflow is created re-using this special address. A fix for v6.0. Patch 2 is similar, but for the case where an endpoint is removed: if this endpoint was used for the initial address, it is important to send a RM_ADDR with this ID set to 0, and look for existing subflows with the ID set to 0. A fix for v6.0 as well. Patch 3 validates the two previous patches. Patch 4 makes the PM selecting an "active" path to send an address notification in an ACK, instead of taking the first path in the list. A fix for v5.11. Patch 5 fixes skipping the establishment of a new subflow if a previous subflow using the same pair of addresses is being closed. A fix for v5.13. Patch 6 resets the ID linked to the initial subflow when the linked endpoint is re-added, possibly with a different ID. A fix for v6.0. Patch 7 validates the three previous patches. Patch 8 is a small fix for the MPTCP Join selftest, when being used with older subflows not supporting all MIB counters. A fix for a commit introduced in v6.4, but backported up to v5.10. Patch 9 avoids the PM to try to close the initial subflow multiple times, and increment counters while nothing happened. A fix for v5.10. Patch 10 stops incrementing local_addr_used and add_addr_accepted counters when dealing with the address ID 0, because these counters are not taking into account the initial subflow, and are then not decremented when the linked addresses are removed. A fix for v6.0. Patch 11 validates the previous patch. Patch 12 avoids the PM to send multiple SUB_CLOSED events for the initial subflow. A fix for v5.12. Patch 13 validates the previous patch. Patch 14 stops treating the ADD_ADDR 0 as a new address, and accepts it in order to re-create the initial subflow if it has been closed, even if the limit for *new* addresses -- not taking into account the address of the initial subflow -- has been reached. A fix for v5.10. Patch 15 validates the previous patch. Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> --- Matthieu Baerts (NGI0) (15): mptcp: pm: reuse ID 0 after delete and re-add mptcp: pm: fix RM_ADDR ID for the initial subflow selftests: mptcp: join: check removing ID 0 endpoint mptcp: pm: send ACK on an active subflow mptcp: pm: skip connecting to already established sf mptcp: pm: reset MPC endp ID when re-added selftests: mptcp: join: check re-adding init endp with != id selftests: mptcp: join: no extra msg if no counter mptcp: pm: do not remove already closed subflows mptcp: pm: fix ID 0 endp usage after multiple re-creations selftests: mptcp: join: check re-re-adding ID 0 endp mptcp: avoid duplicated SUB_CLOSED events selftests: mptcp: join: validate event numbers mptcp: pm: ADD_ADDR 0 is not a new address selftests: mptcp: join: check re-re-adding ID 0 signal net/mptcp/pm.c | 4 +- net/mptcp/pm_netlink.c | 87 ++++++++++---- net/mptcp/protocol.c | 6 + net/mptcp/protocol.h | 5 +- tools/testing/selftests/net/mptcp/mptcp_join.sh | 153 ++++++++++++++++++++---- tools/testing/selftests/net/mptcp/mptcp_lib.sh | 4 + 6 files changed, 209 insertions(+), 50 deletions(-) --- base-commit: 3a0504d change-id: 20240826-net-mptcp-more-pm-fix-ffa61a36f817 Best regards, ==================== Link: https://patch.msgid.link/20240828-net-mptcp-more-pm-fix-v2-0-7f11b283fff7@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 0870b0d + f18fa2a commit b666a65

6 files changed

Lines changed: 209 additions & 50 deletions

File tree

net/mptcp/pm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,9 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
226226
} else {
227227
__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
228228
}
229-
} else if (!READ_ONCE(pm->accept_addr)) {
229+
/* id0 should not have a different address */
230+
} else if ((addr->id == 0 && !mptcp_pm_nl_is_init_remote_addr(msk, addr)) ||
231+
(addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
230232
mptcp_pm_announce_addr(msk, addr, true);
231233
mptcp_pm_add_addr_send_ack(msk);
232234
} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {

net/mptcp/pm_netlink.c

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,15 @@ static bool lookup_subflow_by_daddr(const struct list_head *list,
130130
{
131131
struct mptcp_subflow_context *subflow;
132132
struct mptcp_addr_info cur;
133-
struct sock_common *skc;
134133

135134
list_for_each_entry(subflow, list, node) {
136-
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
135+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
137136

138-
remote_address(skc, &cur);
137+
if (!((1 << inet_sk_state_load(ssk)) &
138+
(TCPF_ESTABLISHED | TCPF_SYN_SENT | TCPF_SYN_RECV)))
139+
continue;
140+
141+
remote_address((struct sock_common *)ssk, &cur);
139142
if (mptcp_addresses_equal(&cur, daddr, daddr->port))
140143
return true;
141144
}
@@ -585,6 +588,11 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
585588

586589
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
587590
msk->pm.add_addr_signaled++;
591+
592+
/* Special case for ID0: set the correct ID */
593+
if (local.addr.id == msk->mpc_endpoint_id)
594+
local.addr.id = 0;
595+
588596
mptcp_pm_announce_addr(msk, &local.addr, false);
589597
mptcp_pm_nl_addr_send_ack(msk);
590598

@@ -607,8 +615,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
607615

608616
fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
609617

610-
msk->pm.local_addr_used++;
611618
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
619+
620+
/* Special case for ID0: set the correct ID */
621+
if (local.addr.id == msk->mpc_endpoint_id)
622+
local.addr.id = 0;
623+
else /* local_addr_used is not decr for ID 0 */
624+
msk->pm.local_addr_used++;
625+
612626
nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs);
613627
if (nr == 0)
614628
continue;
@@ -737,13 +751,24 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
737751
spin_lock_bh(&msk->pm.lock);
738752

739753
if (sf_created) {
740-
msk->pm.add_addr_accepted++;
754+
/* add_addr_accepted is not decr for ID 0 */
755+
if (remote.id)
756+
msk->pm.add_addr_accepted++;
741757
if (msk->pm.add_addr_accepted >= add_addr_accept_max ||
742758
msk->pm.subflows >= subflows_max)
743759
WRITE_ONCE(msk->pm.accept_addr, false);
744760
}
745761
}
746762

763+
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
764+
const struct mptcp_addr_info *remote)
765+
{
766+
struct mptcp_addr_info mpc_remote;
767+
768+
remote_address((struct sock_common *)msk, &mpc_remote);
769+
return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
770+
}
771+
747772
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
748773
{
749774
struct mptcp_subflow_context *subflow;
@@ -755,9 +780,12 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
755780
!mptcp_pm_should_rm_signal(msk))
756781
return;
757782

758-
subflow = list_first_entry_or_null(&msk->conn_list, typeof(*subflow), node);
759-
if (subflow)
760-
mptcp_pm_send_ack(msk, subflow, false, false);
783+
mptcp_for_each_subflow(msk, subflow) {
784+
if (__mptcp_subflow_active(subflow)) {
785+
mptcp_pm_send_ack(msk, subflow, false, false);
786+
break;
787+
}
788+
}
761789
}
762790

763791
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
@@ -790,11 +818,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
790818
return -EINVAL;
791819
}
792820

793-
static bool mptcp_local_id_match(const struct mptcp_sock *msk, u8 local_id, u8 id)
794-
{
795-
return local_id == id || (!local_id && msk->mpc_endpoint_id == id);
796-
}
797-
798821
static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
799822
const struct mptcp_rm_list *rm_list,
800823
enum linux_mptcp_mib_field rm_type)
@@ -827,9 +850,11 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
827850
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
828851
u8 id = subflow_get_local_id(subflow);
829852

853+
if (inet_sk_state_load(ssk) == TCP_CLOSE)
854+
continue;
830855
if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
831856
continue;
832-
if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id))
857+
if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
833858
continue;
834859

835860
pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
@@ -1307,20 +1332,27 @@ static struct pm_nl_pernet *genl_info_pm_nl(struct genl_info *info)
13071332
return pm_nl_get_pernet(genl_info_net(info));
13081333
}
13091334

1310-
static int mptcp_nl_add_subflow_or_signal_addr(struct net *net)
1335+
static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
1336+
struct mptcp_addr_info *addr)
13111337
{
13121338
struct mptcp_sock *msk;
13131339
long s_slot = 0, s_num = 0;
13141340

13151341
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
13161342
struct sock *sk = (struct sock *)msk;
1343+
struct mptcp_addr_info mpc_addr;
13171344

13181345
if (!READ_ONCE(msk->fully_established) ||
13191346
mptcp_pm_is_userspace(msk))
13201347
goto next;
13211348

1349+
/* if the endp linked to the init sf is re-added with a != ID */
1350+
mptcp_local_address((struct sock_common *)msk, &mpc_addr);
1351+
13221352
lock_sock(sk);
13231353
spin_lock_bh(&msk->pm.lock);
1354+
if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
1355+
msk->mpc_endpoint_id = addr->id;
13241356
mptcp_pm_create_subflow_or_signal_addr(msk);
13251357
spin_unlock_bh(&msk->pm.lock);
13261358
release_sock(sk);
@@ -1393,7 +1425,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
13931425
goto out_free;
13941426
}
13951427

1396-
mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk));
1428+
mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk), &entry->addr);
13971429
return 0;
13981430

13991431
out_free:
@@ -1438,14 +1470,20 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
14381470
return false;
14391471
}
14401472

1473+
static u8 mptcp_endp_get_local_id(struct mptcp_sock *msk,
1474+
const struct mptcp_addr_info *addr)
1475+
{
1476+
return msk->mpc_endpoint_id == addr->id ? 0 : addr->id;
1477+
}
1478+
14411479
static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
14421480
const struct mptcp_addr_info *addr,
14431481
bool force)
14441482
{
14451483
struct mptcp_rm_list list = { .nr = 0 };
14461484
bool ret;
14471485

1448-
list.ids[list.nr++] = addr->id;
1486+
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
14491487

14501488
ret = remove_anno_list_by_saddr(msk, addr);
14511489
if (ret || force) {
@@ -1472,14 +1510,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
14721510
const struct mptcp_pm_addr_entry *entry)
14731511
{
14741512
const struct mptcp_addr_info *addr = &entry->addr;
1475-
struct mptcp_rm_list list = { .nr = 0 };
1513+
struct mptcp_rm_list list = { .nr = 1 };
14761514
long s_slot = 0, s_num = 0;
14771515
struct mptcp_sock *msk;
14781516

14791517
pr_debug("remove_id=%d\n", addr->id);
14801518

1481-
list.ids[list.nr++] = addr->id;
1482-
14831519
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
14841520
struct sock *sk = (struct sock *)msk;
14851521
bool remove_subflow;
@@ -1497,6 +1533,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
14971533
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
14981534
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
14991535

1536+
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
15001537
if (remove_subflow) {
15011538
spin_lock_bh(&msk->pm.lock);
15021539
mptcp_pm_nl_rm_subflow_received(msk, &list);
@@ -1509,6 +1546,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
15091546
spin_unlock_bh(&msk->pm.lock);
15101547
}
15111548

1549+
if (msk->mpc_endpoint_id == entry->addr.id)
1550+
msk->mpc_endpoint_id = 0;
15121551
release_sock(sk);
15131552

15141553
next:
@@ -1603,6 +1642,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info)
16031642
return ret;
16041643
}
16051644

1645+
/* Called from the userspace PM only */
16061646
void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
16071647
{
16081648
struct mptcp_rm_list alist = { .nr = 0 };
@@ -1631,6 +1671,7 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
16311671
}
16321672
}
16331673

1674+
/* Called from the in-kernel PM only */
16341675
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
16351676
struct list_head *rm_list)
16361677
{
@@ -1640,11 +1681,11 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
16401681
list_for_each_entry(entry, rm_list, list) {
16411682
if (slist.nr < MPTCP_RM_IDS_MAX &&
16421683
lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
1643-
slist.ids[slist.nr++] = entry->addr.id;
1684+
slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
16441685

16451686
if (alist.nr < MPTCP_RM_IDS_MAX &&
16461687
remove_anno_list_by_saddr(msk, &entry->addr))
1647-
alist.ids[alist.nr++] = entry->addr.id;
1688+
alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
16481689
}
16491690

16501691
spin_lock_bh(&msk->pm.lock);
@@ -1941,7 +1982,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
19411982
{
19421983
struct mptcp_rm_list list = { .nr = 0 };
19431984

1944-
list.ids[list.nr++] = addr->id;
1985+
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
19451986

19461987
spin_lock_bh(&msk->pm.lock);
19471988
mptcp_pm_nl_rm_subflow_received(msk, &list);

net/mptcp/protocol.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,12 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
25082508
void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
25092509
struct mptcp_subflow_context *subflow)
25102510
{
2511+
/* The first subflow can already be closed and still in the list */
2512+
if (subflow->close_event_done)
2513+
return;
2514+
2515+
subflow->close_event_done = true;
2516+
25112517
if (sk->sk_state == TCP_ESTABLISHED)
25122518
mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL);
25132519

net/mptcp/protocol.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,8 @@ struct mptcp_subflow_context {
524524
stale : 1, /* unable to snd/rcv data, do not use for xmit */
525525
valid_csum_seen : 1, /* at least one csum validated */
526526
is_mptfo : 1, /* subflow is doing TFO */
527-
__unused : 10;
527+
close_event_done : 1, /* has done the post-closed part */
528+
__unused : 9;
528529
bool data_avail;
529530
bool scheduled;
530531
u32 remote_nonce;
@@ -992,6 +993,8 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
992993
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
993994
const struct mptcp_addr_info *addr);
994995
void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
996+
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
997+
const struct mptcp_addr_info *remote);
995998
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk);
996999
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
9971000
const struct mptcp_rm_list *rm_list);

0 commit comments

Comments
 (0)