1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2014-2017 Oracle and/or its affiliates. All Rights Reserved. 4# Copyright (c) 2016-2019 Petr Vorel <pvorel@suse.cz> 5# Author: Alexey Kodanev <alexey.kodanev@oracle.com> 6 7[ -n "$TST_LIB_NET_LOADED" ] && return 0 8TST_LIB_NET_LOADED=1 9 10TST_OPTS="6$TST_OPTS" 11TST_PARSE_ARGS_CALLER="$TST_PARSE_ARGS" 12TST_PARSE_ARGS="tst_net_parse_args" 13TST_USAGE_CALLER="$TST_USAGE" 14TST_USAGE="tst_net_usage" 15TST_SETUP_CALLER="$TST_SETUP" 16TST_SETUP="tst_net_setup" 17 18# Blank for an IPV4 test; 6 for an IPV6 test. 19TST_IPV6=${TST_IPV6:-} 20TST_IPVER=${TST_IPV6:-4} 21# Blank for IPv4, '-6' for IPv6 test. 22TST_IPV6_FLAG=${TST_IPV6_FLAG:-} 23 24tst_net_parse_args() 25{ 26 case $1 in 27 6) TST_IPV6=6 TST_IPVER=6 TST_IPV6_FLAG="-6";; 28 *) [ "$TST_PARSE_ARGS_CALLER" ] && $TST_PARSE_ARGS_CALLER "$1" "$2";; 29 esac 30} 31 32tst_net_read_opts() 33{ 34 local OPTIND 35 while getopts ":$TST_OPTS" opt; do 36 $TST_PARSE_ARGS "$opt" "$OPTARG" 37 done 38} 39 40tst_net_usage() 41{ 42 if [ -n "$TST_USAGE_CALLER" ]; then 43 $TST_USAGE_CALLER 44 else 45 echo "Usage: $0 [-6]" 46 echo "OPTIONS" 47 fi 48 echo "-6 IPv6 tests" 49} 50 51tst_net_remote_tmpdir() 52{ 53 [ "$TST_NEEDS_TMPDIR" = 1 ] || return 0 54 [ -n "$TST_USE_LEGACY_API" ] && tst_tmpdir 55 tst_rhost_run -c "mkdir -p $TST_TMPDIR" 56 tst_rhost_run -c "chmod 777 $TST_TMPDIR" 57 export TST_TMPDIR_RHOST=1 58} 59 60tst_net_setup() 61{ 62 tst_net_remote_tmpdir 63 [ -n "$TST_SETUP_CALLER" ] && $TST_SETUP_CALLER 64 65 if [ -z "$NS_ICMP_SENDER_DATA_MAXSIZE" ]; then 66 if [ "$TST_IPV6" ]; then 67 NS_ICMP_SENDER_DATA_MAXSIZE="$NS_ICMPV6_SENDER_DATA_MAXSIZE" 68 else 69 NS_ICMP_SENDER_DATA_MAXSIZE="$NS_ICMPV4_SENDER_DATA_MAXSIZE" 70 fi 71 fi 72} 73 74[ -n "$TST_USE_LEGACY_API" ] && . test.sh || . tst_test.sh 75 76if [ "$TST_PARSE_ARGS_CALLER" = "$TST_PARSE_ARGS" ]; then 77 tst_res TWARN "TST_PARSE_ARGS_CALLER same as TST_PARSE_ARGS, unset it ($TST_PARSE_ARGS)" 78 unset TST_PARSE_ARGS_CALLER 79fi 80if [ "$TST_SETUP_CALLER" = "$TST_SETUP" ]; then 81 tst_res TWARN "TST_SETUP_CALLER same as TST_SETUP, unset it ($TST_SETUP)" 82 unset TST_SETUP_CALLER 83fi 84if [ "$TST_USAGE_CALLER" = "$TST_USAGE" ]; then 85 tst_res TWARN "TST_USAGE_CALLER same as TST_USAGE, unset it ($TST_USAGE)" 86 unset TST_USAGE_CALLER 87fi 88 89if [ -n "$TST_USE_LEGACY_API" ]; then 90 tst_net_read_opts "$@" 91fi 92 93# old vs. new API compatibility layer 94tst_res_() 95{ 96 [ -z "$TST_USE_LEGACY_API" ] && tst_res $@ || tst_resm $@ 97} 98tst_brk_() 99{ 100 [ -z "$TST_USE_LEGACY_API" ] && tst_brk $@ || tst_brkm $@ 101} 102 103init_ltp_netspace() 104{ 105 local pid 106 107 if [ ! -f /var/run/netns/ltp_ns -a -z "$LTP_NETNS" ]; then 108 tst_require_cmds ip 109 tst_require_root 110 111 tst_require_drivers veth 112 ROD ip li add name ltp_ns_veth1 type veth peer name ltp_ns_veth2 113 pid="$(ROD ns_create net,mnt)" 114 mkdir -p /var/run/netns 115 ROD ln -s /proc/$pid/ns/net /var/run/netns/ltp_ns 116 ROD ns_exec $pid net,mnt mount --make-rprivate /sys 117 ROD ns_exec $pid net,mnt mount -t sysfs none /sys 118 ROD ns_ifmove ltp_ns_veth1 $pid 119 ROD ns_exec $pid net,mnt ip li set lo up 120 elif [ -n "$LTP_NETNS" ]; then 121 tst_res_ TINFO "using not default LTP netns: '$LTP_NETNS'" 122 fi 123 124 LHOST_IFACES="${LHOST_IFACES:-ltp_ns_veth2}" 125 RHOST_IFACES="${RHOST_IFACES:-ltp_ns_veth1}" 126 127 export TST_INIT_NETNS="no" 128 129 pid="$(echo $(readlink /var/run/netns/ltp_ns) | cut -f3 -d'/')" 130 export LTP_NETNS="${LTP_NETNS:-ns_exec $pid net,mnt}" 131 132 tst_restore_ipaddr 133 tst_restore_ipaddr rhost 134} 135 136# return 0: use ssh, 1: use netns 137tst_net_use_netns() 138{ 139 [ -n "$TST_USE_NETNS" ] 140} 141 142# Run command on remote host. 143# tst_rhost_run -c CMD [-b] [-s] [-u USER] 144# Options: 145# -b run in background 146# -c CMD specify command to run (this must be binary, not shell builtin/function) 147# -s safe option, if something goes wrong, will exit with TBROK 148# -u USER for ssh (default root) 149# RETURN: 0 on success, 1 on failure 150# TST_NET_RHOST_RUN_DEBUG=1 enables debugging 151tst_rhost_run() 152{ 153 local post_cmd=' || echo RTERR' 154 local user="root" 155 local ret=0 156 local cmd out output pre_cmd rcmd sh_cmd safe use 157 158 local OPTIND 159 while getopts :bc:su: opt; do 160 case "$opt" in 161 b) [ "${TST_USE_NETNS:-}" ] && pre_cmd= || pre_cmd="nohup" 162 post_cmd=" > /dev/null 2>&1 &" 163 out="1> /dev/null" 164 ;; 165 c) cmd="$OPTARG" ;; 166 s) safe=1 ;; 167 u) user="$OPTARG" ;; 168 *) tst_brk_ TBROK "tst_rhost_run: unknown option: $OPTARG" ;; 169 esac 170 done 171 172 if [ -z "$cmd" ]; then 173 [ "$safe" ] && \ 174 tst_brk_ TBROK "tst_rhost_run: command not defined" 175 tst_res_ TWARN "tst_rhost_run: command not defined" 176 return 1 177 fi 178 179 sh_cmd="$pre_cmd $cmd $post_cmd" 180 181 if [ -n "${TST_USE_NETNS:-}" ]; then 182 use="NETNS" 183 rcmd="$LTP_NETNS sh -c" 184 else 185 tst_require_cmds ssh 186 use="SSH" 187 rcmd="ssh -nq $user@$RHOST" 188 fi 189 190 if [ "$TST_NET_RHOST_RUN_DEBUG" = 1 ]; then 191 tst_res_ TINFO "tst_rhost_run: cmd: $cmd" 192 tst_res_ TINFO "$use: $rcmd \"$sh_cmd\" $out 2>&1" 193 fi 194 195 output=$($rcmd "$sh_cmd" $out 2>&1 || echo 'RTERR') 196 197 echo "$output" | grep -q 'RTERR$' && ret=1 198 if [ $ret -eq 1 ]; then 199 output=$(echo "$output" | sed 's/RTERR//') 200 [ "$safe" ] && \ 201 tst_brk_ TBROK "'$cmd' failed on '$RHOST': '$output'" 202 fi 203 204 [ -z "$out" -a -n "$output" ] && echo "$output" 205 206 return $ret 207} 208 209# Run command on both lhost and rhost. 210# tst_net_run [-s] [-l LPARAM] [-r RPARAM] [ -q ] CMD [ARG [ARG2]] 211# Options: 212# -l LPARAM: parameter passed to CMD in lhost 213# -r RPARAM: parameter passed to CMD in rhost 214# -q: quiet mode (suppress failure warnings) 215# CMD: command to run (this must be binary, not shell builtin/function due 216# tst_rhost_run() limitation) 217# RETURN: 0 on success, 1 on missing CMD or exit code on lhost or rhost 218tst_net_run() 219{ 220 local cmd 221 local lparams 222 local rparams 223 local lsafe 224 local rsafe 225 local lret 226 local rret 227 local quiet 228 229 local OPTIND 230 while getopts l:qr:s opt; do 231 case "$opt" in 232 l) lparams="$OPTARG" ;; 233 q) quiet=1 ;; 234 r) rparams="$OPTARG" ;; 235 s) lsafe="ROD"; rsafe="-s" ;; 236 *) tst_brk_ TBROK "tst_net_run: unknown option: $OPTARG" ;; 237 esac 238 done 239 shift $((OPTIND - 1)) 240 cmd="$1" 241 shift 242 243 if [ -z "$cmd" ]; then 244 [ -n "$lsafe" ] && \ 245 tst_brk_ TBROK "tst_net_run: command not defined" 246 tst_res_ TWARN "tst_net_run: command not defined" 247 return 1 248 fi 249 250 $lsafe $cmd $lparams $@ 251 lret=$? 252 tst_rhost_run $rsafe -c "$cmd $rparams $@" 253 rret=$? 254 255 if [ -z "$quiet" ]; then 256 [ $lret -ne 0 ] && tst_res_ TWARN "tst_net_run: lhost command failed: $lret" 257 [ $rret -ne 0 ] && tst_res_ TWARN "tst_net_run: rhost command failed: $rret" 258 fi 259 260 [ $lret -ne 0 ] && return $lret 261 return $rret 262} 263 264EXPECT_RHOST_PASS() 265{ 266 local log="$TMPDIR/log.$$" 267 268 tst_rhost_run -c "$*" > $log 269 if [ $? -eq 0 ]; then 270 tst_res_ TPASS "$* passed as expected" 271 else 272 tst_res_ TFAIL "$* failed unexpectedly" 273 cat $log 274 fi 275 276 rm -f $log 277} 278 279EXPECT_RHOST_FAIL() 280{ 281 local log="$TMPDIR/log.$$" 282 283 tst_rhost_run -c "$*" > $log 284 if [ $? -ne 0 ]; then 285 tst_res_ TPASS "$* failed as expected" 286 else 287 tst_res_ TFAIL "$* passed unexpectedly" 288 cat $log 289 fi 290 291 rm -f $log 292} 293 294# Get test interface names for local/remote host. 295# tst_get_ifaces [TYPE] 296# TYPE: { lhost | rhost }; Default value is 'lhost'. 297tst_get_ifaces() 298{ 299 local type="${1:-lhost}" 300 if [ "$type" = "lhost" ]; then 301 echo "$LHOST_IFACES" 302 else 303 echo "$RHOST_IFACES" 304 fi 305} 306 307# Get count of test interfaces for local/remote host. 308tst_get_ifaces_cnt() 309{ 310 tst_require_cmds awk 311 local type="${1:-lhost}" 312 echo "$(tst_get_ifaces $type)" | awk '{print NF}' 313} 314 315# Get HW addresses from defined test interface names. 316# tst_get_hwaddrs [TYPE] 317# TYPE: { lhost | rhost }; Default value is 'lhost'. 318tst_get_hwaddrs() 319{ 320 local type="${1:-lhost}" 321 local addr= 322 local list= 323 324 for eth in $(tst_get_ifaces $type); do 325 326 local addr_path="/sys/class/net/${eth}/address" 327 328 case $type in 329 lhost) addr=$(cat $addr_path) ;; 330 rhost) addr=$(tst_rhost_run -s -c "cat $addr_path") 331 esac 332 333 [ -z "$list" ] && list="$addr" || list="$list $addr" 334 done 335 echo "$list" 336} 337 338# Get test HW address. 339# tst_hwaddr [TYPE] [LINK] 340# TYPE: { lhost | rhost }; Default value is 'lhost'. 341# LINK: link number starting from 0. Default value is '0'. 342tst_hwaddr() 343{ 344 tst_require_cmds awk 345 346 local type="${1:-lhost}" 347 local link_num="${2:-0}" 348 local hwaddrs= 349 link_num=$(( $link_num + 1 )) 350 [ "$type" = "lhost" ] && hwaddrs=$LHOST_HWADDRS || hwaddrs=$RHOST_HWADDRS 351 echo "$hwaddrs" | awk '{ print $'"$link_num"' }' 352} 353 354# Get test interface name. 355# tst_iface [TYPE] [LINK] 356# TYPE: { lhost | rhost }; Default value is 'lhost'. 357# LINK: link number starting from 0. Default value is '0'. 358tst_iface() 359{ 360 tst_require_cmds awk 361 362 local type="${1:-lhost}" 363 local link_num="${2:-0}" 364 link_num="$(( $link_num + 1 ))" 365 echo "$(tst_get_ifaces $type)" | awk '{ print $'"$link_num"' }' 366} 367 368# Get IP address 369# tst_ipaddr [TYPE] 370# TYPE: { lhost | rhost }; Default value is 'lhost'. 371tst_ipaddr() 372{ 373 local type="${1:-lhost}" 374 if [ "$TST_IPV6" ]; then 375 [ "$type" = "lhost" ] && echo "$IPV6_LHOST" || echo "$IPV6_RHOST" 376 else 377 [ "$type" = "lhost" ] && echo "$IPV4_LHOST" || echo "$IPV4_RHOST" 378 fi 379} 380 381# Get IP address of unused network, specified either counter and type 382# or by net and host. 383# counter mode: 384# tst_ipaddr_un [-h MIN,MAX] [-n MIN,MAX] [-p] [-c COUNTER] [TYPE] 385# net & host mode: 386# tst_ipaddr_un [-h MIN,MAX] [-n MIN,MAX] [-p] NET_ID [HOST_ID] 387# 388# TYPE: { lhost | rhost } (default: 'lhost') 389# NET_ID: integer or hex value of net (IPv4: 3rd octet <0,255>, IPv6: 3rd 390# hextet <0,65535>) 391# HOST_ID: integer or hex value of host (IPv4: 4th octet <0,255>, IPv6: the 392# last hextet <0, 65535>, default: 0) 393# 394# OPTIONS 395# -c COUNTER: integer value for counting HOST_ID and NET_ID (default: 1) 396# 397# -h: specify *host* address range (HOST_ID) 398# -h MIN,MAX or -h MIN or -h ,MAX 399# 400# -n: specify *network* address range (NET_ID) 401# -n MIN,MAX or -n MIN or -n ,MAX 402# 403# -p: print also prefix 404tst_ipaddr_un() 405{ 406 local default_max=255 407 [ "$TST_IPV6" ] && default_max=65535 408 local max_net_id=$default_max 409 local min_net_id=0 410 411 local counter host_id host_range is_counter max_host_id min_host_id net_id prefix tmp type 412 413 local OPTIND 414 while getopts "c:h:n:p" opt; do 415 case $opt in 416 c) counter="$OPTARG";; 417 h) 418 if echo $OPTARG | grep -q ','; then # 'min,max' or 'min,' or ',max' 419 min_host_id="$(echo $OPTARG | cut -d, -f1)" 420 max_host_id="$(echo $OPTARG | cut -d, -f2)" 421 else # min 422 min_host_id="$OPTARG" 423 fi 424 ;; 425 n) 426 if echo $OPTARG | grep -q ','; then # 'min,max' or 'min,' or ',max' 427 min_net_id="$(echo $OPTARG | cut -d, -f1)" 428 max_net_id="$(echo $OPTARG | cut -d, -f2)" 429 else # min 430 min_net_id="$OPTARG" 431 fi 432 ;; 433 m) 434 ! tst_is_int "$OPTARG" || [ "$OPTARG" -lt 0 ]|| [ "$OPTARG" -gt $max_net_id ] && \ 435 tst_brk TBROK "tst_ipaddr_un: -m must be integer <0,$max_net_id> ($OPTARG)" 436 [ "$OPTARG" -gt $max_net_id ] && \ 437 tst_brk_ TBROK "tst_ipaddr_un: -m cannot be higher than $max_net_id ($OPTARG)" 438 max_host_id="$OPTARG" 439 ;; 440 p) [ "$TST_IPV6" ] && prefix="/64" || prefix="/24";; 441 esac 442 done 443 shift $(($OPTIND - 1)) 444 [ $# -eq 0 -o "$1" = "lhost" -o "$1" = "rhost" ] && is_counter=1 445 446 if [ -z "$min_host_id" ]; then 447 [ "$is_counter" ] && min_host_id=1 || min_host_id=0 448 fi 449 if [ -z "$max_host_id" ]; then 450 [ "$is_counter" ] && max_host_id=$((default_max - 1)) || max_host_id=$default_max 451 fi 452 453 ! tst_is_int "$min_host_id" || ! tst_is_int "$max_host_id" || \ 454 [ $min_host_id -lt 0 -o $min_host_id -gt $default_max ] || \ 455 [ $max_host_id -lt 0 -o $max_host_id -gt $default_max ] && \ 456 tst_brk TBROK "tst_ipaddr_un: HOST_ID must be int in range <0,$default_max> ($min_host_id,$max_host_id)" 457 ! tst_is_int "$min_net_id" || ! tst_is_int "$max_net_id" || \ 458 [ $min_net_id -lt 0 -o $min_net_id -gt $default_max ] || \ 459 [ $max_net_id -lt 0 -o $max_net_id -gt $default_max ] && \ 460 tst_brk TBROK "tst_ipaddr_un: NET_ID must be int in range <0,$default_max> ($min_net_id,$max_net_id)" 461 462 [ $min_host_id -gt $max_host_id ] && \ 463 tst_brk TBROK "tst_ipaddr_un: max HOST_ID ($max_host_id) must be >= min HOST_ID ($min_host_id)" 464 [ $min_net_id -gt $max_net_id ] && \ 465 tst_brk TBROK "tst_ipaddr_un: max NET_ID ($max_net_id) must be >= min NET_ID ($min_net_id)" 466 467 # counter 468 host_range=$((max_host_id - min_host_id + 1)) 469 if [ "$is_counter" ]; then 470 [ -z "$counter" ] && counter=1 471 [ $counter -lt 1 ] && counter=1 472 type="${1:-lhost}" 473 tmp=$((counter * 2)) 474 [ "$type" = "rhost" ] && tmp=$((tmp - 1)) 475 net_id=$(((tmp - 1) / host_range)) 476 host_id=$((tmp - net_id * host_range + min_host_id - 1)) 477 else # net_id & host_id 478 net_id="$1" 479 host_id="${2:-0}" 480 if [ "$TST_IPV6" ]; then 481 net_id=$(printf %d $net_id) 482 host_id=$(printf %d $host_id) 483 fi 484 host_id=$((host_id % host_range + min_host_id)) 485 fi 486 487 net_id=$((net_id % (max_net_id - min_net_id + 1) + min_net_id)) 488 489 if [ -z "$TST_IPV6" ]; then 490 echo "${IPV4_NET16_UNUSED}.${net_id}.${host_id}${prefix}" 491 return 492 fi 493 494 [ $host_id -gt 0 ] && host_id="$(printf %x $host_id)" || host_id= 495 [ $net_id -gt 0 ] && net_id="$(printf %x $net_id)" || net_id= 496 [ "$net_id" ] && net_id=":$net_id" 497 echo "${IPV6_NET32_UNUSED}${net_id}::${host_id}${prefix}" 498} 499 500# tst_init_iface [TYPE] [LINK] 501# TYPE: { lhost | rhost }; Default value is 'lhost'. 502# LINK: link number starting from 0. Default value is '0'. 503tst_init_iface() 504{ 505 local type="${1:-lhost}" 506 local link_num="${2:-0}" 507 local iface="$(tst_iface $type $link_num)" 508 tst_res_ TINFO "initialize '$type' '$iface' interface" 509 510 if [ "$type" = "lhost" ]; then 511 if ip xfrm state 1>/dev/null 2>&1; then 512 ip xfrm policy flush || return $? 513 ip xfrm state flush || return $? 514 fi 515 ip link set $iface down || return $? 516 ip route flush dev $iface || return $? 517 ip addr flush dev $iface || return $? 518 ip link set $iface up 519 return $? 520 fi 521 522 if tst_rhost_run -c "ip xfrm state 1>/dev/null 2>&1"; then 523 tst_rhost_run -c "ip xfrm policy flush" || return $? 524 tst_rhost_run -c "ip xfrm state flush" || return $? 525 fi 526 tst_rhost_run -c "ip link set $iface down" || return $? 527 tst_rhost_run -c "ip route flush dev $iface" || return $? 528 tst_rhost_run -c "ip addr flush dev $iface" || return $? 529 tst_rhost_run -c "ip link set $iface up" 530} 531 532# tst_add_ipaddr [TYPE] [LINK] [-a IP] [-d] [-q] [-s] 533# Options: 534# TYPE: { lhost | rhost }, default value is 'lhost' 535# LINK: link number starting from 0, default value is '0' 536# -a IP: IP address to be added, default value is 537# $(tst_ipaddr)/$IPV{4,6}_{L,R}PREFIX 538# -d: delete address instead of adding 539# -q: quiet mode (don't print info) 540# -s: safe option, if something goes wrong, will exit with TBROK 541tst_add_ipaddr() 542{ 543 local action="add" 544 local addr dad lsafe mask quiet rsafe 545 546 local OPTIND 547 while getopts a:dqs opt; do 548 case "$opt" in 549 a) addr="$OPTARG" ;; 550 d) action="del" ;; 551 q) quiet=1 ;; 552 s) lsafe="ROD"; rsafe="-s" ;; 553 *) tst_brk TBROK "tst_add_ipaddr: unknown option: $OPTARG" ;; 554 esac 555 done 556 shift $((OPTIND - 1)) 557 558 local type="${1:-lhost}" 559 local link_num="${2:-0}" 560 local iface=$(tst_iface $type $link_num) 561 562 if [ "$TST_IPV6" ]; then 563 dad="nodad" 564 [ "$type" = "lhost" ] && mask=$IPV6_LPREFIX || mask=$IPV6_RPREFIX 565 else 566 [ "$type" = "lhost" ] && mask=$IPV4_LPREFIX || mask=$IPV4_RPREFIX 567 fi 568 [ -n "$addr" ] || addr="$(tst_ipaddr $type)" 569 echo $addr | grep -q / || addr="$addr/$mask" 570 571 if [ $type = "lhost" ]; then 572 [ "$quiet" ] || tst_res_ TINFO "$action local addr $addr" 573 $lsafe ip addr $action $addr dev $iface $dad 574 return $? 575 fi 576 577 [ "$quiet" ] || tst_res_ TINFO "$action remote addr $addr" 578 tst_rhost_run $rsafe -c "ip addr $action $addr dev $iface $dad" 579} 580 581# tst_del_ipaddr [ tst_add_ipaddr options ] 582# Delete IP address 583tst_del_ipaddr() 584{ 585 tst_add_ipaddr -d $@ 586} 587 588# tst_restore_ipaddr [TYPE] [LINK] 589# Restore default ip addresses defined in network.sh 590# TYPE: { lhost | rhost }; Default value is 'lhost'. 591# LINK: link number starting from 0. Default value is '0'. 592tst_restore_ipaddr() 593{ 594 tst_require_cmds ip 595 tst_require_root 596 597 local type="${1:-lhost}" 598 local link_num="${2:-0}" 599 600 tst_init_iface $type $link_num || return $? 601 602 local ret=0 603 local backup_tst_ipv6=$TST_IPV6 604 TST_IPV6= tst_add_ipaddr $type $link_num || ret=$? 605 TST_IPV6=6 tst_add_ipaddr $type $link_num || ret=$? 606 TST_IPV6=$backup_tst_ipv6 607 608 return $ret 609} 610 611# tst_wait_ipv6_dad [LHOST_IFACE] [RHOST_IFACE] 612# wait for IPv6 DAD completion 613tst_wait_ipv6_dad() 614{ 615 local ret= 616 local i= 617 local iface_loc=${1:-$(tst_iface)} 618 local iface_rmt=${2:-$(tst_iface rhost)} 619 620 for i in $(seq 1 50); do 621 ip a sh $iface_loc | grep -q tentative 622 ret=$? 623 624 tst_rhost_run -c "ip a sh $iface_rmt | grep -q tentative" 625 626 [ $ret -ne 0 -a $? -ne 0 ] && return 627 628 [ $(($i % 10)) -eq 0 ] && \ 629 tst_res_ TINFO "wait for IPv6 DAD completion $((i / 10))/5 sec" 630 631 tst_sleep 100ms 632 done 633} 634 635tst_netload_brk() 636{ 637 tst_rhost_run -c "cat $TST_TMPDIR/netstress.log" 638 cat tst_netload.log 639 tst_brk_ $1 $2 640} 641 642# Run network load test, see 'netstress -h' for option description 643tst_netload() 644{ 645 local rfile="tst_netload.res" 646 local expect_res="pass" 647 local ret=0 648 local type="tcp" 649 local hostopt= 650 local setup_srchost=0 651 # common options for client and server 652 local cs_opts= 653 654 local run_cnt="$TST_NETLOAD_RUN_COUNT" 655 local c_num="$TST_NETLOAD_CLN_NUMBER" 656 local c_requests="$TST_NETLOAD_CLN_REQUESTS" 657 local c_opts= 658 659 # number of server replies after which TCP connection is closed 660 local s_replies="${TST_NETLOAD_MAX_SRV_REPLIES:-500000}" 661 local s_opts= 662 local bind_to_device=1 663 664 if [ ! "$TST_NEEDS_TMPDIR" = 1 ]; then 665 tst_brk_ TBROK "Using tst_netload requires setting TST_NEEDS_TMPDIR=1" 666 fi 667 668 OPTIND=0 669 while getopts :a:H:d:n:N:r:R:S:b:t:T:fFe:m:A:D: opt; do 670 case "$opt" in 671 a) c_num="$OPTARG" ;; 672 H) c_opts="${c_opts}-H $OPTARG " 673 hostopt="$OPTARG" ;; 674 d) rfile="$OPTARG" ;; 675 n) c_opts="${c_opts}-n $OPTARG " ;; 676 N) c_opts="${c_opts}-N $OPTARG " ;; 677 r) c_requests="$OPTARG" ;; 678 A) c_opts="${c_opts}-A $OPTARG " ;; 679 R) s_replies="$OPTARG" ;; 680 S) c_opts="${c_opts}-S $OPTARG " 681 setup_srchost=1 ;; 682 b) cs_opts="${cs_opts}-b $OPTARG " ;; 683 t) cs_opts="${cs_opts}-t $OPTARG " ;; 684 T) cs_opts="${cs_opts}-T $OPTARG " 685 type="$OPTARG" ;; 686 m) cs_opts="${cs_opts}-m $OPTARG " ;; 687 f) cs_opts="${cs_opts}-f " ;; 688 F) cs_opts="${cs_opts}-F " ;; 689 e) expect_res="$OPTARG" ;; 690 D) [ "$TST_NETLOAD_BINDTODEVICE" = 1 ] && cs_opts="${cs_opts}-D $OPTARG " 691 bind_to_device=0 ;; 692 *) tst_brk_ TBROK "tst_netload: unknown option: $OPTARG" ;; 693 esac 694 done 695 OPTIND=0 696 697 [ "$setup_srchost" = 1 ] && s_opts="${s_opts}-S $hostopt " 698 699 if [ "$bind_to_device" = 1 -a "$TST_NETLOAD_BINDTODEVICE" = 1 ]; then 700 c_opts="${c_opts}-D $(tst_iface) " 701 s_opts="${s_opts}-D $(tst_iface rhost) " 702 fi 703 704 local expect_ret=0 705 [ "$expect_res" != "pass" ] && expect_ret=3 706 707 local was_failure=0 708 if [ "$run_cnt" -lt 2 ]; then 709 run_cnt=1 710 was_failure=1 711 fi 712 713 s_opts="${cs_opts}${s_opts}-R $s_replies -B $TST_TMPDIR" 714 c_opts="${cs_opts}${c_opts}-a $c_num -r $((c_requests / run_cnt)) -d $rfile" 715 716 tst_res_ TINFO "run server 'netstress $s_opts'" 717 tst_res_ TINFO "run client 'netstress -l $c_opts' $run_cnt times" 718 719 tst_rhost_run -c "pkill -9 netstress\$" 720 rm -f tst_netload.log 721 722 local results 723 local passed=0 724 725 for i in $(seq 1 $run_cnt); do 726 tst_rhost_run -c "netstress $s_opts" > tst_netload.log 2>&1 727 if [ $? -ne 0 ]; then 728 cat tst_netload.log 729 local ttype="TFAIL" 730 grep -e 'CONF:' tst_netload.log && ttype="TCONF" 731 tst_brk_ $ttype "server failed" 732 fi 733 734 local port=$(tst_rhost_run -s -c "cat $TST_TMPDIR/netstress_port") 735 netstress -l ${c_opts} -g $port > tst_netload.log 2>&1 736 ret=$? 737 tst_rhost_run -c "pkill -9 netstress\$" 738 739 if [ "$expect_ret" -ne 0 ]; then 740 if [ $((ret & expect_ret)) -ne 0 ]; then 741 tst_res_ TPASS "netstress failed as expected" 742 else 743 tst_res_ TFAIL "expected '$expect_res' but ret: '$ret'" 744 fi 745 return $ret 746 fi 747 748 if [ "$ret" -ne 0 ]; then 749 [ $((ret & 32)) -ne 0 ] && \ 750 tst_netload_brk TCONF "not supported configuration" 751 752 [ $((ret & 3)) -ne 0 -a $was_failure -gt 0 ] && \ 753 tst_netload_brk TFAIL "expected '$expect_res' but ret: '$ret'" 754 755 tst_res_ TWARN "netstress failed, ret: $ret" 756 was_failure=1 757 continue 758 fi 759 760 [ ! -f $rfile ] && \ 761 tst_netload_brk TFAIL "can't read $rfile" 762 763 results="$results $(cat $rfile)" 764 passed=$((passed + 1)) 765 done 766 767 if [ "$ret" -ne 0 ]; then 768 [ $((ret & 4)) -ne 0 ] && \ 769 tst_res_ TWARN "netstress has warnings" 770 tst_netload_brk TFAIL "expected '$expect_res' but ret: '$ret'" 771 fi 772 773 local median=$(tst_get_median $results) 774 echo "$median" > $rfile 775 776 tst_res_ TPASS "netstress passed, median time $median ms, data:$results" 777 778 return $ret 779} 780 781# Compares results for netload runs. 782# tst_netload_compare TIME_BASE TIME THRESHOLD_LOW [THRESHOLD_HI] 783# TIME_BASE: time taken to run netstress load test - 100% 784# TIME: time that is compared to the base one 785# THRESHOD_LOW: lower limit for TFAIL 786# THRESHOD_HIGH: upper limit for TWARN 787tst_netload_compare() 788{ 789 local base_time=$1 790 local new_time=$2 791 local threshold_low=$3 792 local threshold_hi=$4 793 794 if [ -z "$base_time" -o -z "$new_time" -o -z "$threshold_low" ]; then 795 tst_brk_ TBROK "tst_netload_compare: invalid argument(s)" 796 fi 797 798 local res=$(((base_time - new_time) * 100 / base_time)) 799 local msg="performance result is ${res}%" 800 801 if [ "$res" -lt "$threshold_low" ]; then 802 tst_res_ TFAIL "$msg < threshold ${threshold_low}%" 803 return 804 fi 805 806 [ "$threshold_hi" ] && [ "$res" -gt "$threshold_hi" ] && \ 807 tst_res_ TWARN "$msg > threshold ${threshold_hi}%" 808 809 tst_res_ TPASS "$msg, in range [${threshold_low}:${threshold_hi}]%" 810} 811 812tst_ping_opt_unsupported() 813{ 814 ping $@ 2>&1 | grep -q "invalid option" 815} 816 817# tst_ping -c COUNT -s MESSAGE_SIZES -p PATTERN -I IFACE -H HOST 818# Check icmp connectivity 819# IFACE: source interface name or IP address 820# HOST: destination IPv4 or IPv6 address 821# MESSAGE_SIZES: message size array 822tst_ping() 823{ 824 # The max number of ICMP echo request 825 local ping_count="${PING_MAX:-500}" 826 local flood_opt="-f" 827 local pattern_opt 828 local msg_sizes 829 local src_iface="$(tst_iface)" 830 local dst_addr="$(tst_ipaddr rhost)" 831 local cmd="ping" 832 local ret=0 833 local opts 834 835 local OPTIND 836 while getopts c:s:p:I:H: opt; do 837 case "$opt" in 838 c) ping_count="$OPTARG";; 839 s) msg_sizes="$OPTARG";; 840 p) pattern_opt="-p $OPTARG";; 841 I) src_iface="$OPTARG";; 842 H) dst_addr="$OPTARG";; 843 *) tst_brk_ TBROK "tst_ping: unknown option: $OPTARG";; 844 esac 845 done 846 847 echo "$dst_addr" | grep -q ':' && cmd="ping6" 848 tst_require_cmds $cmd 849 850 if tst_ping_opt_unsupported $flood_opt; then 851 flood_opt="-i 0.01" 852 [ "$pattern_opt" ] && pattern_opt="-p aa" 853 854 tst_ping_opt_unsupported -i $pattern_opt && \ 855 tst_brk_ TCONF "unsupported ping version (old busybox?)" 856 fi 857 858 # ping cmd use 56 as default message size 859 for size in ${msg_sizes:-"56"}; do 860 EXPECT_PASS $cmd -I $src_iface -c $ping_count -s $size \ 861 $flood_opt $pattern_opt $dst_addr \>/dev/null 862 ret=$? 863 [ "$ret" -ne 0 ] && break 864 done 865 return $ret 866} 867 868# tst_icmp -t TIMEOUT -s MESSAGE_SIZE_ARRAY OPTS 869# TIMEOUT: total time for the test in seconds 870# OPTS: additional options for ns-icmpv4|6-sender tool 871tst_icmp() 872{ 873 local timeout=1 874 local msg_sizes=56 875 local opts= 876 local num= 877 local ret=0 878 879 OPTIND=0 880 while getopts :t:s: opt; do 881 case "$opt" in 882 t) timeout="$OPTARG" ;; 883 s) msg_sizes="$OPTARG" ;; 884 *) opts="-$OPTARG $opts" ;; 885 esac 886 done 887 OPTIND=0 888 889 local num=$(echo "$msg_sizes" | wc -w) 890 timeout="$(($timeout / $num))" 891 [ "$timeout" -eq 0 ] && timeout=1 892 893 opts="${opts}-I $(tst_iface) -S $(tst_ipaddr) -D $(tst_ipaddr rhost) " 894 opts="${opts}-M $(tst_hwaddr rhost) -t $timeout" 895 896 for size in $msg_sizes; do 897 ns-icmpv${TST_IPVER}_sender -s $size $opts 898 ret=$? 899 if [ $ret -eq 0 ]; then 900 tst_res_ TPASS "'ns-icmpv${TST_IPVER}_sender -s $size $opts' pass" 901 else 902 tst_res_ TFAIL "'ns-icmpv${TST_IPVER}_sender -s $size $opts' fail" 903 break 904 fi 905 done 906 return $ret 907} 908 909# tst_set_sysctl NAME VALUE [safe] 910# It can handle netns case when sysctl not namespaceified. 911tst_set_sysctl() 912{ 913 local name="$1" 914 local value="$2" 915 local safe= 916 [ "$3" = "safe" ] && safe="-s" 917 918 local rparam= 919 [ "$TST_USE_NETNS" = "yes" ] && rparam="-r '-e'" 920 921 tst_net_run $safe $rparam "sysctl -q -w $name=$value" 922} 923 924tst_cleanup_rhost() 925{ 926 tst_rhost_run -c "rm -rf $TST_TMPDIR" 927} 928 929tst_default_max_pkt() 930{ 931 local mtu="$(cat /sys/class/net/$(tst_iface)/mtu)" 932 933 echo "$((mtu + mtu / 10))" 934} 935 936# Management Link 937[ -z "$RHOST" ] && TST_USE_NETNS="yes" 938export RHOST="$RHOST" 939export PASSWD="${PASSWD:-}" 940# Don't use it in new tests, use tst_rhost_run() from tst_net.sh instead. 941export LTP_RSH="${LTP_RSH:-ssh -nq}" 942 943# Test Links 944# IPV{4,6}_{L,R}HOST can be set with or without prefix (e.g. IP or IP/prefix), 945# but if you use IP/prefix form, /prefix will be removed by tst_net_vars. 946IPV4_LHOST="${IPV4_LHOST:-10.0.0.2/24}" 947IPV4_RHOST="${IPV4_RHOST:-10.0.0.1/24}" 948IPV6_LHOST="${IPV6_LHOST:-fd00:1:1:1::2/64}" 949IPV6_RHOST="${IPV6_RHOST:-fd00:1:1:1::1/64}" 950 951# tst_net_ip_prefix 952# Strip prefix from IP address and save both If no prefix found sets 953# default prefix. 954# 955# tst_net_iface_prefix reads prefix and interface from rtnetlink. 956# If nothing found sets default prefix value. 957# 958# tst_net_vars exports environment variables related to test links and 959# networks that aren't reachable through the test links. 960# 961# For full list of exported environment variables see: 962# tst_net_ip_prefix -h 963# tst_net_iface_prefix -h 964# tst_net_vars -h 965if [ -z "$_tst_net_parse_variables" ]; then 966 eval $(tst_net_ip_prefix $IPV4_LHOST || echo "exit $?") 967 eval $(tst_net_ip_prefix -r $IPV4_RHOST || echo "exit $?") 968 eval $(tst_net_ip_prefix $IPV6_LHOST || echo "exit $?") 969 eval $(tst_net_ip_prefix -r $IPV6_RHOST || echo "exit $?") 970fi 971 972[ -n "$TST_USE_NETNS" -a "$TST_INIT_NETNS" != "no" ] && init_ltp_netspace 973 974if [ -z "$_tst_net_parse_variables" ]; then 975 eval $(tst_net_iface_prefix $IPV4_LHOST || echo "exit $?") 976 eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV4_RHOST \ 977 || echo "exit $?") 978 eval $(tst_net_iface_prefix $IPV6_LHOST || echo "exit $?") 979 eval $(tst_rhost_run -c 'tst_net_iface_prefix -r '$IPV6_RHOST \ 980 || echo "exit $?") 981 982 eval $(tst_net_vars $IPV4_LHOST/$IPV4_LPREFIX \ 983 $IPV4_RHOST/$IPV4_RPREFIX || echo "exit $?") 984 eval $(tst_net_vars $IPV6_LHOST/$IPV6_LPREFIX \ 985 $IPV6_RHOST/$IPV6_RPREFIX || echo "exit $?") 986 987 tst_res_ TINFO "Network config (local -- remote):" 988 tst_res_ TINFO "$LHOST_IFACES -- $RHOST_IFACES" 989 tst_res_ TINFO "$IPV4_LHOST/$IPV4_LPREFIX -- $IPV4_RHOST/$IPV4_RPREFIX" 990 tst_res_ TINFO "$IPV6_LHOST/$IPV6_LPREFIX -- $IPV6_RHOST/$IPV6_RPREFIX" 991 export _tst_net_parse_variables="yes" 992fi 993 994export TST_NET_DATAROOT="$LTPROOT/testcases/bin/datafiles" 995 996export TST_NETLOAD_CLN_REQUESTS="${TST_NETLOAD_CLN_REQUESTS:-10000}" 997export TST_NETLOAD_CLN_NUMBER="${TST_NETLOAD_CLN_NUMBER:-2}" 998export TST_NETLOAD_BINDTODEVICE="${TST_NETLOAD_BINDTODEVICE-1}" 999export TST_NETLOAD_RUN_COUNT="${TST_NETLOAD_RUN_COUNT:-5}" 1000export HTTP_DOWNLOAD_DIR="${HTTP_DOWNLOAD_DIR:-/var/www/html}" 1001export FTP_DOWNLOAD_DIR="${FTP_DOWNLOAD_DIR:-/var/ftp}" 1002export FTP_UPLOAD_DIR="${FTP_UPLOAD_DIR:-/var/ftp/pub}" 1003export FTP_UPLOAD_URLDIR="${FTP_UPLOAD_URLDIR:-pub}" 1004 1005# network/stress tests require additional parameters 1006export NS_DURATION="${NS_DURATION:-10}" 1007export NS_TIMES="${NS_TIMES:-10}" 1008export CONNECTION_TOTAL="${CONNECTION_TOTAL:-10}" 1009export IP_TOTAL="${IP_TOTAL:-100}" 1010export IP_TOTAL_FOR_TCPIP="${IP_TOTAL_FOR_TCPIP:-100}" 1011export ROUTE_TOTAL="${ROUTE_TOTAL:-100}" 1012export MTU_CHANGE_TIMES="${MTU_CHANGE_TIMES:-100}" 1013export IF_UPDOWN_TIMES="${IF_UPDOWN_TIMES:-100}" 1014export DOWNLOAD_BIGFILESIZE="${DOWNLOAD_BIGFILESIZE:-2147483647}" 1015export DOWNLOAD_REGFILESIZE="${DOWNLOAD_REGFILESIZE:-1048576}" 1016export UPLOAD_BIGFILESIZE="${UPLOAD_BIGFILESIZE:-2147483647}" 1017export UPLOAD_REGFILESIZE="${UPLOAD_REGFILESIZE:-1024}" 1018export MCASTNUM_NORMAL="${MCASTNUM_NORMAL:-20}" 1019export MCASTNUM_HEAVY="${MCASTNUM_HEAVY:-4000}" 1020export ROUTE_CHANGE_IP="${ROUTE_CHANGE_IP:-100}" 1021export ROUTE_CHANGE_NETLINK="${ROUTE_CHANGE_NETLINK:-10000}" 1022 1023# Warning: make sure to set valid interface names and IP addresses below. 1024# Set names for test interfaces, e.g. "eth0 eth1" 1025# This is fallback for LHOST_IFACES in case tst_net_vars finds nothing or we 1026# want to use more ifaces. 1027export LHOST_IFACES="${LHOST_IFACES:-eth0}" 1028export RHOST_IFACES="${RHOST_IFACES:-eth0}" 1029# Maximum payload size for 'virt' performance tests, by default eqauls to 1.1 * MTU 1030export TST_NET_MAX_PKT="${TST_NET_MAX_PKT:-$(tst_default_max_pkt)}" 1031# Set corresponding HW addresses, e.g. "00:00:00:00:00:01 00:00:00:00:00:02" 1032export LHOST_HWADDRS="${LHOST_HWADDRS:-$(tst_get_hwaddrs lhost)}" 1033export RHOST_HWADDRS="${RHOST_HWADDRS:-$(tst_get_hwaddrs rhost)}" 1034 1035export NS_ICMPV4_SENDER_DATA_MAXSIZE=1472 1036export NS_ICMPV6_SENDER_DATA_MAXSIZE=1452 1037 1038# More information about network parameters can be found 1039# in the following document: testcases/network/stress/README 1040 1041if [ -n "$TST_USE_LEGACY_API" ]; then 1042 tst_net_remote_tmpdir 1043fi 1044 1045if [ -z "$TST_USE_LEGACY_API" ] && ! tst_cmd_available ping6; then 1046 ping6() 1047 { 1048 ping -6 $@ 1049 } 1050 if [ -z "$_tst_net_ping6_warn_printed" ]; then 1051 tst_res_ TINFO "ping6 binary/symlink is missing, using workaround. Please, report missing ping6 to your distribution." 1052 export _tst_net_ping6_warn_printed=1 1053 fi 1054fi 1055