Commit 986d2e3d authored by David S. Miller's avatar David S. Miller

Merge branch 'mptcp-selftests'

Mat Martineau says:

====================
mptcp: Some selftest improvements

Here are a couple of selftest changes for MPTCP.

Patch 1 fixes a mistake where the wrong protocol (TCP vs MPTCP) could be
requested on the listening socket in some link failure tests.

Patch 2 refactors the simulataneous flow tests to improve timing
accuracy and give more consistent results.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f7536ffb b6ab64b0
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <strings.h> #include <strings.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/sendfile.h> #include <sys/sendfile.h>
...@@ -64,6 +65,7 @@ static int cfg_sndbuf; ...@@ -64,6 +65,7 @@ static int cfg_sndbuf;
static int cfg_rcvbuf; static int cfg_rcvbuf;
static bool cfg_join; static bool cfg_join;
static bool cfg_remove; static bool cfg_remove;
static unsigned int cfg_time;
static unsigned int cfg_do_w; static unsigned int cfg_do_w;
static int cfg_wait; static int cfg_wait;
static uint32_t cfg_mark; static uint32_t cfg_mark;
...@@ -78,9 +80,10 @@ static struct cfg_cmsg_types cfg_cmsg_types; ...@@ -78,9 +80,10 @@ static struct cfg_cmsg_types cfg_cmsg_types;
static void die_usage(void) static void die_usage(void)
{ {
fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]" fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]"
"[-l] [-w sec] connect_address\n"); "[-l] [-w sec] [-t num] [-T num] connect_address\n");
fprintf(stderr, "\t-6 use ipv6\n"); fprintf(stderr, "\t-6 use ipv6\n");
fprintf(stderr, "\t-t num -- set poll timeout to num\n"); fprintf(stderr, "\t-t num -- set poll timeout to num\n");
fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n"); fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n"); fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
fprintf(stderr, "\t-p num -- use port num\n"); fprintf(stderr, "\t-p num -- use port num\n");
...@@ -448,7 +451,7 @@ static void set_nonblock(int fd) ...@@ -448,7 +451,7 @@ static void set_nonblock(int fd)
fcntl(fd, F_SETFL, flags | O_NONBLOCK); fcntl(fd, F_SETFL, flags | O_NONBLOCK);
} }
static int copyfd_io_poll(int infd, int peerfd, int outfd) static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
{ {
struct pollfd fds = { struct pollfd fds = {
.fd = peerfd, .fd = peerfd,
...@@ -487,9 +490,11 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd) ...@@ -487,9 +490,11 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd)
*/ */
fds.events &= ~POLLIN; fds.events &= ~POLLIN;
if ((fds.events & POLLOUT) == 0) if ((fds.events & POLLOUT) == 0) {
*in_closed_after_out = true;
/* and nothing more to send */ /* and nothing more to send */
break; break;
}
/* Else, still have data to transmit */ /* Else, still have data to transmit */
} else if (len < 0) { } else if (len < 0) {
...@@ -547,7 +552,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd) ...@@ -547,7 +552,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd)
} }
/* leave some time for late join/announce */ /* leave some time for late join/announce */
if (cfg_join || cfg_remove) if (cfg_remove)
usleep(cfg_wait); usleep(cfg_wait);
close(peerfd); close(peerfd);
...@@ -646,7 +651,7 @@ static int do_sendfile(int infd, int outfd, unsigned int count) ...@@ -646,7 +651,7 @@ static int do_sendfile(int infd, int outfd, unsigned int count)
} }
static int copyfd_io_mmap(int infd, int peerfd, int outfd, static int copyfd_io_mmap(int infd, int peerfd, int outfd,
unsigned int size) unsigned int size, bool *in_closed_after_out)
{ {
int err; int err;
...@@ -664,13 +669,14 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd, ...@@ -664,13 +669,14 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd,
shutdown(peerfd, SHUT_WR); shutdown(peerfd, SHUT_WR);
err = do_recvfile(peerfd, outfd); err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
} }
return err; return err;
} }
static int copyfd_io_sendfile(int infd, int peerfd, int outfd, static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
unsigned int size) unsigned int size, bool *in_closed_after_out)
{ {
int err; int err;
...@@ -685,6 +691,7 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd, ...@@ -685,6 +691,7 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
if (err) if (err)
return err; return err;
err = do_recvfile(peerfd, outfd); err = do_recvfile(peerfd, outfd);
*in_closed_after_out = true;
} }
return err; return err;
...@@ -692,27 +699,62 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd, ...@@ -692,27 +699,62 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
static int copyfd_io(int infd, int peerfd, int outfd) static int copyfd_io(int infd, int peerfd, int outfd)
{ {
bool in_closed_after_out = false;
struct timespec start, end;
int file_size; int file_size;
int ret;
if (cfg_time && (clock_gettime(CLOCK_MONOTONIC, &start) < 0))
xerror("can not fetch start time %d", errno);
switch (cfg_mode) { switch (cfg_mode) {
case CFG_MODE_POLL: case CFG_MODE_POLL:
return copyfd_io_poll(infd, peerfd, outfd); ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out);
break;
case CFG_MODE_MMAP: case CFG_MODE_MMAP:
file_size = get_infd_size(infd); file_size = get_infd_size(infd);
if (file_size < 0) if (file_size < 0)
return file_size; return file_size;
return copyfd_io_mmap(infd, peerfd, outfd, file_size); ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out);
break;
case CFG_MODE_SENDFILE: case CFG_MODE_SENDFILE:
file_size = get_infd_size(infd); file_size = get_infd_size(infd);
if (file_size < 0) if (file_size < 0)
return file_size; return file_size;
return copyfd_io_sendfile(infd, peerfd, outfd, file_size); ret = copyfd_io_sendfile(infd, peerfd, outfd, file_size, &in_closed_after_out);
} break;
default:
fprintf(stderr, "Invalid mode %d\n", cfg_mode); fprintf(stderr, "Invalid mode %d\n", cfg_mode);
die_usage(); die_usage();
return 1; return 1;
}
if (ret)
return ret;
if (cfg_time) {
unsigned int delta_ms;
if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
xerror("can not fetch end time %d", errno);
delta_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000;
if (delta_ms > cfg_time) {
xerror("transfer slower than expected! runtime %d ms, expected %d ms",
delta_ms, cfg_time);
}
/* show the runtime only if this end shutdown(wr) before receiving the EOF,
* (that is, if this end got the longer runtime)
*/
if (in_closed_after_out)
fprintf(stderr, "%d", delta_ms);
}
return 0;
} }
static void check_sockaddr(int pf, struct sockaddr_storage *ss, static void check_sockaddr(int pf, struct sockaddr_storage *ss,
...@@ -1005,12 +1047,11 @@ static void parse_opts(int argc, char **argv) ...@@ -1005,12 +1047,11 @@ static void parse_opts(int argc, char **argv)
{ {
int c; int c;
while ((c = getopt(argc, argv, "6jr:lp:s:hut:m:S:R:w:M:P:c:")) != -1) { while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:")) != -1) {
switch (c) { switch (c) {
case 'j': case 'j':
cfg_join = true; cfg_join = true;
cfg_mode = CFG_MODE_POLL; cfg_mode = CFG_MODE_POLL;
cfg_wait = 400000;
break; break;
case 'r': case 'r':
cfg_remove = true; cfg_remove = true;
...@@ -1043,6 +1084,9 @@ static void parse_opts(int argc, char **argv) ...@@ -1043,6 +1084,9 @@ static void parse_opts(int argc, char **argv)
if (poll_timeout <= 0) if (poll_timeout <= 0)
poll_timeout = -1; poll_timeout = -1;
break; break;
case 'T':
cfg_time = atoi(optarg);
break;
case 'm': case 'm':
cfg_mode = parse_mode(optarg); cfg_mode = parse_mode(optarg);
break; break;
......
...@@ -297,7 +297,7 @@ do_transfer() ...@@ -297,7 +297,7 @@ do_transfer()
if [ "$test_link_fail" -eq 2 ];then if [ "$test_link_fail" -eq 2 ];then
timeout ${timeout_test} \ timeout ${timeout_test} \
ip netns exec ${listener_ns} \ ip netns exec ${listener_ns} \
$mptcp_connect -t ${timeout_poll} -l -p $port -s ${cl_proto} \ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
${local_addr} < "$sinfail" > "$sout" & ${local_addr} < "$sinfail" > "$sout" &
else else
timeout ${timeout_test} \ timeout ${timeout_test} \
......
...@@ -51,7 +51,7 @@ setup() ...@@ -51,7 +51,7 @@ setup()
sout=$(mktemp) sout=$(mktemp)
cout=$(mktemp) cout=$(mktemp)
capout=$(mktemp) capout=$(mktemp)
size=$((2048 * 4096)) size=$((2 * 2048 * 4096))
dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1 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 dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1
...@@ -161,17 +161,15 @@ do_transfer() ...@@ -161,17 +161,15 @@ do_transfer()
timeout ${timeout_test} \ timeout ${timeout_test} \
ip netns exec ${ns3} \ ip netns exec ${ns3} \
./mptcp_connect -jt ${timeout_poll} -l -p $port \ ./mptcp_connect -jt ${timeout_poll} -l -p $port -T $time \
0.0.0.0 < "$sin" > "$sout" & 0.0.0.0 < "$sin" > "$sout" &
local spid=$! local spid=$!
wait_local_port_listen "${ns3}" "${port}" wait_local_port_listen "${ns3}" "${port}"
local start
start=$(date +%s%3N)
timeout ${timeout_test} \ timeout ${timeout_test} \
ip netns exec ${ns1} \ ip netns exec ${ns1} \
./mptcp_connect -jt ${timeout_poll} -p $port \ ./mptcp_connect -jt ${timeout_poll} -p $port -T $time \
10.0.3.3 < "$cin" > "$cout" & 10.0.3.3 < "$cin" > "$cout" &
local cpid=$! local cpid=$!
...@@ -180,27 +178,20 @@ do_transfer() ...@@ -180,27 +178,20 @@ do_transfer()
wait $spid wait $spid
local rets=$? local rets=$?
local stop
stop=$(date +%s%3N)
if $capture; then if $capture; then
sleep 1 sleep 1
kill ${cappid_listener} kill ${cappid_listener}
kill ${cappid_connector} kill ${cappid_connector}
fi fi
local duration
duration=$((stop-start))
cmp $sin $cout > /dev/null 2>&1 cmp $sin $cout > /dev/null 2>&1
local cmps=$? local cmps=$?
cmp $cin $sout > /dev/null 2>&1 cmp $cin $sout > /dev/null 2>&1
local cmpc=$? local cmpc=$?
printf "%16s" "$duration max $max_time " printf "%-16s" " max $max_time "
if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \ if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \
[ $cmpc -eq 0 ] && [ $cmps -eq 0 ] && \ [ $cmpc -eq 0 ] && [ $cmps -eq 0 ]; then
[ $duration -lt $max_time ]; then
echo "[ OK ]" echo "[ OK ]"
cat "$capout" cat "$capout"
return 0 return 0
...@@ -244,23 +235,24 @@ run_test() ...@@ -244,23 +235,24 @@ run_test()
tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1 tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1
tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2 tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2
# time is measure in ms # time is measured in ms, account for transfer size, affegated link speed
local time=$((size * 8 * 1000 / (( $rate1 + $rate2) * 1024 *1024) )) # and header overhead (10%)
local time=$((size * 8 * 1000 * 10 / (( $rate1 + $rate2) * 1024 *1024 * 9) ))
# mptcp_connect will do some sleeps to allow the mp_join handshake # mptcp_connect will do some sleeps to allow the mp_join handshake
# completion # completion (see mptcp_connect): 200ms on each side, add some slack
time=$((time + 1350)) time=$((time + 450))
printf "%-50s" "$msg" printf "%-60s" "$msg"
do_transfer $small $large $((time * 11 / 10)) do_transfer $small $large $time
lret=$? lret=$?
if [ $lret -ne 0 ]; then if [ $lret -ne 0 ]; then
ret=$lret ret=$lret
[ $bail -eq 0 ] || exit $ret [ $bail -eq 0 ] || exit $ret
fi fi
printf "%-50s" "$msg - reverse direction" printf "%-60s" "$msg - reverse direction"
do_transfer $large $small $((time * 11 / 10)) do_transfer $large $small $time
lret=$? lret=$?
if [ $lret -ne 0 ]; then if [ $lret -ne 0 ]; then
ret=$lret ret=$lret
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment