Skip to content

Commit b6ab64b

Browse files
Paolo Abenidavem330
authored andcommitted
selftests: mptcp: more stable simult_flows tests
Currently the simult_flows.sh self-tests are not very stable, especially when running on slow VMs. The tests measure runtime for transfers on multiple subflows and check that the time is near the theoretical maximum. The current test infra introduces a bit of jitter in test runtime, due to multiple explicit delays. Additionally the runtime is measured by the shell script wrapper. On a slow VM, the script overhead is measurable and subject to relevant jitter. One solution to make the test more stable would be adding more slack to the expected time; that could possibly hide real regressions. Instead move the measurement inside the command doing the transfer, and drop most unneeded sleeps. Reviewed-by: Matthieu Baerts <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7c909a9 commit b6ab64b

File tree

2 files changed

+72
-36
lines changed

2 files changed

+72
-36
lines changed

tools/testing/selftests/net/mptcp/mptcp_connect.c

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <strings.h>
1515
#include <signal.h>
1616
#include <unistd.h>
17+
#include <time.h>
1718

1819
#include <sys/poll.h>
1920
#include <sys/sendfile.h>
@@ -64,6 +65,7 @@ static int cfg_sndbuf;
6465
static int cfg_rcvbuf;
6566
static bool cfg_join;
6667
static bool cfg_remove;
68+
static unsigned int cfg_time;
6769
static unsigned int cfg_do_w;
6870
static int cfg_wait;
6971
static uint32_t cfg_mark;
@@ -78,9 +80,10 @@ static struct cfg_cmsg_types cfg_cmsg_types;
7880
static void die_usage(void)
7981
{
8082
fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]"
81-
"[-l] [-w sec] connect_address\n");
83+
"[-l] [-w sec] [-t num] [-T num] connect_address\n");
8284
fprintf(stderr, "\t-6 use ipv6\n");
8385
fprintf(stderr, "\t-t num -- set poll timeout to num\n");
86+
fprintf(stderr, "\t-T num -- set expected runtime to num ms\n");
8487
fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n");
8588
fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n");
8689
fprintf(stderr, "\t-p num -- use port num\n");
@@ -448,7 +451,7 @@ static void set_nonblock(int fd)
448451
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
449452
}
450453

451-
static int copyfd_io_poll(int infd, int peerfd, int outfd)
454+
static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out)
452455
{
453456
struct pollfd fds = {
454457
.fd = peerfd,
@@ -487,9 +490,11 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd)
487490
*/
488491
fds.events &= ~POLLIN;
489492

490-
if ((fds.events & POLLOUT) == 0)
493+
if ((fds.events & POLLOUT) == 0) {
494+
*in_closed_after_out = true;
491495
/* and nothing more to send */
492496
break;
497+
}
493498

494499
/* Else, still have data to transmit */
495500
} else if (len < 0) {
@@ -547,7 +552,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd)
547552
}
548553

549554
/* leave some time for late join/announce */
550-
if (cfg_join || cfg_remove)
555+
if (cfg_remove)
551556
usleep(cfg_wait);
552557

553558
close(peerfd);
@@ -646,7 +651,7 @@ static int do_sendfile(int infd, int outfd, unsigned int count)
646651
}
647652

648653
static int copyfd_io_mmap(int infd, int peerfd, int outfd,
649-
unsigned int size)
654+
unsigned int size, bool *in_closed_after_out)
650655
{
651656
int err;
652657

@@ -664,13 +669,14 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd,
664669
shutdown(peerfd, SHUT_WR);
665670

666671
err = do_recvfile(peerfd, outfd);
672+
*in_closed_after_out = true;
667673
}
668674

669675
return err;
670676
}
671677

672678
static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
673-
unsigned int size)
679+
unsigned int size, bool *in_closed_after_out)
674680
{
675681
int err;
676682

@@ -685,34 +691,70 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd,
685691
if (err)
686692
return err;
687693
err = do_recvfile(peerfd, outfd);
694+
*in_closed_after_out = true;
688695
}
689696

690697
return err;
691698
}
692699

693700
static int copyfd_io(int infd, int peerfd, int outfd)
694701
{
702+
bool in_closed_after_out = false;
703+
struct timespec start, end;
695704
int file_size;
705+
int ret;
706+
707+
if (cfg_time && (clock_gettime(CLOCK_MONOTONIC, &start) < 0))
708+
xerror("can not fetch start time %d", errno);
696709

697710
switch (cfg_mode) {
698711
case CFG_MODE_POLL:
699-
return copyfd_io_poll(infd, peerfd, outfd);
712+
ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out);
713+
break;
714+
700715
case CFG_MODE_MMAP:
701716
file_size = get_infd_size(infd);
702717
if (file_size < 0)
703718
return file_size;
704-
return copyfd_io_mmap(infd, peerfd, outfd, file_size);
719+
ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out);
720+
break;
721+
705722
case CFG_MODE_SENDFILE:
706723
file_size = get_infd_size(infd);
707724
if (file_size < 0)
708725
return file_size;
709-
return copyfd_io_sendfile(infd, peerfd, outfd, file_size);
726+
ret = copyfd_io_sendfile(infd, peerfd, outfd, file_size, &in_closed_after_out);
727+
break;
728+
729+
default:
730+
fprintf(stderr, "Invalid mode %d\n", cfg_mode);
731+
732+
die_usage();
733+
return 1;
710734
}
711735

712-
fprintf(stderr, "Invalid mode %d\n", cfg_mode);
736+
if (ret)
737+
return ret;
713738

