2 # SPDX-License-Identifier: GPL-2.0
6 optstring
="S:R:d:e:l:r:h4cm:f:tC"
15 timeout_test
=$
((timeout_poll
* 2 + 1))
17 ethtool_random_on
=true
18 tc_delay
="$((RANDOM%50))"
19 tc_loss
=$
((RANDOM
%101))
28 if [ $tc_loss -eq 100 ];then
30 elif [ $tc_loss -ge 10 ]; then
32 elif [ $tc_loss -ge 1 ]; then
39 echo "Usage: $0 [ -a ]"
40 echo -e "\t-d: tc/netem delay in milliseconds, e.g. \"-d 10\" (default random)"
41 echo -e "\t-l: tc/netem loss percentage, e.g. \"-l 0.02\" (default random)"
42 echo -e "\t-r: tc/netem reorder mode, e.g. \"-r 25% 50% gap 5\", use "-r 0" to disable reordering (default random)"
43 echo -e "\t-e: ethtool features to disable, e.g.: \"-e tso -e gso\" (default: randomly disable any of tso/gso/gro)"
44 echo -e "\t-4: IPv4 only: disable IPv6 tests (default: test both IPv4 and IPv6)"
45 echo -e "\t-c: capture packets for each test using tcpdump (default: no capture)"
46 echo -e "\t-f: size of file to transfer in bytes (default random)"
47 echo -e "\t-S: set sndbuf value (default: use kernel default)"
48 echo -e "\t-R: set rcvbuf value (default: use kernel default)"
49 echo -e "\t-m: test mode (poll, sendfile; default: poll)"
50 echo -e "\t-t: also run tests with TCP (use twice to non-fallback tcp)"
51 echo -e "\t-C: enable the MPTCP data checksum"
54 while getopts "$optstring" option
;do
61 if [ $OPTARG -ge 0 ];then
64 echo "-d requires numeric argument, got \"$OPTARG\"" 1>&2
69 ethtool_args
="$ethtool_args $OPTARG off"
70 ethtool_random_on
=false
85 if [ $OPTARG -ge 0 ];then
88 echo "-S requires numeric argument, got \"$OPTARG\"" 1>&2
93 if [ $OPTARG -ge 0 ];then
96 echo "-R requires numeric argument, got \"$OPTARG\"" 1>&2
120 rndh
=$
(printf %x
$sec)-$
(mktemp
-u XXXXXX
)
135 for netns
in "$ns1" "$ns2" "$ns3" "$ns4";do
137 rm -f /tmp
/$netns.
{nstat
,out
}
141 ip
-Version > /dev
/null
2>&1
143 echo "SKIP: Could not run test without ip tool"
154 for i
in "$ns1" "$ns2" "$ns3" "$ns4";do
155 ip netns add
$i ||
exit $ksft_skip
156 ip
-net $i link
set lo up
160 # ns1eth2 ns2eth1 ns2eth3 ns3eth2 ns3eth4 ns4eth3
161 # - drop 1% -> reorder 25%
164 ip link add ns1eth2 netns
"$ns1" type veth peer name ns2eth1 netns
"$ns2"
165 ip link add ns2eth3 netns
"$ns2" type veth peer name ns3eth2 netns
"$ns3"
166 ip link add ns3eth4 netns
"$ns3" type veth peer name ns4eth3 netns
"$ns4"
168 ip
-net "$ns1" addr add
10.0.1.1/24 dev ns1eth2
169 ip
-net "$ns1" addr add dead
:beef
:1::1/64 dev ns1eth2 nodad
171 ip
-net "$ns1" link
set ns1eth2 up
172 ip
-net "$ns1" route add default via
10.0.1.2
173 ip
-net "$ns1" route add default via dead
:beef
:1::2
175 ip
-net "$ns2" addr add
10.0.1.2/24 dev ns2eth1
176 ip
-net "$ns2" addr add dead
:beef
:1::2/64 dev ns2eth1 nodad
177 ip
-net "$ns2" link
set ns2eth1 up
179 ip
-net "$ns2" addr add
10.0.2.1/24 dev ns2eth3
180 ip
-net "$ns2" addr add dead
:beef
:2::1/64 dev ns2eth3 nodad
181 ip
-net "$ns2" link
set ns2eth3 up
182 ip
-net "$ns2" route add default via
10.0.2.2
183 ip
-net "$ns2" route add default via dead
:beef
:2::2
184 ip netns
exec "$ns2" sysctl
-q net.ipv4.ip_forward
=1
185 ip netns
exec "$ns2" sysctl
-q net.ipv6.conf.all.forwarding
=1
187 ip
-net "$ns3" addr add
10.0.2.2/24 dev ns3eth2
188 ip
-net "$ns3" addr add dead
:beef
:2::2/64 dev ns3eth2 nodad
189 ip
-net "$ns3" link
set ns3eth2 up
191 ip
-net "$ns3" addr add
10.0.3.2/24 dev ns3eth4
192 ip
-net "$ns3" addr add dead
:beef
:3::2/64 dev ns3eth4 nodad
193 ip
-net "$ns3" link
set ns3eth4 up
194 ip
-net "$ns3" route add default via
10.0.2.1
195 ip
-net "$ns3" route add default via dead
:beef
:2::1
196 ip netns
exec "$ns3" sysctl
-q net.ipv4.ip_forward
=1
197 ip netns
exec "$ns3" sysctl
-q net.ipv6.conf.all.forwarding
=1
199 ip
-net "$ns4" addr add
10.0.3.1/24 dev ns4eth3
200 ip
-net "$ns4" addr add dead
:beef
:3::1/64 dev ns4eth3 nodad
201 ip
-net "$ns4" link
set ns4eth3 up
202 ip
-net "$ns4" route add default via
10.0.3.2
203 ip
-net "$ns4" route add default via dead
:beef
:3::2
206 for i
in "$ns1" "$ns2" "$ns3" "$ns4";do
207 ip netns
exec $i sysctl
-q net.mptcp.checksum_enabled
=1
211 set_ethtool_flags
() {
216 ip netns
exec $ns ethtool
-K $dev $flags 2>/dev
/null
217 [ $?
-eq 0 ] && echo "INFO: set $ns dev $dev: ethtool -K $flags"
220 set_random_ethtool_flags
() {
224 local pick1
=$
((r
& 1))
225 local pick2
=$
((r
& 2))
226 local pick3
=$
((r
& 4))
228 [ $pick1 -ne 0 ] && flags
="tso off"
229 [ $pick2 -ne 0 ] && flags
="$flags gso off"
230 [ $pick3 -ne 0 ] && flags
="$flags gro off"
232 [ -z "$flags" ] && return
234 set_ethtool_flags
"$1" "$2" "$flags"
237 if $ethtool_random_on;then
238 set_random_ethtool_flags
"$ns3" ns3eth2
239 set_random_ethtool_flags
"$ns4" ns4eth3
241 set_ethtool_flags
"$ns3" ns3eth2
"$ethtool_args"
242 set_ethtool_flags
"$ns4" ns4eth3
"$ethtool_args"
248 echo "Trailing bytes are: "
258 cmp "$in" "$out" > /dev
/null
2>&1
259 if [ $?
-ne 0 ] ;then
260 echo "[ FAIL ] $what does not match (in, out):"
262 print_file_err
"$out"
270 check_mptcp_disabled
()
273 disabled_ns
="ns_disabled-$sech-$(mktemp -u XXXXXX)"
274 ip netns add
${disabled_ns} ||
exit $ksft_skip
276 # net.mptcp.enabled should be enabled by default
277 if [ "$(ip netns exec ${disabled_ns} sysctl net.mptcp.enabled | awk '{ print $3 }')" -ne 1 ]; then
278 echo -e "net.mptcp.enabled sysctl is not 1 by default\t\t[ FAIL ]"
282 ip netns
exec ${disabled_ns} sysctl
-q net.mptcp.enabled
=0
285 LC_ALL
=C ip netns
exec ${disabled_ns} .
/mptcp_connect
-p 10000 -s MPTCP
127.0.0.1 < "$cin" 2>&1 | \
286 grep -q "^socket: Protocol not available$" && err
=1
287 ip netns delete
${disabled_ns}
289 if [ ${err} -eq 0 ]; then
290 echo -e "New MPTCP socket cannot be blocked via sysctl\t\t[ FAIL ]"
295 echo -e "New MPTCP socket can be blocked via sysctl\t\t[ OK ]"
299 check_mptcp_ulp_setsockopt
()
302 t
="ns_ulp-$sech-$(mktemp -u XXXXXX)"
304 ip netns add
${t} ||
exit $ksft_skip
305 if ! ip netns
exec ${t} .
/mptcp_connect
-u -p 10000 -s TCP
127.0.0.1 2>&1; then
306 printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) allowed\t[ FAIL ]\n"
310 printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) blocked\t[ OK ]\n"
325 local listener_ns
="$1"
326 local connector_ns
="$2"
327 local connect_addr
="$3"
328 local ping_args
="-q -c 1"
330 if is_v6
"${connect_addr}"; then
332 ping_args
="${ping_args} -6"
335 ip netns
exec ${connector_ns} ping ${ping_args} $connect_addr >/dev
/null
336 if [ $?
-ne 0 ] ; then
337 echo "$listener_ns -> $connect_addr connectivity [ FAIL ]" 1>&2
346 # $1: ns, $2: MIB counter
349 local listener_ns
="${1}"
353 ip netns
exec "${listener_ns}" \
354 nstat
-z -a "${mib}" | \
356 while read a count c rest
; do
362 wait_local_port_listen
()
364 local listener_ns
="${1}"
369 port_hex
="$(printf "%04X
" "${port}")"
370 for i
in $
(seq 10); do
371 ip netns
exec "${listener_ns}" cat /proc
/net
/tcp
* | \
372 awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
380 local listener_ns
="$1"
381 local connector_ns
="$2"
384 local connect_addr
="$5"
385 local local_addr
="$6"
386 local extra_args
="$7"
389 port
=$
((10000+$TEST_COUNT))
390 TEST_COUNT
=$
((TEST_COUNT
+1))
392 if [ "$rcvbuf" -gt 0 ]; then
393 extra_args
="$extra_args -R $rcvbuf"
396 if [ "$sndbuf" -gt 0 ]; then
397 extra_args
="$extra_args -S $sndbuf"
400 if [ -n "$testmode" ]; then
401 extra_args
="$extra_args -m $testmode"
404 if [ -n "$extra_args" ] && $options_log; then
405 echo "INFO: extra options: $extra_args"
414 addr_port
=$
(printf "%s:%d" ${connect_addr} ${port})
415 printf "%.3s %-5s -> %.3s (%-20s) %-5s\t" ${connector_ns} ${cl_proto} ${listener_ns} ${addr_port} ${srv_proto}
419 if [ -z $SUDO_USER ] ; then
422 capuser
="-Z $SUDO_USER"
425 local capfile
="${rndh}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}"
426 local capopt
="-i any -s 65535 -B 32768 ${capuser}"
428 ip netns
exec ${listener_ns} tcpdump ${capopt} -w "${capfile}-listener.pcap" >> "${capout}" 2>&1 &
429 local cappid_listener=$!
431 ip netns exec ${connector_ns} tcpdump ${capopt} -w "${capfile}-connector.pcap" >> "${capout}" 2>&1 &
432 local cappid_connector
=$
!
437 NSTAT_HISTORY
=/tmp
/${listener_ns}.nstat ip netns
exec ${listener_ns} \
439 if [ ${listener_ns} != ${connector_ns} ]; then
440 NSTAT_HISTORY
=/tmp
/${connector_ns}.nstat ip netns
exec ${connector_ns} \
444 local stat_synrx_last_l
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtMPCapableSYNRX")
445 local stat_ackrx_last_l
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtMPCapableACKRX")
446 local stat_cookietx_last
=$
(get_mib_counter
"${listener_ns}" "TcpExtSyncookiesSent")
447 local stat_cookierx_last
=$
(get_mib_counter
"${listener_ns}" "TcpExtSyncookiesRecv")
448 local stat_csum_err_s
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtDataCsumErr")
449 local stat_csum_err_c
=$
(get_mib_counter
"${connector_ns}" "MPTcpExtDataCsumErr")
451 timeout
${timeout_test} \
452 ip netns
exec ${listener_ns} \
453 .
/mptcp_connect
-t ${timeout_poll} -l -p $port -s ${srv_proto} \
454 $extra_args $local_addr < "$sin" > "$sout" &
457 wait_local_port_listen
"${listener_ns}" "${port}"
461 timeout
${timeout_test} \
462 ip netns
exec ${connector_ns} \
463 .
/mptcp_connect
-t ${timeout_poll} -p $port -s ${cl_proto} \
464 $extra_args $connect_addr < "$cin" > "$cout" &
477 kill ${cappid_listener}
478 kill ${cappid_connector}
481 NSTAT_HISTORY
=/tmp
/${listener_ns}.nstat ip netns
exec ${listener_ns} \
482 nstat |
grep Tcp
> /tmp
/${listener_ns}.out
483 if [ ${listener_ns} != ${connector_ns} ]; then
484 NSTAT_HISTORY
=/tmp
/${connector_ns}.nstat ip netns
exec ${connector_ns} \
485 nstat |
grep Tcp
> /tmp
/${connector_ns}.out
489 duration
=$
((stop-start
))
490 printf "(duration %05sms) " "${duration}"
491 if [ ${rets} -ne 0 ] ||
[ ${retc} -ne 0 ]; then
492 echo "[ FAIL ] client exit code $retc, server $rets" 1>&2
493 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2
494 ip netns
exec ${listener_ns} ss
-Menita 1>&2 -o "sport = :$port"
495 cat /tmp
/${listener_ns}.out
496 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2
497 ip netns
exec ${connector_ns} ss
-Menita 1>&2 -o "dport = :$port"
498 [ ${listener_ns} != ${connector_ns} ] && cat /tmp/${connector_ns}.out
505 check_transfer
$sin $cout "file received by client"
507 check_transfer
$cin $sout "file received by server"
510 local stat_synrx_now_l
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtMPCapableSYNRX")
511 local stat_ackrx_now_l
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtMPCapableACKRX")
512 local stat_cookietx_now
=$
(get_mib_counter
"${listener_ns}" "TcpExtSyncookiesSent")
513 local stat_cookierx_now
=$
(get_mib_counter
"${listener_ns}" "TcpExtSyncookiesRecv")
514 local stat_ooo_now
=$
(get_mib_counter
"${listener_ns}" "TcpExtTCPOFOQueue")
516 expect_synrx
=$
((stat_synrx_last_l
))
517 expect_ackrx
=$
((stat_ackrx_last_l
))
519 cookies
=$
(ip netns
exec ${listener_ns} sysctl net.ipv4.tcp_syncookies
)
520 cookies
=${cookies##*=}
522 if [ ${cl_proto} = "MPTCP" ] && [ ${srv_proto} = "MPTCP" ]; then
523 expect_synrx
=$
((stat_synrx_last_l
+1))
524 expect_ackrx
=$
((stat_ackrx_last_l
+1))
527 if [ ${stat_synrx_now_l} -lt ${expect_synrx} ]; then
528 printf "[ FAIL ] lower MPC SYN rx (%d) than expected (%d)\n" \
529 "${stat_synrx_now_l}" "${expect_synrx}" 1>&2
532 if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} -a ${stat_ooo_now} -eq 0 ]; then
533 if [ ${stat_ooo_now} -eq 0 ]; then
534 printf "[ FAIL ] lower MPC ACK rx (%d) than expected (%d)\n" \
535 "${stat_ackrx_now_l}" "${expect_ackrx}" 1>&2
538 printf "[ Note ] fallback due to TCP OoO"
543 local csum_err_s
=$
(get_mib_counter
"${listener_ns}" "MPTcpExtDataCsumErr")
544 local csum_err_c
=$
(get_mib_counter
"${connector_ns}" "MPTcpExtDataCsumErr")
546 local csum_err_s_nr
=$
((csum_err_s
- stat_csum_err_s
))
547 if [ $csum_err_s_nr -gt 0 ]; then
548 printf "[ FAIL ]\nserver got $csum_err_s_nr data checksum error[s]"
552 local csum_err_c_nr
=$
((csum_err_c
- stat_csum_err_c
))
553 if [ $csum_err_c_nr -gt 0 ]; then
554 printf "[ FAIL ]\nclient got $csum_err_c_nr data checksum error[s]"
559 if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then
563 if [ $cookies -eq 2 ];then
564 if [ $stat_cookietx_last -ge $stat_cookietx_now ] ;then
565 printf " WARN: CookieSent: did not advance"
567 if [ $stat_cookierx_last -ge $stat_cookierx_now ] ;then
568 printf " WARN: CookieRecv: did not advance"
571 if [ $stat_cookietx_last -ne $stat_cookietx_now ] ;then
572 printf " WARN: CookieSent: changed"
574 if [ $stat_cookierx_last -ne $stat_cookierx_now ] ;then
575 printf " WARN: CookieRecv: changed"
579 if [ ${stat_synrx_now_l} -gt ${expect_synrx} ]; then
580 printf " WARN: SYNRX: expect %d, got %d (probably retransmissions)" \
581 "${expect_synrx}" "${stat_synrx_now_l}"
583 if [ ${stat_ackrx_now_l} -gt ${expect_ackrx} ]; then
584 printf " WARN: ACKRX: expect %d, got %d (probably retransmissions)" \
585 "${expect_ackrx}" "${stat_ackrx_now_l}"
590 [ $retc -eq 0 ] && [ $rets -eq 0 ]
601 if [ $SIZE -eq 0 ]; then
602 local MAXSIZE
=$
((1024 * 1024 * 8))
603 local MINSIZE
=$
((1024 * 256))
605 SIZE
=$
(((RANDOM
* RANDOM
+ MINSIZE
) % MAXSIZE
))
608 ksize
=$
((SIZE
/ 1024))
609 rem
=$
((SIZE
- (ksize
* 1024)))
611 dd if=/dev
/urandom of
="$name" bs
=1024 count
=$ksize 2> /dev
/null
612 dd if=/dev
/urandom conv
=notrunc of
="$name" bs
=1 count
=$rem 2> /dev
/null
613 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
615 echo "Created $name (size $(du -b "$name")) containing data sent by $who"
620 local listener_ns
="$1"
621 local connector_ns
="$2"
622 local connect_addr
="$3"
624 local extra_args
="$5"
627 # skip if test programs are running inside same netns for subsequent runs.
628 if [ $loopback -eq 0 ] && [ ${listener_ns} = ${connector_ns} ]; then
632 # skip if we don't want v6
633 if ! $ipv6 && is_v6
"${connect_addr}"; then
638 if is_v6
"${connect_addr}"; then
644 do_transfer
${listener_ns} ${connector_ns} MPTCP MPTCP \
645 ${connect_addr} ${local_addr} "${extra_args}"
647 if [ $lret -ne 0 ]; then
652 if [ $do_tcp -eq 0 ]; then
653 # don't bother testing fallback tcp except for loopback case.
654 if [ ${listener_ns} != ${connector_ns} ]; then
659 do_transfer ${listener_ns} ${connector_ns} MPTCP TCP \
660 ${connect_addr} ${local_addr} "${extra_args}"
662 if [ $lret -ne 0 ]; then
667 do_transfer
${listener_ns} ${connector_ns} TCP MPTCP \
668 ${connect_addr} ${local_addr} "${extra_args}"
670 if [ $lret -ne 0 ]; then
675 if [ $do_tcp -gt 1 ] ;then
676 do_transfer ${listener_ns} ${connector_ns} TCP TCP \
677 ${connect_addr} ${local_addr} "${extra_args}"
679 if [ $lret -ne 0 ]; then
690 run_tests_lo
$1 $2 $3 0
697 echo "INFO: with peek mode: ${peekmode}"
698 run_tests_lo
"$ns1" "$ns1" 10.0.1.1 1 "-P ${peekmode}"
699 run_tests_lo
"$ns1" "$ns1" dead
:beef
:1::1 1 "-P ${peekmode}"
705 time_run
=$
((time_end-time_start
))
707 echo "Time: ${time_run} seconds"
714 if [ ${ret} -ne 0 ]; then
715 echo "FAIL: ${msg}" 1>&2
721 make_file
"$cin" "client"
722 make_file
"$sin" "server"
726 check_mptcp_ulp_setsockopt
728 stop_if_error
"The kernel configuration is not valid for MPTCP"
730 echo "INFO: validating network environment with pings"
731 for sender
in "$ns1" "$ns2" "$ns3" "$ns4";do
732 do_ping
"$ns1" $sender 10.0.1.1
733 do_ping
"$ns1" $sender dead
:beef
:1::1
735 do_ping
"$ns2" $sender 10.0.1.2
736 do_ping
"$ns2" $sender dead
:beef
:1::2
737 do_ping
"$ns2" $sender 10.0.2.1
738 do_ping
"$ns2" $sender dead
:beef
:2::1
740 do_ping
"$ns3" $sender 10.0.2.2
741 do_ping
"$ns3" $sender dead
:beef
:2::2
742 do_ping
"$ns3" $sender 10.0.3.2
743 do_ping
"$ns3" $sender dead
:beef
:3::2
745 do_ping
"$ns4" $sender 10.0.3.1
746 do_ping
"$ns4" $sender dead
:beef
:3::1
749 stop_if_error
"Could not even run ping tests"
751 [ -n "$tc_loss" ] && tc
-net "$ns2" qdisc add dev ns2eth3 root netem loss random
$tc_loss delay
${tc_delay}ms
752 echo -n "INFO: Using loss of $tc_loss "
753 test "$tc_delay" -gt 0 && echo -n "delay $tc_delay ms "
755 reorder_delay
=$
(($tc_delay / 4))
757 if [ -z "${tc_reorder}" ]; then
758 reorder1
=$
((RANDOM
%10))
759 reorder1
=$
((100 - reorder1
))
760 reorder2
=$
((RANDOM
%100))
762 if [ $reorder_delay -gt 0 ] && [ $reorder1 -lt 100 ] && [ $reorder2 -gt 0 ]; then
763 tc_reorder
="reorder ${reorder1}% ${reorder2}%"
764 echo -n "$tc_reorder with delay ${reorder_delay}ms "
766 elif [ "$tc_reorder" = "0" ];then
768 elif [ "$reorder_delay" -gt 0 ];then
769 # reordering requires some delay
770 tc_reorder
="reorder $tc_reorder"
771 echo -n "$tc_reorder with delay ${reorder_delay}ms "
776 tc
-net "$ns3" qdisc add dev ns3eth4 root netem delay
${reorder_delay}ms
$tc_reorder
778 run_tests_lo
"$ns1" "$ns1" 10.0.1.1 1
779 stop_if_error
"Could not even run loopback test"
781 run_tests_lo
"$ns1" "$ns1" dead
:beef
:1::1 1
782 stop_if_error
"Could not even run loopback v6 test"
784 for sender
in $ns1 $ns2 $ns3 $ns4;do
785 # ns1<->ns2 is not subject to reordering/tc delays. Use it to test
786 # mptcp syncookie support.
787 if [ $sender = $ns1 ]; then
788 ip netns
exec "$ns2" sysctl
-q net.ipv4.tcp_syncookies
=2
790 ip netns
exec "$ns2" sysctl
-q net.ipv4.tcp_syncookies
=1
793 run_tests
"$ns1" $sender 10.0.1.1
794 run_tests
"$ns1" $sender dead
:beef
:1::1
796 run_tests
"$ns2" $sender 10.0.1.2
797 run_tests
"$ns2" $sender dead
:beef
:1::2
798 run_tests
"$ns2" $sender 10.0.2.1
799 run_tests
"$ns2" $sender dead
:beef
:2::1
801 run_tests
"$ns3" $sender 10.0.2.2
802 run_tests
"$ns3" $sender dead
:beef
:2::2
803 run_tests
"$ns3" $sender 10.0.3.2
804 run_tests
"$ns3" $sender dead
:beef
:3::2
806 run_tests
"$ns4" $sender 10.0.3.1
807 run_tests
"$ns4" $sender dead
:beef
:3::1
809 stop_if_error
"Tests with $sender as a sender have failed"
812 run_tests_peekmode
"saveWithPeek"
813 run_tests_peekmode
"saveAfterPeek"
814 stop_if_error
"Tests with peek mode have failed"