aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/net/mptcp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/testing/selftests/net/mptcp/Makefile5
-rw-r--r--tools/testing/selftests/net/mptcp/config8
-rwxr-xr-xtools/testing/selftests/net/mptcp/diag.sh126
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_connect.c93
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_connect.sh23
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_inq.c2
-rwxr-xr-xtools/testing/selftests/net/mptcp/mptcp_join.sh3228
-rw-r--r--tools/testing/selftests/net/mptcp/mptcp_sockopt.c2
-rwxr-xr-xtools/testing/selftests/net/mptcp/pm_netlink.sh18
-rw-r--r--tools/testing/selftests/net/mptcp/pm_nl_ctl.c806
-rw-r--r--tools/testing/selftests/net/mptcp/settings2
-rwxr-xr-xtools/testing/selftests/net/mptcp/simult_flows.sh14
-rwxr-xr-xtools/testing/selftests/net/mptcp/userspace_pm.sh817
13 files changed, 4014 insertions, 1130 deletions
diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
index 0356c4501c99..43a723626126 100644
--- a/tools/testing/selftests/net/mptcp/Makefile
+++ b/tools/testing/selftests/net/mptcp/Makefile
@@ -1,12 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
top_srcdir = ../../../../..
-KSFT_KHDR_INSTALL := 1
-CFLAGS = -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include
+CFLAGS = -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES)
TEST_PROGS := mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \
- simult_flows.sh mptcp_sockopt.sh
+ simult_flows.sh mptcp_sockopt.sh userspace_pm.sh
TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index d36b7da5082a..38021a0dd527 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -12,6 +12,9 @@ CONFIG_NF_TABLES=m
CONFIG_NFT_COMPAT=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_TPROXY=m
CONFIG_NFT_SOCKET=m
@@ -19,3 +22,8 @@ CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_SCH_INGRESS=m
diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh
index 2674ba20d524..515859a5168b 100755
--- a/tools/testing/selftests/net/mptcp/diag.sh
+++ b/tools/testing/selftests/net/mptcp/diag.sh
@@ -61,6 +61,39 @@ chk_msk_nr()
__chk_nr "grep -c token:" $*
}
+wait_msk_nr()
+{
+ local condition="grep -c token:"
+ local expected=$1
+ local timeout=20
+ local msg nr
+ local max=0
+ local i=0
+
+ shift 1
+ msg=$*
+
+ while [ $i -lt $timeout ]; do
+ nr=$(ss -inmHMN $ns | $condition)
+ [ $nr == $expected ] && break;
+ [ $nr -gt $max ] && max=$nr
+ i=$((i + 1))
+ sleep 1
+ done
+
+ printf "%-50s" "$msg"
+ if [ $i -ge $timeout ]; then
+ echo "[ fail ] timeout while expecting $expected max $max last $nr"
+ ret=$test_cnt
+ elif [ $nr != $expected ]; then
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ else
+ echo "[ ok ]"
+ fi
+ test_cnt=$((test_cnt+1))
+}
+
chk_msk_fallback_nr()
{
__chk_nr "grep -c fallback" $*
@@ -71,6 +104,73 @@ chk_msk_remote_key_nr()
__chk_nr "grep -c remote_key" $*
}
+__chk_listen()
+{
+ local filter="$1"
+ local expected=$2
+
+ shift 2
+ msg=$*
+
+ nr=$(ss -N $ns -Ml "$filter" | grep -c LISTEN)
+ printf "%-50s" "$msg"
+
+ if [ $nr != $expected ]; then
+ echo "[ fail ] expected $expected found $nr"
+ ret=$test_cnt
+ else
+ echo "[ ok ]"
+ fi
+}
+
+chk_msk_listen()
+{
+ lport=$1
+ local msg="check for listen socket"
+
+ # destination port search should always return empty list
+ __chk_listen "dport $lport" 0 "listen match for dport $lport"
+
+ # should return 'our' mptcp listen socket
+ __chk_listen "sport $lport" 1 "listen match for sport $lport"
+
+ __chk_listen "src inet:0.0.0.0:$lport" 1 "listen match for saddr and sport"
+
+ __chk_listen "" 1 "all listen sockets"
+
+ nr=$(ss -Ml $filter | wc -l)
+}
+
+# $1: ns, $2: port
+wait_local_port_listen()
+{
+ local listener_ns="${1}"
+ local port="${2}"
+
+ local port_hex i
+
+ port_hex="$(printf "%04X" "${port}")"
+ for i in $(seq 10); do
+ ip netns exec "${listener_ns}" cat /proc/net/tcp | \
+ awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
+ break
+ sleep 0.1
+ done
+}
+
+wait_connected()
+{
+ local listener_ns="${1}"
+ local port="${2}"
+
+ local port_hex i
+
+ port_hex="$(printf "%04X" "${port}")"
+ for i in $(seq 10); do
+ ip netns exec ${listener_ns} grep -q " 0100007F:${port_hex} " /proc/net/tcp && break
+ sleep 0.1
+ done
+}
trap cleanup EXIT
ip netns add $ns
@@ -79,17 +179,18 @@ ip -n $ns link set dev lo up
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -l -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
-sleep 0.1
+wait_local_port_listen $ns 10000
chk_msk_nr 0 "no msk on netns creation"
+chk_msk_listen 10000
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10000 -j -t ${timeout_poll} \
+ ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
-sleep 0.1
+wait_connected $ns 10000
chk_msk_nr 2 "after MPC handshake "
chk_msk_remote_key_nr 2 "....chk remote_key"
chk_msk_fallback_nr 0 "....chk no fallback"
@@ -99,15 +200,15 @@ flush_pids
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
-sleep 0.1
+wait_local_port_listen $ns 10001
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p 10001 -j -t ${timeout_poll} \
+ ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \
127.0.0.1 >/dev/null &
-sleep 0.1
+wait_connected $ns 10001
chk_msk_fallback_nr 1 "check fallback"
flush_pids
@@ -116,21 +217,20 @@ for I in `seq 1 $NR_CLIENTS`; do
echo "a" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -l -w 10 \
+ ./mptcp_connect -p $((I+10001)) -l -w 20 \
-t ${timeout_poll} 0.0.0.0 >/dev/null &
done
-sleep 0.1
+wait_local_port_listen $ns $((NR_CLIENTS + 10001))
for I in `seq 1 $NR_CLIENTS`; do
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
- ./mptcp_connect -p $((I+10001)) -w 10 \
+ ./mptcp_connect -p $((I+10001)) -w 20 \
-t ${timeout_poll} 127.0.0.1 >/dev/null &
done
-sleep 1.5
-chk_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
+wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
flush_pids
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index 8628aa61b763..e54653ea2ed4 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -72,6 +72,8 @@ static int cfg_wait;
static uint32_t cfg_mark;
static char *cfg_input;
static int cfg_repeat = 1;
+static int cfg_truncate;
+static int cfg_rcv_trunc;
struct cfg_cmsg_types {
unsigned int cmsg_enabled:1;
@@ -95,11 +97,15 @@ static struct cfg_sockopt_types cfg_sockopt_types;
static void die_usage(void)
{
- fprintf(stderr, "Usage: mptcp_connect [-6] [-c cmsg] [-i file] [-I num] [-j] [-l] "
+ fprintf(stderr, "Usage: mptcp_connect [-6] [-c cmsg] [-f offset] [-i file] [-I num] [-j] [-l] "
"[-m mode] [-M mark] [-o option] [-p port] [-P mode] [-j] [-l] [-r num] "
"[-s MPTCP|TCP] [-S num] [-r num] [-t num] [-T num] [-u] [-w sec] connect_address\n");
fprintf(stderr, "\t-6 use ipv6\n");
fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
+ fprintf(stderr, "\t-f offset -- stop the I/O after receiving and sending the specified amount "
+ "of bytes. If there are unread bytes in the receive queue, that will cause a MPTCP "
+ "fastclose at close/shutdown. If offset is negative, expect the peer to close before "
+ "all the local data as been sent, thus toleration errors on write and EPIPE signals\n");
fprintf(stderr, "\t-i file -- read the data to send from the given file instead of stdin");
fprintf(stderr, "\t-I num -- repeat the transfer 'num' times. In listen mode accepts num "
"incoming connections, in client mode, disconnect and reconnect to the server\n");
@@ -265,7 +271,7 @@ static void sock_test_tcpulp(int sock, int proto, unsigned int line)
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
@@ -382,7 +388,7 @@ static size_t do_rnd_write(const int fd, char *buf, const size_t len)
bw = write(fd, buf, do_w);
if (bw < 0)
- perror("write");
+ return bw;
/* let the join handshake complete, before going on */
if (cfg_join && first) {
@@ -553,13 +559,25 @@ static void set_nonblock(int fd, bool nonblock)
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
}
+static void shut_wr(int fd)
+{
+ /* Close our write side, ev. give some time
+ * for address notification and/or checking
+ * the current status
+ */
+ if (cfg_wait)
+ usleep(cfg_wait);
+
+ shutdown(fd, SHUT_WR);
+}
+
static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
{
struct pollfd fds = {
.fd = peerfd,
.events = POLLIN | POLLOUT,
};
- unsigned int woff = 0, wlen = 0;
+ unsigned int woff = 0, wlen = 0, total_wlen = 0, total_rlen = 0;
char wbuf[8192];
set_nonblock(peerfd, true);
@@ -585,7 +603,16 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
}
if (fds.revents & POLLIN) {
- len = do_rnd_read(peerfd, rbuf, sizeof(rbuf));
+ ssize_t rb = sizeof(rbuf);
+
+ /* limit the total amount of read data to the trunc value*/
+ if (cfg_truncate > 0) {
+ if (rb + total_rlen > cfg_truncate)
+ rb = cfg_truncate - total_rlen;
+ len = read(peerfd, rbuf, rb);
+ } else {
+ len = do_rnd_read(peerfd, rbuf, sizeof(rbuf));
+ }
if (len == 0) {
/* no more data to receive:
* peer has closed its write side
@@ -600,10 +627,13 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
/* Else, still have data to transmit */
} else if (len < 0) {
+ if (cfg_rcv_trunc)
+ return 0;
perror("read");
return 3;
}
+ total_rlen += len;
do_write(outfd, rbuf, len);
}
@@ -616,12 +646,21 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
if (wlen > 0) {
ssize_t bw;
+ /* limit the total amount of written data to the trunc value */
+ if (cfg_truncate > 0 && wlen + total_wlen > cfg_truncate)
+ wlen = cfg_truncate - total_wlen;
+
bw = do_rnd_write(peerfd, wbuf + woff, wlen);
- if (bw < 0)
+ if (bw < 0) {
+ if (cfg_rcv_trunc)
+ return 0;
+ perror("write");
return 111;
+ }
woff += bw;
wlen -= bw;
+ total_wlen += bw;
} else if (wlen == 0) {
/* We have no more data to send. */
fds.events &= ~POLLOUT;
@@ -630,14 +669,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
/* ... and peer also closed already */
break;
- /* ... but we still receive.
- * Close our write side, ev. give some time
- * for address notification and/or checking
- * the current status
- */
- if (cfg_wait)
- usleep(cfg_wait);
- shutdown(peerfd, SHUT_WR);
+ shut_wr(peerfd);
} else {
if (errno == EINTR)
continue;
@@ -647,10 +679,16 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after
}
if (fds.revents & (POLLERR | POLLNVAL)) {
+ if (cfg_rcv_trunc)
+ return 0;
fprintf(stderr, "Unexpected revents: "
"POLLERR/POLLNVAL(%x)\n", fds.revents);
return 5;
}
+
+ if (cfg_truncate > 0 && total_wlen >= cfg_truncate &&
+ total_rlen >= cfg_truncate)
+ break;
}
/* leave some time for late join/announce */
@@ -767,7 +805,7 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd,
if (err)
return err;
- shutdown(peerfd, SHUT_WR);
+ shut_wr(peerfd);
err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
@@ -791,6 +829,9 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
err = do_sendfile(infd, peerfd, size);
if (err)
return err;
+
+ shut_wr(peerfd);
+
err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
}
@@ -1152,11 +1193,13 @@ again:
}
/* close the client socket open only if we are not going to reconnect */
- ret = copyfd_io(fd_in, fd, 1, cfg_repeat == 1);
+ ret = copyfd_io(fd_in, fd, 1, 0);
if (ret)
return ret;
- if (--cfg_repeat > 0) {
+ if (cfg_truncate > 0) {
+ xdisconnect(fd, peer->ai_addrlen);
+ } else if (--cfg_repeat > 0) {
xdisconnect(fd, peer->ai_addrlen);
/* the socket could be unblocking at this point, we need the
@@ -1168,7 +1211,10 @@ again:
if (cfg_input)
close(fd_in);
goto again;
+ } else {
+ close(fd);
}
+
return 0;
}
@@ -1254,8 +1300,19 @@ static void parse_opts(int argc, char **argv)
{
int c;
- while ((c = getopt(argc, argv, "6c:hi:I:jlm:M:o:p:P:r:R:s:S:t:T:w:")) != -1) {
+ while ((c = getopt(argc, argv, "6c:f:hi:I:jlm:M:o:p:P:r:R:s:S:t:T:w:")) != -1) {
switch (c) {
+ case 'f':
+ cfg_truncate = atoi(optarg);
+
+ /* when receiving a fastclose, ignore PIPE signals and
+ * all the I/O errors later in the code
+ */
+ if (cfg_truncate < 0) {
+ cfg_rcv_trunc = true;
+ signal(SIGPIPE, handle_signal);
+ }
+ break;
case 'j':
cfg_join = true;
cfg_mode = CFG_MODE_POLL;
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
index cb5809b89081..621af6895f4d 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
@@ -432,6 +432,8 @@ do_transfer()
local stat_ackrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent")
local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv")
+ local stat_csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
+ local stat_csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
@@ -524,6 +526,23 @@ do_transfer()
fi
fi
+ if $checksum; then
+ local csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
+ local csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
+
+ local csum_err_s_nr=$((csum_err_s - stat_csum_err_s))
+ if [ $csum_err_s_nr -gt 0 ]; then
+ printf "[ FAIL ]\nserver got $csum_err_s_nr data checksum error[s]"
+ rets=1
+ fi
+
+ local csum_err_c_nr=$((csum_err_c - stat_csum_err_c))
+ if [ $csum_err_c_nr -gt 0 ]; then
+ printf "[ FAIL ]\nclient got $csum_err_c_nr data checksum error[s]"
+ retc=1
+ fi
+ fi
+
if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then
printf "[ OK ]"
fi
@@ -763,8 +782,8 @@ run_tests_disconnect()
run_tests_lo "$ns1" "$ns1" dead:beef:1::1 1 "-I 3 -i $old_cin"
# restore previous status
- cout=$old_cout
- cout_disconnect="$cout".disconnect
+ sin=$old_sin
+ sin_disconnect="$cout".disconnect
cin=$old_cin
cin_disconnect="$cin".disconnect
connect_per_transfer=1
diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
index 29f75e2a1116..8672d898f8cd 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c
@@ -88,7 +88,7 @@ static void xgetaddrinfo(const char *node, const char *service,
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 27d0eb9afdca..f3dd5f2a0272 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -1,6 +1,11 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
+# Double quotes to prevent globbing and word splitting is recommended in new
+# code but we accept it, especially because there were too many before having
+# address all other issues detected by shellcheck.
+#shellcheck disable=SC2086
+
ret=0
sin=""
sinfail=""
@@ -9,15 +14,28 @@ cin=""
cinfail=""
cinsent=""
cout=""
+capout=""
+ns1=""
+ns2=""
ksft_skip=4
timeout_poll=30
timeout_test=$((timeout_poll * 2 + 1))
-mptcp_connect=""
capture=0
checksum=0
-do_all_tests=1
-
+ip_mptcp=0
+check_invert=0
+validate_checksum=0
+init=0
+
+declare -A all_tests
+declare -a only_tests_ids
+declare -a only_tests_names
+declare -A failed_tests
TEST_COUNT=0
+TEST_NAME=""
+nr_blank=40
+
+export FAILING_LINKS=""
# generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x30) ||
# (ip6 && (ip6[74] & 0xf0) == 0x30)'"
@@ -37,19 +55,22 @@ CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
6 0 0 65535,
6 0 0 0"
-init()
+init_partial()
{
capout=$(mktemp)
- rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
+ local rndh
+ rndh=$(mktemp -u XXXXXX)
ns1="ns1-$rndh"
ns2="ns2-$rndh"
- for netns in "$ns1" "$ns2";do
+ local netns
+ for netns in "$ns1" "$ns2"; do
ip netns add $netns || exit $ksft_skip
ip -net $netns link set lo up
ip netns exec $netns sysctl -q net.mptcp.enabled=1
+ ip netns exec $netns sysctl -q net.mptcp.pm_type=0
ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
if [ $checksum -eq 1 ]; then
@@ -57,13 +78,18 @@ init()
fi
done
- # ns1 ns2
+ check_invert=0
+ validate_checksum=$checksum
+ FAILING_LINKS=""
+
+ # ns1 ns2
# ns1eth1 ns2eth1
# ns1eth2 ns2eth2
# ns1eth3 ns2eth3
# ns1eth4 ns2eth4
- for i in `seq 1 4`; do
+ local i
+ for i in $(seq 1 4); do
ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"
ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i
ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad
@@ -75,12 +101,14 @@ init()
# let $ns2 reach any $ns1 address from any interface
ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i
+ ip -net "$ns2" route add default via dead:beef:$i::1 dev ns2eth$i metric 10$i
done
}
init_shapers()
{
- for i in `seq 1 4`; do
+ local i
+ for i in $(seq 1 4); do
tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1
tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1
done
@@ -90,12 +118,48 @@ cleanup_partial()
{
rm -f "$capout"
+ local netns
for netns in "$ns1" "$ns2"; do
ip netns del $netns
rm -f /tmp/$netns.{nstat,out}
done
}
+check_tools()
+{
+ if ! ip -Version &> /dev/null; then
+ echo "SKIP: Could not run test without ip tool"
+ exit $ksft_skip
+ fi
+
+ if ! iptables -V &> /dev/null; then
+ echo "SKIP: Could not run all tests without iptables tool"
+ exit $ksft_skip
+ fi
+
+ if ! ip6tables -V &> /dev/null; then
+ echo "SKIP: Could not run all tests without ip6tables tool"
+ exit $ksft_skip
+ fi
+}
+
+init() {
+ init=1
+
+ check_tools
+
+ sin=$(mktemp)
+ sout=$(mktemp)
+ cin=$(mktemp)
+ cinsent=$(mktemp)
+ cout=$(mktemp)
+
+ trap cleanup EXIT
+
+ make_file "$cin" "client" 1
+ make_file "$sin" "server" 1
+}
+
cleanup()
{
rm -f "$cin" "$cout" "$sinfail"
@@ -103,33 +167,73 @@ cleanup()
cleanup_partial
}
+skip_test()
+{
+ if [ "${#only_tests_ids[@]}" -eq 0 ] && [ "${#only_tests_names[@]}" -eq 0 ]; then
+ return 1
+ fi
+
+ local i
+ for i in "${only_tests_ids[@]}"; do
+ if [ "${TEST_COUNT}" -eq "${i}" ]; then
+ return 1
+ fi
+ done
+ for i in "${only_tests_names[@]}"; do
+ if [ "${TEST_NAME}" = "${i}" ]; then
+ return 1
+ fi
+ done
+
+ return 0
+}
+
+# $1: test name
reset()
{
- cleanup_partial
- init
+ TEST_NAME="${1}"
+
+ TEST_COUNT=$((TEST_COUNT+1))
+
+ if skip_test; then
+ return 1
+ fi
+
+ if [ "${init}" != "1" ]; then
+ init
+ else
+ cleanup_partial
+ fi
+
+ init_partial
+
+ return 0
}
+# $1: test name
reset_with_cookies()
{
- reset
+ reset "${1}" || return 1
- for netns in "$ns1" "$ns2";do
+ local netns
+ for netns in "$ns1" "$ns2"; do
ip netns exec $netns sysctl -q net.ipv4.tcp_syncookies=2
done
}
+# $1: test name
reset_with_add_addr_timeout()
{
- local ip="${1:-4}"
+ local ip="${2:-4}"
local tables
+ reset "${1}" || return 1
+
tables="iptables"
if [ $ip -eq 6 ]; then
tables="ip6tables"
fi
- reset
-
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
ip netns exec $ns2 $tables -A OUTPUT -p tcp \
-m tcp --tcp-option 30 \
@@ -138,45 +242,97 @@ reset_with_add_addr_timeout()
-j DROP
}
+# $1: test name
reset_with_checksum()
{
local ns1_enable=$1
local ns2_enable=$2
- reset
+ reset "checksum test ${1} ${2}" || return 1
ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=$ns1_enable
ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=$ns2_enable
+
+ validate_checksum=1
}
reset_with_allow_join_id0()
{
- local ns1_enable=$1
- local ns2_enable=$2
+ local ns1_enable=$2
+ local ns2_enable=$3
- reset
+ reset "${1}" || return 1
ip netns exec $ns1 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns1_enable
ip netns exec $ns2 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns2_enable
}
-ip -Version > /dev/null 2>&1
-if [ $? -ne 0 ];then
- echo "SKIP: Could not run test without ip tool"
- exit $ksft_skip
-fi
+# Modify TCP payload without corrupting the TCP packet
+#
+# This rule inverts a 8-bit word at byte offset 148 for the 2nd TCP ACK packets
+# carrying enough data.
+# Once it is done, the TCP Checksum field is updated so the packet is still
+# considered as valid at the TCP level.
+# Because the MPTCP checksum, covering the TCP options and data, has not been
+# updated, the modification will be detected and an MP_FAIL will be emitted:
+# what we want to validate here without corrupting "random" MPTCP options.
+#
+# To avoid having tc producing this pr_info() message for each TCP ACK packets
+# not carrying enough data:
+#
+# tc action pedit offset 162 out of bounds
+#
+# Netfilter is used to mark packets with enough data.
+reset_with_fail()
+{
+ reset "${1}" || return 1
-iptables -V > /dev/null 2>&1
-if [ $? -ne 0 ];then
- echo "SKIP: Could not run all tests without iptables tool"
- exit $ksft_skip
-fi
+ ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
+ ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
-ip6tables -V > /dev/null 2>&1
-if [ $? -ne 0 ];then
- echo "SKIP: Could not run all tests without ip6tables tool"
- exit $ksft_skip
-fi
+ check_invert=1
+ validate_checksum=1
+ local i="$2"
+ local ip="${3:-4}"
+ local tables
+
+ tables="iptables"
+ if [ $ip -eq 6 ]; then
+ tables="ip6tables"
+ fi
+
+ ip netns exec $ns2 $tables \
+ -t mangle \
+ -A OUTPUT \
+ -o ns2eth$i \
+ -p tcp \
+ -m length --length 150:9999 \
+ -m statistic --mode nth --packet 1 --every 99999 \
+ -j MARK --set-mark 42 || exit 1
+
+ tc -n $ns2 qdisc add dev ns2eth$i clsact || exit 1
+ tc -n $ns2 filter add dev ns2eth$i egress \
+ protocol ip prio 1000 \
+ handle 42 fw \
+ action pedit munge offset 148 u8 invert \
+ pipe csum tcp \
+ index 100 || exit 1
+}
+
+fail_test()
+{
+ ret=1
+ failed_tests[${TEST_COUNT}]="${TEST_NAME}"
+}
+
+get_failed_tests_ids()
+{
+ # sorted
+ local i
+ for i in "${!failed_tests[@]}"; do
+ echo "${i}"
+ done | sort -n
+}
print_file_err()
{
@@ -187,47 +343,64 @@ print_file_err()
check_transfer()
{
- in=$1
- out=$2
- what=$3
-
- cmp "$in" "$out" > /dev/null 2>&1
- if [ $? -ne 0 ] ;then
- echo "[ FAIL ] $what does not match (in, out):"
- print_file_err "$in"
- print_file_err "$out"
- ret=1
-
- return 1
+ local in=$1
+ local out=$2
+ local what=$3
+ local bytes=$4
+ local i a b
+
+ local line
+ if [ -n "$bytes" ]; then
+ # when truncating we must check the size explicitly
+ local out_size=$(wc -c $out | awk '{print $1}')
+ if [ $out_size -ne $bytes ]; then
+ echo "[ FAIL ] $what output file has wrong size ($out_size, $bytes)"
+ fail_test
+ return 1
+ fi
+ bytes="--bytes=${bytes}"
fi
+ cmp -l "$in" "$out" ${bytes} | while read -r i a b; do
+ local sum=$((0${a} + 0${b}))
+ if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then
+ echo "[ FAIL ] $what does not match (in, out):"
+ print_file_err "$in"
+ print_file_err "$out"
+ fail_test
+
+ return 1
+ else
+ echo "$what has inverted byte at ${i}"
+ fi
+ done
return 0
}
do_ping()
{
- listener_ns="$1"
- connector_ns="$2"
- connect_addr="$3"
+ local listener_ns="$1"
+ local connector_ns="$2"
+ local connect_addr="$3"
- ip netns exec ${connector_ns} ping -q -c 1 $connect_addr >/dev/null
- if [ $? -ne 0 ] ; then
+ if ! ip netns exec ${connector_ns} ping -q -c 1 $connect_addr >/dev/null; then
echo "$listener_ns -> $connect_addr connectivity [ FAIL ]" 1>&2
- ret=1
+ fail_test
fi
}
link_failure()
{
- ns="$1"
+ local ns="$1"
if [ -z "$FAILING_LINKS" ]; then
l=$((RANDOM%4))
FAILING_LINKS=$((l+1))
fi
+ local l
for l in $FAILING_LINKS; do
- veth="ns1eth$l"
+ local veth="ns1eth$l"
ip -net "$ns" link set "$veth" down
done
}
@@ -244,9 +417,10 @@ wait_local_port_listen()
local listener_ns="${1}"
local port="${2}"
- local port_hex i
-
+ local port_hex
port_hex="$(printf "%04X" "${port}")"
+
+ local i
for i in $(seq 10); do
ip netns exec "${listener_ns}" cat /proc/net/tcp* | \
awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
@@ -257,7 +431,7 @@ wait_local_port_listen()
rm_addr_count()
{
- ns=${1}
+ local ns=${1}
ip netns exec ${ns} nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'
}
@@ -268,8 +442,8 @@ wait_rm_addr()
local ns="${1}"
local old_cnt="${2}"
local cnt
- local i
+ local i
for i in $(seq 10); do
cnt=$(rm_addr_count ${ns})
[ "$cnt" = "${old_cnt}" ] || break
@@ -277,27 +451,238 @@ 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
+}
+
+kill_wait()
+{
+ kill $1 > /dev/null 2>&1
+ wait $1 2>/dev/null
+}
+
+pm_nl_set_limits()
+{
+ local ns=$1
+ local addrs=$2
+ local subflows=$3
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp limits set add_addr_accepted $addrs subflows $subflows
+ else
+ ip netns exec $ns ./pm_nl_ctl limits $addrs $subflows
+ fi
+}
+
+pm_nl_add_endpoint()
+{
+ local ns=$1
+ local addr=$2
+ local flags _flags
+ local port _port
+ local dev _dev
+ local id _id
+ local nr=2
+
+ local p
+ for p in "${@}"
+ do
+ if [ $p = "flags" ]; then
+ eval _flags=\$"$nr"
+ [ -n "$_flags" ]; flags="flags $_flags"
+ fi
+ if [ $p = "dev" ]; then
+ eval _dev=\$"$nr"
+ [ -n "$_dev" ]; dev="dev $_dev"
+ fi
+ if [ $p = "id" ]; then
+ eval _id=\$"$nr"
+ [ -n "$_id" ]; id="id $_id"
+ fi
+ if [ $p = "port" ]; then
+ eval _port=\$"$nr"
+ [ -n "$_port" ]; port="port $_port"
+ fi
+
+ nr=$((nr + 1))
+ done
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp endpoint add $addr ${_flags//","/" "} $dev $id $port
+ else
+ ip netns exec $ns ./pm_nl_ctl add $addr $flags $dev $id $port
+ fi
+}
+
+pm_nl_del_endpoint()
+{
+ local ns=$1
+ local id=$2
+ local addr=$3
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp endpoint delete id $id $addr
+ else
+ ip netns exec $ns ./pm_nl_ctl del $id $addr
+ fi
+}
+
+pm_nl_flush_endpoint()
+{
+ local ns=$1
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp endpoint flush
+ else
+ ip netns exec $ns ./pm_nl_ctl flush
+ fi
+}
+
+pm_nl_show_endpoints()
+{
+ local ns=$1
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp endpoint show
+ else
+ ip netns exec $ns ./pm_nl_ctl dump
+ fi
+}
+
+pm_nl_change_endpoint()
+{
+ local ns=$1
+ local id=$2
+ local flags=$3
+
+ if [ $ip_mptcp -eq 1 ]; then
+ ip -n $ns mptcp endpoint change id $id ${flags//","/" "}
+ else
+ ip netns exec $ns ./pm_nl_ctl set id $id flags $flags
+ fi
+}
+
+pm_nl_check_endpoint()
+{
+ local line expected_line
+ local need_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 [ "${need_title}" = 1 ]; then
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
+ else
+ printf "%-${nr_blank}s %s" " " "${msg}"
+ fi
+
+ shift 4
+ while [ -n "$1" ]; do
+ if [ $1 = "flags" ]; then
+ _flags=$2
+ [ -n "$_flags" ]; flags="flags $_flags"
+ shift
+ elif [ $1 = "dev" ]; then
+ [ -n "$2" ]; dev="dev $1"
+ shift
+ elif [ $1 = "id" ]; then
+ _id=$2
+ [ -n "$_id" ]; id="id $_id"
+ shift
+ elif [ $1 = "port" ]; then
+ _port=$2
+ [ -n "$_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'"
+ fail_test
+ fi
+}
+
+filter_tcp_from()
+{
+ local ns="${1}"
+ local src="${2}"
+ local target="${3}"
+
+ ip netns exec "${ns}" iptables -A INPUT -s "${src}" -p tcp -j "${target}"
+}
+
do_transfer()
{
- listener_ns="$1"
- connector_ns="$2"
- cl_proto="$3"
- srv_proto="$4"
- connect_addr="$5"
- test_link_fail="$6"
- addr_nr_ns1="$7"
- addr_nr_ns2="$8"
- speed="$9"
- bkup="${10}"
-
- port=$((10000+$TEST_COUNT))
- TEST_COUNT=$((TEST_COUNT+1))
+ local listener_ns="$1"
+ local connector_ns="$2"
+ local cl_proto="$3"
+ local srv_proto="$4"
+ local connect_addr="$5"
+ local test_link_fail="$6"
+ local addr_nr_ns1="$7"
+ local addr_nr_ns2="$8"
+ local speed="$9"
+ local sflags="${10}"
+
+ local port=$((10000 + TEST_COUNT - 1))
+ local cappid
+ local userspace_pm=0
+ local evts_ns1
+ local evts_ns1_pid
+ local evts_ns2
+ local evts_ns2_pid
:> "$cout"
:> "$sout"
:> "$capout"
if [ $capture -eq 1 ]; then
+ local capuser
if [ -z $SUDO_USER ] ; then
capuser=""
else
@@ -318,12 +703,64 @@ do_transfer()
NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \
nstat -n
+ local extra_args
if [ $speed = "fast" ]; then
- mptcp_connect="./mptcp_connect -j"
+ extra_args="-j"
elif [ $speed = "slow" ]; then
- mptcp_connect="./mptcp_connect -r 50"
- elif [ $speed = "least" ]; then
- mptcp_connect="./mptcp_connect -r 10"
+ extra_args="-r 50"
+ elif [[ $speed = "speed_"* ]]; then
+ extra_args="-r ${speed:6}"
+ fi
+
+ if [[ "${addr_nr_ns1}" = "userspace_"* ]]; then
+ userspace_pm=1
+ addr_nr_ns1=${addr_nr_ns1:10}
+ fi
+
+ local flags="subflow"
+ local extra_cl_args=""
+ local extra_srv_args=""
+ local trunc_size=""
+ if [[ "${addr_nr_ns2}" = "fastclose_"* ]]; then
+ if [ ${test_link_fail} -le 1 ]; then
+ echo "fastclose tests need test_link_fail argument"
+ fail_test
+ return 1
+ fi
+
+ # disconnect
+ trunc_size=${test_link_fail}
+ local side=${addr_nr_ns2:10}
+
+ if [ ${side} = "client" ]; then
+ extra_cl_args="-f ${test_link_fail}"
+ extra_srv_args="-f -1"
+ elif [ ${side} = "server" ]; then
+ extra_srv_args="-f ${test_link_fail}"
+ extra_cl_args="-f -1"
+ else
+ echo "wrong/unknown fastclose spec ${side}"
+ fail_test
+ return 1
+ fi
+ addr_nr_ns2=0
+ elif [[ "${addr_nr_ns2}" = "userspace_"* ]]; then
+ userspace_pm=1
+ addr_nr_ns2=${addr_nr_ns2:10}
+ elif [[ "${addr_nr_ns2}" = "fullmesh_"* ]]; then
+ flags="${flags},fullmesh"
+ addr_nr_ns2=${addr_nr_ns2:9}
+ fi
+
+ if [ $userspace_pm -eq 1 ]; then
+ evts_ns1=$(mktemp)
+ evts_ns2=$(mktemp)
+ :> "$evts_ns1"
+ :> "$evts_ns2"
+ ip netns exec ${listener_ns} ./pm_nl_ctl events >> "$evts_ns1" 2>&1 &
+ evts_ns1_pid=$!
+ ip netns exec ${connector_ns} ./pm_nl_ctl events >> "$evts_ns2" 2>&1 &
+ evts_ns2_pid=$!
fi
local local_addr
@@ -333,43 +770,55 @@ do_transfer()
local_addr="0.0.0.0"
fi
- if [ "$test_link_fail" -eq 2 ];then
+ extra_srv_args="$extra_args $extra_srv_args"
+ if [ "$test_link_fail" -gt 1 ];then
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
- $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
- ${local_addr} < "$sinfail" > "$sout" &
+ ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
+ $extra_srv_args ${local_addr} < "$sinfail" > "$sout" &
else
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
- $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
- ${local_addr} < "$sin" > "$sout" &
+ ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
+ $extra_srv_args ${local_addr} < "$sin" > "$sout" &
fi
- spid=$!
+ local spid=$!
wait_local_port_listen "${listener_ns}" "${port}"
+ extra_cl_args="$extra_args $extra_cl_args"
if [ "$test_link_fail" -eq 0 ];then
timeout ${timeout_test} \
ip netns exec ${connector_ns} \
- $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
- $connect_addr < "$cin" > "$cout" &
- else
+ ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
+ $extra_cl_args $connect_addr < "$cin" > "$cout" &
+ elif [ "$test_link_fail" -eq 1 ] || [ "$test_link_fail" -eq 2 ];then
( cat "$cinfail" ; sleep 2; link_failure $listener_ns ; cat "$cinfail" ) | \
tee "$cinsent" | \
timeout ${timeout_test} \
ip netns exec ${connector_ns} \
- $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
- $connect_addr > "$cout" &
+ ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
+ $extra_cl_args $connect_addr > "$cout" &
+ else
+ tee "$cinsent" < "$cinfail" | \
+ timeout ${timeout_test} \
+ ip netns exec ${connector_ns} \
+ ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
+ $extra_cl_args $connect_addr > "$cout" &
fi
- cpid=$!
+ local cpid=$!
# let the mptcp subflow be established in background before
# do endpoint manipulation
- [ $addr_nr_ns1 = "0" -a $addr_nr_ns2 = "0" ] || sleep 1
+ if [ $addr_nr_ns1 != "0" ] || [ $addr_nr_ns2 != "0" ]; then
+ sleep 1
+ fi
if [ $addr_nr_ns1 -gt 0 ]; then
- let add_nr_ns1=addr_nr_ns1
- counter=2
+ local counter=2
+ local add_nr_ns1=${addr_nr_ns1}
+ local id=10
+ local tk
while [ $add_nr_ns1 -gt 0 ]; do
local addr
if is_v6 "${connect_addr}"; then
@@ -377,47 +826,60 @@ do_transfer()
else
addr="10.0.$counter.1"
fi
- ip netns exec $ns1 ./pm_nl_ctl add $addr flags signal
- let counter+=1
- let add_nr_ns1-=1
+ if [ $userspace_pm -eq 0 ]; then
+ pm_nl_add_endpoint $ns1 $addr flags signal
+ else
+ tk=$(sed -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evts_ns1")
+ ip netns exec ${listener_ns} ./pm_nl_ctl ann $addr token $tk id $id
+ sleep 1
+ ip netns exec ${listener_ns} ./pm_nl_ctl rem token $tk id $id
+ fi
+
+ counter=$((counter + 1))
+ add_nr_ns1=$((add_nr_ns1 - 1))
+ id=$((id + 1))
done
elif [ $addr_nr_ns1 -lt 0 ]; then
- let rm_nr_ns1=-addr_nr_ns1
+ local rm_nr_ns1=$((-addr_nr_ns1))
if [ $rm_nr_ns1 -lt 8 ]; then
- counter=1
- pos=1
- dump=(`ip netns exec ${listener_ns} ./pm_nl_ctl dump`)
- if [ ${#dump[@]} -gt 0 ]; then
- while [ $counter -le $rm_nr_ns1 ]
- do
- id=${dump[$pos]}
- rm_addr=$(rm_addr_count ${connector_ns})
- ip netns exec ${listener_ns} ./pm_nl_ctl del $id
- wait_rm_addr ${connector_ns} ${rm_addr}
- let counter+=1
- let pos+=5
+ local counter=0
+ local line
+ pm_nl_show_endpoints ${listener_ns} | while read -r line; do
+ # shellcheck disable=SC2206 # we do want to split per word
+ local arr=($line)
+ local nr=0
+
+ local i
+ for i in "${arr[@]}"; do
+ if [ $i = "id" ]; then
+ if [ $counter -eq $rm_nr_ns1 ]; then
+ break
+ fi
+ id=${arr[$nr+1]}
+ rm_addr=$(rm_addr_count ${connector_ns})
+ pm_nl_del_endpoint ${listener_ns} $id
+ wait_rm_addr ${connector_ns} ${rm_addr}
+ counter=$((counter + 1))
+ fi
+ nr=$((nr + 1))
done
- fi
+ done
elif [ $rm_nr_ns1 -eq 8 ]; then
- ip netns exec ${listener_ns} ./pm_nl_ctl flush
+ pm_nl_flush_endpoint ${listener_ns}
elif [ $rm_nr_ns1 -eq 9 ]; then
- ip netns exec ${listener_ns} ./pm_nl_ctl del 0 ${connect_addr}
+ pm_nl_del_endpoint ${listener_ns} 0 ${connect_addr}
fi
fi
- flags="subflow"
- if [[ "${addr_nr_ns2}" = "fullmesh_"* ]]; then
- flags="${flags},fullmesh"
- addr_nr_ns2=${addr_nr_ns2:9}
- fi
-
# if newly added endpoints must be deleted, give the background msk
# some time to created them
- [ $addr_nr_ns1 -gt 0 -a $addr_nr_ns2 -lt 0 ] && sleep 1
+ [ $addr_nr_ns1 -gt 0 ] && [ $addr_nr_ns2 -lt 0 ] && sleep 1
if [ $addr_nr_ns2 -gt 0 ]; then
- let add_nr_ns2=addr_nr_ns2
- counter=3
+ local add_nr_ns2=${addr_nr_ns2}
+ local counter=3
+ local id=20
+ local tk da dp sp
while [ $add_nr_ns2 -gt 0 ]; do
local addr
if is_v6 "${connect_addr}"; then
@@ -425,30 +887,54 @@ do_transfer()
else
addr="10.0.$counter.2"
fi
- ip netns exec $ns2 ./pm_nl_ctl add $addr flags $flags
- let counter+=1
- let add_nr_ns2-=1
+ if [ $userspace_pm -eq 0 ]; then
+ pm_nl_add_endpoint $ns2 $addr flags $flags
+ else
+ tk=$(sed -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evts_ns2")
+ da=$(sed -n 's/.*\(daddr4:\)\([0-9.]*\).*$/\2/p;q' "$evts_ns2")
+ dp=$(sed -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts_ns2")
+ ip netns exec ${connector_ns} ./pm_nl_ctl csf lip $addr lid $id \
+ rip $da rport $dp token $tk
+ sleep 1
+ sp=$(grep "type:10" "$evts_ns2" |
+ sed -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q')
+ ip netns exec ${connector_ns} ./pm_nl_ctl dsf lip $addr lport $sp \
+ rip $da rport $dp token $tk
+ fi
+ counter=$((counter + 1))
+ add_nr_ns2=$((add_nr_ns2 - 1))
+ id=$((id + 1))
done
elif [ $addr_nr_ns2 -lt 0 ]; then
- let rm_nr_ns2=-addr_nr_ns2
+ local rm_nr_ns2=$((-addr_nr_ns2))
if [ $rm_nr_ns2 -lt 8 ]; then
- counter=1
- pos=1
- dump=(`ip netns exec ${connector_ns} ./pm_nl_ctl dump`)
- if [ ${#dump[@]} -gt 0 ]; then
- while [ $counter -le $rm_nr_ns2 ]
- do
- # rm_addr are serialized, allow the previous one to complete
- id=${dump[$pos]}
- rm_addr=$(rm_addr_count ${listener_ns})
- ip netns exec ${connector_ns} ./pm_nl_ctl del $id
- wait_rm_addr ${listener_ns} ${rm_addr}
- let counter+=1
- let pos+=5
+ local counter=0
+ local line
+ pm_nl_show_endpoints ${connector_ns} | while read -r line; do
+ # shellcheck disable=SC2206 # we do want to split per word
+ local arr=($line)
+ local nr=0
+
+ local i
+ for i in "${arr[@]}"; do
+ if [ $i = "id" ]; then
+ if [ $counter -eq $rm_nr_ns2 ]; then
+ break
+ fi
+ local id rm_addr
+ # rm_addr are serialized, allow the previous one to
+ # complete
+ id=${arr[$nr+1]}
+ rm_addr=$(rm_addr_count ${listener_ns})
+ pm_nl_del_endpoint ${connector_ns} $id
+ wait_rm_addr ${listener_ns} ${rm_addr}
+ counter=$((counter + 1))
+ fi
+ nr=$((nr + 1))
done
- fi
+ done
elif [ $rm_nr_ns2 -eq 8 ]; then
- ip netns exec ${connector_ns} ./pm_nl_ctl flush
+ pm_nl_flush_endpoint ${connector_ns}
elif [ $rm_nr_ns2 -eq 9 ]; then
local addr
if is_v6 "${connect_addr}"; then
@@ -456,32 +942,50 @@ do_transfer()
else
addr="10.0.1.2"
fi
- ip netns exec ${connector_ns} ./pm_nl_ctl del 0 $addr
+ pm_nl_del_endpoint ${connector_ns} 0 $addr
fi
fi
- if [ ! -z $bkup ]; then
+ if [ -n "${sflags}" ]; then
sleep 1
+
+ local netns
for netns in "$ns1" "$ns2"; do
- dump=(`ip netns exec $netns ./pm_nl_ctl dump`)
- if [ ${#dump[@]} -gt 0 ]; then
- addr=${dump[${#dump[@]} - 1]}
- backup="ip netns exec $netns ./pm_nl_ctl set $addr flags $bkup"
- $backup
- fi
+ local line
+ pm_nl_show_endpoints $netns | while read -r line; do
+ # shellcheck disable=SC2206 # we do want to split per word
+ local arr=($line)
+ local nr=0
+ local id
+
+ local i
+ for i in "${arr[@]}"; do
+ if [ $i = "id" ]; then
+ id=${arr[$nr+1]}
+ fi
+ nr=$((nr + 1))
+ done
+ pm_nl_change_endpoint $netns $id $sflags
+ done
done
fi
wait $cpid
- retc=$?
+ local retc=$?
wait $spid
- rets=$?
+ local rets=$?
if [ $capture -eq 1 ]; then
sleep 1
kill $cappid
fi
+ if [ $userspace_pm -eq 1 ]; then
+ kill_wait $evts_ns1_pid
+ kill_wait $evts_ns2_pid
+ rm -rf $evts_ns1 $evts_ns2
+ fi
+
NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
nstat | grep Tcp > /tmp/${listener_ns}.out
NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \
@@ -497,20 +1001,20 @@ do_transfer()
cat /tmp/${connector_ns}.out
cat "$capout"
- ret=1
+ fail_test
return 1
fi
- if [ "$test_link_fail" -eq 2 ];then
- check_transfer $sinfail $cout "file received by client"
+ if [ "$test_link_fail" -gt 1 ];then
+ check_transfer $sinfail $cout "file received by client" $trunc_size
else
- check_transfer $sin $cout "file received by client"
+ check_transfer $sin $cout "file received by client" $trunc_size
fi
retc=$?
if [ "$test_link_fail" -eq 0 ];then
- check_transfer $cin $sout "file received by server"
+ check_transfer $cin $sout "file received by server" $trunc_size
else
- check_transfer $cinsent $sout "file received by server"
+ check_transfer $cinsent $sout "file received by server" $trunc_size
fi
rets=$?
@@ -525,9 +1029,9 @@ do_transfer()
make_file()
{
- name=$1
- who=$2
- size=$3
+ local name=$1
+ local who=$2
+ local size=$3
dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null
echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
@@ -537,33 +1041,49 @@ make_file()
run_tests()
{
- listener_ns="$1"
- connector_ns="$2"
- connect_addr="$3"
- test_linkfail="${4:-0}"
- addr_nr_ns1="${5:-0}"
- addr_nr_ns2="${6:-0}"
- speed="${7:-fast}"
- bkup="${8:-""}"
- lret=0
- oldin=""
-
+ local listener_ns="$1"
+ local connector_ns="$2"
+ local connect_addr="$3"
+ local test_linkfail="${4:-0}"
+ local addr_nr_ns1="${5:-0}"
+ local addr_nr_ns2="${6:-0}"
+ local speed="${7:-fast}"
+ local sflags="${8:-""}"
+
+ local size
+
+ # The values above 2 are reused to make test files
+ # with the given sizes (KB)
+ if [ "$test_linkfail" -gt 2 ]; then
+ size=$test_linkfail
+
+ if [ -z "$cinfail" ]; then
+ cinfail=$(mktemp)
+ fi
+ make_file "$cinfail" "client" $size
# create the input file for the failure test when
# the first failure test run
- if [ "$test_linkfail" -ne 0 -a -z "$cinfail" ]; then
+ elif [ "$test_linkfail" -ne 0 ] && [ -z "$cinfail" ]; then
# the client file must be considerably larger
# of the maximum expected cwin value, or the
# link utilization will be not predicable
size=$((RANDOM%2))
size=$((size+1))
size=$((size*8192))
- size=$((size + ( $RANDOM % 8192) ))
+ size=$((size + ( RANDOM % 8192) ))
cinfail=$(mktemp)
make_file "$cinfail" "client" $size
fi
- if [ "$test_linkfail" -eq 2 -a -z "$sinfail" ]; then
+ if [ "$test_linkfail" -gt 2 ]; then
+ size=$test_linkfail
+
+ if [ -z "$sinfail" ]; then
+ sinfail=$(mktemp)
+ fi
+ make_file "$sinfail" "server" $size
+ elif [ "$test_linkfail" -eq 2 ] && [ -z "$sinfail" ]; then
size=$((RANDOM%16))
size=$((size+1))
size=$((size*2048))
@@ -573,8 +1093,7 @@ run_tests()
fi
do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \
- ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${bkup}
- lret=$?
+ ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${sflags}
}
dump_stats()
@@ -587,62 +1106,233 @@ dump_stats()
chk_csum_nr()
{
- local msg=${1:-""}
+ local csum_ns1=${1:-0}
+ local csum_ns2=${2:-0}
local count
local dump_stats
+ local extra_msg=""
+ local allow_multi_errors_ns1=0
+ local allow_multi_errors_ns2=0
- if [ ! -z "$msg" ]; then
- printf "%02u" "$TEST_COUNT"
- else
- echo -n " "
+ if [[ "${csum_ns1}" = "+"* ]]; then
+ allow_multi_errors_ns1=1
+ csum_ns1=${csum_ns1:1}
fi
- printf " %-36s %s" "$msg" "sum"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'`
+ if [[ "${csum_ns2}" = "+"* ]]; then
+ allow_multi_errors_ns2=1
+ csum_ns2=${csum_ns2:1}
+ fi
+
+ printf "%-${nr_blank}s %s" " " "sum"
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
[ -z "$count" ] && count=0
- if [ "$count" != 0 ]; then
- echo "[fail] got $count data checksum error[s] expected 0"
- ret=1
+ if [ "$count" != "$csum_ns1" ]; then
+ extra_msg="$extra_msg ns1=$count"
+ fi
+ if { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
+ { [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
+ echo "[fail] got $count data checksum error[s] expected $csum_ns1"
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - csum "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'`
+ count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
[ -z "$count" ] && count=0
- if [ "$count" != 0 ]; then
- echo "[fail] got $count data checksum error[s] expected 0"
- ret=1
+ if [ "$count" != "$csum_ns2" ]; then
+ extra_msg="$extra_msg ns2=$count"
+ fi
+ if { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
+ { [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
+ echo "[fail] got $count data checksum error[s] expected $csum_ns2"
+ fail_test
dump_stats=1
else
- echo "[ ok ]"
+ echo -n "[ ok ]"
fi
[ "${dump_stats}" = 1 ] && dump_stats
+
+ echo "$extra_msg"
}
chk_fail_nr()
{
- local mp_fail_nr_tx=$1
- local mp_fail_nr_rx=$2
+ local fail_tx=$1
+ local fail_rx=$2
+ local ns_invert=${3:-""}
local count
local dump_stats
+ local ns_tx=$ns1
+ local ns_rx=$ns2
+ local extra_msg=""
+ local allow_tx_lost=0
+ local allow_rx_lost=0
+
+ if [[ $ns_invert = "invert" ]]; then
+ ns_tx=$ns2
+ ns_rx=$ns1
+ extra_msg=" invert"
+ fi
- printf "%-39s %s" " " "ftx"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}'`
+ if [[ "${fail_tx}" = "-"* ]]; then
+ allow_tx_lost=1
+ fail_tx=${fail_tx:1}
+ fi
+ if [[ "${fail_rx}" = "-"* ]]; then
+ allow_rx_lost=1
+ fail_rx=${fail_rx:1}
+ fi
+
+ printf "%-${nr_blank}s %s" " " "ftx"
+ count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}')
[ -z "$count" ] && count=0
- if [ "$count" != "$mp_fail_nr_tx" ]; then
- echo "[fail] got $count MP_FAIL[s] TX expected $mp_fail_nr_tx"
- ret=1
+ if [ "$count" != "$fail_tx" ]; then
+ extra_msg="$extra_msg,tx=$count"
+ fi
+ if { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
+ { [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
+ echo "[fail] got $count MP_FAIL[s] TX expected $fail_tx"
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
- echo -n " - frx "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}'`
+ echo -n " - failrx"
+ count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}')
[ -z "$count" ] && count=0
- if [ "$count" != "$mp_fail_nr_rx" ]; then
- echo "[fail] got $count MP_FAIL[s] RX expected $mp_fail_nr_rx"
- ret=1
+ if [ "$count" != "$fail_rx" ]; then
+ extra_msg="$extra_msg,rx=$count"
+ fi
+ if { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
+ { [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
+ echo "[fail] got $count MP_FAIL[s] RX expected $fail_rx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ [ "${dump_stats}" = 1 ] && dump_stats
+
+ echo "$extra_msg"
+}
+
+chk_fclose_nr()
+{
+ local fclose_tx=$1
+ local fclose_rx=$2
+ local ns_invert=$3
+ local count
+ local dump_stats
+ local ns_tx=$ns2
+ local ns_rx=$ns1
+ local extra_msg=" "
+
+ if [[ $ns_invert = "invert" ]]; then
+ ns_tx=$ns1
+ ns_rx=$ns2
+ extra_msg=${extra_msg}"invert"
+ fi
+
+ printf "%-${nr_blank}s %s" " " "ctx"
+ count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFastcloseTx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ [ "$count" != "$fclose_tx" ] && extra_msg="$extra_msg,tx=$count"
+ if [ "$count" != "$fclose_tx" ]; then
+ echo "[fail] got $count MP_FASTCLOSE[s] TX expected $fclose_tx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ echo -n " - fclzrx"
+ count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFastcloseRx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ [ "$count" != "$fclose_rx" ] && extra_msg="$extra_msg,rx=$count"
+ if [ "$count" != "$fclose_rx" ]; then
+ echo "[fail] got $count MP_FASTCLOSE[s] RX expected $fclose_rx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ [ "${dump_stats}" = 1 ] && dump_stats
+
+ echo "$extra_msg"
+}
+
+chk_rst_nr()
+{
+ local rst_tx=$1
+ local rst_rx=$2
+ local ns_invert=${3:-""}
+ local count
+ local dump_stats
+ local ns_tx=$ns1
+ local ns_rx=$ns2
+ local extra_msg=""
+
+ if [[ $ns_invert = "invert" ]]; then
+ ns_tx=$ns2
+ ns_rx=$ns1
+ extra_msg=" invert"
+ fi
+
+ printf "%-${nr_blank}s %s" " " "rtx"
+ count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPRstTx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ $count -lt $rst_tx ]; then
+ echo "[fail] got $count MP_RST[s] TX expected $rst_tx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ echo -n " - rstrx "
+ count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPRstRx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ "$count" -lt "$rst_rx" ]; then
+ echo "[fail] got $count MP_RST[s] RX expected $rst_rx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ [ "${dump_stats}" = 1 ] && dump_stats
+
+ echo "$extra_msg"
+}
+
+chk_infi_nr()
+{
+ local infi_tx=$1
+ local infi_rx=$2
+ local count
+ local dump_stats
+
+ printf "%-${nr_blank}s %s" " " "itx"
+ count=$(ip netns exec $ns2 nstat -as | grep InfiniteMapTx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$infi_tx" ]; then
+ echo "[fail] got $count infinite map[s] TX expected $infi_tx"
+ fail_test
+ dump_stats=1
+ else
+ echo -n "[ ok ]"
+ fi
+
+ echo -n " - infirx"
+ count=$(ip netns exec $ns1 nstat -as | grep InfiniteMapRx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ "$count" != "$infi_rx" ]; then
+ echo "[fail] got $count infinite map[s] RX expected $infi_rx"
+ fail_test
dump_stats=1
else
echo "[ ok ]"
@@ -653,49 +1343,70 @@ chk_fail_nr()
chk_join_nr()
{
- local msg="$1"
- local syn_nr=$2
- local syn_ack_nr=$3
- local ack_nr=$4
+ local syn_nr=$1
+ local syn_ack_nr=$2
+ local ack_nr=$3
+ local csum_ns1=${4:-0}
+ local csum_ns2=${5:-0}
+ local fail_nr=${6:-0}
+ local rst_nr=${7:-0}
+ local infi_nr=${8:-0}
+ local corrupted_pkts=${9:-0}
local count
local dump_stats
+ local with_cookie
+ local title="${TEST_NAME}"
+
+ if [ "${corrupted_pkts}" -gt 0 ]; then
+ title+=": ${corrupted_pkts} corrupted pkts"
+ fi
- printf "%02u %-36s %s" "$TEST_COUNT" "$msg" "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}'`
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "syn"
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn expected $syn_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - synack"
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}'`
+ with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies)
+ count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$syn_ack_nr" ]; then
- echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr"
- ret=1
- dump_stats=1
+ # simult connections exceeding the limit with cookie enabled could go up to
+ # synack validation as the conn limit can be enforced reliably only after
+ # the subflow creation
+ if [ "$with_cookie" = 2 ] && [ "$count" -gt "$syn_ack_nr" ] && [ "$count" -le "$syn_nr" ]; then
+ echo -n "[ ok ]"
+ else
+ echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr"
+ fail_test
+ dump_stats=1
+ fi
else
echo -n "[ ok ]"
fi
echo -n " - ack"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}'`
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack expected $ack_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
fi
[ "${dump_stats}" = 1 ] && dump_stats
- if [ $checksum -eq 1 ]; then
- chk_csum_nr
- chk_fail_nr 0 0
+ if [ $validate_checksum -eq 1 ]; then
+ chk_csum_nr $csum_ns1 $csum_ns2
+ chk_fail_nr $fail_nr $fail_nr
+ chk_rst_nr $rst_nr $rst_nr
+ chk_infi_nr $infi_nr $infi_nr
fi
}
@@ -714,19 +1425,19 @@ chk_stale_nr()
local stale_nr
local recover_nr
- printf "%-39s %-18s" " " "stale"
- stale_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}'`
+ printf "%-${nr_blank}s %-18s" " " "stale"
+ stale_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}')
[ -z "$stale_nr" ] && stale_nr=0
- recover_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}'`
+ recover_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}')
[ -z "$recover_nr" ] && recover_nr=0
if [ $stale_nr -lt $stale_min ] ||
- [ $stale_max -gt 0 -a $stale_nr -gt $stale_max ] ||
- [ $((stale_nr - $recover_nr)) -ne $stale_delta ]; then
+ { [ $stale_max -gt 0 ] && [ $stale_nr -gt $stale_max ]; } ||
+ [ $((stale_nr - recover_nr)) -ne $stale_delta ]; then
echo "[fail] got $stale_nr stale[s] $recover_nr recover[s], " \
" expected stale in range [$stale_min..$stale_max]," \
" stale-recover delta $stale_delta "
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
@@ -751,24 +1462,30 @@ chk_add_nr()
local mis_ack_nr=${8:-0}
local count
local dump_stats
+ local timeout
- printf "%-39s %s" " " "add"
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtAddAddr | awk '{print $2}'`
+ timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
+
+ printf "%-${nr_blank}s %s" " " "add"
+ count=$(ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}')
[ -z "$count" ] && count=0
- if [ "$count" != "$add_nr" ]; then
+
+ # if the test configured a short timeout tolerate greater then expected
+ # add addrs options, due to retransmissions
+ if [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - echo "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}'`
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$echo_nr" ]; then
echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
@@ -776,76 +1493,76 @@ chk_add_nr()
if [ $port_nr -gt 0 ]; then
echo -n " - pt "
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}'`
+ count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$port_nr" ]; then
echo "[fail] got $count ADD_ADDR[s] with a port-number expected $port_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
fi
- printf "%-39s %s" " " "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
- awk '{print $2}'`
+ printf "%-${nr_blank}s %s" " " "syn"
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
+ awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a different \
port-number expected $syn_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - synack"
- count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
- awk '{print $2}'`
+ count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
+ awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$syn_ack_nr" ]; then
echo "[fail] got $count JOIN[s] synack with a different \
port-number expected $syn_ack_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - ack"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
- awk '{print $2}'`
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
+ awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a different \
port-number expected $ack_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
fi
- printf "%-39s %s" " " "syn"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
- awk '{print $2}'`
+ printf "%-${nr_blank}s %s" " " "syn"
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
+ awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$mis_syn_nr" ]; then
echo "[fail] got $count JOIN[s] syn with a mismatched \
port-number expected $mis_syn_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - ack "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
- awk '{print $2}'`
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
+ awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$mis_ack_nr" ]; then
echo "[fail] got $count JOIN[s] ack with a mismatched \
port-number expected $mis_ack_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
@@ -861,43 +1578,75 @@ 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
- local subflow_ns
+ local addr_ns=$ns1
+ local subflow_ns=$ns2
+ local extra_msg=""
+
+ 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 = "invert" ]; then
+ elif [ $invert = "true" ]; then
addr_ns=$ns2
subflow_ns=$ns1
+ extra_msg=" invert"
fi
- printf "%-39s %s" " " "rm "
- count=`ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'`
+ printf "%-${nr_blank}s %s" " " "rm "
+ count=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$rm_addr_nr" ]; then
echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
- echo -n " - sf "
- count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'`
+ 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 suffix
+
+ cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
+
+ # 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))]"
+ fail_test
+ 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
+ fail_test
dump_stats=1
else
- echo "[ ok ]"
+ echo -n "[ ok ]"
fi
[ "${dump_stats}" = 1 ] && dump_stats
+
+ echo "$extra_msg"
}
chk_prio_nr()
@@ -907,23 +1656,23 @@ chk_prio_nr()
local count
local dump_stats
- printf "%-39s %s" " " "ptx"
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}'`
+ printf "%-${nr_blank}s %s" " " "ptx"
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$mp_prio_nr_tx" ]; then
echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx"
- ret=1
+ fail_test
dump_stats=1
else
echo -n "[ ok ]"
fi
echo -n " - prx "
- count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}'`
+ count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
[ -z "$count" ] && count=0
if [ "$count" != "$mp_prio_nr_rx" ]; then
echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx"
- ret=1
+ fail_test
dump_stats=1
else
echo "[ ok ]"
@@ -932,35 +1681,66 @@ chk_prio_nr()
[ "${dump_stats}" = 1 ] && dump_stats
}
+chk_subflow_nr()
+{
+ local need_title="$1"
+ local msg="$2"
+ local subflow_nr=$3
+ local cnt1
+ local cnt2
+
+ if [ -n "${need_title}" ]; then
+ printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
+ else
+ printf "%-${nr_blank}s %s" " " "${msg}"
+ fi
+
+ cnt1=$(ss -N $ns1 -tOni | grep -c token)
+ cnt2=$(ss -N $ns2 -tOni | grep -c token)
+ if [ "$cnt1" != "$subflow_nr" -o "$cnt2" != "$subflow_nr" ]; then
+ echo "[fail] got $cnt1:$cnt2 subflows expected $subflow_nr"
+ fail_test
+ dump_stats=1
+ else
+ echo "[ ok ]"
+ fi
+
+ [ "${dump_stats}" = 1 ] && ( ss -N $ns1 -tOni ; ss -N $ns1 -tOni | grep token; ip -n $ns1 mptcp endpoint )
+}
+
chk_link_usage()
{
local ns=$1
local link=$2
local out=$3
local expected_rate=$4
- local tx_link=`ip netns exec $ns cat /sys/class/net/$link/statistics/tx_bytes`
- local tx_total=`ls -l $out | awk '{print $5}'`
- local tx_rate=$((tx_link * 100 / $tx_total))
+
+ local tx_link tx_total
+ tx_link=$(ip netns exec $ns cat /sys/class/net/$link/statistics/tx_bytes)
+ tx_total=$(stat --format=%s $out)
+ local tx_rate=$((tx_link * 100 / tx_total))
local tolerance=5
- printf "%-39s %-18s" " " "link usage"
- if [ $tx_rate -lt $((expected_rate - $tolerance)) -o \
- $tx_rate -gt $((expected_rate + $tolerance)) ]; then
+ printf "%-${nr_blank}s %-18s" " " "link usage"
+ if [ $tx_rate -lt $((expected_rate - tolerance)) ] || \
+ [ $tx_rate -gt $((expected_rate + tolerance)) ]; then
echo "[fail] got $tx_rate% usage, expected $expected_rate%"
- ret=1
+ fail_test
else
echo "[ ok ]"
fi
}
-wait_for_tw()
+wait_attempt_fail()
{
local timeout_ms=$((timeout_poll * 1000))
local time=0
local ns=$1
while [ $time -lt $timeout_ms ]; do
- local cnt=$(ip netns exec $ns ss -t state time-wait |wc -l)
+ local cnt
+
+ cnt=$(ip netns exec $ns nstat -as TcpAttemptFails | grep TcpAttemptFails | awk '{print $2}')
[ "$cnt" = 1 ] && return 1
time=$((time + 100))
@@ -969,875 +1749,1007 @@ wait_for_tw()
return 1
}
+set_userspace_pm()
+{
+ local ns=$1
+
+ ip netns exec $ns sysctl -q net.mptcp.pm_type=1
+}
+
subflows_tests()
{
- reset
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "no JOIN" "0" "0" "0"
+ if reset "no JOIN"; then
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# subflow limited by client
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 0
- ip netns exec $ns2 ./pm_nl_ctl limits 0 0
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow, limited by client" 0 0 0
+ if reset "single subflow, limited by client"; then
+ pm_nl_set_limits $ns1 0 0
+ pm_nl_set_limits $ns2 0 0
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# subflow limited by server
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 0
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow, limited by server" 1 1 0
+ if reset "single subflow, limited by server"; then
+ pm_nl_set_limits $ns1 0 0
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 0
+ fi
# subflow
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow" 1 1 1
+ if reset "single subflow"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
# multiple subflows
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple subflows" 2 2 2
+ if reset "multiple subflows"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ fi
# multiple subflows limited by server
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple subflows, limited by server" 2 2 1
+ if reset "multiple subflows, limited by server"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 1
+ fi
# single subflow, dev
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow dev ns2eth3
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow, dev" 1 1 1
+ if reset "single subflow, dev"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow dev ns2eth3
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
}
subflows_error_tests()
{
# If a single subflow is configured, and matches the MPC src
# address, no additional subflow should be created
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.1.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr "no MPC reuse with single endpoint" 0 0 0
+ if reset "no MPC reuse with single endpoint"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 0 0 0
+ fi
# multiple subflows, with subflow creation error
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- ip netns exec $ns1 iptables -A INPUT -s 10.0.3.2 -p tcp -j REJECT
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr "multi subflows, with failing subflow" 1 1 1
+ if reset "multi subflows, with failing subflow"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ filter_tcp_from $ns1 10.0.3.2 REJECT
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 1 1 1
+ fi
# multiple subflows, with subflow timeout on MPJ
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- ip netns exec $ns1 iptables -A INPUT -s 10.0.3.2 -p tcp -j DROP
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr "multi subflows, with subflow timeout" 1 1 1
+ if reset "multi subflows, with subflow timeout"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ filter_tcp_from $ns1 10.0.3.2 DROP
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 1 1 1
+ fi
# multiple subflows, check that the endpoint corresponding to
# closed subflow (due to reset) is not reused if additional
# subflows are added later
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns1 iptables -A INPUT -s 10.0.3.2 -p tcp -j REJECT
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
-
- # updates in the child shell do not have any effect here, we
- # need to bump the test counter for the above case
- TEST_COUNT=$((TEST_COUNT+1))
-
- # mpj subflow will be in TW after the reset
- wait_for_tw $ns2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- wait
-
- # additional subflow could be created only if the PM select
- # the later endpoint, skipping the already used one
- chk_join_nr "multi subflows, fair usage on close" 1 1 1
+ if reset "multi subflows, fair usage on close"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ filter_tcp_from $ns1 10.0.3.2 REJECT
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
+
+ # mpj subflow will be in TW after the reset
+ wait_attempt_fail $ns2
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ wait
+
+ # additional subflow could be created only if the PM select
+ # the later endpoint, skipping the already used one
+ chk_join_nr 1 1 1
+ fi
}
signal_address_tests()
{
# add_address, unused
- reset
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "unused signal address" 0 0 0
- chk_add_nr 1 1
+ if reset "unused signal address"; then
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ chk_add_nr 1 1
+ fi
# accept and use add_addr
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address" 1 1 1
- chk_add_nr 1 1
+ if reset "signal address"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# accept and use add_addr with an additional subflow
# note: signal address in server ns and local addresses in client ns must
# belong to different subnets or one of the listed local address could be
# used for 'add_addr' subflow
- reset
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflow and signal" 2 2 2
- chk_add_nr 1 1
+ if reset "subflow and signal"; then
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ fi
# accept and use add_addr with additional subflows
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple subflows and signal" 3 3 3
- chk_add_nr 1 1
+ if reset "multiple subflows and signal"; then
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ fi
# signal addresses
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.4.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal addresses" 3 3 3
- chk_add_nr 3 3
+ if reset "signal addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 3 3 3
+ chk_add_nr 3 3
+ fi
# signal invalid addresses
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.12.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.14.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal invalid addresses" 1 1 1
- chk_add_nr 3 3
+ if reset "signal invalid addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 3 3
+ fi
# signal addresses race test
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 4 4
- ip netns exec $ns2 ./pm_nl_ctl limits 4 4
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.4.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.1.2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags signal
- run_tests $ns1 $ns2 10.0.1.1
-
- # the server will not signal the address terminating
- # the MPC subflow
- chk_add_nr 3 3
+ if reset "signal addresses race test"; then
+ pm_nl_set_limits $ns1 4 4
+ pm_nl_set_limits $ns2 4 4
+ pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags signal
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags signal
+ pm_nl_add_endpoint $ns2 10.0.4.2 flags signal
+
+ # the peer could possibly miss some addr notification, allow retransmission
+ ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 3 3 3
+
+ # the server will not signal the address terminating
+ # the MPC subflow
+ chk_add_nr 3 3
+ fi
}
link_failure_tests()
{
# accept and use add_addr with additional subflows and link loss
- reset
-
- # without any b/w limit each veth could spool the packets and get
- # them acked at xmit time, so that the corresponding subflow will
- # have almost always no outstanding pkts, the scheduler will pick
- # always the first subflow and we will have hard time testing
- # active backup and link switch-over.
- # Let's set some arbitrary (low) virtual link limits.
- init_shapers
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 dev ns2eth4 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 1
- chk_join_nr "multiple flows, signal, link failure" 3 3 3
- chk_add_nr 1 1
- chk_stale_nr $ns2 1 5 1
+ if reset "multiple flows, signal, link failure"; then
+ # without any b/w limit each veth could spool the packets and get
+ # them acked at xmit time, so that the corresponding subflow will
+ # have almost always no outstanding pkts, the scheduler will pick
+ # always the first subflow and we will have hard time testing
+ # active backup and link switch-over.
+ # Let's set some arbitrary (low) virtual link limits.
+ init_shapers
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 1
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ chk_stale_nr $ns2 1 5 1
+ fi
# accept and use add_addr with additional subflows and link loss
# for bidirectional transfer
- reset
- init_shapers
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 dev ns2eth4 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 2
- chk_join_nr "multi flows, signal, bidi, link fail" 3 3 3
- chk_add_nr 1 1
- chk_stale_nr $ns2 1 -1 1
+ if reset "multi flows, signal, bidi, link fail"; then
+ init_shapers
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 2
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ chk_stale_nr $ns2 1 -1 1
+ fi
# 2 subflows plus 1 backup subflow with a lossy link, backup
# will never be used
- reset
- init_shapers
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- export FAILING_LINKS="1"
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
- run_tests $ns1 $ns2 10.0.1.1 1
- chk_join_nr "backup subflow unused, link failure" 2 2 2
- chk_add_nr 1 1
- chk_link_usage $ns2 ns2eth3 $cinsent 0
+ if reset "backup subflow unused, link failure"; then
+ init_shapers
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
+ pm_nl_set_limits $ns2 1 2
+ FAILING_LINKS="1"
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
+ run_tests $ns1 $ns2 10.0.1.1 1
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ chk_link_usage $ns2 ns2eth3 $cinsent 0
+ fi
# 2 lossy links after half transfer, backup will get half of
# the traffic
- reset
- init_shapers
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
- export FAILING_LINKS="1 2"
- run_tests $ns1 $ns2 10.0.1.1 1
- chk_join_nr "backup flow used, multi links fail" 2 2 2
- chk_add_nr 1 1
- chk_stale_nr $ns2 2 4 2
- chk_link_usage $ns2 ns2eth3 $cinsent 50
+ if reset "backup flow used, multi links fail"; then
+ init_shapers
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
+ FAILING_LINKS="1 2"
+ run_tests $ns1 $ns2 10.0.1.1 1
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ chk_stale_nr $ns2 2 4 2
+ chk_link_usage $ns2 ns2eth3 $cinsent 50
+ fi
# use a backup subflow with the first subflow on a lossy link
# for bidirectional transfer
- reset
- init_shapers
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
- run_tests $ns1 $ns2 10.0.1.1 2
- chk_join_nr "backup flow used, bidi, link failure" 2 2 2
- chk_add_nr 1 1
- chk_stale_nr $ns2 1 -1 2
- chk_link_usage $ns2 ns2eth3 $cinsent 50
+ if reset "backup flow used, bidi, link failure"; then
+ init_shapers
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
+ FAILING_LINKS="1 2"
+ run_tests $ns1 $ns2 10.0.1.1 2
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ chk_stale_nr $ns2 1 -1 2
+ chk_link_usage $ns2 ns2eth3 $cinsent 50
+ fi
}
add_addr_timeout_tests()
{
# add_addr timeout
- reset_with_add_addr_timeout
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
- chk_join_nr "signal address, ADD_ADDR timeout" 1 1 1
- chk_add_nr 4 0
+ if reset_with_add_addr_timeout "signal address, ADD_ADDR timeout"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 4 0
+ fi
# add_addr timeout IPv6
- reset_with_add_addr_timeout 6
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal
- run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
- chk_join_nr "signal address, ADD_ADDR6 timeout" 1 1 1
- chk_add_nr 4 0
+ if reset_with_add_addr_timeout "signal address, ADD_ADDR6 timeout" 6; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
+ run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 4 0
+ fi
# signal addresses timeout
- reset_with_add_addr_timeout
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 least
- chk_join_nr "signal addresses, ADD_ADDR timeout" 2 2 2
- chk_add_nr 8 0
+ if reset_with_add_addr_timeout "signal addresses, ADD_ADDR timeout"; then
+ pm_nl_set_limits $ns1 2 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_set_limits $ns2 2 2
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10
+ chk_join_nr 2 2 2
+ chk_add_nr 8 0
+ fi
# signal invalid addresses timeout
- reset_with_add_addr_timeout
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.12.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 least
- chk_join_nr "invalid address, ADD_ADDR timeout" 1 1 1
- chk_add_nr 8 0
+ if reset_with_add_addr_timeout "invalid address, ADD_ADDR timeout"; then
+ pm_nl_set_limits $ns1 2 2
+ pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_set_limits $ns2 2 2
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10
+ chk_join_nr 1 1 1
+ chk_add_nr 8 0
+ fi
}
remove_tests()
{
# single subflow, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
- chk_join_nr "remove single subflow" 1 1 1
- chk_rm_nr 1 1
+ if reset "remove single subflow"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
+ chk_join_nr 1 1 1
+ chk_rm_nr 1 1
+ fi
# multiple subflows, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 0 -2 slow
- chk_join_nr "remove multiple subflows" 2 2 2
- chk_rm_nr 2 2
+ if reset "remove multiple subflows"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 -2 slow
+ chk_join_nr 2 2 2
+ chk_rm_nr 2 2
+ fi
# single address, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
- chk_join_nr "remove single address" 1 1 1
- chk_add_nr 1 1
- chk_rm_nr 1 1 invert
+ if reset "remove single address"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_rm_nr 1 1 invert
+ fi
# subflow and signal, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
- chk_join_nr "remove subflow and signal" 2 2 2
- chk_add_nr 1 1
- chk_rm_nr 1 1
+ if reset "remove subflow and signal"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ chk_rm_nr 1 1
+ fi
# subflows and signal, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 -1 -2 slow
- chk_join_nr "remove subflows and signal" 3 3 3
- chk_add_nr 1 1
- chk_rm_nr 2 2
+ if reset "remove subflows and signal"; then
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 -1 -2 slow
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ chk_rm_nr 2 2
+ fi
# addresses remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal id 250
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.4.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
- chk_join_nr "remove addresses" 3 3 3
- chk_add_nr 3 3
- chk_rm_nr 3 3 invert
+ if reset "remove addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
+ chk_join_nr 3 3 3
+ chk_add_nr 3 3
+ chk_rm_nr 3 3 invert
+ fi
# invalid addresses remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.12.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.14.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
- chk_join_nr "remove invalid addresses" 1 1 1
- chk_add_nr 3 3
- chk_rm_nr 3 1 invert
+ if reset "remove invalid addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 3 3
+ chk_rm_nr 3 1 invert
+ fi
# subflows and signal, flush
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
- 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
+ if reset "flush subflows and signal"; then
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ 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 3 3 3
+ chk_add_nr 1 1
+ chk_rm_nr 1 3 invert simult
+ fi
# subflows flush
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow id 150
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 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
+ if reset "flush subflows"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_set_limits $ns2 3 3
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow id 150
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ 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 3 3 3
+ chk_rm_nr 0 3 simult
+ fi
# addresses flush
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal id 250
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.4.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- 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
+ if reset "flush addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
+ chk_join_nr 3 3 3
+ chk_add_nr 3 3
+ chk_rm_nr 3 3 invert simult
+ fi
# invalid addresses flush
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 3 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.12.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.14.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 3 3
- run_tests $ns1 $ns2 10.0.1.1 0 -8 0 slow
- chk_join_nr "flush invalid addresses" 1 1 1
- chk_add_nr 3 3
- chk_rm_nr 3 1 invert
+ if reset "flush invalid addresses"; then
+ pm_nl_set_limits $ns1 3 3
+ pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
+ pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
+ pm_nl_set_limits $ns2 3 3
+ run_tests $ns1 $ns2 10.0.1.1 0 -8 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 3 3
+ chk_rm_nr 3 1 invert
+ fi
# remove id 0 subflow
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 0 -9 slow
- chk_join_nr "remove id 0 subflow" 1 1 1
- chk_rm_nr 1 1
+ if reset "remove id 0 subflow"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 -9 slow
+ chk_join_nr 1 1 1
+ chk_rm_nr 1 1
+ fi
# remove id 0 address
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 10.0.1.1 0 -9 0 slow
- chk_join_nr "remove id 0 address" 1 1 1
- chk_add_nr 1 1
- chk_rm_nr 1 1 invert
+ if reset "remove id 0 address"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 -9 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_rm_nr 1 1 invert
+ fi
}
add_tests()
{
# add single subflow
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow
- chk_join_nr "add single subflow" 1 1 1
+ if reset "add single subflow"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow
+ chk_join_nr 1 1 1
+ fi
# add signal address
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
- chk_join_nr "add signal address" 1 1 1
- chk_add_nr 1 1
+ if reset "add signal address"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# add multiple subflows
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- run_tests $ns1 $ns2 10.0.1.1 0 0 2 slow
- chk_join_nr "add multiple subflows" 2 2 2
+ if reset "add multiple subflows"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ run_tests $ns1 $ns2 10.0.1.1 0 0 2 slow
+ chk_join_nr 2 2 2
+ fi
# add multiple subflows IPv6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- run_tests $ns1 $ns2 dead:beef:1::1 0 0 2 slow
- chk_join_nr "add multiple subflows IPv6" 2 2 2
+ if reset "add multiple subflows IPv6"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ run_tests $ns1 $ns2 dead:beef:1::1 0 0 2 slow
+ chk_join_nr 2 2 2
+ fi
# add multiple addresses IPv6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- run_tests $ns1 $ns2 dead:beef:1::1 0 2 0 slow
- chk_join_nr "add multiple addresses IPv6" 2 2 2
- chk_add_nr 2 2
+ if reset "add multiple addresses IPv6"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 2 2
+ run_tests $ns1 $ns2 dead:beef:1::1 0 2 0 slow
+ chk_join_nr 2 2 2
+ chk_add_nr 2 2
+ fi
}
ipv6_tests()
{
# subflow IPv6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 flags subflow
- run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
- chk_join_nr "single subflow IPv6" 1 1 1
+ if reset "single subflow IPv6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 dead:beef:3::2 dev ns2eth3 flags subflow
+ run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
+ chk_join_nr 1 1 1
+ fi
# add_address, unused IPv6
- reset
- ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal
- run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
- chk_join_nr "unused signal address IPv6" 0 0 0
- chk_add_nr 1 1
+ if reset "unused signal address IPv6"; then
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
+ run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
+ chk_join_nr 0 0 0
+ chk_add_nr 1 1
+ fi
# signal address IPv6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
- chk_join_nr "single address IPv6" 1 1 1
- chk_add_nr 1 1
+ if reset "single address IPv6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# single address IPv6, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 dead:beef:1::1 0 -1 0 slow
- chk_join_nr "remove single address IPv6" 1 1 1
- chk_add_nr 1 1
- chk_rm_nr 1 1 invert
+ if reset "remove single address IPv6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 dead:beef:1::1 0 -1 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_rm_nr 1 1 invert
+ fi
# subflow and signal IPv6, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 flags subflow
- run_tests $ns1 $ns2 dead:beef:1::1 0 -1 -1 slow
- chk_join_nr "remove subflow and signal IPv6" 2 2 2
- chk_add_nr 1 1
- chk_rm_nr 1 1
+ if reset "remove subflow and signal IPv6"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 dead:beef:3::2 dev ns2eth3 flags subflow
+ run_tests $ns1 $ns2 dead:beef:1::1 0 -1 -1 slow
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ chk_rm_nr 1 1
+ fi
}
v4mapped_tests()
{
# subflow IPv4-mapped to IPv4-mapped
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add "::ffff:10.0.3.2" flags subflow
- run_tests $ns1 $ns2 "::ffff:10.0.1.1"
- chk_join_nr "single subflow IPv4-mapped" 1 1 1
+ if reset "single subflow IPv4-mapped"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 "::ffff:10.0.3.2" flags subflow
+ run_tests $ns1 $ns2 "::ffff:10.0.1.1"
+ chk_join_nr 1 1 1
+ fi
# signal address IPv4-mapped with IPv4-mapped sk
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add "::ffff:10.0.2.1" flags signal
- run_tests $ns1 $ns2 "::ffff:10.0.1.1"
- chk_join_nr "signal address IPv4-mapped" 1 1 1
- chk_add_nr 1 1
+ if reset "signal address IPv4-mapped"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 "::ffff:10.0.2.1" flags signal
+ run_tests $ns1 $ns2 "::ffff:10.0.1.1"
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# subflow v4-map-v6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 "::ffff:10.0.1.1"
- chk_join_nr "single subflow v4-map-v6" 1 1 1
+ if reset "single subflow v4-map-v6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 "::ffff:10.0.1.1"
+ chk_join_nr 1 1 1
+ fi
# signal address v4-map-v6
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 "::ffff:10.0.1.1"
- chk_join_nr "signal address v4-map-v6" 1 1 1
- chk_add_nr 1 1
+ if reset "signal address v4-map-v6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 "::ffff:10.0.1.1"
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# subflow v6-map-v4
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add "::ffff:10.0.3.2" flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow v6-map-v4" 1 1 1
+ if reset "single subflow v6-map-v4"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 "::ffff:10.0.3.2" flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
# signal address v6-map-v4
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add "::ffff:10.0.2.1" flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address v6-map-v4" 1 1 1
- chk_add_nr 1 1
+ if reset "signal address v6-map-v4"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 "::ffff:10.0.2.1" flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# no subflow IPv6 to v4 address
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:2::2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "no JOIN with diff families v4-v6" 0 0 0
+ if reset "no JOIN with diff families v4-v6"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# no subflow IPv6 to v4 address even if v6 has a valid v4 at the end
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:2::10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "no JOIN with diff families v4-v6-2" 0 0 0
+ if reset "no JOIN with diff families v4-v6-2"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 dead:beef:2::10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# no subflow IPv4 to v6 address, no need to slow down too then
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 dead:beef:1::1
- chk_join_nr "no JOIN with diff families v6-v4" 0 0 0
+ if reset "no JOIN with diff families v6-v4"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 dead:beef:1::1
+ chk_join_nr 0 0 0
+ fi
}
backup_tests()
{
# single subflow, backup
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow,backup
- run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup
- chk_join_nr "single subflow, backup" 1 1 1
- chk_prio_nr 0 1
+ if reset "single subflow, backup"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup
+ chk_join_nr 1 1 1
+ chk_prio_nr 0 1
+ fi
# single address, backup
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- 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
+ if reset "single address, backup"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_prio_nr 1 1
+ fi
+
+ # single address with port, backup
+ if reset "single address with port, backup"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_prio_nr 1 1
+ fi
+
+ if reset "mpc backup"; then
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 0 0 0
+ chk_prio_nr 0 1
+ fi
+
+ if reset "mpc backup both sides"; then
+ pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow,backup
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,backup
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
+ chk_join_nr 0 0 0
+ chk_prio_nr 1 1
+ fi
+
+ if reset "mpc switch to backup"; then
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+ chk_join_nr 0 0 0
+ chk_prio_nr 0 1
+ fi
+
+ if reset "mpc switch to backup both sides"; then
+ pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+ chk_join_nr 0 0 0
+ chk_prio_nr 1 1
+ fi
}
add_addr_ports_tests()
{
# signal address with port
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address with port" 1 1 1
- chk_add_nr 1 1 1
+ if reset "signal address with port"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1 1
+ fi
# subflow and signal with port
- reset
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflow and signal with port" 2 2 2
- chk_add_nr 1 1 1
+ if reset "subflow and signal with port"; then
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1 1
+ fi
# single address with port, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
- chk_join_nr "remove single address with port" 1 1 1
- chk_add_nr 1 1 1
- chk_rm_nr 1 1 invert
+ if reset "remove single address with port"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1 1
+ chk_rm_nr 1 1 invert
+ fi
# subflow and signal with port, remove
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
- chk_join_nr "remove subflow and signal with port" 2 2 2
- chk_add_nr 1 1 1
- chk_rm_nr 1 1
+ if reset "remove subflow and signal with port"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1 1
+ chk_rm_nr 1 1
+ fi
# subflows and signal with port, flush
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
- 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
+ if reset "flush subflows and signal with port"; then
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 -8 -2 slow
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ chk_rm_nr 1 3 invert simult
+ fi
# multiple addresses with port
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal port 10100
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple addresses with port" 2 2 2
- chk_add_nr 2 2 2
+ if reset "multiple addresses with port"; then
+ pm_nl_set_limits $ns1 2 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10100
+ pm_nl_set_limits $ns2 2 2
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ chk_add_nr 2 2 2
+ fi
# multiple addresses with ports
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal port 10100
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.3.1 flags signal port 10101
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple addresses with ports" 2 2 2
- chk_add_nr 2 2 2
+ if reset "multiple addresses with ports"; then
+ pm_nl_set_limits $ns1 2 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
+ pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10101
+ pm_nl_set_limits $ns2 2 2
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ chk_add_nr 2 2 2
+ fi
}
syncookies_tests()
{
# single subflow, syncookies
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow with syn cookies" 1 1 1
+ if reset_with_cookies "single subflow with syn cookies"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
# multiple subflows with syn cookies
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "multiple subflows with syn cookies" 2 2 2
+ if reset_with_cookies "multiple subflows with syn cookies"; then
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ fi
# multiple subflows limited by server
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflows limited by server w cookies" 2 1 1
+ if reset_with_cookies "subflows limited by server w cookies"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 1 1
+ fi
# test signal address with cookies
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address with syn cookies" 1 1 1
- chk_add_nr 1 1
+ if reset_with_cookies "signal address with syn cookies"; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# test cookie with subflow and signal
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns1 ./pm_nl_ctl limits 0 2
- ip netns exec $ns2 ./pm_nl_ctl limits 1 2
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflow and signal w cookies" 2 2 2
- chk_add_nr 1 1
+ if reset_with_cookies "subflow and signal w cookies"; then
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 1 2
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ chk_add_nr 1 1
+ fi
# accept and use add_addr with additional subflows
- reset_with_cookies
- ip netns exec $ns1 ./pm_nl_ctl limits 0 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflows and signal w. cookies" 3 3 3
- chk_add_nr 1 1
+ if reset_with_cookies "subflows and signal w. cookies"; then
+ pm_nl_set_limits $ns1 0 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ fi
}
checksum_tests()
{
# checksum test 0 0
- reset_with_checksum 0 0
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- run_tests $ns1 $ns2 10.0.1.1
- chk_csum_nr "checksum test 0 0"
+ if reset_with_checksum 0 0; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# checksum test 1 1
- reset_with_checksum 1 1
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- run_tests $ns1 $ns2 10.0.1.1
- chk_csum_nr "checksum test 1 1"
+ if reset_with_checksum 1 1; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# checksum test 0 1
- reset_with_checksum 0 1
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- run_tests $ns1 $ns2 10.0.1.1
- chk_csum_nr "checksum test 0 1"
+ if reset_with_checksum 0 1; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# checksum test 1 0
- reset_with_checksum 1 0
- ip netns exec $ns1 ./pm_nl_ctl limits 0 1
- ip netns exec $ns2 ./pm_nl_ctl limits 0 1
- run_tests $ns1 $ns2 10.0.1.1
- chk_csum_nr "checksum test 1 0"
+ if reset_with_checksum 1 0; then
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
}
deny_join_id0_tests()
{
# subflow allow join id0 ns1
- reset_with_allow_join_id0 1 0
- ip netns exec $ns1 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow allow join id0 ns1" 1 1 1
+ if reset_with_allow_join_id0 "single subflow allow join id0 ns1" 1 0; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
# subflow allow join id0 ns2
- reset_with_allow_join_id0 0 1
- ip netns exec $ns1 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "single subflow allow join id0 ns2" 0 0 0
+ if reset_with_allow_join_id0 "single subflow allow join id0 ns2" 0 1; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
# signal address allow join id0 ns1
# ADD_ADDRs are not affected by allow_join_id0 value.
- reset_with_allow_join_id0 1 0
- ip netns exec $ns1 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address allow join id0 ns1" 1 1 1
- chk_add_nr 1 1
+ if reset_with_allow_join_id0 "signal address allow join id0 ns1" 1 0; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# signal address allow join id0 ns2
# ADD_ADDRs are not affected by allow_join_id0 value.
- reset_with_allow_join_id0 0 1
- ip netns exec $ns1 ./pm_nl_ctl limits 1 1
- ip netns exec $ns2 ./pm_nl_ctl limits 1 1
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "signal address allow join id0 ns2" 1 1 1
- chk_add_nr 1 1
+ if reset_with_allow_join_id0 "signal address allow join id0 ns2" 0 1; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ fi
# subflow and address allow join id0 ns1
- reset_with_allow_join_id0 1 0
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflow and address allow join id0 1" 2 2 2
+ if reset_with_allow_join_id0 "subflow and address allow join id0 1" 1 0; then
+ 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
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 2 2 2
+ fi
# subflow and address allow join id0 ns2
- reset_with_allow_join_id0 0 1
- ip netns exec $ns1 ./pm_nl_ctl limits 2 2
- ip netns exec $ns2 ./pm_nl_ctl limits 2 2
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
- run_tests $ns1 $ns2 10.0.1.1
- chk_join_nr "subflow and address allow join id0 2" 1 1 1
+ if reset_with_allow_join_id0 "subflow and address allow join id0 2" 0 1; then
+ 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
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 1
+ fi
}
fullmesh_tests()
@@ -1845,177 +2757,377 @@ fullmesh_tests()
# fullmesh 1
# 2 fullmesh addrs in ns2, added before the connection,
# 1 non-fullmesh addr in ns1, added during the connection.
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 0 4
- ip netns exec $ns2 ./pm_nl_ctl limits 1 4
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow,fullmesh
- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow,fullmesh
- run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
- chk_join_nr "fullmesh test 2x1" 4 4 4
- chk_add_nr 1 1
+ if reset "fullmesh test 2x1"; then
+ pm_nl_set_limits $ns1 0 4
+ pm_nl_set_limits $ns2 1 4
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,fullmesh
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,fullmesh
+ run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
+ chk_join_nr 4 4 4
+ chk_add_nr 1 1
+ fi
# fullmesh 2
# 1 non-fullmesh addr in ns1, added before the connection,
# 1 fullmesh addr in ns2, added during the connection.
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 1 3
- ip netns exec $ns2 ./pm_nl_ctl limits 1 3
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow
- chk_join_nr "fullmesh test 1x1" 3 3 3
- chk_add_nr 1 1
+ if reset "fullmesh test 1x1"; then
+ pm_nl_set_limits $ns1 1 3
+ pm_nl_set_limits $ns2 1 3
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow
+ chk_join_nr 3 3 3
+ chk_add_nr 1 1
+ fi
# fullmesh 3
# 1 non-fullmesh addr in ns1, added before the connection,
# 2 fullmesh addrs in ns2, added during the connection.
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 2 5
- ip netns exec $ns2 ./pm_nl_ctl limits 1 5
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
- chk_join_nr "fullmesh test 1x2" 5 5 5
- chk_add_nr 1 1
+ if reset "fullmesh test 1x2"; then
+ pm_nl_set_limits $ns1 2 5
+ pm_nl_set_limits $ns2 1 5
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
+ chk_join_nr 5 5 5
+ chk_add_nr 1 1
+ fi
# fullmesh 4
# 1 non-fullmesh addr in ns1, added before the connection,
# 2 fullmesh addrs in ns2, added during the connection,
# limit max_subflows to 4.
- reset
- ip netns exec $ns1 ./pm_nl_ctl limits 2 4
- ip netns exec $ns2 ./pm_nl_ctl limits 1 4
- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
- run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
- chk_join_nr "fullmesh test 1x2, limited" 4 4 4
- chk_add_nr 1 1
-}
-
-all_tests()
-{
- subflows_tests
- subflows_error_tests
- signal_address_tests
- link_failure_tests
- add_addr_timeout_tests
- remove_tests
- add_tests
- ipv6_tests
- v4mapped_tests
- backup_tests
- add_addr_ports_tests
- syncookies_tests
- checksum_tests
- deny_join_id0_tests
- fullmesh_tests
+ if reset "fullmesh test 1x2, limited"; then
+ pm_nl_set_limits $ns1 2 4
+ pm_nl_set_limits $ns2 1 4
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
+ chk_join_nr 4 4 4
+ chk_add_nr 1 1
+ fi
+
+ # set fullmesh flag
+ if reset "set fullmesh flag test"; then
+ pm_nl_set_limits $ns1 4 4
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
+ pm_nl_set_limits $ns2 4 4
+ run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow fullmesh
+ chk_join_nr 2 2 2
+ chk_rm_nr 0 1
+ fi
+
+ # set nofullmesh flag
+ if reset "set nofullmesh flag test"; then
+ pm_nl_set_limits $ns1 4 4
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow,fullmesh
+ pm_nl_set_limits $ns2 4 4
+ run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow nofullmesh
+ chk_join_nr 2 2 2
+ chk_rm_nr 0 1
+ fi
+
+ # set backup,fullmesh flags
+ if reset "set backup,fullmesh flags test"; then
+ pm_nl_set_limits $ns1 4 4
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
+ pm_nl_set_limits $ns2 4 4
+ run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow backup,fullmesh
+ chk_join_nr 2 2 2
+ chk_prio_nr 0 1
+ chk_rm_nr 0 1
+ fi
+
+ # set nobackup,nofullmesh flags
+ if reset "set nobackup,nofullmesh flags test"; then
+ pm_nl_set_limits $ns1 4 4
+ pm_nl_set_limits $ns2 4 4
+ pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup,fullmesh
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup,nofullmesh
+ chk_join_nr 2 2 2
+ chk_prio_nr 0 1
+ chk_rm_nr 0 1
+ fi
+}
+
+fastclose_tests()
+{
+ if reset "fastclose test"; then
+ run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_client
+ chk_join_nr 0 0 0
+ chk_fclose_nr 1 1
+ chk_rst_nr 1 1 invert
+ fi
+
+ if reset "fastclose server test"; then
+ run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_server
+ chk_join_nr 0 0 0
+ chk_fclose_nr 1 1 invert
+ chk_rst_nr 1 1
+ fi
+}
+
+pedit_action_pkts()
+{
+ tc -n $ns2 -j -s action show action pedit index 100 | \
+ grep "packets" | \
+ sed 's/.*"packets":\([0-9]\+\),.*/\1/'
+}
+
+fail_tests()
+{
+ # single subflow
+ if reset_with_fail "Infinite map" 1; then
+ run_tests $ns1 $ns2 10.0.1.1 128
+ chk_join_nr 0 0 0 +1 +0 1 0 1 "$(pedit_action_pkts)"
+ chk_fail_nr 1 -1 invert
+ fi
+
+ # multiple subflows
+ if reset_with_fail "MP_FAIL MP_RST" 2; then
+ tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 1024
+ chk_join_nr 1 1 1 1 0 1 1 0 "$(pedit_action_pkts)"
+ fi
}
+userspace_tests()
+{
+ # userspace pm type prevents add_addr
+ if reset "userspace pm type prevents add_addr"; then
+ set_userspace_pm $ns1
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ chk_add_nr 0 0
+ fi
+
+ # userspace pm type does not echo add_addr without daemon
+ if reset "userspace pm no echo w/o daemon"; then
+ set_userspace_pm $ns2
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ chk_add_nr 1 0
+ fi
+
+ # userspace pm type rejects join
+ if reset "userspace pm type rejects join"; then
+ set_userspace_pm $ns1
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 1 1 0
+ fi
+
+ # userspace pm type does not send join
+ if reset "userspace pm type does not send join"; then
+ set_userspace_pm $ns2
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1
+ chk_join_nr 0 0 0
+ fi
+
+ # userspace pm type prevents mp_prio
+ if reset "userspace pm type prevents mp_prio"; then
+ set_userspace_pm $ns1
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
+ chk_join_nr 1 1 0
+ chk_prio_nr 0 0
+ fi
+
+ # userspace pm type prevents rm_addr
+ if reset "userspace pm type prevents rm_addr"; then
+ set_userspace_pm $ns1
+ set_userspace_pm $ns2
+ pm_nl_set_limits $ns1 0 1
+ pm_nl_set_limits $ns2 0 1
+ pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
+ chk_join_nr 0 0 0
+ chk_rm_nr 0 0
+ fi
+
+ # userspace pm add & remove address
+ if reset "userspace pm add & remove address"; then
+ set_userspace_pm $ns1
+ pm_nl_set_limits $ns2 1 1
+ run_tests $ns1 $ns2 10.0.1.1 0 userspace_1 0 slow
+ chk_join_nr 1 1 1
+ chk_add_nr 1 1
+ chk_rm_nr 1 1 invert
+ fi
+
+ # userspace pm create destroy subflow
+ if reset "userspace pm create destroy subflow"; then
+ set_userspace_pm $ns2
+ pm_nl_set_limits $ns1 0 1
+ run_tests $ns1 $ns2 10.0.1.1 0 0 userspace_1 slow
+ chk_join_nr 1 1 1
+ chk_rm_nr 0 1
+ fi
+}
+
+endpoint_tests()
+{
+ # userspace pm type prevents add_addr
+ if reset "implicit EP"; then
+ 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
+ pm_nl_check_endpoint 1 "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 0 "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 0 "modif is allowed" \
+ $ns2 10.0.2.2 id 1 flags signal
+ wait
+ fi
+
+ if reset "delete and re-add"; then
+ pm_nl_set_limits $ns1 1 1
+ pm_nl_set_limits $ns2 1 1
+ pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 4 0 0 slow &
+
+ wait_mpj $ns2
+ pm_nl_del_endpoint $ns2 2 10.0.2.2
+ sleep 0.5
+ chk_subflow_nr needtitle "after delete" 1
+
+ pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
+ wait_mpj $ns2
+ chk_subflow_nr "" "after re-add" 2
+ wait
+ fi
+}
+
+# [$1: error message]
usage()
{
+ if [ -n "${1}" ]; then
+ echo "${1}"
+ ret=1
+ fi
+
echo "mptcp_join usage:"
- echo " -f subflows_tests"
- echo " -e subflows_error_tests"
- echo " -s signal_address_tests"
- echo " -l link_failure_tests"
- echo " -t add_addr_timeout_tests"
- echo " -r remove_tests"
- echo " -a add_tests"
- echo " -6 ipv6_tests"
- echo " -4 v4mapped_tests"
- echo " -b backup_tests"
- echo " -p add_addr_ports_tests"
- echo " -k syncookies_tests"
- echo " -S checksum_tests"
- echo " -d deny_join_id0_tests"
- echo " -m fullmesh_tests"
+
+ local key
+ for key in "${!all_tests[@]}"; do
+ echo " -${key} ${all_tests[${key}]}"
+ done
+
echo " -c capture pcap files"
echo " -C enable data checksum"
+ echo " -i use ip mptcp"
echo " -h help"
-}
-sin=$(mktemp)
-sout=$(mktemp)
-cin=$(mktemp)
-cinsent=$(mktemp)
-cout=$(mktemp)
-init
-make_file "$cin" "client" 1
-make_file "$sin" "server" 1
-trap cleanup EXIT
+ echo "[test ids|names]"
-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
+ exit ${ret}
+}
- # exception for the capture/checksum options, the rest means: a part of the tests
- if [ "${arg}" != "-c" ] && [ "${arg}" != "-C" ]; then
- do_all_tests=0
- fi
-done
-if [ $do_all_tests -eq 1 ]; then
- all_tests
- exit $ret
-fi
+# Use a "simple" array to force an specific order we cannot have with an associative one
+all_tests_sorted=(
+ f@subflows_tests
+ e@subflows_error_tests
+ s@signal_address_tests
+ l@link_failure_tests
+ t@add_addr_timeout_tests
+ r@remove_tests
+ a@add_tests
+ 6@ipv6_tests
+ 4@v4mapped_tests
+ b@backup_tests
+ p@add_addr_ports_tests
+ k@syncookies_tests
+ S@checksum_tests
+ d@deny_join_id0_tests
+ m@fullmesh_tests
+ z@fastclose_tests
+ F@fail_tests
+ u@userspace_tests
+ I@endpoint_tests
+)
+
+all_tests_args=""
+all_tests_names=()
+for subtests in "${all_tests_sorted[@]}"; do
+ key="${subtests%@*}"
+ value="${subtests#*@}"
+
+ all_tests_args+="${key}"
+ all_tests_names+=("${value}")
+ all_tests[${key}]="${value}"
+done
-while getopts 'fesltra64bpkdmchCS' opt; do
+tests=()
+while getopts "${all_tests_args}cCih" opt; do
case $opt in
- f)
- subflows_tests
- ;;
- e)
- subflows_error_tests
- ;;
- s)
- signal_address_tests
- ;;
- l)
- link_failure_tests
- ;;
- t)
- add_addr_timeout_tests
- ;;
- r)
- remove_tests
- ;;
- a)
- add_tests
- ;;
- 6)
- ipv6_tests
- ;;
- 4)
- v4mapped_tests
- ;;
- b)
- backup_tests
- ;;
- p)
- add_addr_ports_tests
- ;;
- k)
- syncookies_tests
- ;;
- S)
- checksum_tests
- ;;
- d)
- deny_join_id0_tests
- ;;
- m)
- fullmesh_tests
+ ["${all_tests_args}"])
+ tests+=("${all_tests[${opt}]}")
;;
c)
+ capture=1
;;
C)
+ checksum=1
;;
- h | *)
+ i)
+ ip_mptcp=1
+ ;;
+ h)
usage
;;
+ *)
+ usage "Unknown option: -${opt}"
+ ;;
esac
done
+shift $((OPTIND - 1))
+
+for arg in "${@}"; do
+ if [[ "${arg}" =~ ^[0-9]+$ ]]; then
+ only_tests_ids+=("${arg}")
+ else
+ only_tests_names+=("${arg}")
+ fi
+done
+
+if [ ${#tests[@]} -eq 0 ]; then
+ tests=("${all_tests_names[@]}")
+fi
+
+for subtests in "${tests[@]}"; do
+ "${subtests}"
+done
+
+if [ ${ret} -ne 0 ]; then
+ echo
+ echo "${#failed_tests[@]} failure(s) has(ve) been detected:"
+ for i in $(get_failed_tests_ids); do
+ echo -e "\t- ${i}: ${failed_tests[${i}]}"
+ done
+ echo
+fi
+
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index ac9a4d9c1764..ae61f39556ca 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -136,7 +136,7 @@ static void xgetaddrinfo(const char *node, const char *service,
static int sock_listen_mptcp(const char * const listenaddr,
const char * const port)
{
- int sock;
+ int sock = -1;
struct addrinfo hints = {
.ai_protocol = IPPROTO_TCP,
.ai_socktype = SOCK_STREAM,
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index cbacf9f6538b..89839d1ff9d8 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -164,4 +164,22 @@ id 253 flags 10.0.0.5
id 254 flags 10.0.0.2
id 255 flags 10.0.0.3" "wrap-around ids"
+ip netns exec $ns1 ./pm_nl_ctl flush
+ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 flags subflow
+ip netns exec $ns1 ./pm_nl_ctl set 10.0.1.1 flags backup
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+subflow,backup 10.0.1.1" "set flags (backup)"
+ip netns exec $ns1 ./pm_nl_ctl set 10.0.1.1 flags nobackup
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+subflow 10.0.1.1" " (nobackup)"
+ip netns exec $ns1 ./pm_nl_ctl set id 1 flags fullmesh
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+subflow,fullmesh 10.0.1.1" " (fullmesh)"
+ip netns exec $ns1 ./pm_nl_ctl set id 1 flags nofullmesh
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+subflow 10.0.1.1" " (nofullmesh)"
+ip netns exec $ns1 ./pm_nl_ctl set id 1 flags backup,fullmesh
+check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags \
+subflow,backup,fullmesh 10.0.1.1" " (backup,fullmesh)"
+
exit $ret
diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
index 354784512748..abddf4c63e79 100644
--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -21,17 +22,29 @@
#ifndef MPTCP_PM_NAME
#define MPTCP_PM_NAME "mptcp_pm"
#endif
+#ifndef MPTCP_PM_EVENTS
+#define MPTCP_PM_EVENTS "mptcp_pm_events"
+#endif
+#ifndef IPPROTO_MPTCP
+#define IPPROTO_MPTCP 262
+#endif
static void syntax(char *argv[])
{
- fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", argv[0]);
+ fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
fprintf(stderr, "\tadd [flags signal|subflow|backup|fullmesh] [id <nr>] [dev <name>] <ip>\n");
+ fprintf(stderr, "\tann <local-ip> id <local-id> token <token> [port <local-port>] [dev <name>]\n");
+ fprintf(stderr, "\trem id <local-id> token <token>\n");
+ fprintf(stderr, "\tcsf lip <local-ip> lid <local-id> rip <remote-ip> rport <remote-port> token <token>\n");
+ fprintf(stderr, "\tdsf lip <local-ip> lport <local-port> rip <remote-ip> rport <remote-port> token <token>\n");
fprintf(stderr, "\tdel <id> [<ip>]\n");
fprintf(stderr, "\tget <id>\n");
- fprintf(stderr, "\tset <ip> [flags backup|nobackup]\n");
+ fprintf(stderr, "\tset [<ip>] [id <nr>] flags [no]backup|[no]fullmesh [port <nr>] [token <token>] [rip <ip>] [rport <port>]\n");
fprintf(stderr, "\tflush\n");
fprintf(stderr, "\tdump\n");
fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
+ fprintf(stderr, "\tevents\n");
+ fprintf(stderr, "\tlisten <local-ip> <local-port>\n");
exit(0);
}
@@ -83,6 +96,108 @@ static void nl_error(struct nlmsghdr *nh)
}
}
+static int capture_events(int fd, int event_group)
+{
+ u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
+ struct genlmsghdr *ghdr;
+ struct rtattr *attrs;
+ struct nlmsghdr *nh;
+ int ret = 0;
+ int res_len;
+ int msg_len;
+ fd_set rfds;
+
+ if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &event_group, sizeof(event_group)) < 0)
+ error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
+
+ do {
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
+
+ ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
+
+ if (ret < 0)
+ error(1, ret, "error in select() on NL socket");
+
+ res_len = recv(fd, buffer, res_len, 0);
+ if (res_len < 0)
+ error(1, res_len, "error on recv() from NL socket");
+
+ nh = (struct nlmsghdr *)buffer;
+
+ for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
+ if (nh->nlmsg_type == NLMSG_ERROR)
+ error(1, NLMSG_ERROR, "received invalid NL message");
+
+ ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
+
+ if (ghdr->cmd == 0)
+ continue;
+
+ fprintf(stderr, "type:%d", ghdr->cmd);
+
+ msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
+
+ attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
+ while (RTA_OK(attrs, msg_len)) {
+ if (attrs->rta_type == MPTCP_ATTR_TOKEN)
+ fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
+ fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
+ fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
+ fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
+ u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
+
+ fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
+ (saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
+ (saddr4 & 0xFF));
+ } else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
+ char buf[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
+ sizeof(buf)) != NULL)
+ fprintf(stderr, ",saddr6:%s", buf);
+ } else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
+ u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
+
+ fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
+ (daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
+ (daddr4 & 0xFF));
+ } else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
+ char buf[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
+ sizeof(buf)) != NULL)
+ fprintf(stderr, ",daddr6:%s", buf);
+ } else if (attrs->rta_type == MPTCP_ATTR_SPORT)
+ fprintf(stderr, ",sport:%u",
+ ntohs(*(__u16 *)RTA_DATA(attrs)));
+ else if (attrs->rta_type == MPTCP_ATTR_DPORT)
+ fprintf(stderr, ",dport:%u",
+ ntohs(*(__u16 *)RTA_DATA(attrs)));
+ else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
+ fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_ERROR)
+ fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
+ fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
+
+ attrs = RTA_NEXT(attrs, msg_len);
+ }
+ }
+ fprintf(stderr, "\n");
+ } while (1);
+
+ return 0;
+}
+
/* do a netlink command and, if max > 0, fetch the reply */
static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
{
@@ -116,11 +231,18 @@ static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
return ret;
}
-static int genl_parse_getfamily(struct nlmsghdr *nlh)
+static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
+ int *events_mcast_grp)
{
struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
int len = nlh->nlmsg_len;
struct rtattr *attrs;
+ struct rtattr *grps;
+ struct rtattr *grp;
+ int got_events_grp;
+ int got_family;
+ int grps_len;
+ int grp_len;
if (nlh->nlmsg_type != GENL_ID_CTRL)
error(1, errno, "Not a controller message, len=%d type=0x%x\n",
@@ -135,9 +257,42 @@ static int genl_parse_getfamily(struct nlmsghdr *nlh)
error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
+ got_family = 0;
+ got_events_grp = 0;
+
while (RTA_OK(attrs, len)) {
- if (attrs->rta_type == CTRL_ATTR_FAMILY_ID)
- return *(__u16 *)RTA_DATA(attrs);
+ if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
+ *pm_family = *(__u16 *)RTA_DATA(attrs);
+ got_family = 1;
+ } else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
+ grps = RTA_DATA(attrs);
+ grps_len = RTA_PAYLOAD(attrs);
+
+ while (RTA_OK(grps, grps_len)) {
+ grp = RTA_DATA(grps);
+ grp_len = RTA_PAYLOAD(grps);
+ got_events_grp = 0;
+
+ while (RTA_OK(grp, grp_len)) {
+ if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
+ *events_mcast_grp = *(__u32 *)RTA_DATA(grp);
+ else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
+ !strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
+ got_events_grp = 1;
+
+ grp = RTA_NEXT(grp, grp_len);
+ }
+
+ if (got_events_grp)
+ break;
+
+ grps = RTA_NEXT(grps, grps_len);
+ }
+ }
+
+ if (got_family && got_events_grp)
+ return 0;
+
attrs = RTA_NEXT(attrs, len);
}
@@ -145,7 +300,7 @@ static int genl_parse_getfamily(struct nlmsghdr *nlh)
return -1;
}
-static int resolve_mptcp_pm_netlink(int fd)
+static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
{
char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
@@ -167,7 +322,421 @@ static int resolve_mptcp_pm_netlink(int fd)
off += NLMSG_ALIGN(rta->rta_len);
do_nl_req(fd, nh, off, sizeof(data));
- return genl_parse_getfamily((void *)data);
+ return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
+}
+
+int dsf(int fd, int pm_family, int argc, char *argv[])
+{
+ char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
+ 1024];
+ struct rtattr *rta, *addr;
+ u_int16_t family, port;
+ struct nlmsghdr *nh;
+ u_int32_t token;
+ int addr_start;
+ int off = 0;
+ int arg;
+
+ const char *params[5];
+
+ memset(params, 0, 5 * sizeof(const char *));
+
+ memset(data, 0, sizeof(data));
+ nh = (void *)data;
+ off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_DESTROY,
+ MPTCP_PM_VER);
+
+ if (argc < 12)
+ syntax(argv);
+
+ /* Params recorded in this order:
+ * <local-ip>, <local-port>, <remote-ip>, <remote-port>, <token>
+ */
+ for (arg = 2; arg < argc; arg++) {
+ if (!strcmp(argv[arg], "lip")) {
+ if (++arg >= argc)
+ error(1, 0, " missing local IP");
+
+ params[0] = argv[arg];
+ } else if (!strcmp(argv[arg], "lport")) {
+ if (++arg >= argc)
+ error(1, 0, " missing local port");
+
+ params[1] = argv[arg];
+ } else if (!strcmp(argv[arg], "rip")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote IP");
+
+ params[2] = argv[arg];
+ } else if (!strcmp(argv[arg], "rport")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote port");
+
+ params[3] = argv[arg];
+ } else if (!strcmp(argv[arg], "token")) {
+ if (++arg >= argc)
+ error(1, 0, " missing token");
+
+ params[4] = argv[arg];
+ } else
+ error(1, 0, "unknown keyword %s", argv[arg]);
+ }
+
+ for (arg = 0; arg < 4; arg = arg + 2) {
+ /* addr header */
+ addr_start = off;
+ addr = (void *)(data + off);
+ addr->rta_type = NLA_F_NESTED |
+ ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
+ addr->rta_len = RTA_LENGTH(0);
+ off += NLMSG_ALIGN(addr->rta_len);
+
+ /* addr data */
+ rta = (void *)(data + off);
+ if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
+ family = AF_INET;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+ rta->rta_len = RTA_LENGTH(4);
+ } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
+ family = AF_INET6;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+ rta->rta_len = RTA_LENGTH(16);
+ } else
+ error(1, errno, "can't parse ip %s", params[arg]);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* family */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &family, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* port */
+ port = atoi(params[arg + 1]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &port, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ addr->rta_len = off - addr_start;
+ }
+
+ /* token */
+ token = atoi(params[4]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &token, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ do_nl_req(fd, nh, off, 0);
+
+ return 0;
+}
+
+int csf(int fd, int pm_family, int argc, char *argv[])
+{
+ char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
+ 1024];
+ const char *params[5];
+ struct nlmsghdr *nh;
+ struct rtattr *addr;
+ struct rtattr *rta;
+ u_int16_t family;
+ u_int32_t token;
+ u_int16_t port;
+ int addr_start;
+ u_int8_t id;
+ int off = 0;
+ int arg;
+
+ memset(params, 0, 5 * sizeof(const char *));
+
+ memset(data, 0, sizeof(data));
+ nh = (void *)data;
+ off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SUBFLOW_CREATE,
+ MPTCP_PM_VER);
+
+ if (argc < 12)
+ syntax(argv);
+
+ /* Params recorded in this order:
+ * <local-ip>, <local-id>, <remote-ip>, <remote-port>, <token>
+ */
+ for (arg = 2; arg < argc; arg++) {
+ if (!strcmp(argv[arg], "lip")) {
+ if (++arg >= argc)
+ error(1, 0, " missing local IP");
+
+ params[0] = argv[arg];
+ } else if (!strcmp(argv[arg], "lid")) {
+ if (++arg >= argc)
+ error(1, 0, " missing local id");
+
+ params[1] = argv[arg];
+ } else if (!strcmp(argv[arg], "rip")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote ip");
+
+ params[2] = argv[arg];
+ } else if (!strcmp(argv[arg], "rport")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote port");
+
+ params[3] = argv[arg];
+ } else if (!strcmp(argv[arg], "token")) {
+ if (++arg >= argc)
+ error(1, 0, " missing token");
+
+ params[4] = argv[arg];
+ } else
+ error(1, 0, "unknown param %s", argv[arg]);
+ }
+
+ for (arg = 0; arg < 4; arg = arg + 2) {
+ /* addr header */
+ addr_start = off;
+ addr = (void *)(data + off);
+ addr->rta_type = NLA_F_NESTED |
+ ((arg == 0) ? MPTCP_PM_ATTR_ADDR : MPTCP_PM_ATTR_ADDR_REMOTE);
+ addr->rta_len = RTA_LENGTH(0);
+ off += NLMSG_ALIGN(addr->rta_len);
+
+ /* addr data */
+ rta = (void *)(data + off);
+ if (inet_pton(AF_INET, params[arg], RTA_DATA(rta))) {
+ family = AF_INET;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+ rta->rta_len = RTA_LENGTH(4);
+ } else if (inet_pton(AF_INET6, params[arg], RTA_DATA(rta))) {
+ family = AF_INET6;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+ rta->rta_len = RTA_LENGTH(16);
+ } else
+ error(1, errno, "can't parse ip %s", params[arg]);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* family */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &family, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ if (arg == 2) {
+ /* port */
+ port = atoi(params[arg + 1]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &port, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+ }
+
+ if (arg == 0) {
+ /* id */
+ id = atoi(params[arg + 1]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
+ rta->rta_len = RTA_LENGTH(1);
+ memcpy(RTA_DATA(rta), &id, 1);
+ off += NLMSG_ALIGN(rta->rta_len);
+ }
+
+ addr->rta_len = off - addr_start;
+ }
+
+ /* token */
+ token = atoi(params[4]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &token, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ do_nl_req(fd, nh, off, 0);
+
+ return 0;
+}
+
+int remove_addr(int fd, int pm_family, int argc, char *argv[])
+{
+ char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
+ 1024];
+ struct nlmsghdr *nh;
+ struct rtattr *rta;
+ u_int32_t token;
+ u_int8_t id;
+ int off = 0;
+ int arg;
+
+ memset(data, 0, sizeof(data));
+ nh = (void *)data;
+ off = init_genl_req(data, pm_family, MPTCP_PM_CMD_REMOVE,
+ MPTCP_PM_VER);
+
+ if (argc < 6)
+ syntax(argv);
+
+ for (arg = 2; arg < argc; arg++) {
+ if (!strcmp(argv[arg], "id")) {
+ if (++arg >= argc)
+ error(1, 0, " missing id value");
+
+ id = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_LOC_ID;
+ rta->rta_len = RTA_LENGTH(1);
+ memcpy(RTA_DATA(rta), &id, 1);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "token")) {
+ if (++arg >= argc)
+ error(1, 0, " missing token value");
+
+ token = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &token, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else
+ error(1, 0, "unknown keyword %s", argv[arg]);
+ }
+
+ do_nl_req(fd, nh, off, 0);
+ return 0;
+}
+
+int announce_addr(int fd, int pm_family, int argc, char *argv[])
+{
+ char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
+ 1024];
+ u_int32_t flags = MPTCP_PM_ADDR_FLAG_SIGNAL;
+ u_int32_t token = UINT_MAX;
+ struct rtattr *rta, *addr;
+ u_int32_t id = UINT_MAX;
+ struct nlmsghdr *nh;
+ u_int16_t family;
+ int addr_start;
+ int off = 0;
+ int arg;
+
+ memset(data, 0, sizeof(data));
+ nh = (void *)data;
+ off = init_genl_req(data, pm_family, MPTCP_PM_CMD_ANNOUNCE,
+ MPTCP_PM_VER);
+
+ if (argc < 7)
+ syntax(argv);
+
+ /* local-ip header */
+ addr_start = off;
+ addr = (void *)(data + off);
+ addr->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR;
+ addr->rta_len = RTA_LENGTH(0);
+ off += NLMSG_ALIGN(addr->rta_len);
+
+ /* local-ip data */
+ /* record addr type */
+ rta = (void *)(data + off);
+ if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
+ family = AF_INET;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+ rta->rta_len = RTA_LENGTH(4);
+ } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
+ family = AF_INET6;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+ rta->rta_len = RTA_LENGTH(16);
+ } else
+ error(1, errno, "can't parse ip %s", argv[2]);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* addr family */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &family, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ for (arg = 3; arg < argc; arg++) {
+ if (!strcmp(argv[arg], "id")) {
+ /* local-id */
+ if (++arg >= argc)
+ error(1, 0, " missing id value");
+
+ id = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
+ rta->rta_len = RTA_LENGTH(1);
+ memcpy(RTA_DATA(rta), &id, 1);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "dev")) {
+ /* for the if_index */
+ int32_t ifindex;
+
+ if (++arg >= argc)
+ error(1, 0, " missing dev name");
+
+ ifindex = if_nametoindex(argv[arg]);
+ if (!ifindex)
+ error(1, errno, "unknown device %s", argv[arg]);
+
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_IF_IDX;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &ifindex, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "port")) {
+ /* local-port (optional) */
+ u_int16_t port;
+
+ if (++arg >= argc)
+ error(1, 0, " missing port value");
+
+ port = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &port, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "token")) {
+ /* MPTCP connection token */
+ if (++arg >= argc)
+ error(1, 0, " missing token value");
+
+ token = atoi(argv[arg]);
+ } else
+ error(1, 0, "unknown keyword %s", argv[arg]);
+ }
+
+ /* addr flags */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &flags, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ addr->rta_len = off - addr_start;
+
+ if (id == UINT_MAX || token == UINT_MAX)
+ error(1, 0, " missing mandatory inputs");
+
+ /* token */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &token, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ do_nl_req(fd, nh, off, 0);
+
+ return 0;
}
int add_addr(int fd, int pm_family, int argc, char *argv[])
@@ -436,6 +1005,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);
@@ -647,6 +1223,54 @@ int get_set_limits(int fd, int pm_family, int argc, char *argv[])
return 0;
}
+int add_listener(int argc, char *argv[])
+{
+ struct sockaddr_storage addr;
+ struct sockaddr_in6 *a6;
+ struct sockaddr_in *a4;
+ u_int16_t family;
+ int enable = 1;
+ int sock;
+ int err;
+
+ if (argc < 4)
+ syntax(argv);
+
+ memset(&addr, 0, sizeof(struct sockaddr_storage));
+ a4 = (struct sockaddr_in *)&addr;
+ a6 = (struct sockaddr_in6 *)&addr;
+
+ if (inet_pton(AF_INET, argv[2], &a4->sin_addr)) {
+ family = AF_INET;
+ a4->sin_family = family;
+ a4->sin_port = htons(atoi(argv[3]));
+ } else if (inet_pton(AF_INET6, argv[2], &a6->sin6_addr)) {
+ family = AF_INET6;
+ a6->sin6_family = family;
+ a6->sin6_port = htons(atoi(argv[3]));
+ } else
+ error(1, errno, "can't parse ip %s", argv[2]);
+
+ sock = socket(family, SOCK_STREAM, IPPROTO_MPTCP);
+ if (sock < 0)
+ error(1, errno, "can't create listener sock\n");
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) {
+ close(sock);
+ error(1, errno, "can't set SO_REUSEADDR on listener sock\n");
+ }
+
+ err = bind(sock, (struct sockaddr *)&addr,
+ ((family == AF_INET) ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6)));
+
+ if (err == 0 && listen(sock, 30) == 0)
+ pause();
+
+ close(sock);
+ return 0;
+}
+
int set_flags(int fd, int pm_family, int argc, char *argv[])
{
char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
@@ -655,10 +1279,15 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
struct rtattr *rta, *nest;
struct nlmsghdr *nh;
u_int32_t flags = 0;
+ u_int32_t token = 0;
+ u_int16_t rport = 0;
u_int16_t family;
+ void *rip = NULL;
int nest_start;
+ int use_id = 0;
+ u_int8_t id;
int off = 0;
- int arg;
+ int arg = 2;
memset(data, 0, sizeof(data));
nh = (void *)data;
@@ -674,42 +1303,66 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
nest->rta_len = RTA_LENGTH(0);
off += NLMSG_ALIGN(nest->rta_len);
- /* addr data */
- rta = (void *)(data + off);
- if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) {
- family = AF_INET;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
- rta->rta_len = RTA_LENGTH(4);
- } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) {
- family = AF_INET6;
- rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
- rta->rta_len = RTA_LENGTH(16);
+ if (!strcmp(argv[arg], "id")) {
+ if (++arg >= argc)
+ error(1, 0, " missing id value");
+
+ use_id = 1;
+ id = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ID;
+ rta->rta_len = RTA_LENGTH(1);
+ memcpy(RTA_DATA(rta), &id, 1);
+ off += NLMSG_ALIGN(rta->rta_len);
} else {
- error(1, errno, "can't parse ip %s", argv[2]);
+ /* addr data */
+ rta = (void *)(data + off);
+ if (inet_pton(AF_INET, argv[arg], RTA_DATA(rta))) {
+ family = AF_INET;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+ rta->rta_len = RTA_LENGTH(4);
+ } else if (inet_pton(AF_INET6, argv[arg], RTA_DATA(rta))) {
+ family = AF_INET6;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+ rta->rta_len = RTA_LENGTH(16);
+ } else {
+ error(1, errno, "can't parse ip %s", argv[arg]);
+ }
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* family */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &family, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
}
- off += NLMSG_ALIGN(rta->rta_len);
- /* family */
- rta = (void *)(data + off);
- rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
- rta->rta_len = RTA_LENGTH(2);
- memcpy(RTA_DATA(rta), &family, 2);
- off += NLMSG_ALIGN(rta->rta_len);
+ if (++arg >= argc)
+ error(1, 0, " missing flags keyword");
- for (arg = 3; arg < argc; arg++) {
- if (!strcmp(argv[arg], "flags")) {
+ for (; arg < argc; arg++) {
+ if (!strcmp(argv[arg], "token")) {
+ if (++arg >= argc)
+ error(1, 0, " missing token value");
+
+ /* token */
+ token = atoi(argv[arg]);
+ } else if (!strcmp(argv[arg], "flags")) {
char *tok, *str;
/* flags */
if (++arg >= argc)
error(1, 0, " missing flags value");
- /* do not support flag list yet */
for (str = argv[arg]; (tok = strtok(str, ","));
str = NULL) {
if (!strcmp(tok, "backup"))
flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
- else if (strcmp(tok, "nobackup"))
+ else if (!strcmp(tok, "fullmesh"))
+ flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
+ else if (strcmp(tok, "nobackup") &&
+ strcmp(tok, "nofullmesh"))
error(1, errno,
"unknown flag %s", argv[arg]);
}
@@ -719,19 +1372,96 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
rta->rta_len = RTA_LENGTH(4);
memcpy(RTA_DATA(rta), &flags, 4);
off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "port")) {
+ u_int16_t port;
+
+ if (use_id)
+ error(1, 0, " port can't be used with id");
+
+ if (++arg >= argc)
+ error(1, 0, " missing port value");
+
+ port = atoi(argv[arg]);
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &port, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+ } else if (!strcmp(argv[arg], "rport")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote port");
+
+ rport = atoi(argv[arg]);
+ } else if (!strcmp(argv[arg], "rip")) {
+ if (++arg >= argc)
+ error(1, 0, " missing remote ip");
+
+ rip = argv[arg];
} else {
error(1, 0, "unknown keyword %s", argv[arg]);
}
}
nest->rta_len = off - nest_start;
+ /* token */
+ if (token) {
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ATTR_TOKEN;
+ rta->rta_len = RTA_LENGTH(4);
+ memcpy(RTA_DATA(rta), &token, 4);
+ off += NLMSG_ALIGN(rta->rta_len);
+ }
+
+ /* remote addr/port */
+ if (rip) {
+ nest_start = off;
+ nest = (void *)(data + off);
+ nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR_REMOTE;
+ nest->rta_len = RTA_LENGTH(0);
+ off += NLMSG_ALIGN(nest->rta_len);
+
+ /* addr data */
+ rta = (void *)(data + off);
+ if (inet_pton(AF_INET, rip, RTA_DATA(rta))) {
+ family = AF_INET;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4;
+ rta->rta_len = RTA_LENGTH(4);
+ } else if (inet_pton(AF_INET6, rip, RTA_DATA(rta))) {
+ family = AF_INET6;
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6;
+ rta->rta_len = RTA_LENGTH(16);
+ } else {
+ error(1, errno, "can't parse ip %s", (char *)rip);
+ }
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ /* family */
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &family, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+
+ if (rport) {
+ rta = (void *)(data + off);
+ rta->rta_type = MPTCP_PM_ADDR_ATTR_PORT;
+ rta->rta_len = RTA_LENGTH(2);
+ memcpy(RTA_DATA(rta), &rport, 2);
+ off += NLMSG_ALIGN(rta->rta_len);
+ }
+
+ nest->rta_len = off - nest_start;
+ }
+
do_nl_req(fd, nh, off, 0);
return 0;
}
int main(int argc, char *argv[])
{
- int fd, pm_family;
+ int events_mcast_grp;
+ int pm_family;
+ int fd;
if (argc < 2)
syntax(argv);
@@ -740,10 +1470,18 @@ int main(int argc, char *argv[])
if (fd == -1)
error(1, errno, "socket netlink");
- pm_family = resolve_mptcp_pm_netlink(fd);
+ resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
if (!strcmp(argv[1], "add"))
return add_addr(fd, pm_family, argc, argv);
+ else if (!strcmp(argv[1], "ann"))
+ return announce_addr(fd, pm_family, argc, argv);
+ else if (!strcmp(argv[1], "rem"))
+ return remove_addr(fd, pm_family, argc, argv);
+ else if (!strcmp(argv[1], "csf"))
+ return csf(fd, pm_family, argc, argv);
+ else if (!strcmp(argv[1], "dsf"))
+ return dsf(fd, pm_family, argc, argv);
else if (!strcmp(argv[1], "del"))
return del_addr(fd, pm_family, argc, argv);
else if (!strcmp(argv[1], "flush"))
@@ -756,6 +1494,10 @@ int main(int argc, char *argv[])
return get_set_limits(fd, pm_family, argc, argv);
else if (!strcmp(argv[1], "set"))
return set_flags(fd, pm_family, argc, argv);
+ else if (!strcmp(argv[1], "events"))
+ return capture_events(fd, events_mcast_grp);
+ else if (!strcmp(argv[1], "listen"))
+ return add_listener(argc, argv);
fprintf(stderr, "unknown sub-command: %s", argv[1]);
syntax(argv);
diff --git a/tools/testing/selftests/net/mptcp/settings b/tools/testing/selftests/net/mptcp/settings
index a62d2fa1275c..79b65bdf05db 100644
--- a/tools/testing/selftests/net/mptcp/settings
+++ b/tools/testing/selftests/net/mptcp/settings
@@ -1 +1 @@
-timeout=600
+timeout=1200
diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
index f441ff7904fc..ffa13a957a36 100755
--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
+++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
@@ -12,6 +12,7 @@ timeout_test=$((timeout_poll * 2 + 1))
test_cnt=1
ret=0
bail=0
+slack=50
usage() {
echo "Usage: $0 [ -b ] [ -c ] [ -d ]"
@@ -52,6 +53,7 @@ setup()
cout=$(mktemp)
capout=$(mktemp)
size=$((2 * 2048 * 4096))
+
dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1
dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1
@@ -104,6 +106,16 @@ setup()
ip -net "$ns3" route add default via dead:beef:3::2
ip netns exec "$ns3" ./pm_nl_ctl limits 1 1
+
+ # debug build can slow down measurably the test program
+ # we use quite tight time limit on the run-time, to ensure
+ # maximum B/W usage.
+ # Use kmemleak/lockdep/kasan/prove_locking presence as a rough
+ # estimate for this being a debug kernel and increase the
+ # maximum run-time accordingly. Observed run times for CI builds
+ # running selftests, including kbuild, were used to determine the
+ # amount of time to add.
+ grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550))
}
# $1: ns, $2: port
@@ -241,7 +253,7 @@ run_test()
# mptcp_connect will do some sleeps to allow the mp_join handshake
# completion (see mptcp_connect): 200ms on each side, add some slack
- time=$((time + 450))
+ time=$((time + 400 + slack))
printf "%-60s" "$msg"
do_transfer $small $large $time
diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh
new file mode 100755
index 000000000000..3229725b64b0
--- /dev/null
+++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh
@@ -0,0 +1,817 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+ echo "SKIP: Cannot not run test without ip tool"
+ exit 1
+fi
+
+ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
+REMOVED=7 # MPTCP_EVENT_REMOVED
+SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED
+SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED
+
+AF_INET=2
+AF_INET6=10
+
+evts_pid=0
+client4_pid=0
+server4_pid=0
+client6_pid=0
+server6_pid=0
+client4_token=""
+server4_token=""
+client6_token=""
+server6_token=""
+client4_port=0;
+client6_port=0;
+app4_port=50002
+new4_port=50003
+app6_port=50004
+client_addr_id=${RANDOM:0:2}
+server_addr_id=${RANDOM:0:2}
+
+sec=$(date +%s)
+rndh=$(stdbuf -o0 -e0 printf %x "$sec")-$(mktemp -u XXXXXX)
+ns1="ns1-$rndh"
+ns2="ns2-$rndh"
+
+kill_wait()
+{
+ kill $1 > /dev/null 2>&1
+ wait $1 2>/dev/null
+}
+
+cleanup()
+{
+ echo "cleanup"
+
+ rm -rf $file
+
+ # Terminate the MPTCP connection and related processes
+ if [ $client4_pid -ne 0 ]; then
+ kill -SIGUSR1 $client4_pid > /dev/null 2>&1
+ fi
+ if [ $server4_pid -ne 0 ]; then
+ kill_wait $server4_pid
+ fi
+ if [ $client6_pid -ne 0 ]; then
+ kill -SIGUSR1 $client6_pid > /dev/null 2>&1
+ fi
+ if [ $server6_pid -ne 0 ]; then
+ kill_wait $server6_pid
+ fi
+ if [ $evts_pid -ne 0 ]; then
+ kill_wait $evts_pid
+ fi
+ local netns
+ for netns in "$ns1" "$ns2" ;do
+ ip netns del "$netns"
+ done
+}
+
+trap cleanup EXIT
+
+# Create and configure network namespaces for testing
+for i in "$ns1" "$ns2" ;do
+ ip netns add "$i" || exit 1
+ ip -net "$i" link set lo up
+ ip netns exec "$i" sysctl -q net.mptcp.enabled=1
+ ip netns exec "$i" sysctl -q net.mptcp.pm_type=1
+done
+
+# "$ns1" ns2
+# ns1eth2 ns2eth1
+
+ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
+
+# Add IPv4/v6 addresses to the namespaces
+ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth2
+ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2
+ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth2 nodad
+ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad
+ip -net "$ns1" link set ns1eth2 up
+
+ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1
+ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth1
+ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad
+ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth1 nodad
+ip -net "$ns2" link set ns2eth1 up
+
+stdbuf -o0 -e0 printf "Created network namespaces ns1, ns2 \t\t\t[OK]\n"
+
+make_file()
+{
+ # Store a chunk of data in a file to transmit over an MPTCP connection
+ local name=$1
+ local ksize=1
+
+ dd if=/dev/urandom of="$name" bs=2 count=$ksize 2> /dev/null
+ echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
+}
+
+make_connection()
+{
+ local file
+ file=$(mktemp)
+ make_file "$file" "client"
+
+ local is_v6=$1
+ local app_port=$app4_port
+ local connect_addr="10.0.1.1"
+ local listen_addr="0.0.0.0"
+ if [ "$is_v6" = "v6" ]
+ then
+ connect_addr="dead:beef:1::1"
+ listen_addr="::"
+ app_port=$app6_port
+ else
+ is_v6="v4"
+ fi
+
+ # Capture netlink events over the two network namespaces running
+ # the MPTCP client and server
+ local client_evts
+ client_evts=$(mktemp)
+ :>"$client_evts"
+ ip netns exec "$ns2" ./pm_nl_ctl events >> "$client_evts" 2>&1 &
+ local client_evts_pid=$!
+ local server_evts
+ server_evts=$(mktemp)
+ :>"$server_evts"
+ ip netns exec "$ns1" ./pm_nl_ctl events >> "$server_evts" 2>&1 &
+ local server_evts_pid=$!
+ sleep 0.5
+
+ # Run the server
+ ip netns exec "$ns1" \
+ ./mptcp_connect -s MPTCP -w 300 -p $app_port -l $listen_addr > /dev/null 2>&1 &
+ local server_pid=$!
+ sleep 0.5
+
+ # Run the client, transfer $file and stay connected to the server
+ # to conduct tests
+ ip netns exec "$ns2" \
+ ./mptcp_connect -s MPTCP -w 300 -m sendfile -p $app_port $connect_addr\
+ 2>&1 > /dev/null < "$file" &
+ local client_pid=$!
+ sleep 1
+
+ # Capture client/server attributes from MPTCP connection netlink events
+ kill_wait $client_evts_pid
+
+ local client_token
+ local client_port
+ local client_serverside
+ local server_token
+ local server_serverside
+
+ client_token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
+ client_port=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
+ client_serverside=$(sed --unbuffered -n 's/.*\(server_side:\)\([[:digit:]]*\).*$/\2/p;q'\
+ "$client_evts")
+ kill_wait $server_evts_pid
+ server_token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$server_evts")
+ server_serverside=$(sed --unbuffered -n 's/.*\(server_side:\)\([[:digit:]]*\).*$/\2/p;q'\
+ "$server_evts")
+ rm -f "$client_evts" "$server_evts" "$file"
+
+ if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] &&
+ [ "$server_serverside" = 1 ]
+ then
+ stdbuf -o0 -e0 printf "Established IP%s MPTCP Connection ns2 => ns1 \t\t[OK]\n" $is_v6
+ else
+ exit 1
+ fi
+
+ if [ "$is_v6" = "v6" ]
+ then
+ client6_token=$client_token
+ server6_token=$server_token
+ client6_port=$client_port
+ client6_pid=$client_pid
+ server6_pid=$server_pid
+ else
+ client4_token=$client_token
+ server4_token=$server_token
+ client4_port=$client_port
+ client4_pid=$client_pid
+ server4_pid=$server_pid
+ fi
+}
+
+verify_announce_event()
+{
+ local evt=$1
+ local e_type=$2
+ local e_token=$3
+ local e_addr=$4
+ local e_id=$5
+ local e_dport=$6
+ local e_af=$7
+ local type
+ local token
+ local addr
+ local dport
+ local id
+
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ if [ "$e_af" = "v6" ]
+ then
+ addr=$(sed --unbuffered -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
+ else
+ addr=$(sed --unbuffered -n 's/.*\(daddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
+ fi
+ dport=$(sed --unbuffered -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ id=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
+ [ "$addr" = "$e_addr" ] && [ "$dport" = "$e_dport" ] &&
+ [ "$id" = "$e_id" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ return 0
+ fi
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+}
+
+test_announce()
+{
+ local evts
+ evts=$(mktemp)
+ # Capture events on the network namespace running the server
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # ADD_ADDR using an invalid token should result in no action
+ local invalid_token=$(( client4_token - 1))
+ ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token $invalid_token id\
+ $client_addr_id dev ns2eth1 > /dev/null 2>&1
+
+ local type
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+ stdbuf -o0 -e0 printf "ADD_ADDR 10.0.2.2 (ns2) => ns1, invalid token \t\t"
+ if [ "$type" = "" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ else
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+ fi
+
+ # ADD_ADDR from the client to server machine reusing the subflow port
+ :>"$evts"
+ ip netns exec "$ns2"\
+ ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id $client_addr_id dev\
+ ns2eth1 > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.2 (ns2) => ns1, reuse port \t\t" $client_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$server4_token" "10.0.2.2" "$client_addr_id"\
+ "$client4_port"
+
+ # ADD_ADDR6 from the client to server machine reusing the subflow port
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl ann\
+ dead:beef:2::2 token "$client6_token" id $client_addr_id dev ns2eth1 > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR6 id:%d dead:beef:2::2 (ns2) => ns1, reuse port\t\t" $client_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$server6_token" "dead:beef:2::2"\
+ "$client_addr_id" "$client6_port" "v6"
+
+ # ADD_ADDR from the client to server machine using a new port
+ :>"$evts"
+ client_addr_id=$((client_addr_id+1))
+ ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
+ $client_addr_id dev ns2eth1 port $new4_port > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.2 (ns2) => ns1, new port \t\t\t" $client_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$server4_token" "10.0.2.2"\
+ "$client_addr_id" "$new4_port"
+
+ kill_wait $evts_pid
+
+ # Capture events on the network namespace running the client
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # ADD_ADDR from the server to client machine reusing the subflow port
+ ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
+ $server_addr_id dev ns1eth2 > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.1 (ns1) => ns2, reuse port \t\t" $server_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
+ "$server_addr_id" "$app4_port"
+
+ # ADD_ADDR6 from the server to client machine reusing the subflow port
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
+ $server_addr_id dev ns1eth2 > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR6 id:%d dead:beef:2::1 (ns1) => ns2, reuse port\t\t" $server_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$client6_token" "dead:beef:2::1"\
+ "$server_addr_id" "$app6_port" "v6"
+
+ # ADD_ADDR from the server to client machine using a new port
+ :>"$evts"
+ server_addr_id=$((server_addr_id+1))
+ ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
+ $server_addr_id dev ns1eth2 port $new4_port > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.1 (ns1) => ns2, new port \t\t\t" $server_addr_id
+ sleep 0.5
+ verify_announce_event "$evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
+ "$server_addr_id" "$new4_port"
+
+ kill_wait $evts_pid
+ rm -f "$evts"
+}
+
+verify_remove_event()
+{
+ local evt=$1
+ local e_type=$2
+ local e_token=$3
+ local e_id=$4
+ local type
+ local token
+ local id
+
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ id=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
+ [ "$id" = "$e_id" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ return 0
+ fi
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+}
+
+test_remove()
+{
+ local evts
+ evts=$(mktemp)
+
+ # Capture events on the network namespace running the server
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # RM_ADDR using an invalid token should result in no action
+ local invalid_token=$(( client4_token - 1 ))
+ ip netns exec "$ns2" ./pm_nl_ctl rem token $invalid_token id\
+ $client_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1, invalid token \t"\
+ $client_addr_id
+ local type
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+ if [ "$type" = "" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ else
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ fi
+
+ # RM_ADDR using an invalid addr id should result in no action
+ local invalid_id=$(( client_addr_id + 1 ))
+ ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
+ $invalid_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1, invalid id \t"\
+ $invalid_id
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+ if [ "$type" = "" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ else
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ fi
+
+ # RM_ADDR from the client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
+ $client_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1 \t"\
+ $client_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$server4_token" "$client_addr_id"
+
+ # RM_ADDR from the client to server machine
+ :>"$evts"
+ client_addr_id=$(( client_addr_id - 1 ))
+ ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
+ $client_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1 \t"\
+ $client_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$server4_token" "$client_addr_id"
+
+ # RM_ADDR6 from the client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl rem token "$client6_token" id\
+ $client_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR6 id:%d ns2 => ns1 \t"\
+ $client_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$server6_token" "$client_addr_id"
+
+ kill_wait $evts_pid
+
+ # Capture events on the network namespace running the client
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # RM_ADDR from the server to client machine
+ ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
+ $server_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns1 => ns2 \t"\
+ $server_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$client4_token" "$server_addr_id"
+
+ # RM_ADDR from the server to client machine
+ :>"$evts"
+ server_addr_id=$(( server_addr_id - 1 ))
+ ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
+ $server_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR id:%d ns1 => ns2 \t" $server_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$client4_token" "$server_addr_id"
+
+ # RM_ADDR6 from the server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl rem token "$server6_token" id\
+ $server_addr_id > /dev/null 2>&1
+ stdbuf -o0 -e0 printf "RM_ADDR6 id:%d ns1 => ns2 \t" $server_addr_id
+ sleep 0.5
+ verify_remove_event "$evts" "$REMOVED" "$client6_token" "$server_addr_id"
+
+ kill_wait $evts_pid
+ rm -f "$evts"
+}
+
+verify_subflow_events()
+{
+ local evt=$1
+ local e_type=$2
+ local e_token=$3
+ local e_family=$4
+ local e_saddr=$5
+ local e_daddr=$6
+ local e_dport=$7
+ local e_locid=$8
+ local e_remid=$9
+ shift 2
+ local e_from=$8
+ local e_to=$9
+ local type
+ local token
+ local family
+ local saddr
+ local daddr
+ local dport
+ local locid
+ local remid
+
+ if [ "$e_type" = "$SUB_ESTABLISHED" ]
+ then
+ if [ "$e_family" = "$AF_INET6" ]
+ then
+ stdbuf -o0 -e0 printf "CREATE_SUBFLOW6 %s (%s) => %s (%s) "\
+ "$e_saddr" "$e_from" "$e_daddr" "$e_to"
+ else
+ stdbuf -o0 -e0 printf "CREATE_SUBFLOW %s (%s) => %s (%s) \t"\
+ "$e_saddr" "$e_from" "$e_daddr" "$e_to"
+ fi
+ else
+ if [ "$e_family" = "$AF_INET6" ]
+ then
+ stdbuf -o0 -e0 printf "DESTROY_SUBFLOW6 %s (%s) => %s (%s) "\
+ "$e_saddr" "$e_from" "$e_daddr" "$e_to"
+ else
+ stdbuf -o0 -e0 printf "DESTROY_SUBFLOW %s (%s) => %s (%s) \t"\
+ "$e_saddr" "$e_from" "$e_daddr" "$e_to"
+ fi
+ fi
+
+ type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ family=$(sed --unbuffered -n 's/.*\(family:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ dport=$(sed --unbuffered -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ locid=$(sed --unbuffered -n 's/.*\(loc_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ remid=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
+ if [ "$family" = "$AF_INET6" ]
+ then
+ saddr=$(sed --unbuffered -n 's/.*\(saddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
+ daddr=$(sed --unbuffered -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
+ else
+ saddr=$(sed --unbuffered -n 's/.*\(saddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
+ daddr=$(sed --unbuffered -n 's/.*\(daddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
+ fi
+
+ if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
+ [ "$daddr" = "$e_daddr" ] && [ "$e_dport" = "$dport" ] &&
+ [ "$family" = "$e_family" ] && [ "$saddr" = "$e_saddr" ] &&
+ [ "$e_locid" = "$locid" ] && [ "$e_remid" = "$remid" ]
+ then
+ stdbuf -o0 -e0 printf "[OK]\n"
+ return 0
+ fi
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+}
+
+test_subflows()
+{
+ local evts
+ evts=$(mktemp)
+ # Capture events on the network namespace running the server
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # Attempt to add a listener at 10.0.2.2:<subflow-port>
+ ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
+ "$client4_port" > /dev/null 2>&1 &
+ local listener_pid=$!
+
+ # ADD_ADDR from client to server machine reusing the subflow port
+ ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
+ $client_addr_id > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2\
+ rport "$client4_port" token "$server4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server4_token" "$AF_INET" "10.0.2.1"\
+ "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"
+
+ # Delete the listener from the client ns, if one was created
+ kill_wait $listener_pid
+
+ local sport
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
+ "$client4_port" token "$server4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
+ "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"
+
+ # RM_ADDR from client to server machine
+ ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
+ "$client4_token" > /dev/null 2>&1
+ sleep 0.5
+
+ # Attempt to add a listener at dead:beef:2::2:<subflow-port>
+ ip netns exec "$ns2" ./pm_nl_ctl listen dead:beef:2::2\
+ "$client6_port" > /dev/null 2>&1 &
+ listener_pid=$!
+
+ # ADD_ADDR6 from client to server machine reusing the subflow port
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl ann dead:beef:2::2 token "$client6_token" id\
+ $client_addr_id > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW6 from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl csf lip dead:beef:2::1 lid 23 rip\
+ dead:beef:2::2 rport "$client6_port" token "$server6_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server6_token" "$AF_INET6"\
+ "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
+ "$client_addr_id" "ns1" "ns2"
+
+ # Delete the listener from the client ns, if one was created
+ kill_wait $listener_pid
+
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW6 from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl dsf lip dead:beef:2::1 lport "$sport" rip\
+ dead:beef:2::2 rport "$client6_port" token "$server6_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$server6_token" "$AF_INET6"\
+ "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
+ "$client_addr_id" "ns1" "ns2"
+
+ # RM_ADDR from client to server machine
+ ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
+ "$client6_token" > /dev/null 2>&1
+ sleep 0.5
+
+ # Attempt to add a listener at 10.0.2.2:<new-port>
+ ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
+ $new4_port > /dev/null 2>&1 &
+ listener_pid=$!
+
+ # ADD_ADDR from client to server machine using a new port
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
+ $client_addr_id port $new4_port > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2 rport\
+ $new4_port token "$server4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server4_token" "$AF_INET"\
+ "10.0.2.1" "10.0.2.2" "$new4_port" "23"\
+ "$client_addr_id" "ns1" "ns2"
+
+ # Delete the listener from the client ns, if one was created
+ kill_wait $listener_pid
+
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW from server to client machine
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
+ $new4_port token "$server4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
+ "10.0.2.2" "$new4_port" "23" "$client_addr_id" "ns1" "ns2"
+
+ # RM_ADDR from client to server machine
+ ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
+ "$client4_token" > /dev/null 2>&1
+
+ kill_wait $evts_pid
+
+ # Capture events on the network namespace running the client
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
+ evts_pid=$!
+ sleep 0.5
+
+ # Attempt to add a listener at 10.0.2.1:<subflow-port>
+ ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
+ $app4_port > /dev/null 2>&1 &
+ listener_pid=$!
+
+ # ADD_ADDR from server to client machine reusing the subflow port
+ ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
+ $server_addr_id > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
+ $app4_port token "$client4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client4_token" "$AF_INET" "10.0.2.2"\
+ "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"
+
+ # Delete the listener from the server ns, if one was created
+ kill_wait $listener_pid
+
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
+ $app4_port token "$client4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
+ "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"
+
+ # RM_ADDR from server to client machine
+ ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
+ "$server4_token" > /dev/null 2>&1
+ sleep 0.5
+
+ # Attempt to add a listener at dead:beef:2::1:<subflow-port>
+ ip netns exec "$ns1" ./pm_nl_ctl listen dead:beef:2::1\
+ $app6_port > /dev/null 2>&1 &
+ listener_pid=$!
+
+ # ADD_ADDR6 from server to client machine reusing the subflow port
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
+ $server_addr_id > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW6 from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl csf lip dead:beef:2::2 lid 23 rip\
+ dead:beef:2::1 rport $app6_port token "$client6_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client6_token"\
+ "$AF_INET6" "dead:beef:2::2"\
+ "dead:beef:2::1" "$app6_port" "23"\
+ "$server_addr_id" "ns2" "ns1"
+
+ # Delete the listener from the server ns, if one was created
+ kill_wait $listener_pid
+
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW6 from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl dsf lip dead:beef:2::2 lport "$sport" rip\
+ dead:beef:2::1 rport $app6_port token "$client6_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$client6_token" "$AF_INET6" "dead:beef:2::2"\
+ "dead:beef:2::1" "$app6_port" "23" "$server_addr_id" "ns2" "ns1"
+
+ # RM_ADDR6 from server to client machine
+ ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
+ "$server6_token" > /dev/null 2>&1
+ sleep 0.5
+
+ # Attempt to add a listener at 10.0.2.1:<new-port>
+ ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
+ $new4_port > /dev/null 2>&1 &
+ listener_pid=$!
+
+ # ADD_ADDR from server to client machine using a new port
+ :>"$evts"
+ ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
+ $server_addr_id port $new4_port > /dev/null 2>&1
+ sleep 0.5
+
+ # CREATE_SUBFLOW from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
+ $new4_port token "$client4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client4_token" "$AF_INET"\
+ "10.0.2.2" "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"
+
+ # Delete the listener from the server ns, if one was created
+ kill_wait $listener_pid
+
+ sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
+
+ # DESTROY_SUBFLOW from client to server machine
+ :>"$evts"
+ ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
+ $new4_port token "$client4_token" > /dev/null 2>&1
+ sleep 0.5
+ verify_subflow_events "$evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
+ "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"
+
+ # RM_ADDR from server to client machine
+ ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
+ "$server4_token" > /dev/null 2>&1
+
+ kill_wait $evts_pid
+ rm -f "$evts"
+}
+
+test_prio()
+{
+ local count
+
+ # Send MP_PRIO signal from client to server machine
+ ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$server4_port"
+ sleep 0.5
+
+ # Check TX
+ stdbuf -o0 -e0 printf "MP_PRIO TX \t"
+ count=$(ip netns exec "$ns2" nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ $count != 1 ]; then
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+ else
+ stdbuf -o0 -e0 printf "[OK]\n"
+ fi
+
+ # Check RX
+ stdbuf -o0 -e0 printf "MP_PRIO RX \t"
+ count=$(ip netns exec "$ns1" nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
+ [ -z "$count" ] && count=0
+ if [ $count != 1 ]; then
+ stdbuf -o0 -e0 printf "[FAIL]\n"
+ exit 1
+ else
+ stdbuf -o0 -e0 printf "[OK]\n"
+ fi
+}
+
+make_connection
+make_connection "v6"
+test_announce
+test_remove
+test_subflows
+test_prio
+
+exit 0