Commit 964efdab authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mptcp-advertisement-reliability-improvement-and-misc-updates'

Mat Martineau says:

====================
mptcp: Advertisement reliability improvement and misc. updates

Patch 1 adds a helpful debug tracepoint for outgoing MPTCP packets.

Patch 2 is a small "magic number" refactor.

Patches 3 & 4 refactor parts of the mptcp_join.sh selftest. No change in
test coverage.

Patch 5 ensures only advertised address IDs are un-advertised.

Patches 6-8 improve handling of an edge case where endpoint IDs need to
be created on-the-fly when adding subflows. Includes selftest coverage.

Patch 9 adds validation of the fullmesh flag in a MPTCP netlink command,
which was overlooked when this flag was introduced for 5.18.
====================

Link: https://lore.kernel.org/r/20220307204439.65164-1-mathew.j.martineau@linux.intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d307eab5 0dc626e5
......@@ -115,6 +115,10 @@ DECLARE_EVENT_CLASS(mptcp_dump_mpext,
__entry->csum_reqd)
);
DEFINE_EVENT(mptcp_dump_mpext, mptcp_sendmsg_frag,
TP_PROTO(struct mptcp_ext *mpext),
TP_ARGS(mpext));
DEFINE_EVENT(mptcp_dump_mpext, get_mapping_status,
TP_PROTO(struct mptcp_ext *mpext),
TP_ARGS(mpext));
......
......@@ -81,6 +81,7 @@ enum {
#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
#define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3)
#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4)
enum {
MPTCP_PM_CMD_UNSPEC,
......
......@@ -83,16 +83,6 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
return a->port == b->port;
}
static bool address_zero(const struct mptcp_addr_info *addr)
{
struct mptcp_addr_info zero;
memset(&zero, 0, sizeof(zero));
zero.family = addr->family;
return addresses_equal(addr, &zero, true);
}
static void local_address(const struct sock_common *skc,
struct mptcp_addr_info *addr)
{
......@@ -877,10 +867,18 @@ static bool address_use_port(struct mptcp_pm_addr_entry *entry)
MPTCP_PM_ADDR_FLAG_SIGNAL;
}
/* caller must ensure the RCU grace period is already elapsed */
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
{
if (entry->lsk)
sock_release(entry->lsk);
kfree(entry);
}
static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
struct mptcp_pm_addr_entry *entry)
{
struct mptcp_pm_addr_entry *cur;
struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
unsigned int addr_max;
int ret = -EINVAL;
......@@ -901,8 +899,22 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
list_for_each_entry(cur, &pernet->local_addr_list, list) {
if (addresses_equal(&cur->addr, &entry->addr,
address_use_port(entry) &&
address_use_port(cur)))
goto out;
address_use_port(cur))) {
/* allow replacing the exiting endpoint only if such
* endpoint is an implicit one and the user-space
* did not provide an endpoint id
*/
if (!(cur->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT))
goto out;
if (entry->addr.id)
goto out;
pernet->addrs--;
entry->addr.id = cur->addr.id;
list_del_rcu(&cur->list);
del_entry = cur;
break;
}
}
if (!entry->addr.id) {
......@@ -938,6 +950,12 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
out:
spin_unlock_bh(&pernet->lock);
/* just replaced an existing entry, free it */
if (del_entry) {
synchronize_rcu();
__mptcp_pm_release_addr_entry(del_entry);
}
return ret;
}
......@@ -1011,9 +1029,6 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
if (addresses_equal(&msk_local, &skc_local, false))
return 0;
if (address_zero(&skc_local))
return 0;
pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
rcu_read_lock();
......@@ -1036,7 +1051,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
entry->addr.id = 0;
entry->addr.port = 0;
entry->ifindex = 0;
entry->flags = 0;
entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
entry->lsk = NULL;
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
if (ret < 0)
......@@ -1249,6 +1264,17 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
if (addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
GENL_SET_ERR_MSG(info, "flags mustn't have both signal and fullmesh");
return -EINVAL;
}
if (addr.flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
GENL_SET_ERR_MSG(info, "can't create IMPLICIT endpoint");
return -EINVAL;
}
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
GENL_SET_ERR_MSG(info, "can't allocate addr");
......@@ -1333,11 +1359,12 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
}
static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
struct mptcp_addr_info *addr)
const struct mptcp_pm_addr_entry *entry)
{
struct mptcp_sock *msk;
long s_slot = 0, s_num = 0;
const struct mptcp_addr_info *addr = &entry->addr;
struct mptcp_rm_list list = { .nr = 0 };
long s_slot = 0, s_num = 0;
struct mptcp_sock *msk;
pr_debug("remove_id=%d", addr->id);
......@@ -1354,7 +1381,8 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
lock_sock(sk);
remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
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));
if (remove_subflow)
mptcp_pm_remove_subflow(msk, &list);
release_sock(sk);
......@@ -1367,14 +1395,6 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
return 0;
}
/* caller must ensure the RCU grace period is already elapsed */
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
{
if (entry->lsk)
sock_release(entry->lsk);
kfree(entry);
}
static int mptcp_nl_remove_id_zero_address(struct net *net,
struct mptcp_addr_info *addr)
{
......@@ -1451,7 +1471,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
__clear_bit(entry->addr.id, pernet->id_bitmap);
spin_unlock_bh(&pernet->lock);
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), entry);
synchronize_rcu();
__mptcp_pm_release_addr_entry(entry);
......@@ -1466,14 +1486,12 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
list_for_each_entry(entry, rm_list, list) {
if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
alist.nr < MPTCP_RM_IDS_MAX &&
slist.nr < MPTCP_RM_IDS_MAX) {
alist.ids[alist.nr++] = entry->addr.id;
slist.nr < MPTCP_RM_IDS_MAX)
slist.ids[slist.nr++] = entry->addr.id;
} else if (remove_anno_list_by_saddr(msk, &entry->addr) &&
alist.nr < MPTCP_RM_IDS_MAX) {
if (remove_anno_list_by_saddr(msk, &entry->addr) &&
alist.nr < MPTCP_RM_IDS_MAX)
alist.ids[alist.nr++] = entry->addr.id;
}
}
if (alist.nr) {
......
......@@ -117,6 +117,9 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
list_add(&subflow->node, &msk->conn_list);
sock_hold(ssock->sk);
subflow->request_mptcp = 1;
/* This is the first subflow, always with id 0 */
subflow->local_id_valid = 1;
mptcp_sock_graft(msk->first, sk->sk_socket);
return 0;
......@@ -1356,6 +1359,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
out:
if (READ_ONCE(msk->csum_enabled))
mptcp_update_data_checksum(skb, copy);
trace_mptcp_sendmsg_frag(mpext);
mptcp_subflow_ctx(ssk)->rel_write_seq += copy;
return copy;
}
......
......@@ -442,7 +442,8 @@ struct mptcp_subflow_context {
rx_eof : 1,
can_ack : 1, /* only after processing the remote a key */
disposable : 1, /* ctx can be free at ulp release time */
stale : 1; /* unable to snd/rcv data, do not use for xmit */
stale : 1, /* unable to snd/rcv data, do not use for xmit */
local_id_valid : 1; /* local_id is correctly initialized */
enum mptcp_data_avail data_avail;
u32 remote_nonce;
u64 thmac;
......
......@@ -481,6 +481,51 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
mptcp_subflow_reset(sk);
}
static void subflow_set_local_id(struct mptcp_subflow_context *subflow, int local_id)
{
subflow->local_id = local_id;
subflow->local_id_valid = 1;
}
static int subflow_chk_local_id(struct sock *sk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
int err;
if (likely(subflow->local_id_valid))
return 0;
err = mptcp_pm_get_local_id(msk, (struct sock_common *)sk);
if (err < 0)
return err;
subflow_set_local_id(subflow, err);
return 0;
}
static int subflow_rebuild_header(struct sock *sk)
{
int err = subflow_chk_local_id(sk);
if (unlikely(err < 0))
return err;
return inet_sk_rebuild_header(sk);
}
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
static int subflow_v6_rebuild_header(struct sock *sk)
{
int err = subflow_chk_local_id(sk);
if (unlikely(err < 0))
return err;
return inet6_sk_rebuild_header(sk);
}
#endif
struct request_sock_ops mptcp_subflow_request_sock_ops;
static struct tcp_request_sock_ops subflow_request_sock_ipv4_ops __ro_after_init;
......@@ -1104,7 +1149,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
struct sk_buff *skb;
if (!skb_peek(&ssk->sk_receive_queue))
WRITE_ONCE(subflow->data_avail, 0);
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
if (subflow->data_avail)
return true;
......@@ -1169,7 +1214,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
subflow->reset_transient = 0;
subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
tcp_send_active_reset(ssk, GFP_ATOMIC);
WRITE_ONCE(subflow->data_avail, 0);
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
return true;
}
......@@ -1182,7 +1227,7 @@ static bool subflow_check_data_avail(struct sock *ssk)
subflow->reset_transient = 0;
subflow->reset_reason = MPTCP_RST_EMPTCP;
tcp_send_active_reset(ssk, GFP_ATOMIC);
WRITE_ONCE(subflow->data_avail, 0);
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
return false;
}
......@@ -1204,7 +1249,7 @@ bool mptcp_subflow_data_available(struct sock *sk)
if (subflow->map_valid &&
mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) {
subflow->map_valid = 0;
WRITE_ONCE(subflow->data_avail, 0);
WRITE_ONCE(subflow->data_avail, MPTCP_SUBFLOW_NODATA);
pr_debug("Done with mapping: seq=%u data_len=%u",
subflow->map_subflow_seq,
......@@ -1398,13 +1443,8 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
get_random_bytes(&subflow->local_nonce, sizeof(u32));
} while (!subflow->local_nonce);
if (!local_id) {
err = mptcp_pm_get_local_id(msk, (struct sock_common *)ssk);
if (err < 0)
goto failed;
local_id = err;
}
if (local_id)
subflow_set_local_id(subflow, local_id);
mptcp_pm_get_flags_and_ifindex_by_id(sock_net(sk), local_id,
&flags, &ifindex);
......@@ -1429,7 +1469,6 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk,
remote_token, local_id, remote_id);
subflow->remote_token = remote_token;
subflow->local_id = local_id;
subflow->remote_id = remote_id;
subflow->request_join = 1;
subflow->request_bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
......@@ -1728,15 +1767,22 @@ static void subflow_ulp_clone(const struct request_sock *req,
new_ctx->token = subflow_req->token;
new_ctx->ssn_offset = subflow_req->ssn_offset;
new_ctx->idsn = subflow_req->idsn;
/* this is the first subflow, id is always 0 */
new_ctx->local_id_valid = 1;
} else if (subflow_req->mp_join) {
new_ctx->ssn_offset = subflow_req->ssn_offset;
new_ctx->mp_join = 1;
new_ctx->fully_established = 1;
new_ctx->backup = subflow_req->backup;
new_ctx->local_id = subflow_req->local_id;
new_ctx->remote_id = subflow_req->remote_id;
new_ctx->token = subflow_req->token;
new_ctx->thmac = subflow_req->thmac;
/* the subflow req id is valid, fetched via subflow_check_req()
* and subflow_token_join_request()
*/
subflow_set_local_id(new_ctx, subflow_req->local_id);
}
}
......@@ -1789,6 +1835,7 @@ void __init mptcp_subflow_init(void)
subflow_specific.conn_request = subflow_v4_conn_request;
subflow_specific.syn_recv_sock = subflow_syn_recv_sock;
subflow_specific.sk_rx_dst_set = subflow_finish_connect;
subflow_specific.rebuild_header = subflow_rebuild_header;
tcp_prot_override = tcp_prot;
tcp_prot_override.release_cb = tcp_release_cb_override;
......@@ -1801,6 +1848,7 @@ void __init mptcp_subflow_init(void)
subflow_v6_specific.conn_request = subflow_v6_conn_request;
subflow_v6_specific.syn_recv_sock = subflow_syn_recv_sock;
subflow_v6_specific.sk_rx_dst_set = subflow_finish_connect;
subflow_v6_specific.rebuild_header = subflow_v6_rebuild_header;
subflow_v6m_specific = subflow_v6_specific;
subflow_v6m_specific.queue_xmit = ipv4_specific.queue_xmit;
......@@ -1808,6 +1856,7 @@ void __init mptcp_subflow_init(void)
subflow_v6m_specific.net_header_len = ipv4_specific.net_header_len;
subflow_v6m_specific.mtu_reduced = ipv4_specific.mtu_reduced;
subflow_v6m_specific.net_frag_header_len = 0;
subflow_v6m_specific.rebuild_header = subflow_rebuild_header;
tcpv6_prot_override = tcpv6_prot;
tcpv6_prot_override.release_cb = tcp_release_cb_override;
......
......@@ -16,7 +16,6 @@ capture=0
checksum=0
ip_mptcp=0
check_invert=0
do_all_tests=1
init=0
TEST_COUNT=0
......@@ -311,6 +310,21 @@ wait_rm_addr()
done
}
wait_mpj()
{
local ns="${1}"
local cnt old_cnt
old_cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
local i
for i in $(seq 10); do
cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
[ "$cnt" = "${old_cnt}" ] || break
sleep 0.1
done
}
pm_nl_set_limits()
{
local ns=$1
......@@ -411,6 +425,80 @@ pm_nl_change_endpoint()
fi
}
pm_nl_check_endpoint()
{
local line expected_line
local title="$1"
local msg="$2"
local ns=$3
local addr=$4
local _flags=""
local flags
local _port
local port
local dev
local _id
local id
if [ -n "${title}" ]; then
printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "${msg}"
else
printf "%-${nr_blank}s %s" " " "${msg}"
fi
shift 4
while [ -n "$1" ]; do
if [ $1 = "flags" ]; then
_flags=$2
[ ! -z $_flags ]; flags="flags $_flags"
shift
elif [ $1 = "dev" ]; then
[ ! -z $2 ]; dev="dev $1"
shift
elif [ $1 = "id" ]; then
_id=$2
[ ! -z $_id ]; id="id $_id"
shift
elif [ $1 = "port" ]; then
_port=$2
[ ! -z $_port ]; port=" port $_port"
shift
fi
shift
done
if [ -z "$id" ]; then
echo "[skip] bad test - missing endpoint id"
return
fi
if [ $ip_mptcp -eq 1 ]; then
line=$(ip -n $ns mptcp endpoint show $id)
# the dump order is: address id flags port dev
expected_line="$addr"
[ -n "$addr" ] && expected_line="$expected_line $addr"
expected_line="$expected_line $id"
[ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
[ -n "$dev" ] && expected_line="$expected_line $dev"
[ -n "$port" ] && expected_line="$expected_line $port"
else
line=$(ip netns exec $ns ./pm_nl_ctl get $_id)
# the dump order is: id flags dev address port
expected_line="$id"
[ -n "$flags" ] && expected_line="$expected_line $flags"
[ -n "$dev" ] && expected_line="$expected_line $dev"
[ -n "$addr" ] && expected_line="$expected_line $addr"
[ -n "$_port" ] && expected_line="$expected_line $_port"
fi
if [ "$line" = "$expected_line" ]; then
echo "[ ok ]"
else
echo "[fail] expected '$expected_line' found '$line'"
ret=1
fi
}
do_transfer()
{
listener_ns="$1"
......@@ -1150,14 +1238,25 @@ chk_rm_nr()
{
local rm_addr_nr=$1
local rm_subflow_nr=$2
local invert=${3:-""}
local invert
local simult
local count
local dump_stats
local addr_ns=$ns1
local subflow_ns=$ns2
local extra_msg=""
if [[ $invert = "invert" ]]; then
shift 2
while [ -n "$1" ]; do
[ "$1" = "invert" ] && invert=true
[ "$1" = "simult" ] && simult=true
shift
done
if [ -z $invert ]; then
addr_ns=$ns1
subflow_ns=$ns2
elif [ $invert = "true" ]; then
addr_ns=$ns2
subflow_ns=$ns1
extra_msg=" invert"
......@@ -1177,6 +1276,25 @@ chk_rm_nr()
echo -n " - rmsf "
count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
[ -z "$count" ] && count=0
if [ -n "$simult" ]; then
local cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
local suffix
# in case of simult flush, the subflow removal count on each side is
# unreliable
[ -z "$cnt" ] && cnt=0
count=$((count + cnt))
[ "$count" != "$rm_subflow_nr" ] && suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
if [ $count -ge "$rm_subflow_nr" ] && \
[ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
echo "[ ok ] $suffix"
else
echo "[fail] got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]"
ret=1
dump_stats=1
fi
return
fi
if [ "$count" != "$rm_subflow_nr" ]; then
echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
ret=1
......@@ -1243,7 +1361,7 @@ chk_link_usage()
fi
}
wait_for_tw()
wait_attempt_fail()
{
local timeout_ms=$((timeout_poll * 1000))
local time=0
......@@ -1362,7 +1480,7 @@ subflows_error_tests()
TEST_COUNT=$((TEST_COUNT+1))
# mpj subflow will be in TW after the reset
wait_for_tw $ns2
wait_attempt_fail $ns2
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
wait
......@@ -1667,7 +1785,7 @@ remove_tests()
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr "flush subflows and signal" 3 3 3
chk_add_nr 1 1
chk_rm_nr 2 2
chk_rm_nr 1 3 invert simult
# subflows flush
reset
......@@ -1678,7 +1796,7 @@ remove_tests()
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr "flush subflows" 3 3 3
chk_rm_nr 3 3
chk_rm_nr 0 3 simult
# addresses flush
reset
......@@ -1690,7 +1808,7 @@ remove_tests()
run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
chk_join_nr "flush addresses" 3 3 3
chk_add_nr 3 3
chk_rm_nr 3 3 invert
chk_rm_nr 3 3 invert simult
# invalid addresses flush
reset
......@@ -1909,7 +2027,7 @@ backup_tests()
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
chk_join_nr "single address, backup" 1 1 1
chk_add_nr 1 1
chk_prio_nr 1 0
chk_prio_nr 1 1
# single address with port, backup
reset
......@@ -1919,7 +2037,7 @@ backup_tests()
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
chk_join_nr "single address with port, backup" 1 1 1
chk_add_nr 1 1
chk_prio_nr 1 0
chk_prio_nr 1 1
}
add_addr_ports_tests()
......@@ -1974,7 +2092,7 @@ add_addr_ports_tests()
run_tests $ns1 $ns2 10.0.1.1 0 -8 -2 slow
chk_join_nr "flush subflows and signal with port" 3 3 3
chk_add_nr 1 1
chk_rm_nr 2 2
chk_rm_nr 1 3 invert simult
# multiple addresses with port
reset
......@@ -2240,6 +2358,30 @@ fastclose_tests()
chk_rst_nr 1 1 invert
}
implicit_tests()
{
# userspace pm type prevents add_addr
reset
pm_nl_set_limits $ns1 2 2
pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
wait_mpj $ns1
TEST_COUNT=$((TEST_COUNT + 1))
pm_nl_check_endpoint "implicit EP" "creation" \
$ns2 10.0.2.2 id 1 flags implicit
pm_nl_add_endpoint $ns2 10.0.2.2 id 33
pm_nl_check_endpoint "" "ID change is prevented" \
$ns2 10.0.2.2 id 1 flags implicit
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
pm_nl_check_endpoint "" "modif is allowed" \
$ns2 10.0.2.2 id 1 flags signal
wait
}
all_tests()
{
subflows_tests
......@@ -2258,6 +2400,7 @@ all_tests()
deny_join_id0_tests
fullmesh_tests
fastclose_tests
implicit_tests
}
# [$1: error message]
......@@ -2285,6 +2428,7 @@ usage()
echo " -d deny_join_id0_tests"
echo " -m fullmesh_tests"
echo " -z fastclose_tests"
echo " -I implicit_tests"
echo " -c capture pcap files"
echo " -C enable data checksum"
echo " -i use ip mptcp"
......@@ -2293,84 +2437,69 @@ usage()
exit ${ret}
}
for arg in "$@"; do
# check for "capture/checksum" args before launching tests
if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"c"[0-9a-zA-Z]*$ ]]; then
capture=1
fi
if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"C"[0-9a-zA-Z]*$ ]]; then
checksum=1
fi
if [[ "${arg}" =~ ^"-"[0-9a-zA-Z]*"i"[0-9a-zA-Z]*$ ]]; then
ip_mptcp=1
fi
# exception for the capture/checksum/ip_mptcp options, the rest means: a part of the tests
if [ "${arg}" != "-c" ] && [ "${arg}" != "-C" ] && [ "${arg}" != "-i" ]; then
do_all_tests=0
fi
done
if [ $do_all_tests -eq 1 ]; then
all_tests
exit $ret
fi
while getopts 'fesltra64bpkdmchzCSi' opt; do
tests=()
while getopts 'fesltra64bpkdmchzICSi' opt; do
case $opt in
f)
subflows_tests
tests+=(subflows_tests)
;;
e)
subflows_error_tests
tests+=(subflows_error_tests)
;;
s)
signal_address_tests
tests+=(signal_address_tests)
;;
l)
link_failure_tests
tests+=(link_failure_tests)
;;
t)
add_addr_timeout_tests
tests+=(add_addr_timeout_tests)
;;
r)
remove_tests
tests+=(remove_tests)
;;
a)
add_tests
tests+=(add_tests)
;;
6)
ipv6_tests
tests+=(ipv6_tests)
;;
4)
v4mapped_tests
tests+=(v4mapped_tests)
;;
b)
backup_tests
tests+=(backup_tests)
;;
p)
add_addr_ports_tests
tests+=(add_addr_ports_tests)
;;
k)
syncookies_tests
tests+=(syncookies_tests)
;;
S)
checksum_tests
tests+=(checksum_tests)
;;
d)
deny_join_id0_tests
tests+=(deny_join_id0_tests)
;;
m)
fullmesh_tests
tests+=(fullmesh_tests)
;;
z)
fastclose_tests
tests+=(fastclose_tests)
;;
I)
tests+=(implicit_tests)
;;
c)
capture=1
;;
C)
checksum=1
;;
i)
ip_mptcp=1
;;
h)
usage
......@@ -2381,4 +2510,12 @@ while getopts 'fesltra64bpkdmchzCSi' opt; do
esac
done
if [ ${#tests[@]} -eq 0 ]; then
all_tests
else
for subtests in "${tests[@]}"; do
"${subtests}"
done
fi
exit $ret
......@@ -436,6 +436,13 @@ static void print_addr(struct rtattr *attrs, int len)
printf(",");
}
if (flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
printf("implicit");
flags &= ~MPTCP_PM_ADDR_FLAG_IMPLICIT;
if (flags)
printf(",");
}
/* bump unknown flags, if any */
if (flags)
printf("0x%x", flags);
......
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