1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4ret=0 5sin="" 6sout="" 7cin="" 8cout="" 9ksft_skip=4 10timeout=30 11mptcp_connect="" 12capture=0 13 14TEST_COUNT=0 15 16init() 17{ 18 capout=$(mktemp) 19 20 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 21 22 ns1="ns1-$rndh" 23 ns2="ns2-$rndh" 24 25 for netns in "$ns1" "$ns2";do 26 ip netns add $netns || exit $ksft_skip 27 ip -net $netns link set lo up 28 ip netns exec $netns sysctl -q net.mptcp.enabled=1 29 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0 30 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0 31 done 32 33 # ns1 ns2 34 # ns1eth1 ns2eth1 35 # ns1eth2 ns2eth2 36 # ns1eth3 ns2eth3 37 # ns1eth4 ns2eth4 38 39 for i in `seq 1 4`; do 40 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2" 41 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i 42 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad 43 ip -net "$ns1" link set ns1eth$i up 44 45 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i 46 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad 47 ip -net "$ns2" link set ns2eth$i up 48 49 # let $ns2 reach any $ns1 address from any interface 50 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i 51 done 52} 53 54cleanup_partial() 55{ 56 rm -f "$capout" 57 58 for netns in "$ns1" "$ns2"; do 59 ip netns del $netns 60 done 61} 62 63cleanup() 64{ 65 rm -f "$cin" "$cout" 66 rm -f "$sin" "$sout" 67 cleanup_partial 68} 69 70reset() 71{ 72 cleanup_partial 73 init 74} 75 76reset_with_cookies() 77{ 78 reset 79 80 for netns in "$ns1" "$ns2";do 81 ip netns exec $netns sysctl -q net.ipv4.tcp_syncookies=2 82 done 83} 84 85for arg in "$@"; do 86 if [ "$arg" = "-c" ]; then 87 capture=1 88 fi 89done 90 91ip -Version > /dev/null 2>&1 92if [ $? -ne 0 ];then 93 echo "SKIP: Could not run test without ip tool" 94 exit $ksft_skip 95fi 96 97 98check_transfer() 99{ 100 in=$1 101 out=$2 102 what=$3 103 104 cmp "$in" "$out" > /dev/null 2>&1 105 if [ $? -ne 0 ] ;then 106 echo "[ FAIL ] $what does not match (in, out):" 107 print_file_err "$in" 108 print_file_err "$out" 109 110 return 1 111 fi 112 113 return 0 114} 115 116do_ping() 117{ 118 listener_ns="$1" 119 connector_ns="$2" 120 connect_addr="$3" 121 122 ip netns exec ${connector_ns} ping -q -c 1 $connect_addr >/dev/null 123 if [ $? -ne 0 ] ; then 124 echo "$listener_ns -> $connect_addr connectivity [ FAIL ]" 1>&2 125 ret=1 126 fi 127} 128 129do_transfer() 130{ 131 listener_ns="$1" 132 connector_ns="$2" 133 cl_proto="$3" 134 srv_proto="$4" 135 connect_addr="$5" 136 rm_nr_ns1="$6" 137 rm_nr_ns2="$7" 138 139 port=$((10000+$TEST_COUNT)) 140 TEST_COUNT=$((TEST_COUNT+1)) 141 142 :> "$cout" 143 :> "$sout" 144 :> "$capout" 145 146 if [ $capture -eq 1 ]; then 147 if [ -z $SUDO_USER ] ; then 148 capuser="" 149 else 150 capuser="-Z $SUDO_USER" 151 fi 152 153 capfile=$(printf "mp_join-%02u-%s.pcap" "$TEST_COUNT" "${listener_ns}") 154 155 echo "Capturing traffic for test $TEST_COUNT into $capfile" 156 ip netns exec ${listener_ns} tcpdump -i any -s 65535 -B 32768 $capuser -w $capfile > "$capout" 2>&1 & 157 cappid=$! 158 159 sleep 1 160 fi 161 162 if [[ $rm_nr_ns1 -eq 0 && $rm_nr_ns2 -eq 0 ]]; then 163 mptcp_connect="./mptcp_connect -j" 164 else 165 mptcp_connect="./mptcp_connect -r" 166 fi 167 168 ip netns exec ${listener_ns} $mptcp_connect -t $timeout -l -p $port -s ${srv_proto} 0.0.0.0 < "$sin" > "$sout" & 169 spid=$! 170 171 sleep 1 172 173 ip netns exec ${connector_ns} $mptcp_connect -t $timeout -p $port -s ${cl_proto} $connect_addr < "$cin" > "$cout" & 174 cpid=$! 175 176 if [ $rm_nr_ns1 -gt 0 ]; then 177 counter=1 178 sleep 1 179 180 while [ $counter -le $rm_nr_ns1 ] 181 do 182 ip netns exec ${listener_ns} ./pm_nl_ctl del $counter 183 sleep 1 184 let counter+=1 185 done 186 fi 187 188 if [ $rm_nr_ns2 -gt 0 ]; then 189 counter=1 190 sleep 1 191 192 while [ $counter -le $rm_nr_ns2 ] 193 do 194 ip netns exec ${connector_ns} ./pm_nl_ctl del $counter 195 sleep 1 196 let counter+=1 197 done 198 fi 199 200 wait $cpid 201 retc=$? 202 wait $spid 203 rets=$? 204 205 if [ $capture -eq 1 ]; then 206 sleep 1 207 kill $cappid 208 fi 209 210 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then 211 echo " client exit code $retc, server $rets" 1>&2 212 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2 213 ip netns exec ${listener_ns} ss -nita 1>&2 -o "sport = :$port" 214 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2 215 ip netns exec ${connector_ns} ss -nita 1>&2 -o "dport = :$port" 216 217 cat "$capout" 218 return 1 219 fi 220 221 check_transfer $sin $cout "file received by client" 222 retc=$? 223 check_transfer $cin $sout "file received by server" 224 rets=$? 225 226 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 227 cat "$capout" 228 return 0 229 fi 230 231 cat "$capout" 232 return 1 233} 234 235make_file() 236{ 237 name=$1 238 who=$2 239 240 SIZE=1 241 242 dd if=/dev/urandom of="$name" bs=1024 count=$SIZE 2> /dev/null 243 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name" 244 245 echo "Created $name (size $SIZE KB) containing data sent by $who" 246} 247 248run_tests() 249{ 250 listener_ns="$1" 251 connector_ns="$2" 252 connect_addr="$3" 253 lret=0 254 255 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 0 0 256 lret=$? 257 if [ $lret -ne 0 ]; then 258 ret=$lret 259 return 260 fi 261} 262 263run_remove_tests() 264{ 265 listener_ns="$1" 266 connector_ns="$2" 267 connect_addr="$3" 268 rm_nr_ns1="$4" 269 rm_nr_ns2="$5" 270 lret=0 271 272 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} ${rm_nr_ns1} ${rm_nr_ns2} 273 lret=$? 274 if [ $lret -ne 0 ]; then 275 ret=$lret 276 return 277 fi 278} 279 280chk_join_nr() 281{ 282 local msg="$1" 283 local syn_nr=$2 284 local syn_ack_nr=$3 285 local ack_nr=$4 286 local count 287 local dump_stats 288 289 printf "%02u %-36s %s" "$TEST_COUNT" "$msg" "syn" 290 count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}'` 291 [ -z "$count" ] && count=0 292 if [ "$count" != "$syn_nr" ]; then 293 echo "[fail] got $count JOIN[s] syn expected $syn_nr" 294 ret=1 295 dump_stats=1 296 else 297 echo -n "[ ok ]" 298 fi 299 300 echo -n " - synack" 301 count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}'` 302 [ -z "$count" ] && count=0 303 if [ "$count" != "$syn_ack_nr" ]; then 304 echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr" 305 ret=1 306 dump_stats=1 307 else 308 echo -n "[ ok ]" 309 fi 310 311 echo -n " - ack" 312 count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}'` 313 [ -z "$count" ] && count=0 314 if [ "$count" != "$ack_nr" ]; then 315 echo "[fail] got $count JOIN[s] ack expected $ack_nr" 316 ret=1 317 dump_stats=1 318 else 319 echo "[ ok ]" 320 fi 321 if [ "${dump_stats}" = 1 ]; then 322 echo Server ns stats 323 ip netns exec $ns1 nstat -as | grep MPTcp 324 echo Client ns stats 325 ip netns exec $ns2 nstat -as | grep MPTcp 326 fi 327} 328 329chk_add_nr() 330{ 331 local add_nr=$1 332 local echo_nr=$2 333 local count 334 local dump_stats 335 336 printf "%-39s %s" " " "add" 337 count=`ip netns exec $ns2 nstat -as | grep MPTcpExtAddAddr | awk '{print $2}'` 338 [ -z "$count" ] && count=0 339 if [ "$count" != "$add_nr" ]; then 340 echo "[fail] got $count ADD_ADDR[s] expected $add_nr" 341 ret=1 342 dump_stats=1 343 else 344 echo -n "[ ok ]" 345 fi 346 347 echo -n " - echo " 348 count=`ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}'` 349 [ -z "$count" ] && count=0 350 if [ "$count" != "$echo_nr" ]; then 351 echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr" 352 ret=1 353 dump_stats=1 354 else 355 echo "[ ok ]" 356 fi 357 358 if [ "${dump_stats}" = 1 ]; then 359 echo Server ns stats 360 ip netns exec $ns1 nstat -as | grep MPTcp 361 echo Client ns stats 362 ip netns exec $ns2 nstat -as | grep MPTcp 363 fi 364} 365 366chk_rm_nr() 367{ 368 local rm_addr_nr=$1 369 local rm_subflow_nr=$2 370 local count 371 local dump_stats 372 373 printf "%-39s %s" " " "rm " 374 count=`ip netns exec $ns1 nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'` 375 [ -z "$count" ] && count=0 376 if [ "$count" != "$rm_addr_nr" ]; then 377 echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr" 378 ret=1 379 dump_stats=1 380 else 381 echo -n "[ ok ]" 382 fi 383 384 echo -n " - sf " 385 count=`ip netns exec $ns2 nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'` 386 [ -z "$count" ] && count=0 387 if [ "$count" != "$rm_subflow_nr" ]; then 388 echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr" 389 ret=1 390 dump_stats=1 391 else 392 echo "[ ok ]" 393 fi 394 395 if [ "${dump_stats}" = 1 ]; then 396 echo Server ns stats 397 ip netns exec $ns1 nstat -as | grep MPTcp 398 echo Client ns stats 399 ip netns exec $ns2 nstat -as | grep MPTcp 400 fi 401} 402 403sin=$(mktemp) 404sout=$(mktemp) 405cin=$(mktemp) 406cout=$(mktemp) 407init 408make_file "$cin" "client" 409make_file "$sin" "server" 410trap cleanup EXIT 411 412run_tests $ns1 $ns2 10.0.1.1 413chk_join_nr "no JOIN" "0" "0" "0" 414 415# subflow limted by client 416reset 417ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 418run_tests $ns1 $ns2 10.0.1.1 419chk_join_nr "single subflow, limited by client" 0 0 0 420 421# subflow limted by server 422reset 423ip netns exec $ns2 ./pm_nl_ctl limits 0 1 424ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 425run_tests $ns1 $ns2 10.0.1.1 426chk_join_nr "single subflow, limited by server" 1 1 0 427 428# subflow 429reset 430ip netns exec $ns1 ./pm_nl_ctl limits 0 1 431ip netns exec $ns2 ./pm_nl_ctl limits 0 1 432ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 433run_tests $ns1 $ns2 10.0.1.1 434chk_join_nr "single subflow" 1 1 1 435 436# multiple subflows 437reset 438ip netns exec $ns1 ./pm_nl_ctl limits 0 2 439ip netns exec $ns2 ./pm_nl_ctl limits 0 2 440ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 441ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow 442run_tests $ns1 $ns2 10.0.1.1 443chk_join_nr "multiple subflows" 2 2 2 444 445# multiple subflows limited by serverf 446reset 447ip netns exec $ns1 ./pm_nl_ctl limits 0 1 448ip netns exec $ns2 ./pm_nl_ctl limits 0 2 449ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 450ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow 451run_tests $ns1 $ns2 10.0.1.1 452chk_join_nr "multiple subflows, limited by server" 2 2 1 453 454# add_address, unused 455reset 456ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 457run_tests $ns1 $ns2 10.0.1.1 458chk_join_nr "unused signal address" 0 0 0 459chk_add_nr 1 1 460 461# accept and use add_addr 462reset 463ip netns exec $ns1 ./pm_nl_ctl limits 0 1 464ip netns exec $ns2 ./pm_nl_ctl limits 1 1 465ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 466run_tests $ns1 $ns2 10.0.1.1 467chk_join_nr "signal address" 1 1 1 468chk_add_nr 1 1 469 470# accept and use add_addr with an additional subflow 471# note: signal address in server ns and local addresses in client ns must 472# belong to different subnets or one of the listed local address could be 473# used for 'add_addr' subflow 474reset 475ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 476ip netns exec $ns1 ./pm_nl_ctl limits 0 2 477ip netns exec $ns2 ./pm_nl_ctl limits 1 2 478ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 479run_tests $ns1 $ns2 10.0.1.1 480chk_join_nr "subflow and signal" 2 2 2 481chk_add_nr 1 1 482 483# accept and use add_addr with additional subflows 484reset 485ip netns exec $ns1 ./pm_nl_ctl limits 0 3 486ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 487ip netns exec $ns2 ./pm_nl_ctl limits 1 3 488ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 489ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow 490run_tests $ns1 $ns2 10.0.1.1 491chk_join_nr "multiple subflows and signal" 3 3 3 492chk_add_nr 1 1 493 494# single subflow, remove 495reset 496ip netns exec $ns1 ./pm_nl_ctl limits 0 1 497ip netns exec $ns2 ./pm_nl_ctl limits 0 1 498ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 499run_remove_tests $ns1 $ns2 10.0.1.1 0 1 500chk_join_nr "remove single subflow" 1 1 1 501chk_rm_nr 1 1 502 503# multiple subflows, remove 504reset 505ip netns exec $ns1 ./pm_nl_ctl limits 0 2 506ip netns exec $ns2 ./pm_nl_ctl limits 0 2 507ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow 508ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 509run_remove_tests $ns1 $ns2 10.0.1.1 0 2 510chk_join_nr "remove multiple subflows" 2 2 2 511chk_rm_nr 2 2 512 513# single address, remove 514reset 515ip netns exec $ns1 ./pm_nl_ctl limits 0 1 516ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 517ip netns exec $ns2 ./pm_nl_ctl limits 1 1 518run_remove_tests $ns1 $ns2 10.0.1.1 1 0 519chk_join_nr "remove single address" 1 1 1 520chk_add_nr 1 1 521chk_rm_nr 0 0 522 523# subflow and signal, remove 524reset 525ip netns exec $ns1 ./pm_nl_ctl limits 0 2 526ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 527ip netns exec $ns2 ./pm_nl_ctl limits 1 2 528ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 529run_remove_tests $ns1 $ns2 10.0.1.1 1 1 530chk_join_nr "remove subflow and signal" 2 2 2 531chk_add_nr 1 1 532chk_rm_nr 1 1 533 534# subflows and signal, remove 535reset 536ip netns exec $ns1 ./pm_nl_ctl limits 0 3 537ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 538ip netns exec $ns2 ./pm_nl_ctl limits 1 3 539ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 540ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow 541run_remove_tests $ns1 $ns2 10.0.1.1 1 2 542chk_join_nr "remove subflows and signal" 3 3 3 543chk_add_nr 1 1 544chk_rm_nr 2 2 545 546# single subflow, syncookies 547reset_with_cookies 548ip netns exec $ns1 ./pm_nl_ctl limits 0 1 549ip netns exec $ns2 ./pm_nl_ctl limits 0 1 550ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 551run_tests $ns1 $ns2 10.0.1.1 552chk_join_nr "single subflow with syn cookies" 1 1 1 553 554# multiple subflows with syn cookies 555reset_with_cookies 556ip netns exec $ns1 ./pm_nl_ctl limits 0 2 557ip netns exec $ns2 ./pm_nl_ctl limits 0 2 558ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 559ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow 560run_tests $ns1 $ns2 10.0.1.1 561chk_join_nr "multiple subflows with syn cookies" 2 2 2 562 563# multiple subflows limited by server 564reset_with_cookies 565ip netns exec $ns1 ./pm_nl_ctl limits 0 1 566ip netns exec $ns2 ./pm_nl_ctl limits 0 2 567ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 568ip netns exec $ns2 ./pm_nl_ctl add 10.0.2.2 flags subflow 569run_tests $ns1 $ns2 10.0.1.1 570chk_join_nr "subflows limited by server w cookies" 2 2 1 571 572# test signal address with cookies 573reset_with_cookies 574ip netns exec $ns1 ./pm_nl_ctl limits 0 1 575ip netns exec $ns2 ./pm_nl_ctl limits 1 1 576ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 577run_tests $ns1 $ns2 10.0.1.1 578chk_join_nr "signal address with syn cookies" 1 1 1 579chk_add_nr 1 1 580 581# test cookie with subflow and signal 582reset_with_cookies 583ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 584ip netns exec $ns1 ./pm_nl_ctl limits 0 2 585ip netns exec $ns2 ./pm_nl_ctl limits 1 2 586ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 587run_tests $ns1 $ns2 10.0.1.1 588chk_join_nr "subflow and signal w cookies" 2 2 2 589chk_add_nr 1 1 590 591# accept and use add_addr with additional subflows 592reset_with_cookies 593ip netns exec $ns1 ./pm_nl_ctl limits 0 3 594ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal 595ip netns exec $ns2 ./pm_nl_ctl limits 1 3 596ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow 597ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow 598run_tests $ns1 $ns2 10.0.1.1 599chk_join_nr "subflows and signal w. cookies" 3 3 3 600chk_add_nr 1 1 601 602exit $ret 603