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