1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# Double quotes to prevent globbing and word splitting is recommended in new 5# code but we accept it, especially because there were too many before having 6# address all other issues detected by shellcheck. 7#shellcheck disable=SC2086 8 9. "$(dirname "${0}")/mptcp_lib.sh" 10 11ret=0 12sin="" 13sout="" 14cin="" 15cout="" 16timeout_poll=30 17timeout_test=$((timeout_poll * 2 + 1)) 18iptables="iptables" 19ip6tables="ip6tables" 20 21ns1="" 22ns2="" 23ns_sbox="" 24 25usage() { 26 echo "Usage: $0 [ -i ] [ -h ]" 27 echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'" 28 echo -e "\t-h: help" 29} 30 31while getopts "hi" option;do 32 case "$option" in 33 "h") 34 usage "$0" 35 exit ${KSFT_PASS} 36 ;; 37 "i") 38 mptcp_lib_set_ip_mptcp 39 ;; 40 "?") 41 usage "$0" 42 exit ${KSFT_FAIL} 43 ;; 44 esac 45done 46 47add_mark_rules() 48{ 49 local ns=$1 50 local m=$2 51 52 local t 53 for t in ${iptables} ${ip6tables}; do 54 # just to debug: check we have multiple subflows connection requests 55 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT 56 57 # RST packets might be handled by a internal dummy socket 58 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT 59 60 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT 61 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP 62 done 63} 64 65init() 66{ 67 mptcp_lib_ns_init ns1 ns2 ns_sbox 68 69 local i 70 for i in $(seq 1 4); do 71 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2" 72 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i 73 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad 74 ip -net "$ns1" link set ns1eth$i up 75 76 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i 77 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad 78 ip -net "$ns2" link set ns2eth$i up 79 80 # let $ns2 reach any $ns1 address from any interface 81 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i 82 83 mptcp_lib_pm_nl_add_endpoint "${ns1}" "10.0.${i}.1" flags signal 84 mptcp_lib_pm_nl_add_endpoint "${ns1}" "dead:beef:${i}::1" flags signal 85 86 mptcp_lib_pm_nl_add_endpoint "${ns2}" "10.0.${i}.2" flags signal 87 mptcp_lib_pm_nl_add_endpoint "${ns2}" "dead:beef:${i}::2" flags signal 88 done 89 90 mptcp_lib_pm_nl_set_limits "${ns1}" 8 8 91 mptcp_lib_pm_nl_set_limits "${ns2}" 8 8 92 93 add_mark_rules $ns1 1 94 add_mark_rules $ns2 2 95} 96 97# This function is used in the cleanup trap 98#shellcheck disable=SC2317 99cleanup() 100{ 101 mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns_sbox}" 102 rm -f "$cin" "$cout" 103 rm -f "$sin" "$sout" 104} 105 106mptcp_lib_check_mptcp 107mptcp_lib_check_kallsyms 108mptcp_lib_check_tools ip "${iptables}" "${ip6tables}" 109 110check_mark() 111{ 112 local ns=$1 113 local af=$2 114 115 local tables=${iptables} 116 117 if [ $af -eq 6 ];then 118 tables=${ip6tables} 119 fi 120 121 local counters values 122 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP) 123 values=${counters%DROP*} 124 125 local v 126 for v in $values; do 127 if [ $v -ne 0 ]; then 128 mptcp_lib_pr_fail "got $tables $values in ns $ns," \ 129 "not 0 - not all expected packets marked" 130 ret=${KSFT_FAIL} 131 return 1 132 fi 133 done 134 135 return 0 136} 137 138print_title() 139{ 140 mptcp_lib_print_title "${@}" 141} 142 143do_transfer() 144{ 145 local listener_ns="$1" 146 local connector_ns="$2" 147 local cl_proto="$3" 148 local srv_proto="$4" 149 local connect_addr="$5" 150 151 local port=12001 152 153 :> "$cout" 154 :> "$sout" 155 156 local mptcp_connect="./mptcp_connect -r 20" 157 158 local local_addr ip 159 if mptcp_lib_is_v6 "${connect_addr}"; then 160 local_addr="::" 161 ip=ipv6 162 else 163 local_addr="0.0.0.0" 164 ip=ipv4 165 fi 166 167 cmsg="TIMESTAMPNS" 168 if mptcp_lib_kallsyms_has "mptcp_ioctl$"; then 169 cmsg+=",TCPINQ" 170 fi 171 172 NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \ 173 nstat -n 174 NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \ 175 nstat -n 176 177 timeout ${timeout_test} \ 178 ip netns exec ${listener_ns} \ 179 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \ 180 ${local_addr} < "$sin" > "$sout" & 181 local spid=$! 182 183 sleep 1 184 185 timeout ${timeout_test} \ 186 ip netns exec ${connector_ns} \ 187 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \ 188 $connect_addr < "$cin" > "$cout" & 189 190 local cpid=$! 191 192 wait $cpid 193 local retc=$? 194 wait $spid 195 local rets=$? 196 197 NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \ 198 nstat | grep Tcp > /tmp/${listener_ns}.out 199 NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \ 200 nstat | grep Tcp > /tmp/${connector_ns}.out 201 202 print_title "Transfer ${ip:2}" 203 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then 204 mptcp_lib_pr_fail "client exit code $retc, server $rets" 205 mptcp_lib_pr_err_stats "${listener_ns}" "${connector_ns}" "${port}" \ 206 "/tmp/${listener_ns}.out" "/tmp/${connector_ns}.out" 207 208 mptcp_lib_result_fail "transfer ${ip}" 209 210 ret=${KSFT_FAIL} 211 return 1 212 fi 213 if ! mptcp_lib_check_transfer $cin $sout "file received by server"; then 214 rets=1 215 else 216 mptcp_lib_pr_ok 217 fi 218 mptcp_lib_result_code "${rets}" "transfer ${ip}" 219 220 print_title "Mark ${ip:2}" 221 if [ $local_addr = "::" ];then 222 check_mark $listener_ns 6 || retc=1 223 check_mark $connector_ns 6 || retc=1 224 else 225 check_mark $listener_ns 4 || retc=1 226 check_mark $connector_ns 4 || retc=1 227 fi 228 229 mptcp_lib_result_code "${retc}" "mark ${ip}" 230 231 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 232 mptcp_lib_pr_ok 233 return 0 234 fi 235 mptcp_lib_pr_fail 236 237 return 1 238} 239 240make_file() 241{ 242 local name=$1 243 local who=$2 244 local size=$3 245 246 mptcp_lib_make_file $name 1024 $size 247 248 echo "Created $name (size $size KB) containing data sent by $who" 249} 250 251do_mptcp_sockopt_tests() 252{ 253 local lret=0 254 255 if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then 256 mptcp_lib_pr_skip "MPTCP sockopt not supported" 257 mptcp_lib_result_skip "sockopt" 258 return 259 fi 260 261 ip netns exec "$ns_sbox" ./mptcp_sockopt 262 lret=$? 263 264 print_title "SOL_MPTCP sockopt v4" 265 if [ $lret -ne 0 ]; then 266 mptcp_lib_pr_fail 267 mptcp_lib_result_fail "sockopt v4" 268 ret=$lret 269 return 270 fi 271 mptcp_lib_pr_ok 272 mptcp_lib_result_pass "sockopt v4" 273 274 ip netns exec "$ns_sbox" ./mptcp_sockopt -6 275 lret=$? 276 277 print_title "SOL_MPTCP sockopt v6" 278 if [ $lret -ne 0 ]; then 279 mptcp_lib_pr_fail 280 mptcp_lib_result_fail "sockopt v6" 281 ret=$lret 282 return 283 fi 284 mptcp_lib_pr_ok 285 mptcp_lib_result_pass "sockopt v6" 286} 287 288run_tests() 289{ 290 local listener_ns="$1" 291 local connector_ns="$2" 292 local connect_addr="$3" 293 local lret=0 294 295 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 296 297 lret=$? 298 299 if [ $lret -ne 0 ]; then 300 ret=$lret 301 return 302 fi 303} 304 305do_tcpinq_test() 306{ 307 print_title "TCP_INQ cmsg/ioctl $*" 308 ip netns exec "$ns_sbox" ./mptcp_inq "$@" 309 local lret=$? 310 if [ $lret -ne 0 ];then 311 ret=$lret 312 mptcp_lib_pr_fail 313 mptcp_lib_result_fail "TCP_INQ: $*" 314 return $lret 315 fi 316 317 mptcp_lib_pr_ok 318 mptcp_lib_result_pass "TCP_INQ: $*" 319 return $lret 320} 321 322do_tcpinq_tests() 323{ 324 local lret=0 325 326 if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then 327 mptcp_lib_pr_skip "TCP_INQ not supported" 328 mptcp_lib_result_skip "TCP_INQ" 329 return 330 fi 331 332 local args 333 for args in "-t tcp" "-r tcp"; do 334 do_tcpinq_test $args 335 lret=$? 336 if [ $lret -ne 0 ] ; then 337 return $lret 338 fi 339 do_tcpinq_test -6 $args 340 lret=$? 341 if [ $lret -ne 0 ] ; then 342 return $lret 343 fi 344 done 345 346 do_tcpinq_test -r tcp -t tcp 347 348 return $? 349} 350 351sin=$(mktemp) 352sout=$(mktemp) 353cin=$(mktemp) 354cout=$(mktemp) 355init 356make_file "$cin" "client" 1 357make_file "$sin" "server" 1 358trap cleanup EXIT 359mptcp_lib_subtests_last_ts_reset 360 361run_tests $ns1 $ns2 10.0.1.1 362run_tests $ns1 $ns2 dead:beef:1::1 363 364do_mptcp_sockopt_tests 365do_tcpinq_tests 366 367mptcp_lib_result_print_all_tap 368exit $ret 369