• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2# Copyright (c) 2014-2016 Oracle and/or its affiliates. All Rights Reserved.
3# Copyright (c) 2016-2017 Petr Vorel <pvorel@suse.cz>
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License as
7# published by the Free Software Foundation; either version 2 of
8# the License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it would be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write the Free Software Foundation,
17# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18#
19# Author: Alexey Kodanev <alexey.kodanev@oracle.com>
20#
21
22[ -z "$TST_LIB_LOADED" ] && . test.sh
23
24init_ltp_netspace()
25{
26	if [ ! -f /var/run/netns/ltp_ns ]; then
27		ROD ip net add ltp_ns
28		ROD ip li add name ltp_ns_veth1 type veth peer name ltp_ns_veth2
29		ROD ip li set dev ltp_ns_veth1 netns ltp_ns
30		ROD ip netns exec ltp_ns ip li set lo up
31	fi
32
33	LHOST_IFACES="${LHOST_IFACES:-ltp_ns_veth2}"
34	RHOST_IFACES="${RHOST_IFACES:-ltp_ns_veth1}"
35
36	export TST_INIT_NETNS="no"
37	export LTP_NETNS="${LTP_NETNS:-ip netns exec ltp_ns}"
38
39	tst_restore_ipaddr
40	tst_restore_ipaddr rhost
41
42	tst_wait_ipv6_dad
43}
44
45# Run command on remote host.
46# Options:
47# -b run in background
48# -s safe option, if something goes wrong, will exit with TBROK
49# -c specify command to run
50
51tst_rhost_run()
52{
53	local pre_cmd=
54	local post_cmd=' || echo RTERR'
55	local out=
56	local user="root"
57	local cmd=
58	local safe=0
59
60	OPTIND=0
61
62	while getopts :bsc:u: opt; do
63		case "$opt" in
64		b) [ "$TST_USE_NETNS" ] && pre_cmd="" || pre_cmd="nohup"
65		   post_cmd=" > /dev/null 2>&1 &"
66		   out="1> /dev/null"
67		;;
68		s) safe=1 ;;
69		c) cmd="$OPTARG" ;;
70		u) user="$OPTARG" ;;
71		*) tst_brkm TBROK "tst_rhost_run: unknown option: $OPTARG" ;;
72		esac
73	done
74
75	OPTIND=0
76
77	if [ -z "$cmd" ]; then
78		[ "$safe" -eq 1 ] && \
79			tst_brkm TBROK "tst_rhost_run: command not defined"
80		tst_resm TWARN "tst_rhost_run: command not defined"
81		return 1
82	fi
83
84	local output=
85	local ret=0
86	if [ -n "$TST_USE_SSH" ]; then
87		output=`ssh -n -q $user@$RHOST "sh -c \
88			'$pre_cmd $cmd $post_cmd'" $out 2>&1 || echo 'RTERR'`
89	elif [ -n "$TST_USE_NETNS" ]; then
90		output=`$LTP_NETNS sh -c \
91			"$pre_cmd $cmd $post_cmd" $out 2>&1 || echo 'RTERR'`
92	else
93		output=`rsh -n -l $user $RHOST "sh -c \
94			'$pre_cmd $cmd $post_cmd'" $out 2>&1 || echo 'RTERR'`
95	fi
96	echo "$output" | grep -q 'RTERR$' && ret=1
97	if [ $ret -eq 1 ]; then
98		output=$(echo "$output" | sed 's/RTERR//')
99		[ "$safe" -eq 1 ] && \
100			tst_brkm TBROK "'$cmd' failed on '$RHOST': '$output'"
101	fi
102
103	[ -z "$out" -a -n "$output" ] && echo "$output"
104
105	return $ret
106}
107
108# Get test interface names for local/remote host.
109# tst_get_ifaces [TYPE]
110# TYPE: { lhost | rhost }; Default value is 'lhost'.
111tst_get_ifaces()
112{
113	local type="${1:-lhost}"
114	if [ "$type" = "lhost" ]; then
115		echo "$LHOST_IFACES"
116	else
117		echo "$RHOST_IFACES"
118	fi
119}
120
121# Get HW addresses from defined test interface names.
122# tst_get_hwaddrs [TYPE]
123# TYPE: { lhost | rhost }; Default value is 'lhost'.
124tst_get_hwaddrs()
125{
126	local type="${1:-lhost}"
127	local addr=
128	local list=
129
130	for eth in $(tst_get_ifaces $type); do
131
132		local addr_path="/sys/class/net/${eth}/address"
133
134		case $type in
135		lhost) addr=$(cat $addr_path) ;;
136		rhost) addr=$(tst_rhost_run -s -c "cat $addr_path")
137		esac
138
139		[ -z "$list" ] && list="$addr" || list="$list $addr"
140	done
141	echo "$list"
142}
143
144# Get test HW address.
145# tst_hwaddr [TYPE] [LINK]
146# TYPE: { lhost | rhost }; Default value is 'lhost'.
147# LINK: link number starting from 0. Default value is '0'.
148tst_hwaddr()
149{
150	local type="${1:-lhost}"
151	local link_num="${2:-0}"
152	local hwaddrs=
153	link_num=$(( $link_num + 1 ))
154	[ "$type" = "lhost" ] && hwaddrs=$LHOST_HWADDRS || hwaddrs=$RHOST_HWADDRS
155	echo "$hwaddrs" | awk '{ print $'"$link_num"' }'
156}
157
158# Get test interface name.
159# tst_iface [TYPE] [LINK]
160# TYPE: { lhost | rhost }; Default value is 'lhost'.
161# LINK: link number starting from 0. Default value is '0'.
162tst_iface()
163{
164	local type="${1:-lhost}"
165	local link_num="${2:-0}"
166	link_num="$(( $link_num + 1 ))"
167	echo "$(tst_get_ifaces $type)" | awk '{ print $'"$link_num"' }'
168}
169
170# Blank for an IPV4 test; 6 for an IPV6 test.
171TST_IPV6=
172
173tst_read_opts()
174{
175	OPTIND=0
176	while getopts ":6" opt; do
177		case "$opt" in
178		6)
179			TST_IPV6=6;;
180		esac
181	done
182	OPTIND=0
183}
184
185tst_read_opts $*
186
187# Get IP address
188# tst_ipaddr [TYPE]
189# TYPE: { lhost | rhost }; Default value is 'lhost'.
190tst_ipaddr()
191{
192	local type="${1:-lhost}"
193	local ipv="${TST_IPV6:-4}"
194	local tst_host=
195
196	if [ "$type" = "lhost" ]; then
197		eval "tst_host=\$LHOST_IPV${ipv}_HOST"
198	else
199		eval "tst_host=\$RHOST_IPV${ipv}_HOST"
200	fi
201
202	if [ "$TST_IPV6" ]; then
203		echo "${IPV6_NETWORK}:${tst_host}"
204	else
205		echo "${IPV4_NETWORK}.${tst_host}"
206	fi
207}
208
209# tst_init_iface [TYPE] [LINK]
210# TYPE: { lhost | rhost }; Default value is 'lhost'.
211# LINK: link number starting from 0. Default value is '0'.
212tst_init_iface()
213{
214	local type="${1:-lhost}"
215	local link_num="${2:-0}"
216	local iface="$(tst_iface $type $link_num)"
217	tst_resm TINFO "initialize '$type' '$iface' interface"
218
219	if [ "$type" = "lhost" ]; then
220		ip xfrm policy flush || return $?
221		ip xfrm state flush || return $?
222		ip link set $iface down || return $?
223		ip route flush dev $iface || return $?
224		ip addr flush dev $iface || return $?
225		ip link set $iface up
226		return $?
227	fi
228
229	tst_rhost_run -c "ip xfrm policy flush" || return $?
230	tst_rhost_run -c "ip xfrm state flush" || return $?
231	tst_rhost_run -c "ip link set $iface down" || return $?
232	tst_rhost_run -c "ip route flush dev $iface" || return $?
233	tst_rhost_run -c "ip addr flush dev $iface" || return $?
234	tst_rhost_run -c "ip link set $iface up"
235}
236
237# tst_add_ipaddr [TYPE] [LINK]
238# TYPE: { lhost | rhost }; Default value is 'lhost'.
239# LINK: link number starting from 0. Default value is '0'.
240tst_add_ipaddr()
241{
242	local type="${1:-lhost}"
243	local link_num="${2:-0}"
244
245	local mask=24
246	[ "$TST_IPV6" ] && mask=64
247
248	local iface=$(tst_iface $type $link_num)
249
250	if [ $type = "lhost" ]; then
251		tst_resm TINFO "set local addr $(tst_ipaddr)/$mask"
252		ip addr add $(tst_ipaddr)/$mask dev $iface
253		return $?
254	fi
255
256	tst_resm TINFO "set remote addr $(tst_ipaddr rhost)/$mask"
257	tst_rhost_run -c "ip addr add $(tst_ipaddr rhost)/$mask dev $iface"
258}
259
260# tst_restore_ipaddr [TYPE] [LINK]
261# Restore default ip addresses defined in network.sh
262# TYPE: { lhost | rhost }; Default value is 'lhost'.
263# LINK: link number starting from 0. Default value is '0'.
264tst_restore_ipaddr()
265{
266	local type="${1:-lhost}"
267	local link_num="${2:-0}"
268
269	tst_init_iface $type $link_num || return $?
270
271	local ret=0
272	local backup_tst_ipv6=$TST_IPV6
273	TST_IPV6= tst_add_ipaddr $type $link_num || ret=$?
274	TST_IPV6=6 tst_add_ipaddr $type $link_num || ret=$?
275	TST_IPV6=$backup_tst_ipv6
276
277	return $ret
278}
279
280# tst_wait_ipv6_dad [LHOST_IFACE] [RHOST_IFACE]
281# wait for IPv6 DAD completion
282tst_wait_ipv6_dad()
283{
284	local ret=
285	local i=
286	local iface_loc=${1:-$(tst_iface)}
287	local iface_rmt=${2:-$(tst_iface rhost)}
288
289	for i in $(seq 1 50); do
290		ip a sh $iface_loc | grep -q tentative
291		ret=$?
292
293		tst_rhost_run -c "ip a sh $iface_rmt | grep -q tentative"
294
295		[ $ret -ne 0 -a $? -ne 0 ] && return
296
297		[ $(($i % 10)) -eq 0 ] && \
298			tst_resm TINFO "wait for IPv6 DAD completion $((i / 10))/5 sec"
299
300		tst_sleep 100ms
301	done
302}
303
304# Run network load test, see 'netstress -h' for option description
305tst_netload()
306{
307	local rfile="tst_netload.res"
308	local expect_res="pass"
309	local ret=0
310
311	# common options for client and server
312	local cs_opts=
313
314	local c_num="${TST_NETLOAD_CLN_NUMBER:-2}"
315	local c_requests="${TST_NETLOAD_CLN_REQUESTS:-500000}"
316	local c_opts=
317
318	# number of server replies after which TCP connection is closed
319	local s_replies="${TST_NETLOAD_MAX_SRV_REPLIES:-500000}"
320	local s_opts=
321
322	OPTIND=0
323	while getopts :a:H:d:n:N:r:R:b:t:Ufe: opt; do
324		case "$opt" in
325		a) c_num="$OPTARG" ;;
326		H) c_opts="${c_opts}-H $OPTARG " ;;
327		d) rfile="$OPTARG" ;;
328		n) c_opts="${c_opts}-n $OPTARG " ;;
329		N) c_opts="${c_opts}-N $OPTARG " ;;
330		r) c_requests="$OPTARG" ;;
331		R) s_replies="$OPTARG" ;;
332		b) cs_opts="${cs_opts}-b $OPTARG " ;;
333		t) cs_opts="${cs_opts}-t $OPTARG " ;;
334		U) cs_opts="${cs_opts}-U " ;;
335		f) cs_opts="${cs_opts}-f " ;;
336
337		e) expect_res="$OPTARG" ;;
338		*) tst_brkm TBROK "tst_netload: unknown option: $OPTARG" ;;
339		esac
340	done
341	OPTIND=0
342
343	local expect_ret=0
344	[ "$expect_res" != "pass" ] && expect_ret=1
345
346	local port="$(tst_rhost_run -c 'tst_get_unused_port ipv6 stream')"
347	[ $? -ne 0 ] && tst_brkm TBROK "failed to get unused port"
348
349	tst_rhost_run -c "pkill -9 netstress\$"
350
351	c_opts="${cs_opts}${c_opts}-a $c_num -r $c_requests -d $rfile -g $port"
352	s_opts="${cs_opts}${s_opts}-R $s_replies -g $port"
353
354	tst_resm TINFO "run server 'netstress $s_opts'"
355	tst_rhost_run -s -b -c "netstress $s_opts"
356
357	tst_resm TINFO "check that server port in 'LISTEN' state"
358	local sec_waited=
359	for sec_waited in $(seq 1 600); do
360		tst_rhost_run -c "ss -lutn | grep -q $port" && break
361		if [ $sec_waited -eq 600 ]; then
362			tst_rhost_run -c "ss -utnp | grep $port"
363			tst_brkm TFAIL "server not in LISTEN state"
364		fi
365		tst_sleep 100ms
366	done
367
368	tst_resm TINFO "run client 'netstress -l $c_opts'"
369	netstress -l $c_opts > tst_netload.log 2>&1 || ret=1
370	tst_rhost_run -c "pkill -9 netstress\$"
371
372	if [ "$expect_ret" -ne "$ret" ]; then
373		cat tst_netload.log
374		tst_brkm TFAIL "expected '$expect_res' but ret: '$ret'"
375	fi
376
377	if [ "$ret" -eq 0 ]; then
378		if [ ! -f $rfile ]; then
379			cat tst_netload.log
380			tst_brkm TFAIL "can't read $rfile"
381		fi
382		tst_resm TPASS "netstress passed, time spent '$(cat $rfile)' ms"
383	else
384		tst_resm TPASS "netstress failed as expected"
385	fi
386
387	return $ret
388}
389
390# tst_ping [IFACE] [DST ADDR] [MESSAGE SIZE ARRAY]
391# Check icmp connectivity
392# IFACE: source interface name
393# DST ADDR: destination IPv4 or IPv6 address
394# MESSAGE SIZE ARRAY: message size array
395tst_ping()
396{
397	# The max number of ICMP echo request
398	PING_MAX="${PING_MAX:-500}"
399
400	local src_iface="${1:-$(tst_iface)}"
401	local dst_addr="${2:-$(tst_ipaddr rhost)}"; shift $(( $# >= 2 ? 2 : 0 ))
402	local msg_sizes="$*"
403	local ret=0
404
405	# ping cmd use 56 as default message size
406	for size in ${msg_sizes:-"56"}; do
407		ping$TST_IPV6 -I $src_iface -c $PING_MAX $dst_addr \
408			-s $size -i 0 > /dev/null 2>&1
409		ret=$?
410		if [ $ret -eq 0 ]; then
411			tst_resm TINFO "tst_ping IPv${TST_IPV6:-4} msg_size $size pass"
412		else
413			tst_resm TINFO "tst_ping IPv${TST_IPV6:-4} msg_size $size fail"
414			break
415		fi
416	done
417	return $ret
418}
419
420# tst_icmp -t TIMEOUT -s MESSAGE_SIZE_ARRAY OPTS
421# TIMEOUT: total time for the test in seconds
422# OPTS: additional options for ns-icmpv4|6-sender tool
423tst_icmp()
424{
425	local timeout=1
426	local msg_sizes=56
427	local opts=
428	local num=
429	local ret=0
430	local ver="${TST_IPV6:-4}"
431
432	OPTIND=0
433	while getopts :t:s: opt; do
434		case "$opt" in
435		t) timeout="$OPTARG" ;;
436		s) msg_sizes="$OPTARG" ;;
437		*) opts="-$OPTARG $opts" ;;
438		esac
439	done
440	OPTIND=0
441
442	local num=$(echo "$msg_sizes" | wc -w)
443	timeout="$(($timeout / $num))"
444	[ "$timeout" -eq 0 ] && timeout=1
445
446	opts="${opts}-I $(tst_iface) -S $(tst_ipaddr) -D $(tst_ipaddr rhost) "
447	opts="${opts}-M $(tst_hwaddr rhost) -t $timeout"
448
449	for size in $msg_sizes; do
450		ns-icmpv${ver}_sender -s $size $opts
451		ret=$?
452		if [ $ret -eq 0 ]; then
453			tst_resm TPASS "'ns-icmpv${ver}_sender -s $size $opts' pass"
454		else
455			tst_resm TFAIL "'ns-icmpv${ver}_sender -s $size $opts' fail"
456			break
457		fi
458	done
459	return $ret
460}
461
462# tst_set_sysctl NAME VALUE [safe]
463# It can handle netns case when sysctl not namespaceified.
464tst_set_sysctl()
465{
466	local name="$1"
467	local value="$2"
468	local safe=
469	[ "$3" = "safe" ] && safe="-s"
470
471	local add_opt=
472	[ "$TST_USE_NETNS" = "yes" ] && add_opt="-e"
473
474	if [ "$safe" ]; then
475		ROD sysctl -qw $name=$value
476	else
477		sysctl -qw $name=$value
478	fi
479
480	tst_rhost_run $safe -c "sysctl -qw $add_opt $name=$value"
481}
482
483# Management Link
484[ -z "$RHOST" ] && TST_USE_NETNS="yes"
485export RHOST="$RHOST"
486export PASSWD="${PASSWD:-}"
487# Don't use it in new tests, use tst_rhost_run() from test_net.sh instead.
488export LTP_RSH="${LTP_RSH:-rsh -n}"
489
490# Test Links
491# Set first three octets of the network address, default is '10.0.0'
492export IPV4_NETWORK="${IPV4_NETWORK:-10.0.0}"
493# Set local host last octet, default is '2'
494export LHOST_IPV4_HOST="${LHOST_IPV4_HOST:-2}"
495# Set remote host last octet, default is '1'
496export RHOST_IPV4_HOST="${RHOST_IPV4_HOST:-1}"
497# Set the reverse of IPV4_NETWORK
498export IPV4_NET_REV="${IPV4_NET_REV:-0.0.10}"
499# Set first three octets of the network address, default is 'fd00:1:1:1'
500export IPV6_NETWORK="${IPV6_NETWORK:-fd00:1:1:1}"
501# Set local host last octet, default is '2'
502export LHOST_IPV6_HOST="${LHOST_IPV6_HOST:-:2}"
503# Set remote host last octet, default is '1'
504export RHOST_IPV6_HOST="${RHOST_IPV6_HOST:-:1}"
505
506# Networks that aren't reachable through the test links
507export IPV4_NET16_UNUSED="${IPV4_NET16_UNUSED:-10.23}"
508export IPV6_NET32_UNUSED="${IPV6_NET32_UNUSED:-fd00:23}"
509
510export HTTP_DOWNLOAD_DIR="${HTTP_DOWNLOAD_DIR:-/var/www/html}"
511export FTP_DOWNLOAD_DIR="${FTP_DOWNLOAD_DIR:-/var/ftp}"
512export FTP_UPLOAD_DIR="${FTP_UPLOAD_DIR:-/var/ftp/pub}"
513export FTP_UPLOAD_URLDIR="${FTP_UPLOAD_URLDIR:-pub}"
514
515# network/stress tests require additional parameters
516export NS_DURATION="${NS_DURATION:-3600}"
517export NS_TIMES="${NS_TIMES:-10000}"
518export CONNECTION_TOTAL="${CONNECTION_TOTAL:-4000}"
519export IP_TOTAL="${IP_TOTAL:-10000}"
520export IP_TOTAL_FOR_TCPIP="${IP_TOTAL_FOR_TCPIP:-100}"
521export ROUTE_TOTAL="${ROUTE_TOTAL:-10000}"
522export MTU_CHANGE_TIMES="${MTU_CHANGE_TIMES:-1000}"
523export IF_UPDOWN_TIMES="${IF_UPDOWN_TIMES:-10000}"
524export DOWNLOAD_BIGFILESIZE="${DOWNLOAD_BIGFILESIZE:-2147483647}"
525export DOWNLOAD_REGFILESIZE="${DOWNLOAD_REGFILESIZE:-1048576}"
526export UPLOAD_BIGFILESIZE="${UPLOAD_BIGFILESIZE:-2147483647}"
527export UPLOAD_REGFILESIZE="${UPLOAD_REGFILESIZE:-1024}"
528export MCASTNUM_NORMAL="${MCASTNUM_NORMAL:-20}"
529export MCASTNUM_HEAVY="${MCASTNUM_HEAVY:-40000}"
530
531[ -n "$TST_USE_NETNS" -a "$TST_INIT_NETNS" != "no" ] && init_ltp_netspace
532
533# Warning: make sure to set valid interface names and IP addresses below.
534# Set names for test interfaces, e.g. "eth0 eth1"
535export LHOST_IFACES="${LHOST_IFACES:-eth0}"
536export RHOST_IFACES="${RHOST_IFACES:-eth0}"
537# Set corresponding HW addresses, e.g. "00:00:00:00:00:01 00:00:00:00:00:02"
538export LHOST_HWADDRS="${LHOST_HWADDRS:-$(tst_get_hwaddrs lhost)}"
539export RHOST_HWADDRS="${RHOST_HWADDRS:-$(tst_get_hwaddrs rhost)}"
540
541# More information about network parameters can be found
542# in the following document: testcases/network/stress/README
543