1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4ret=0 5sin="" 6sout="" 7cin="" 8cout="" 9ksft_skip=4 10timeout_poll=30 11timeout_test=$((timeout_poll * 2 + 1)) 12mptcp_connect="" 13 14sec=$(date +%s) 15rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 16ns1="ns1-$rndh" 17ns2="ns2-$rndh" 18ns_sbox="ns_sbox-$rndh" 19 20add_mark_rules() 21{ 22 local ns=$1 23 local m=$2 24 25 local t 26 for t in iptables ip6tables; do 27 # just to debug: check we have multiple subflows connection requests 28 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT 29 30 # RST packets might be handled by a internal dummy socket 31 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT 32 33 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT 34 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP 35 done 36} 37 38init() 39{ 40 local netns 41 for netns in "$ns1" "$ns2" "$ns_sbox";do 42 ip netns add $netns || exit $ksft_skip 43 ip -net $netns link set lo up 44 ip netns exec $netns sysctl -q net.mptcp.enabled=1 45 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0 46 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0 47 done 48 49 local i 50 for i in `seq 1 4`; do 51 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2" 52 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i 53 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad 54 ip -net "$ns1" link set ns1eth$i up 55 56 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i 57 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad 58 ip -net "$ns2" link set ns2eth$i up 59 60 # let $ns2 reach any $ns1 address from any interface 61 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i 62 63 ip netns exec $ns1 ./pm_nl_ctl add 10.0.$i.1 flags signal 64 ip netns exec $ns1 ./pm_nl_ctl add dead:beef:$i::1 flags signal 65 66 ip netns exec $ns2 ./pm_nl_ctl add 10.0.$i.2 flags signal 67 ip netns exec $ns2 ./pm_nl_ctl add dead:beef:$i::2 flags signal 68 done 69 70 ip netns exec $ns1 ./pm_nl_ctl limits 8 8 71 ip netns exec $ns2 ./pm_nl_ctl limits 8 8 72 73 add_mark_rules $ns1 1 74 add_mark_rules $ns2 2 75} 76 77cleanup() 78{ 79 local netns 80 for netns in "$ns1" "$ns2" "$ns_sbox"; do 81 ip netns del $netns 82 done 83 rm -f "$cin" "$cout" 84 rm -f "$sin" "$sout" 85} 86 87ip -Version > /dev/null 2>&1 88if [ $? -ne 0 ];then 89 echo "SKIP: Could not run test without ip tool" 90 exit $ksft_skip 91fi 92 93iptables -V > /dev/null 2>&1 94if [ $? -ne 0 ];then 95 echo "SKIP: Could not run all tests without iptables tool" 96 exit $ksft_skip 97fi 98 99ip6tables -V > /dev/null 2>&1 100if [ $? -ne 0 ];then 101 echo "SKIP: Could not run all tests without ip6tables tool" 102 exit $ksft_skip 103fi 104 105check_mark() 106{ 107 local ns=$1 108 local af=$2 109 110 local tables=iptables 111 112 if [ $af -eq 6 ];then 113 tables=ip6tables 114 fi 115 116 local counters values 117 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP) 118 values=${counters%DROP*} 119 120 local v 121 for v in $values; do 122 if [ $v -ne 0 ]; then 123 echo "FAIL: got $tables $values in ns $ns , not 0 - not all expected packets marked" 1>&2 124 return 1 125 fi 126 done 127 128 return 0 129} 130 131print_file_err() 132{ 133 ls -l "$1" 1>&2 134 echo "Trailing bytes are: " 135 tail -c 27 "$1" 136} 137 138check_transfer() 139{ 140 local in=$1 141 local out=$2 142 local what=$3 143 144 cmp "$in" "$out" > /dev/null 2>&1 145 if [ $? -ne 0 ] ;then 146 echo "[ FAIL ] $what does not match (in, out):" 147 print_file_err "$in" 148 print_file_err "$out" 149 ret=1 150 151 return 1 152 fi 153 154 return 0 155} 156 157# $1: IP address 158is_v6() 159{ 160 [ -z "${1##*:*}" ] 161} 162 163do_transfer() 164{ 165 local listener_ns="$1" 166 local connector_ns="$2" 167 local cl_proto="$3" 168 local srv_proto="$4" 169 local connect_addr="$5" 170 171 local port=12001 172 173 :> "$cout" 174 :> "$sout" 175 176 local mptcp_connect="./mptcp_connect -r 20" 177 178 local local_addr 179 if is_v6 "${connect_addr}"; then 180 local_addr="::" 181 else 182 local_addr="0.0.0.0" 183 fi 184 185 timeout ${timeout_test} \ 186 ip netns exec ${listener_ns} \ 187 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS,TCPINQ \ 188 ${local_addr} < "$sin" > "$sout" & 189 local spid=$! 190 191 sleep 1 192 193 timeout ${timeout_test} \ 194 ip netns exec ${connector_ns} \ 195 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS,TCPINQ \ 196 $connect_addr < "$cin" > "$cout" & 197 198 local cpid=$! 199 200 wait $cpid 201 local retc=$? 202 wait $spid 203 local rets=$? 204 205 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then 206 echo " client exit code $retc, server $rets" 1>&2 207 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2 208 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port" 209 210 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2 211 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port" 212 213 ret=1 214 return 1 215 fi 216 217 if [ $local_addr = "::" ];then 218 check_mark $listener_ns 6 219 check_mark $connector_ns 6 220 else 221 check_mark $listener_ns 4 222 check_mark $connector_ns 4 223 fi 224 225 check_transfer $cin $sout "file received by server" 226 227 rets=$? 228 229 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 230 return 0 231 fi 232 233 return 1 234} 235 236make_file() 237{ 238 local name=$1 239 local who=$2 240 local size=$3 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 248do_mptcp_sockopt_tests() 249{ 250 local lret=0 251 252 ip netns exec "$ns_sbox" ./mptcp_sockopt 253 lret=$? 254 255 if [ $lret -ne 0 ]; then 256 echo "FAIL: SOL_MPTCP getsockopt" 1>&2 257 ret=$lret 258 return 259 fi 260 261 ip netns exec "$ns_sbox" ./mptcp_sockopt -6 262 lret=$? 263 264 if [ $lret -ne 0 ]; then 265 echo "FAIL: SOL_MPTCP getsockopt (ipv6)" 1>&2 266 ret=$lret 267 return 268 fi 269} 270 271run_tests() 272{ 273 local listener_ns="$1" 274 local connector_ns="$2" 275 local connect_addr="$3" 276 local lret=0 277 278 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 279 280 lret=$? 281 282 if [ $lret -ne 0 ]; then 283 ret=$lret 284 return 285 fi 286} 287 288do_tcpinq_test() 289{ 290 ip netns exec "$ns_sbox" ./mptcp_inq "$@" 291 local lret=$? 292 if [ $lret -ne 0 ];then 293 ret=$lret 294 echo "FAIL: mptcp_inq $@" 1>&2 295 return $lret 296 fi 297 298 echo "PASS: TCP_INQ cmsg/ioctl $@" 299 return $lret 300} 301 302do_tcpinq_tests() 303{ 304 local lret=0 305 306 local args 307 for args in "-t tcp" "-r tcp"; do 308 do_tcpinq_test $args 309 lret=$? 310 if [ $lret -ne 0 ] ; then 311 return $lret 312 fi 313 do_tcpinq_test -6 $args 314 lret=$? 315 if [ $lret -ne 0 ] ; then 316 return $lret 317 fi 318 done 319 320 do_tcpinq_test -r tcp -t tcp 321 322 return $? 323} 324 325sin=$(mktemp) 326sout=$(mktemp) 327cin=$(mktemp) 328cout=$(mktemp) 329init 330make_file "$cin" "client" 1 331make_file "$sin" "server" 1 332trap cleanup EXIT 333 334run_tests $ns1 $ns2 10.0.1.1 335run_tests $ns1 $ns2 dead:beef:1::1 336 337if [ $ret -eq 0 ];then 338 echo "PASS: all packets had packet mark set" 339fi 340 341do_mptcp_sockopt_tests 342if [ $ret -eq 0 ];then 343 echo "PASS: SOL_MPTCP getsockopt has expected information" 344fi 345 346do_tcpinq_tests 347exit $ret 348