Commit b666a651 authored by Paolo Abeni's avatar Paolo Abeni

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: default avatarMatthieu 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: 3a0504d5
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.orgSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 0870b0d8 f18fa2ab
...@@ -226,7 +226,9 @@ void mptcp_pm_add_addr_received(const struct sock *ssk, ...@@ -226,7 +226,9 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
} else { } else {
__MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
} }
} else if (!READ_ONCE(pm->accept_addr)) { /* id0 should not have a different address */
} else if ((addr->id == 0 && !mptcp_pm_nl_is_init_remote_addr(msk, addr)) ||
(addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
mptcp_pm_announce_addr(msk, addr, true); mptcp_pm_announce_addr(msk, addr, true);
mptcp_pm_add_addr_send_ack(msk); mptcp_pm_add_addr_send_ack(msk);
} else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) { } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
......
...@@ -130,12 +130,15 @@ static bool lookup_subflow_by_daddr(const struct list_head *list, ...@@ -130,12 +130,15 @@ static bool lookup_subflow_by_daddr(const struct list_head *list,
{ {
struct mptcp_subflow_context *subflow; struct mptcp_subflow_context *subflow;
struct mptcp_addr_info cur; struct mptcp_addr_info cur;
struct sock_common *skc;
list_for_each_entry(subflow, list, node) { list_for_each_entry(subflow, list, node) {
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow); struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
remote_address(skc, &cur); if (!((1 << inet_sk_state_load(ssk)) &
(TCPF_ESTABLISHED | TCPF_SYN_SENT | TCPF_SYN_RECV)))
continue;
remote_address((struct sock_common *)ssk, &cur);
if (mptcp_addresses_equal(&cur, daddr, daddr->port)) if (mptcp_addresses_equal(&cur, daddr, daddr->port))
return true; return true;
} }
...@@ -585,6 +588,11 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) ...@@ -585,6 +588,11 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap); __clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
msk->pm.add_addr_signaled++; msk->pm.add_addr_signaled++;
/* Special case for ID0: set the correct ID */
if (local.addr.id == msk->mpc_endpoint_id)
local.addr.id = 0;
mptcp_pm_announce_addr(msk, &local.addr, false); mptcp_pm_announce_addr(msk, &local.addr, false);
mptcp_pm_nl_addr_send_ack(msk); mptcp_pm_nl_addr_send_ack(msk);
...@@ -607,8 +615,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) ...@@ -607,8 +615,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH); fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
msk->pm.local_addr_used++;
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap); __clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
/* Special case for ID0: set the correct ID */
if (local.addr.id == msk->mpc_endpoint_id)
local.addr.id = 0;
else /* local_addr_used is not decr for ID 0 */
msk->pm.local_addr_used++;
nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs); nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs);
if (nr == 0) if (nr == 0)
continue; continue;
...@@ -737,13 +751,24 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk) ...@@ -737,13 +751,24 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
if (sf_created) { if (sf_created) {
msk->pm.add_addr_accepted++; /* add_addr_accepted is not decr for ID 0 */
if (remote.id)
msk->pm.add_addr_accepted++;
if (msk->pm.add_addr_accepted >= add_addr_accept_max || if (msk->pm.add_addr_accepted >= add_addr_accept_max ||
msk->pm.subflows >= subflows_max) msk->pm.subflows >= subflows_max)
WRITE_ONCE(msk->pm.accept_addr, false); WRITE_ONCE(msk->pm.accept_addr, false);
} }
} }
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *remote)
{
struct mptcp_addr_info mpc_remote;
remote_address((struct sock_common *)msk, &mpc_remote);
return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
}
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
{ {
struct mptcp_subflow_context *subflow; struct mptcp_subflow_context *subflow;
...@@ -755,9 +780,12 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk) ...@@ -755,9 +780,12 @@ void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
!mptcp_pm_should_rm_signal(msk)) !mptcp_pm_should_rm_signal(msk))
return; return;
subflow = list_first_entry_or_null(&msk->conn_list, typeof(*subflow), node); mptcp_for_each_subflow(msk, subflow) {
if (subflow) if (__mptcp_subflow_active(subflow)) {
mptcp_pm_send_ack(msk, subflow, false, false); mptcp_pm_send_ack(msk, subflow, false, false);
break;
}
}
} }
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk, 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, ...@@ -790,11 +818,6 @@ int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
return -EINVAL; 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, static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list, const struct mptcp_rm_list *rm_list,
enum linux_mptcp_mib_field rm_type) enum linux_mptcp_mib_field rm_type)
...@@ -827,9 +850,11 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, ...@@ -827,9 +850,11 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
int how = RCV_SHUTDOWN | SEND_SHUTDOWN; int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
u8 id = subflow_get_local_id(subflow); u8 id = subflow_get_local_id(subflow);
if (inet_sk_state_load(ssk) == TCP_CLOSE)
continue;
if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id) if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
continue; continue;
if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id)) if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
continue; continue;
pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n", 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) ...@@ -1307,20 +1332,27 @@ static struct pm_nl_pernet *genl_info_pm_nl(struct genl_info *info)
return pm_nl_get_pernet(genl_info_net(info)); return pm_nl_get_pernet(genl_info_net(info));
} }
static int mptcp_nl_add_subflow_or_signal_addr(struct net *net) static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
struct mptcp_addr_info *addr)
{ {
struct mptcp_sock *msk; struct mptcp_sock *msk;
long s_slot = 0, s_num = 0; long s_slot = 0, s_num = 0;
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) { while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
struct mptcp_addr_info mpc_addr;
if (!READ_ONCE(msk->fully_established) || if (!READ_ONCE(msk->fully_established) ||
mptcp_pm_is_userspace(msk)) mptcp_pm_is_userspace(msk))
goto next; goto next;
/* if the endp linked to the init sf is re-added with a != ID */
mptcp_local_address((struct sock_common *)msk, &mpc_addr);
lock_sock(sk); lock_sock(sk);
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
msk->mpc_endpoint_id = addr->id;
mptcp_pm_create_subflow_or_signal_addr(msk); mptcp_pm_create_subflow_or_signal_addr(msk);
spin_unlock_bh(&msk->pm.lock); spin_unlock_bh(&msk->pm.lock);
release_sock(sk); release_sock(sk);
...@@ -1393,7 +1425,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info) ...@@ -1393,7 +1425,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
goto out_free; goto out_free;
} }
mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk)); mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk), &entry->addr);
return 0; return 0;
out_free: out_free:
...@@ -1438,6 +1470,12 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk, ...@@ -1438,6 +1470,12 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
return false; return false;
} }
static u8 mptcp_endp_get_local_id(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr)
{
return msk->mpc_endpoint_id == addr->id ? 0 : addr->id;
}
static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr, const struct mptcp_addr_info *addr,
bool force) bool force)
...@@ -1445,7 +1483,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, ...@@ -1445,7 +1483,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 0 };
bool ret; bool ret;
list.ids[list.nr++] = addr->id; list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
ret = remove_anno_list_by_saddr(msk, addr); ret = remove_anno_list_by_saddr(msk, addr);
if (ret || force) { if (ret || force) {
...@@ -1472,14 +1510,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, ...@@ -1472,14 +1510,12 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
const struct mptcp_pm_addr_entry *entry) const struct mptcp_pm_addr_entry *entry)
{ {
const struct mptcp_addr_info *addr = &entry->addr; const struct mptcp_addr_info *addr = &entry->addr;
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 1 };
long s_slot = 0, s_num = 0; long s_slot = 0, s_num = 0;
struct mptcp_sock *msk; struct mptcp_sock *msk;
pr_debug("remove_id=%d\n", addr->id); pr_debug("remove_id=%d\n", addr->id);
list.ids[list.nr++] = addr->id;
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) { while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
bool remove_subflow; bool remove_subflow;
...@@ -1497,6 +1533,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, ...@@ -1497,6 +1533,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow && mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT)); !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
if (remove_subflow) { if (remove_subflow) {
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
mptcp_pm_nl_rm_subflow_received(msk, &list); mptcp_pm_nl_rm_subflow_received(msk, &list);
...@@ -1509,6 +1546,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, ...@@ -1509,6 +1546,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
spin_unlock_bh(&msk->pm.lock); spin_unlock_bh(&msk->pm.lock);
} }
if (msk->mpc_endpoint_id == entry->addr.id)
msk->mpc_endpoint_id = 0;
release_sock(sk); release_sock(sk);
next: next:
...@@ -1603,6 +1642,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info) ...@@ -1603,6 +1642,7 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info)
return ret; return ret;
} }
/* Called from the userspace PM only */
void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list) void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
{ {
struct mptcp_rm_list alist = { .nr = 0 }; 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) ...@@ -1631,6 +1671,7 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
} }
} }
/* Called from the in-kernel PM only */
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list) struct list_head *rm_list)
{ {
...@@ -1640,11 +1681,11 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, ...@@ -1640,11 +1681,11 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
list_for_each_entry(entry, rm_list, list) { list_for_each_entry(entry, rm_list, list) {
if (slist.nr < MPTCP_RM_IDS_MAX && if (slist.nr < MPTCP_RM_IDS_MAX &&
lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
slist.ids[slist.nr++] = entry->addr.id; slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
if (alist.nr < MPTCP_RM_IDS_MAX && if (alist.nr < MPTCP_RM_IDS_MAX &&
remove_anno_list_by_saddr(msk, &entry->addr)) remove_anno_list_by_saddr(msk, &entry->addr))
alist.ids[alist.nr++] = entry->addr.id; alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
} }
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
...@@ -1941,7 +1982,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, ...@@ -1941,7 +1982,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
{ {
struct mptcp_rm_list list = { .nr = 0 }; struct mptcp_rm_list list = { .nr = 0 };
list.ids[list.nr++] = addr->id; list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
mptcp_pm_nl_rm_subflow_received(msk, &list); mptcp_pm_nl_rm_subflow_received(msk, &list);
......
...@@ -2508,6 +2508,12 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, ...@@ -2508,6 +2508,12 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
void mptcp_close_ssk(struct sock *sk, struct sock *ssk, void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
struct mptcp_subflow_context *subflow) struct mptcp_subflow_context *subflow)
{ {
/* The first subflow can already be closed and still in the list */
if (subflow->close_event_done)
return;
subflow->close_event_done = true;
if (sk->sk_state == TCP_ESTABLISHED) if (sk->sk_state == TCP_ESTABLISHED)
mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL); mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL);
......
...@@ -524,7 +524,8 @@ struct mptcp_subflow_context { ...@@ -524,7 +524,8 @@ struct mptcp_subflow_context {
stale : 1, /* unable to snd/rcv data, do not use for xmit */ stale : 1, /* unable to snd/rcv data, do not use for xmit */
valid_csum_seen : 1, /* at least one csum validated */ valid_csum_seen : 1, /* at least one csum validated */
is_mptfo : 1, /* subflow is doing TFO */ is_mptfo : 1, /* subflow is doing TFO */
__unused : 10; close_event_done : 1, /* has done the post-closed part */
__unused : 9;
bool data_avail; bool data_avail;
bool scheduled; bool scheduled;
u32 remote_nonce; u32 remote_nonce;
...@@ -992,6 +993,8 @@ void mptcp_pm_add_addr_received(const struct sock *ssk, ...@@ -992,6 +993,8 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk, void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr); const struct mptcp_addr_info *addr);
void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk); void mptcp_pm_add_addr_send_ack(struct mptcp_sock *msk);
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *remote);
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk); void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk);
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, void mptcp_pm_rm_addr_received(struct mptcp_sock *msk,
const struct mptcp_rm_list *rm_list); const struct mptcp_rm_list *rm_list);
......
...@@ -420,12 +420,17 @@ reset_with_fail() ...@@ -420,12 +420,17 @@ reset_with_fail()
fi fi
} }
start_events()
{
mptcp_lib_events "${ns1}" "${evts_ns1}" evts_ns1_pid
mptcp_lib_events "${ns2}" "${evts_ns2}" evts_ns2_pid
}
reset_with_events() reset_with_events()
{ {
reset "${1}" || return 1 reset "${1}" || return 1
mptcp_lib_events "${ns1}" "${evts_ns1}" evts_ns1_pid start_events
mptcp_lib_events "${ns2}" "${evts_ns2}" evts_ns2_pid
} }
reset_with_tcp_filter() reset_with_tcp_filter()
...@@ -1112,26 +1117,26 @@ chk_csum_nr() ...@@ -1112,26 +1117,26 @@ chk_csum_nr()
print_check "sum" print_check "sum"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr") count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns1" ]; then if [ -n "$count" ] && [ "$count" != "$csum_ns1" ]; then
extra_msg+=" ns1=$count" extra_msg+=" ns1=$count"
fi fi
if [ -z "$count" ]; then if [ -z "$count" ]; then
print_skip print_skip
elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } || elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then { [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
fail_test "got $count data checksum error[s] expected $csum_ns1" fail_test "got $count data checksum error[s] expected $csum_ns1"
else else
print_ok print_ok
fi fi
print_check "csum" print_check "csum"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr") count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr")
if [ "$count" != "$csum_ns2" ]; then if [ -n "$count" ] && [ "$count" != "$csum_ns2" ]; then
extra_msg+=" ns2=$count" extra_msg+=" ns2=$count"
fi fi
if [ -z "$count" ]; then if [ -z "$count" ]; then
print_skip print_skip
elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } || elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then { [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
fail_test "got $count data checksum error[s] expected $csum_ns2" fail_test "got $count data checksum error[s] expected $csum_ns2"
else else
print_ok print_ok
...@@ -1169,13 +1174,13 @@ chk_fail_nr() ...@@ -1169,13 +1174,13 @@ chk_fail_nr()
print_check "ftx" print_check "ftx"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx") count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx")
if [ "$count" != "$fail_tx" ]; then if [ -n "$count" ] && [ "$count" != "$fail_tx" ]; then
extra_msg+=",tx=$count" extra_msg+=",tx=$count"
fi fi
if [ -z "$count" ]; then if [ -z "$count" ]; then
print_skip print_skip
elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } || elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then { [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
fail_test "got $count MP_FAIL[s] TX expected $fail_tx" fail_test "got $count MP_FAIL[s] TX expected $fail_tx"
else else
print_ok print_ok
...@@ -1183,13 +1188,13 @@ chk_fail_nr() ...@@ -1183,13 +1188,13 @@ chk_fail_nr()
print_check "failrx" print_check "failrx"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx") count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx")
if [ "$count" != "$fail_rx" ]; then if [ -n "$count" ] && [ "$count" != "$fail_rx" ]; then
extra_msg+=",rx=$count" extra_msg+=",rx=$count"
fi fi
if [ -z "$count" ]; then if [ -z "$count" ]; then
print_skip print_skip
elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } || elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then { [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
fail_test "got $count MP_FAIL[s] RX expected $fail_rx" fail_test "got $count MP_FAIL[s] RX expected $fail_rx"
else else
print_ok print_ok
...@@ -3333,6 +3338,36 @@ userspace_pm_chk_get_addr() ...@@ -3333,6 +3338,36 @@ userspace_pm_chk_get_addr()
fi fi
} }
# $1: ns ; $2: event type ; $3: count
chk_evt_nr()
{
local ns=${1}
local evt_name="${2}"
local exp="${3}"
local evts="${evts_ns1}"
local evt="${!evt_name}"
local count
evt_name="${evt_name:16}" # without MPTCP_LIB_EVENT_
[ "${ns}" == "ns2" ] && evts="${evts_ns2}"
print_check "event ${ns} ${evt_name} (${exp})"
if [[ "${evt_name}" = "LISTENER_"* ]] &&
! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
print_skip "event not supported"
return
fi
count=$(grep -cw "type:${evt}" "${evts}")
if [ "${count}" != "${exp}" ]; then
fail_test "got ${count} events, expected ${exp}"
else
print_ok
fi
}
userspace_tests() userspace_tests()
{ {
# userspace pm type prevents add_addr # userspace pm type prevents add_addr
...@@ -3572,27 +3607,29 @@ endpoint_tests() ...@@ -3572,27 +3607,29 @@ endpoint_tests()
if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT && if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT &&
mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 2 start_events
pm_nl_set_limits $ns2 0 2 pm_nl_set_limits $ns1 0 3
pm_nl_set_limits $ns2 0 3
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
test_linkfail=4 speed=20 \ test_linkfail=4 speed=5 \
run_tests $ns1 $ns2 10.0.1.1 & run_tests $ns1 $ns2 10.0.1.1 &
local tests_pid=$! local tests_pid=$!
wait_mpj $ns2 wait_mpj $ns2
pm_nl_check_endpoint "creation" \ pm_nl_check_endpoint "creation" \
$ns2 10.0.2.2 id 2 flags subflow dev ns2eth2 $ns2 10.0.2.2 id 2 flags subflow dev ns2eth2
chk_subflow_nr "before delete" 2 chk_subflow_nr "before delete id 2" 2
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
pm_nl_del_endpoint $ns2 2 10.0.2.2 pm_nl_del_endpoint $ns2 2 10.0.2.2
sleep 0.5 sleep 0.5
chk_subflow_nr "after delete" 1 chk_subflow_nr "after delete id 2" 1
chk_mptcp_info subflows 0 subflows 0 chk_mptcp_info subflows 0 subflows 0
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
wait_mpj $ns2 wait_mpj $ns2
chk_subflow_nr "after re-add" 2 chk_subflow_nr "after re-add id 2" 2
chk_mptcp_info subflows 1 subflows 1 chk_mptcp_info subflows 1 subflows 1
pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow
...@@ -3607,21 +3644,51 @@ endpoint_tests() ...@@ -3607,21 +3644,51 @@ endpoint_tests()
chk_subflow_nr "after no reject" 3 chk_subflow_nr "after no reject" 3
chk_mptcp_info subflows 2 subflows 2 chk_mptcp_info subflows 2 subflows 2
local i
for i in $(seq 3); do
pm_nl_del_endpoint $ns2 1 10.0.1.2
sleep 0.5
chk_subflow_nr "after delete id 0 ($i)" 2
chk_mptcp_info subflows 2 subflows 2 # only decr for additional sf
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
wait_mpj $ns2
chk_subflow_nr "after re-add id 0 ($i)" 3
chk_mptcp_info subflows 3 subflows 3
done
mptcp_lib_kill_wait $tests_pid mptcp_lib_kill_wait $tests_pid
chk_join_nr 3 3 3 kill_events_pids
chk_rm_nr 1 1 chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
chk_evt_nr ns1 MPTCP_LIB_EVENT_CREATED 1
chk_evt_nr ns1 MPTCP_LIB_EVENT_ESTABLISHED 1
chk_evt_nr ns1 MPTCP_LIB_EVENT_ANNOUNCED 0
chk_evt_nr ns1 MPTCP_LIB_EVENT_REMOVED 4
chk_evt_nr ns1 MPTCP_LIB_EVENT_SUB_ESTABLISHED 6
chk_evt_nr ns1 MPTCP_LIB_EVENT_SUB_CLOSED 4
chk_evt_nr ns2 MPTCP_LIB_EVENT_CREATED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ESTABLISHED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ANNOUNCED 0
chk_evt_nr ns2 MPTCP_LIB_EVENT_REMOVED 0
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_ESTABLISHED 6
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 5 # one has been closed before estab
chk_join_nr 6 6 6
chk_rm_nr 4 4
fi fi
# remove and re-add # remove and re-add
if reset "delete re-add signal" && if reset_with_events "delete re-add signal" &&
mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 2 pm_nl_set_limits $ns1 0 3
pm_nl_set_limits $ns2 2 2 pm_nl_set_limits $ns2 3 3
pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal
# broadcast IP: no packet for this address will be received on ns1 # broadcast IP: no packet for this address will be received on ns1
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
test_linkfail=4 speed=20 \ pm_nl_add_endpoint $ns1 10.0.1.1 id 42 flags signal
test_linkfail=4 speed=5 \
run_tests $ns1 $ns2 10.0.1.1 & run_tests $ns1 $ns2 10.0.1.1 &
local tests_pid=$! local tests_pid=$!
...@@ -3642,11 +3709,47 @@ endpoint_tests() ...@@ -3642,11 +3709,47 @@ endpoint_tests()
wait_mpj $ns2 wait_mpj $ns2
chk_subflow_nr "after re-add" 3 chk_subflow_nr "after re-add" 3
chk_mptcp_info subflows 2 subflows 2 chk_mptcp_info subflows 2 subflows 2
pm_nl_del_endpoint $ns1 42 10.0.1.1
sleep 0.5
chk_subflow_nr "after delete ID 0" 2
chk_mptcp_info subflows 2 subflows 2
pm_nl_add_endpoint $ns1 10.0.1.1 id 99 flags signal
wait_mpj $ns2
chk_subflow_nr "after re-add ID 0" 3
chk_mptcp_info subflows 3 subflows 3
pm_nl_del_endpoint $ns1 99 10.0.1.1
sleep 0.5
chk_subflow_nr "after re-delete ID 0" 2
chk_mptcp_info subflows 2 subflows 2
pm_nl_add_endpoint $ns1 10.0.1.1 id 88 flags signal
wait_mpj $ns2
chk_subflow_nr "after re-re-add ID 0" 3
chk_mptcp_info subflows 3 subflows 3
mptcp_lib_kill_wait $tests_pid mptcp_lib_kill_wait $tests_pid
chk_join_nr 3 3 3 kill_events_pids
chk_add_nr 4 4 chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
chk_rm_nr 2 1 invert chk_evt_nr ns1 MPTCP_LIB_EVENT_CREATED 1
chk_evt_nr ns1 MPTCP_LIB_EVENT_ESTABLISHED 1
chk_evt_nr ns1 MPTCP_LIB_EVENT_ANNOUNCED 0
chk_evt_nr ns1 MPTCP_LIB_EVENT_REMOVED 0
chk_evt_nr ns1 MPTCP_LIB_EVENT_SUB_ESTABLISHED 5
chk_evt_nr ns1 MPTCP_LIB_EVENT_SUB_CLOSED 3
chk_evt_nr ns2 MPTCP_LIB_EVENT_CREATED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ESTABLISHED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ANNOUNCED 6
chk_evt_nr ns2 MPTCP_LIB_EVENT_REMOVED 4
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_ESTABLISHED 5
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 3
chk_join_nr 5 5 5
chk_add_nr 6 6
chk_rm_nr 4 3 invert
fi fi
# flush and re-add # flush and re-add
......
...@@ -12,10 +12,14 @@ readonly KSFT_SKIP=4 ...@@ -12,10 +12,14 @@ readonly KSFT_SKIP=4
readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}" readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}"
# These variables are used in some selftests, read-only # These variables are used in some selftests, read-only
declare -rx MPTCP_LIB_EVENT_CREATED=1 # MPTCP_EVENT_CREATED
declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2 # MPTCP_EVENT_ESTABLISHED
declare -rx MPTCP_LIB_EVENT_CLOSED=3 # MPTCP_EVENT_CLOSED
declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED
declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED
declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED
declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13 # MPTCP_EVENT_SUB_PRIORITY
declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED
declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment