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,SC2329 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 mptcp_lib_nstat_init "${listener_ns}" 173 mptcp_lib_nstat_init "${connector_ns}" 174 175 ip netns exec ${listener_ns} \ 176 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \ 177 ${local_addr} < "$sin" > "$sout" & 178 local spid=$! 179 180 mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" 181 182 ip netns exec ${connector_ns} \ 183 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \ 184 $connect_addr < "$cin" > "$cout" & 185 186 local cpid=$! 187 188 mptcp_lib_wait_timeout "${timeout_test}" "${listener_ns}" \ 189 "${connector_ns}" "${port}" "${cpid}" "${spid}" & 190 local timeout_pid=$! 191 192 wait $cpid 193 local retc=$? 194 wait $spid 195 local rets=$? 196 197 if kill -0 $timeout_pid; then 198 # Finished before the timeout: kill the background job 199 mptcp_lib_kill_group_wait $timeout_pid 200 timeout_pid=0 201 fi 202 203 mptcp_lib_nstat_get "${listener_ns}" 204 mptcp_lib_nstat_get "${connector_ns}" 205 206 print_title "Transfer ${ip:2}" 207 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ] || [ ${timeout_pid} -ne 0 ]; then 208 mptcp_lib_pr_fail "client exit code $retc, server $rets" 209 mptcp_lib_pr_err_stats "${listener_ns}" "${connector_ns}" "${port}" 210 211 mptcp_lib_result_fail "transfer ${ip}" 212 213 ret=${KSFT_FAIL} 214 return 1 215 fi 216 if ! mptcp_lib_check_transfer $cin $sout "file received by server"; then 217 rets=1 218 else 219 mptcp_lib_pr_ok 220 fi 221 mptcp_lib_result_code "${rets}" "transfer ${ip}" 222 223 print_title "Mark ${ip:2}" 224 if [ $local_addr = "::" ];then 225 check_mark $listener_ns 6 || retc=1 226 check_mark $connector_ns 6 || retc=1 227 else 228 check_mark $listener_ns 4 || retc=1 229 check_mark $connector_ns 4 || retc=1 230 fi 231 232 mptcp_lib_result_code "${retc}" "mark ${ip}" 233 234 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 235 mptcp_lib_pr_ok 236 return 0 237 fi 238 mptcp_lib_pr_fail 239 240 return 1 241} 242 243make_file() 244{ 245 local name=$1 246 local who=$2 247 local size=$3 248 249 mptcp_lib_make_file $name 1024 $size 250 251 echo "Created $name (size $size KB) containing data sent by $who" 252} 253 254do_mptcp_sockopt_tests() 255{ 256 local lret=0 257 258 if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then 259 mptcp_lib_pr_skip "MPTCP sockopt not supported" 260 mptcp_lib_result_skip "sockopt" 261 return 262 fi 263 264 ip netns exec "$ns_sbox" ./mptcp_sockopt 265 lret=$? 266 267 print_title "SOL_MPTCP sockopt v4" 268 if [ $lret -ne 0 ]; then 269 mptcp_lib_pr_fail 270 mptcp_lib_result_fail "sockopt v4" 271 ret=$lret 272 return 273 fi 274 mptcp_lib_pr_ok 275 mptcp_lib_result_pass "sockopt v4" 276 277 ip netns exec "$ns_sbox" ./mptcp_sockopt -6 278 lret=$? 279 280 print_title "SOL_MPTCP sockopt v6" 281 if [ $lret -ne 0 ]; then 282 mptcp_lib_pr_fail 283 mptcp_lib_result_fail "sockopt v6" 284 ret=$lret 285 return 286 fi 287 mptcp_lib_pr_ok 288 mptcp_lib_result_pass "sockopt v6" 289} 290 291run_tests() 292{ 293 local listener_ns="$1" 294 local connector_ns="$2" 295 local connect_addr="$3" 296 local lret=0 297 298 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 299 300 lret=$? 301 302 if [ $lret -ne 0 ]; then 303 ret=$lret 304 return 305 fi 306} 307 308do_tcpinq_test() 309{ 310 print_title "TCP_INQ cmsg/ioctl $*" 311 ip netns exec "$ns_sbox" ./mptcp_inq "$@" 312 local lret=$? 313 if [ $lret -ne 0 ];then 314 ret=$lret 315 mptcp_lib_pr_fail 316 mptcp_lib_result_fail "TCP_INQ: $*" 317 return $lret 318 fi 319 320 mptcp_lib_pr_ok 321 mptcp_lib_result_pass "TCP_INQ: $*" 322 return $lret 323} 324 325do_tcpinq_tests() 326{ 327 local lret=0 328 329 if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then 330 mptcp_lib_pr_skip "TCP_INQ not supported" 331 mptcp_lib_result_skip "TCP_INQ" 332 return 333 fi 334 335 local args 336 for args in "-t tcp" "-r tcp"; do 337 do_tcpinq_test $args 338 lret=$? 339 if [ $lret -ne 0 ] ; then 340 return $lret 341 fi 342 do_tcpinq_test -6 $args 343 lret=$? 344 if [ $lret -ne 0 ] ; then 345 return $lret 346 fi 347 done 348 349 do_tcpinq_test -r tcp -t tcp 350 351 return $? 352} 353 354sin=$(mktemp) 355sout=$(mktemp) 356cin=$(mktemp) 357cout=$(mktemp) 358init 359make_file "$cin" "client" 1 360make_file "$sin" "server" 1 361trap cleanup EXIT 362mptcp_lib_subtests_last_ts_reset 363 364run_tests $ns1 $ns2 10.0.1.1 365run_tests $ns1 $ns2 dead:beef:1::1 366 367do_mptcp_sockopt_tests 368do_tcpinq_tests 369 370mptcp_lib_result_print_all_tap 371exit $ret 372