33
44ret=0
55sin=" "
6+ sinfail=" "
67sout=" "
78cin=" "
9+ cinfail=" "
810cinsent=" "
911cout=" "
1012ksft_skip=4
@@ -76,6 +78,14 @@ init()
7678 done
7779}
7880
81+ init_shapers ()
82+ {
83+ for i in ` seq 1 4` ; do
84+ tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1
85+ tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1
86+ done
87+ }
88+
7989cleanup_partial ()
8090{
8191 rm -f " $capout "
@@ -88,8 +98,8 @@ cleanup_partial()
8898
8999cleanup ()
90100{
91- rm -f " $cin " " $cout "
92- rm -f " $sin " " $sout " " $cinsent "
101+ rm -f " $cin " " $cout " " $sinfail "
102+ rm -f " $sin " " $sout " " $cinsent " " $cinfail "
93103 cleanup_partial
94104}
95105
@@ -211,11 +221,15 @@ link_failure()
211221{
212222 ns=" $1 "
213223
214- l=$(( RANDOM% 4 ))
215- l=$(( l+ 1 ))
224+ if [ -z " $FAILING_LINKS " ]; then
225+ l=$(( RANDOM% 4 ))
226+ FAILING_LINKS=$(( l+ 1 ))
227+ fi
216228
217- veth=" ns1eth$l "
218- ip -net " $ns " link set " $veth " down
229+ for l in $FAILING_LINKS ; do
230+ veth=" ns1eth$l "
231+ ip -net " $ns " link set " $veth " down
232+ done
219233}
220234
221235# $1: IP address
@@ -280,10 +294,17 @@ do_transfer()
280294 local_addr=" 0.0.0.0"
281295 fi
282296
283- timeout ${timeout_test} \
284- ip netns exec ${listener_ns} \
285- $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
286- ${local_addr} < " $sin " > " $sout " &
297+ if [ " $test_link_fail " -eq 2 ]; then
298+ timeout ${timeout_test} \
299+ ip netns exec ${listener_ns} \
300+ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${cl_proto} \
301+ ${local_addr} < " $sinfail " > " $sout " &
302+ else
303+ timeout ${timeout_test} \
304+ ip netns exec ${listener_ns} \
305+ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
306+ ${local_addr} < " $sin " > " $sout " &
307+ fi
287308 spid=$!
288309
289310 sleep 1
@@ -294,7 +315,7 @@ do_transfer()
294315 $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
295316 $connect_addr < " $cin " > " $cout " &
296317 else
297- ( cat " $cin " ; sleep 2; link_failure $listener_ns ; cat " $cin " ) | \
318+ ( cat " $cinfail " ; sleep 2; link_failure $listener_ns ; cat " $cinfail " ) | \
298319 tee " $cinsent " | \
299320 timeout ${timeout_test} \
300321 ip netns exec ${connector_ns} \
@@ -434,7 +455,11 @@ do_transfer()
434455 return 1
435456 fi
436457
437- check_transfer $sin $cout " file received by client"
458+ if [ " $test_link_fail " -eq 2 ]; then
459+ check_transfer $sinfail $cout " file received by client"
460+ else
461+ check_transfer $sin $cout " file received by client"
462+ fi
438463 retc=$?
439464 if [ " $test_link_fail " -eq 0 ]; then
440465 check_transfer $cin $sout " file received by server"
@@ -477,29 +502,33 @@ run_tests()
477502 lret=0
478503 oldin=" "
479504
480- if [ " $test_linkfail " -eq 1 ]; then
481- size=$(( RANDOM% 1024 ))
505+ # create the input file for the failure test when
506+ # the first failure test run
507+ if [ " $test_linkfail " -ne 0 -a -z " $cinfail " ]; then
508+ # the client file must be considerably larger
509+ # of the maximum expected cwin value, or the
510+ # link utilization will be not predicable
511+ size=$(( RANDOM% 2 ))
482512 size=$(( size+ 1 ))
483- size=$(( size* 128 ))
513+ size=$(( size* 8192 ))
514+ size=$(( size + ( $RANDOM % 8192 ) ))
484515
485- oldin=$( mktemp)
486- cp " $cin " " $oldin "
487- make_file " $cin " " client" $size
516+ cinfail=$( mktemp)
517+ make_file " $cinfail " " client" $size
488518 fi
489519
490- do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \
491- ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${bkup}
492- lret=$?
520+ if [ " $test_linkfail " -eq 2 -a -z " $sinfail " ]; then
521+ size=$(( RANDOM% 16 ))
522+ size=$(( size+ 1 ))
523+ size=$(( size* 2048 ))
493524
494- if [ " $test_linkfail " -eq 1 ]; then
495- cp " $oldin " " $cin "
496- rm -f " $oldin "
525+ sinfail=$( mktemp)
526+ make_file " $sinfail " " server" $size
497527 fi
498528
499- if [ $lret -ne 0 ]; then
500- ret=$lret
501- return
502- fi
529+ do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \
530+ ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${bkup}
531+ lret=$?
503532}
504533
505534chk_csum_nr ()
@@ -593,6 +622,46 @@ chk_join_nr()
593622 fi
594623}
595624
625+ # a negative value for 'stale_max' means no upper bound:
626+ # for bidirectional transfer, if one peer sleep for a while
627+ # - as these tests do - we can have a quite high number of
628+ # stale/recover conversions, proportional to
629+ # sleep duration/ MPTCP-level RTX interval.
630+ chk_stale_nr ()
631+ {
632+ local ns=$1
633+ local stale_min=$2
634+ local stale_max=$3
635+ local stale_delta=$4
636+ local dump_stats
637+ local stale_nr
638+ local recover_nr
639+
640+ printf " %-39s %-18s" " " " stale"
641+ stale_nr=` ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk ' {print $2}' `
642+ [ -z " $stale_nr " ] && stale_nr=0
643+ recover_nr=` ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk ' {print $2}' `
644+ [ -z " $recover_nr " ] && recover_nr=0
645+
646+ if [ $stale_nr -lt $stale_min ] ||
647+ [ $stale_max -gt 0 -a $stale_nr -gt $stale_max ] ||
648+ [ $(( stale_nr - $recover_nr )) -ne $stale_delta ]; then
649+ echo " [fail] got $stale_nr stale[s] $recover_nr recover[s], " \
650+ " expected stale in range [$stale_min ..$stale_max ]," \
651+ " stale-recover delta $stale_delta "
652+ ret=1
653+ dump_stats=1
654+ else
655+ echo " [ ok ]"
656+ fi
657+
658+ if [ " ${dump_stats} " = 1 ]; then
659+ echo $ns stats
660+ ip netns exec $ns ip -s link show
661+ ip netns exec $ns nstat -as | grep MPTcp
662+ fi
663+ }
664+
596665chk_add_nr ()
597666{
598667 local add_nr=$1
@@ -801,6 +870,27 @@ chk_prio_nr()
801870 fi
802871}
803872
873+ chk_link_usage ()
874+ {
875+ local ns=$1
876+ local link=$2
877+ local out=$3
878+ local expected_rate=$4
879+ local tx_link=` ip netns exec $ns cat /sys/class/net/$link /statistics/tx_bytes`
880+ local tx_total=` ls -l $out | awk ' {print $5}' `
881+ local tx_rate=$(( tx_link * 100 / $tx_total ))
882+ local tolerance=5
883+
884+ printf " %-39s %-18s" " " " link usage"
885+ if [ $tx_rate -lt $(( expected_rate - $tolerance )) -o \
886+ $tx_rate -gt $(( expected_rate + $tolerance )) ]; then
887+ echo " [fail] got $tx_rate % usage, expected $expected_rate %"
888+ ret=1
889+ else
890+ echo " [ ok ]"
891+ fi
892+ }
893+
804894subflows_tests ()
805895{
806896 reset
@@ -924,14 +1014,80 @@ link_failure_tests()
9241014{
9251015 # accept and use add_addr with additional subflows and link loss
9261016 reset
1017+
1018+ # without any b/w limit each veth could spool the packets and get
1019+ # them acked at xmit time, so that the corresponding subflow will
1020+ # have almost always no outstanding pkts, the scheduler will pick
1021+ # always the first subflow and we will have hard time testing
1022+ # active backup and link switch-over.
1023+ # Let's set some arbitrary (low) virtual link limits.
1024+ init_shapers
9271025 ip netns exec $ns1 ./pm_nl_ctl limits 0 3
928- ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal
1026+ ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
9291027 ip netns exec $ns2 ./pm_nl_ctl limits 1 3
930- ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow
931- ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow
1028+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow
1029+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 dev ns2eth4 flags subflow
9321030 run_tests $ns1 $ns2 10.0.1.1 1
9331031 chk_join_nr " multiple flows, signal, link failure" 3 3 3
9341032 chk_add_nr 1 1
1033+ chk_stale_nr $ns2 1 5 1
1034+
1035+ # accept and use add_addr with additional subflows and link loss
1036+ # for bidirectional transfer
1037+ reset
1038+ init_shapers
1039+ ip netns exec $ns1 ./pm_nl_ctl limits 0 3
1040+ ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
1041+ ip netns exec $ns2 ./pm_nl_ctl limits 1 3
1042+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow
1043+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 dev ns2eth4 flags subflow
1044+ run_tests $ns1 $ns2 10.0.1.1 2
1045+ chk_join_nr " multi flows, signal, bidi, link fail" 3 3 3
1046+ chk_add_nr 1 1
1047+ chk_stale_nr $ns2 1 -1 1
1048+
1049+ # 2 subflows plus 1 backup subflow with a lossy link, backup
1050+ # will never be used
1051+ reset
1052+ init_shapers
1053+ ip netns exec $ns1 ./pm_nl_ctl limits 0 2
1054+ ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
1055+ ip netns exec $ns2 ./pm_nl_ctl limits 1 2
1056+ export FAILING_LINKS=" 1"
1057+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
1058+ run_tests $ns1 $ns2 10.0.1.1 1
1059+ chk_join_nr " backup subflow unused, link failure" 2 2 2
1060+ chk_add_nr 1 1
1061+ chk_link_usage $ns2 ns2eth3 $cinsent 0
1062+
1063+ # 2 lossy links after half transfer, backup will get half of
1064+ # the traffic
1065+ reset
1066+ init_shapers
1067+ ip netns exec $ns1 ./pm_nl_ctl limits 0 2
1068+ ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
1069+ ip netns exec $ns2 ./pm_nl_ctl limits 1 2
1070+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
1071+ export FAILING_LINKS=" 1 2"
1072+ run_tests $ns1 $ns2 10.0.1.1 1
1073+ chk_join_nr " backup flow used, multi links fail" 2 2 2
1074+ chk_add_nr 1 1
1075+ chk_stale_nr $ns2 2 4 2
1076+ chk_link_usage $ns2 ns2eth3 $cinsent 50
1077+
1078+ # use a backup subflow with the first subflow on a lossy link
1079+ # for bidirectional transfer
1080+ reset
1081+ init_shapers
1082+ ip netns exec $ns1 ./pm_nl_ctl limits 0 2
1083+ ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags signal
1084+ ip netns exec $ns2 ./pm_nl_ctl limits 1 3
1085+ ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 dev ns2eth3 flags subflow,backup
1086+ run_tests $ns1 $ns2 10.0.1.1 2
1087+ chk_join_nr " backup flow used, bidi, link failure" 2 2 2
1088+ chk_add_nr 1 1
1089+ chk_stale_nr $ns2 1 -1 2
1090+ chk_link_usage $ns2 ns2eth3 $cinsent 50
9351091}
9361092
9371093add_addr_timeout_tests ()
0 commit comments