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