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