714-
die_usage();
715-
return 1;
739+
if (cfg_time) {
740+
unsigned int delta_ms;
741+
742+
if (clock_gettime(CLOCK_MONOTONIC, &end) < 0)
743+
xerror("can not fetch end time %d", errno);
744+
delta_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000;
745+
if (delta_ms > cfg_time) {
746+
xerror("transfer slower than expected! runtime %d ms, expected %d ms",
747+
delta_ms, cfg_time);
748+
}
749+
750+
/* show the runtime only if this end shutdown(wr) before receiving the EOF,
751+
* (that is, if this end got the longer runtime)
752+
*/
753+
if (in_closed_after_out)
754+
fprintf(stderr, "%d", delta_ms);
755+
}
756+
757+
return 0;
716758
}
717759

718760
static void check_sockaddr(int pf, struct sockaddr_storage *ss,
@@ -1005,12 +1047,11 @@ static void parse_opts(int argc, char **argv)
10051047
{
10061048
int c;
10071049

1008-
while ((c = getopt(argc, argv, "6jr:lp:s:hut:m:S:R:w:M:P:c:")) != -1) {
1050+
while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:")) != -1) {
10091051
switch (c) {
10101052
case 'j':
10111053
cfg_join = true;
10121054
cfg_mode = CFG_MODE_POLL;
1013-
cfg_wait = 400000;
10141055
break;
10151056
case 'r':
10161057
cfg_remove = true;
@@ -1043,6 +1084,9 @@ static void parse_opts(int argc, char **argv)
10431084
if (poll_timeout <= 0)
10441085
poll_timeout = -1;
10451086
break;
1087+
case 'T':
1088+
cfg_time = atoi(optarg);
1089+
break;
10461090
case 'm':
10471091
cfg_mode = parse_mode(optarg);
10481092
break;

tools/testing/selftests/net/mptcp/simult_flows.sh

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ setup()
5151
sout=$(mktemp)
5252
cout=$(mktemp)
5353
capout=$(mktemp)
54-
size=$((2048 * 4096))
54+
size=$((2 * 2048 * 4096))
5555
dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1
5656
dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1
5757

@@ -161,17 +161,15 @@ do_transfer()
161161

162162
timeout ${timeout_test} \
163163
ip netns exec ${ns3} \
164-
./mptcp_connect -jt ${timeout_poll} -l -p $port \
164+
./mptcp_connect -jt ${timeout_poll} -l -p $port -T $time \
165165
0.0.0.0 < "$sin" > "$sout" &
166166
local spid=$!
167167

168168
wait_local_port_listen "${ns3}" "${port}"
169169

170-
local start
171-
start=$(date +%s%3N)
172170
timeout ${timeout_test} \
173171
ip netns exec ${ns1} \
174-
./mptcp_connect -jt ${timeout_poll} -p $port \
172+
./mptcp_connect -jt ${timeout_poll} -p $port -T $time \
175173
10.0.3.3 < "$cin" > "$cout" &
176174
local cpid=$!
177175

@@ -180,27 +178,20 @@ do_transfer()
180178
wait $spid
181179
local rets=$?
182180

183-
local stop
184-
stop=$(date +%s%3N)
185-
186181
if $capture; then
187182
sleep 1
188183
kill ${cappid_listener}
189184
kill ${cappid_connector}
190185
fi
191186

192-
local duration
193-
duration=$((stop-start))
194-
195187
cmp $sin $cout > /dev/null 2>&1
196188
local cmps=$?
197189
cmp $cin $sout > /dev/null 2>&1
198190
local cmpc=$?
199191

200-
printf "%16s" "$duration max $max_time "
192+
printf "%-16s" " max $max_time "
201193
if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \
202-
[ $cmpc -eq 0 ] && [ $cmps -eq 0 ] && \
203-
[ $duration -lt $max_time ]; then
194+
[ $cmpc -eq 0 ] && [ $cmps -eq 0 ]; then
204195
echo "[ OK ]"
205196
cat "$capout"
206197
return 0
@@ -244,23 +235,24 @@ run_test()
244235
tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1
245236
tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2
246237

247-
# time is measure in ms
248-
local time=$((size * 8 * 1000 / (( $rate1 + $rate2) * 1024 *1024) ))
238+
# time is measured in ms, account for transfer size, affegated link speed
239+
# and header overhead (10%)
240+
local time=$((size * 8 * 1000 * 10 / (( $rate1 + $rate2) * 1024 *1024 * 9) ))
249241

250242
# mptcp_connect will do some sleeps to allow the mp_join handshake
251-
# completion
252-
time=$((time + 1350))
243+
# completion (see mptcp_connect): 200ms on each side, add some slack
244+
time=$((time + 450))
253245

254-
printf "%-50s" "$msg"
255-
do_transfer $small $large $((time * 11 / 10))
246+
printf "%-60s" "$msg"
247+
do_transfer $small $large $time
256248
lret=$?
257249
if [ $lret -ne 0 ]; then
258250
ret=$lret
259251
[ $bail -eq 0 ] || exit $ret
260252
fi
261253

262-
printf "%-50s" "$msg - reverse direction"
263-
do_transfer $large $small $((time * 11 / 10))
254+
printf "%-60s" "$msg - reverse direction"
255+
do_transfer $large $small $time
264256
lret=$?
265257
if [ $lret -ne 0 ]; then
266258
ret=$lret

0 commit comments

Comments
 (0)