xref: /openbmc/linux/tools/testing/selftests/net/openvswitch/openvswitch.sh (revision 55e43d6abd078ed6d219902ce8cb4d68e3c993ba)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# OVS kernel module self tests
5
6trap ovs_exit_sig EXIT TERM INT ERR
7
8# Kselftest framework requirement - SKIP code is 4.
9ksft_skip=4
10
11PAUSE_ON_FAIL=no
12VERBOSE=0
13TRACING=0
14
15tests="
16	arp_ping				eth-arp: Basic arp ping between two NS
17	ct_connect_v4				ip4-ct-xon: Basic ipv4 tcp connection using ct
18	connect_v4				ip4-xon: Basic ipv4 ping between two NS
19	nat_connect_v4				ip4-nat-xon: Basic ipv4 tcp connection via NAT
20	netlink_checks				ovsnl: validate netlink attrs and settings
21	upcall_interfaces			ovs: test the upcall interfaces
22	drop_reason				drop: test drop reasons are emitted"
23
24info() {
25    [ $VERBOSE = 0 ] || echo $*
26}
27
28ovs_base=`pwd`
29sbxs=
30sbx_add () {
31	info "adding sandbox '$1'"
32
33	sbxs="$sbxs $1"
34
35	NO_BIN=0
36
37	# Create sandbox.
38	local d="$ovs_base"/$1
39	if [ -e $d ]; then
40		info "removing $d"
41		rm -rf "$d"
42	fi
43	mkdir "$d" || return 1
44	ovs_setenv $1
45}
46
47ovs_exit_sig() {
48	[ -e ${ovs_dir}/cleanup ] && . "$ovs_dir/cleanup"
49}
50
51on_exit() {
52	echo "$1" > ${ovs_dir}/cleanup.tmp
53	cat ${ovs_dir}/cleanup >> ${ovs_dir}/cleanup.tmp
54	mv ${ovs_dir}/cleanup.tmp ${ovs_dir}/cleanup
55}
56
57ovs_setenv() {
58	sandbox=$1
59
60	ovs_dir=$ovs_base${1:+/$1}; export ovs_dir
61
62	test -e ${ovs_dir}/cleanup || : > ${ovs_dir}/cleanup
63}
64
65ovs_sbx() {
66	if test "X$2" != X; then
67		(ovs_setenv $1; shift; "$@" >> ${ovs_dir}/debug.log)
68	else
69		ovs_setenv $1
70	fi
71}
72
73ovs_add_dp () {
74	info "Adding DP/Bridge IF: sbx:$1 dp:$2 {$3, $4, $5}"
75	sbxname="$1"
76	shift
77	ovs_sbx "$sbxname" python3 $ovs_base/ovs-dpctl.py add-dp $*
78	on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;"
79}
80
81ovs_add_if () {
82	info "Adding IF to DP: br:$2 if:$3"
83	if [ "$4" != "-u" ]; then
84		ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" \
85		    || return 1
86	else
87		python3 $ovs_base/ovs-dpctl.py add-if \
88		    -u "$2" "$3" >$ovs_dir/$3.out 2>$ovs_dir/$3.err &
89		pid=$!
90		on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null"
91	fi
92}
93
94ovs_del_if () {
95	info "Deleting IF from DP: br:$2 if:$3"
96	ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-if "$2" "$3" || return 1
97}
98
99ovs_netns_spawn_daemon() {
100	sbx=$1
101	shift
102	netns=$1
103	shift
104	info "spawning cmd: $*"
105	ip netns exec $netns $*  >> $ovs_dir/stdout  2>> $ovs_dir/stderr &
106	pid=$!
107	ovs_sbx "$sbx" on_exit "kill -TERM $pid 2>/dev/null"
108}
109
110ovs_add_netns_and_veths () {
111	info "Adding netns attached: sbx:$1 dp:$2 {$3, $4, $5}"
112	ovs_sbx "$1" ip netns add "$3" || return 1
113	on_exit "ovs_sbx $1 ip netns del $3"
114	ovs_sbx "$1" ip link add "$4" type veth peer name "$5" || return 1
115	on_exit "ovs_sbx $1 ip link del $4 >/dev/null 2>&1"
116	ovs_sbx "$1" ip link set "$4" up || return 1
117	ovs_sbx "$1" ip link set "$5" netns "$3" || return 1
118	ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1
119
120	if [ "$6" != "" ]; then
121		ovs_sbx "$1" ip netns exec "$3" ip addr add "$6" dev "$5" \
122		    || return 1
123	fi
124
125	if [ "$7" != "-u" ]; then
126		ovs_add_if "$1" "$2" "$4" || return 1
127	else
128		ovs_add_if "$1" "$2" "$4" -u || return 1
129	fi
130
131	if [ $TRACING -eq 1 ]; then
132		ovs_netns_spawn_daemon "$1" "$3" tcpdump -l -i any -s 6553
133		ovs_wait grep -q "listening on any" ${ovs_dir}/stderr
134	fi
135
136	return 0
137}
138
139ovs_add_flow () {
140	info "Adding flow to DP: sbx:$1 br:$2 flow:$3 act:$4"
141	ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-flow "$2" "$3" "$4"
142	if [ $? -ne 0 ]; then
143		echo "Flow [ $3 : $4 ] failed" >> ${ovs_dir}/debug.log
144		return 1
145	fi
146	return 0
147}
148
149ovs_del_flows () {
150	info "Deleting all flows from DP: sbx:$1 br:$2"
151	ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-flows "$2"
152	return 0
153}
154
155ovs_drop_record_and_run () {
156	local sbx=$1
157	shift
158
159	perf record -a -q -e skb:kfree_skb -o ${ovs_dir}/perf.data $* \
160		>> ${ovs_dir}/stdout 2>> ${ovs_dir}/stderr
161	return $?
162}
163
164ovs_drop_reason_count()
165{
166	local reason=$1
167
168	local perf_output=`perf script -i ${ovs_dir}/perf.data -F trace:event,trace`
169	local pattern="skb:kfree_skb:.*reason: $reason"
170
171	return `echo "$perf_output" | grep "$pattern" | wc -l`
172}
173
174usage() {
175	echo
176	echo "$0 [OPTIONS] [TEST]..."
177	echo "If no TEST argument is given, all tests will be run."
178	echo
179	echo "Options"
180	echo "  -t: capture traffic via tcpdump"
181	echo "  -v: verbose"
182	echo "  -p: pause on failure"
183	echo
184	echo "Available tests${tests}"
185	exit 1
186}
187
188# drop_reason test
189# - drop packets and verify the right drop reason is reported
190test_drop_reason() {
191	which perf >/dev/null 2>&1 || return $ksft_skip
192
193	sbx_add "test_drop_reason" || return $?
194
195	ovs_add_dp "test_drop_reason" dropreason || return 1
196
197	info "create namespaces"
198	for ns in client server; do
199		ovs_add_netns_and_veths "test_drop_reason" "dropreason" "$ns" \
200			"${ns:0:1}0" "${ns:0:1}1" || return 1
201	done
202
203	# Setup client namespace
204	ip netns exec client ip addr add 172.31.110.10/24 dev c1
205	ip netns exec client ip link set c1 up
206
207	# Setup server namespace
208	ip netns exec server ip addr add 172.31.110.20/24 dev s1
209	ip netns exec server ip link set s1 up
210
211	# Check if drop reasons can be sent
212	ovs_add_flow "test_drop_reason" dropreason \
213		'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(10)' 2>/dev/null
214	if [ $? == 1 ]; then
215		info "no support for drop reasons - skipping"
216		ovs_exit_sig
217		return $ksft_skip
218	fi
219
220	ovs_del_flows "test_drop_reason" dropreason
221
222	# Allow ARP
223	ovs_add_flow "test_drop_reason" dropreason \
224		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
225	ovs_add_flow "test_drop_reason" dropreason \
226		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
227
228	# Allow client ICMP traffic but drop return path
229	ovs_add_flow "test_drop_reason" dropreason \
230		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=1),icmp()" '2'
231	ovs_add_flow "test_drop_reason" dropreason \
232		"in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20,proto=1),icmp()" 'drop'
233
234	ovs_drop_record_and_run "test_drop_reason" ip netns exec client ping -c 2 172.31.110.20
235	ovs_drop_reason_count 0x30001 # OVS_DROP_FLOW_ACTION
236	if [[ "$?" -ne "2" ]]; then
237		info "Did not detect expected drops: $?"
238		return 1
239	fi
240
241	# Drop UDP 6000 traffic with an explicit action and an error code.
242	ovs_add_flow "test_drop_reason" dropreason \
243		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=6000)" \
244                'drop(42)'
245	# Drop UDP 7000 traffic with an explicit action with no error code.
246	ovs_add_flow "test_drop_reason" dropreason \
247		"in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10,proto=17),udp(dst=7000)" \
248                'drop(0)'
249
250	ovs_drop_record_and_run \
251            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 6000
252	ovs_drop_reason_count 0x30004 # OVS_DROP_EXPLICIT_ACTION_ERROR
253	if [[ "$?" -ne "1" ]]; then
254		info "Did not detect expected explicit error drops: $?"
255		return 1
256	fi
257
258	ovs_drop_record_and_run \
259            "test_drop_reason" ip netns exec client nc -i 1 -zuv 172.31.110.20 7000
260	ovs_drop_reason_count 0x30003 # OVS_DROP_EXPLICIT_ACTION
261	if [[ "$?" -ne "1" ]]; then
262		info "Did not detect expected explicit drops: $?"
263		return 1
264	fi
265
266	return 0
267}
268
269# arp_ping test
270# - client has 1500 byte MTU
271# - server has 1500 byte MTU
272# - send ARP ping between two ns
273test_arp_ping () {
274
275	which arping >/dev/null 2>&1 || return $ksft_skip
276
277	sbx_add "test_arp_ping" || return $?
278
279	ovs_add_dp "test_arp_ping" arpping || return 1
280
281	info "create namespaces"
282	for ns in client server; do
283		ovs_add_netns_and_veths "test_arp_ping" "arpping" "$ns" \
284		    "${ns:0:1}0" "${ns:0:1}1" || return 1
285	done
286
287	# Setup client namespace
288	ip netns exec client ip addr add 172.31.110.10/24 dev c1
289	ip netns exec client ip link set c1 up
290	HW_CLIENT=`ip netns exec client ip link show dev c1 | grep -E 'link/ether [0-9a-f:]+' | awk '{print $2;}'`
291	info "Client hwaddr: $HW_CLIENT"
292
293	# Setup server namespace
294	ip netns exec server ip addr add 172.31.110.20/24 dev s1
295	ip netns exec server ip link set s1 up
296	HW_SERVER=`ip netns exec server ip link show dev s1 | grep -E 'link/ether [0-9a-f:]+' | awk '{print $2;}'`
297	info "Server hwaddr: $HW_SERVER"
298
299	ovs_add_flow "test_arp_ping" arpping \
300		"in_port(1),eth(),eth_type(0x0806),arp(sip=172.31.110.10,tip=172.31.110.20,sha=$HW_CLIENT,tha=ff:ff:ff:ff:ff:ff)" '2' || return 1
301	ovs_add_flow "test_arp_ping" arpping \
302		"in_port(2),eth(),eth_type(0x0806),arp()" '1' || return 1
303
304	ovs_sbx "test_arp_ping" ip netns exec client arping -I c1 172.31.110.20 -c 1 || return 1
305
306	return 0
307}
308
309# ct_connect_v4 test
310#  - client has 1500 byte MTU
311#  - server has 1500 byte MTU
312#  - use ICMP to ping in each direction
313#  - only allow CT state stuff to pass through new in c -> s
314test_ct_connect_v4 () {
315
316	which nc >/dev/null 2>/dev/null || return $ksft_skip
317
318	sbx_add "test_ct_connect_v4" || return $?
319
320	ovs_add_dp "test_ct_connect_v4" ct4 || return 1
321	info "create namespaces"
322	for ns in client server; do
323		ovs_add_netns_and_veths "test_ct_connect_v4" "ct4" "$ns" \
324		    "${ns:0:1}0" "${ns:0:1}1" || return 1
325	done
326
327	ip netns exec client ip addr add 172.31.110.10/24 dev c1
328	ip netns exec client ip link set c1 up
329	ip netns exec server ip addr add 172.31.110.20/24 dev s1
330	ip netns exec server ip link set s1 up
331
332	# Add forwarding for ARP and ip packets - completely wildcarded
333	ovs_add_flow "test_ct_connect_v4" ct4 \
334		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
335	ovs_add_flow "test_ct_connect_v4" ct4 \
336		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
337	ovs_add_flow "test_ct_connect_v4" ct4 \
338		     'ct_state(-trk),eth(),eth_type(0x0800),ipv4()' \
339		     'ct(commit),recirc(0x1)' || return 1
340	ovs_add_flow "test_ct_connect_v4" ct4 \
341		     'recirc_id(0x1),ct_state(+trk+new),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \
342		     '2' || return 1
343	ovs_add_flow "test_ct_connect_v4" ct4 \
344		     'recirc_id(0x1),ct_state(+trk+est),in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' \
345		     '2' || return 1
346	ovs_add_flow "test_ct_connect_v4" ct4 \
347		     'recirc_id(0x1),ct_state(+trk+est),in_port(2),eth(),eth_type(0x0800),ipv4(dst=172.31.110.10)' \
348		     '1' || return 1
349	ovs_add_flow "test_ct_connect_v4" ct4 \
350		     'recirc_id(0x1),ct_state(+trk+inv),eth(),eth_type(0x0800),ipv4()' 'drop' || \
351		     return 1
352
353	# do a ping
354	ovs_sbx "test_ct_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1
355
356	# create an echo server in 'server'
357	echo "server" | \
358		ovs_netns_spawn_daemon "test_ct_connect_v4" "server" \
359				nc -lvnp 4443
360	ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.20 4443 || return 1
361
362	# Now test in the other direction (should fail)
363	echo "client" | \
364		ovs_netns_spawn_daemon "test_ct_connect_v4" "client" \
365				nc -lvnp 4443
366	ovs_sbx "test_ct_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443
367	if [ $? == 0 ]; then
368	   info "ct connect to client was successful"
369	   return 1
370	fi
371
372	info "done..."
373	return 0
374}
375
376# connect_v4 test
377#  - client has 1500 byte MTU
378#  - server has 1500 byte MTU
379#  - use ICMP to ping in each direction
380test_connect_v4 () {
381
382	sbx_add "test_connect_v4" || return $?
383
384	ovs_add_dp "test_connect_v4" cv4 || return 1
385
386	info "create namespaces"
387	for ns in client server; do
388		ovs_add_netns_and_veths "test_connect_v4" "cv4" "$ns" \
389		    "${ns:0:1}0" "${ns:0:1}1" || return 1
390	done
391
392
393	ip netns exec client ip addr add 172.31.110.10/24 dev c1
394	ip netns exec client ip link set c1 up
395	ip netns exec server ip addr add 172.31.110.20/24 dev s1
396	ip netns exec server ip link set s1 up
397
398	# Add forwarding for ARP and ip packets - completely wildcarded
399	ovs_add_flow "test_connect_v4" cv4 \
400		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
401	ovs_add_flow "test_connect_v4" cv4 \
402		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
403	ovs_add_flow "test_connect_v4" cv4 \
404		'in_port(1),eth(),eth_type(0x0800),ipv4(src=172.31.110.10)' '2' || return 1
405	ovs_add_flow "test_connect_v4" cv4 \
406		'in_port(2),eth(),eth_type(0x0800),ipv4(src=172.31.110.20)' '1' || return 1
407
408	# do a ping
409	ovs_sbx "test_connect_v4" ip netns exec client ping 172.31.110.20 -c 3 || return 1
410
411	info "done..."
412	return 0
413}
414
415# nat_connect_v4 test
416#  - client has 1500 byte MTU
417#  - server has 1500 byte MTU
418#  - use ICMP to ping in each direction
419#  - only allow CT state stuff to pass through new in c -> s
420test_nat_connect_v4 () {
421	which nc >/dev/null 2>/dev/null || return $ksft_skip
422
423	sbx_add "test_nat_connect_v4" || return $?
424
425	ovs_add_dp "test_nat_connect_v4" nat4 || return 1
426	info "create namespaces"
427	for ns in client server; do
428		ovs_add_netns_and_veths "test_nat_connect_v4" "nat4" "$ns" \
429		    "${ns:0:1}0" "${ns:0:1}1" || return 1
430	done
431
432	ip netns exec client ip addr add 172.31.110.10/24 dev c1
433	ip netns exec client ip link set c1 up
434	ip netns exec server ip addr add 172.31.110.20/24 dev s1
435	ip netns exec server ip link set s1 up
436
437	ip netns exec client ip route add default via 172.31.110.20
438
439	ovs_add_flow "test_nat_connect_v4" nat4 \
440		'in_port(1),eth(),eth_type(0x0806),arp()' '2' || return 1
441	ovs_add_flow "test_nat_connect_v4" nat4 \
442		'in_port(2),eth(),eth_type(0x0806),arp()' '1' || return 1
443	ovs_add_flow "test_nat_connect_v4" nat4 \
444		"ct_state(-trk),in_port(1),eth(),eth_type(0x0800),ipv4(dst=192.168.0.20)" \
445		"ct(commit,nat(dst=172.31.110.20)),recirc(0x1)"
446	ovs_add_flow "test_nat_connect_v4" nat4 \
447		"ct_state(-trk),in_port(2),eth(),eth_type(0x0800),ipv4()" \
448		"ct(commit,nat),recirc(0x2)"
449
450	ovs_add_flow "test_nat_connect_v4" nat4 \
451		"recirc_id(0x1),ct_state(+trk-inv),in_port(1),eth(),eth_type(0x0800),ipv4()" "2"
452	ovs_add_flow "test_nat_connect_v4" nat4 \
453		"recirc_id(0x2),ct_state(+trk-inv),in_port(2),eth(),eth_type(0x0800),ipv4()" "1"
454
455	# do a ping
456	ovs_sbx "test_nat_connect_v4" ip netns exec client ping 192.168.0.20 -c 3 || return 1
457
458	# create an echo server in 'server'
459	echo "server" | \
460		ovs_netns_spawn_daemon "test_nat_connect_v4" "server" \
461				nc -lvnp 4443
462	ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 192.168.0.20 4443 || return 1
463
464	# Now test in the other direction (should fail)
465	echo "client" | \
466		ovs_netns_spawn_daemon "test_nat_connect_v4" "client" \
467				nc -lvnp 4443
468	ovs_sbx "test_nat_connect_v4" ip netns exec client nc -i 1 -zv 172.31.110.10 4443
469	if [ $? == 0 ]; then
470	   info "connect to client was successful"
471	   return 1
472	fi
473
474	info "done..."
475	return 0
476}
477
478# netlink_validation
479# - Create a dp
480# - check no warning with "old version" simulation
481test_netlink_checks () {
482	sbx_add "test_netlink_checks" || return 1
483
484	info "setting up new DP"
485	ovs_add_dp "test_netlink_checks" nv0 || return 1
486	# now try again
487	PRE_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
488	ovs_add_dp "test_netlink_checks" nv0 -V 0 || return 1
489	POST_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
490	if [ "$PRE_TEST" != "$POST_TEST" ]; then
491		info "failed - gen warning"
492		return 1
493	fi
494
495	ovs_add_netns_and_veths "test_netlink_checks" nv0 left left0 l0 || \
496	    return 1
497	ovs_add_netns_and_veths "test_netlink_checks" nv0 right right0 r0 || \
498	    return 1
499	[ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \
500	    wc -l) == 3 ] || \
501	      return 1
502	ovs_del_if "test_netlink_checks" nv0 right0 || return 1
503	[ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \
504	    wc -l) == 2 ] || \
505	      return 1
506
507	info "Checking clone depth"
508	ERR_MSG="Flow actions may not be safe on all matching packets"
509	PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
510	ovs_add_flow "test_netlink_checks" nv0 \
511		'in_port(1),eth(),eth_type(0x800),ipv4()' \
512		'clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(clone(drop)))))))))))))))))' \
513		>/dev/null 2>&1 && return 1
514	POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
515
516	if [ "$PRE_TEST" == "$POST_TEST" ]; then
517		info "failed - clone depth too large"
518		return 1
519	fi
520
521	PRE_TEST=$(dmesg | grep -c "${ERR_MSG}")
522	ovs_add_flow "test_netlink_checks" nv0 \
523		'in_port(1),eth(),eth_type(0x0806),arp()' 'drop(0),2' \
524		&> /dev/null && return 1
525	POST_TEST=$(dmesg | grep -c "${ERR_MSG}")
526	if [ "$PRE_TEST" == "$POST_TEST" ]; then
527		info "failed - error not generated"
528		return 1
529	fi
530	return 0
531}
532
533test_upcall_interfaces() {
534	sbx_add "test_upcall_interfaces" || return 1
535
536	info "setting up new DP"
537	ovs_add_dp "test_upcall_interfaces" ui0 -V 2:1 || return 1
538
539	ovs_add_netns_and_veths "test_upcall_interfaces" ui0 upc left0 l0 \
540	    172.31.110.1/24 -u || return 1
541
542	sleep 1
543	info "sending arping"
544	ip netns exec upc arping -I l0 172.31.110.20 -c 1 \
545	    >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr
546
547	grep -E "MISS upcall\[0/yes\]: .*arp\(sip=172.31.110.1,tip=172.31.110.20,op=1,sha=" $ovs_dir/left0.out >/dev/null 2>&1 || return 1
548	return 0
549}
550
551run_test() {
552	(
553	tname="$1"
554	tdesc="$2"
555
556	if ! lsmod | grep openvswitch >/dev/null 2>&1; then
557		stdbuf -o0 printf "TEST: %-60s  [NOMOD]\n" "${tdesc}"
558		return $ksft_skip
559	fi
560
561	if python3 ovs-dpctl.py -h 2>&1 | \
562	     grep -E "Need to (install|upgrade) the python" >/dev/null 2>&1; then
563		stdbuf -o0 printf "TEST: %-60s  [PYLIB]\n" "${tdesc}"
564		return $ksft_skip
565	fi
566	printf "TEST: %-60s  [START]\n" "${tname}"
567
568	unset IFS
569
570	eval test_${tname}
571	ret=$?
572
573	if [ $ret -eq 0 ]; then
574		printf "TEST: %-60s  [ OK ]\n" "${tdesc}"
575		ovs_exit_sig
576		rm -rf "$ovs_dir"
577	elif [ $ret -eq 1 ]; then
578		printf "TEST: %-60s  [FAIL]\n" "${tdesc}"
579		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
580			echo
581			echo "Pausing. Logs in $ovs_dir/. Hit enter to continue"
582			read a
583		fi
584		ovs_exit_sig
585		[ "${PAUSE_ON_FAIL}" = "yes" ] || rm -rf "$ovs_dir"
586		exit 1
587	elif [ $ret -eq $ksft_skip ]; then
588		printf "TEST: %-60s  [SKIP]\n" "${tdesc}"
589	elif [ $ret -eq 2 ]; then
590		rm -rf test_${tname}
591		run_test "$1" "$2"
592	fi
593
594	return $ret
595	)
596	ret=$?
597	case $ret in
598		0)
599			[ $all_skipped = true ] && [ $exitcode=$ksft_skip ] && exitcode=0
600			all_skipped=false
601		;;
602		$ksft_skip)
603			[ $all_skipped = true ] && exitcode=$ksft_skip
604		;;
605		*)
606			all_skipped=false
607			exitcode=1
608		;;
609	esac
610
611	return $ret
612}
613
614
615exitcode=0
616desc=0
617all_skipped=true
618
619while getopts :pvt o
620do
621	case $o in
622	p) PAUSE_ON_FAIL=yes;;
623	v) VERBOSE=1;;
624	t) if which tcpdump > /dev/null 2>&1; then
625		TRACING=1
626	   else
627		echo "=== tcpdump not available, tracing disabled"
628	   fi
629	   ;;
630	*) usage;;
631	esac
632done
633shift $(($OPTIND-1))
634
635IFS="
636"
637
638for arg do
639	# Check first that all requested tests are available before running any
640	command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; }
641done
642
643name=""
644desc=""
645for t in ${tests}; do
646	[ "${name}" = "" ]	&& name="${t}"	&& continue
647	[ "${desc}" = "" ]	&& desc="${t}"
648
649	run_this=1
650	for arg do
651		[ "${arg}" != "${arg#--*}" ] && continue
652		[ "${arg}" = "${name}" ] && run_this=1 && break
653		run_this=0
654	done
655	if [ $run_this -eq 1 ]; then
656		run_test "${name}" "${desc}"
657	fi
658	name=""
659	desc=""
660done
661
662exit ${exitcode}
663