1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# OVS kernel module self tests
5
6# Kselftest framework requirement - SKIP code is 4.
7ksft_skip=4
8
9PAUSE_ON_FAIL=no
10VERBOSE=0
11TRACING=0
12
13tests="
14	netlink_checks				ovsnl: validate netlink attrs and settings"
15
16info() {
17    [ $VERBOSE = 0 ] || echo $*
18}
19
20ovs_base=`pwd`
21sbxs=
22sbx_add () {
23	info "adding sandbox '$1'"
24
25	sbxs="$sbxs $1"
26
27	NO_BIN=0
28
29	# Create sandbox.
30	local d="$ovs_base"/$1
31	if [ -e $d ]; then
32		info "removing $d"
33		rm -rf "$d"
34	fi
35	mkdir "$d" || return 1
36	ovs_setenv $1
37}
38
39ovs_exit_sig() {
40	[ -e ${ovs_dir}/cleanup ] && . "$ovs_dir/cleanup"
41}
42
43on_exit() {
44	echo "$1" > ${ovs_dir}/cleanup.tmp
45	cat ${ovs_dir}/cleanup >> ${ovs_dir}/cleanup.tmp
46	mv ${ovs_dir}/cleanup.tmp ${ovs_dir}/cleanup
47}
48
49ovs_setenv() {
50	sandbox=$1
51
52	ovs_dir=$ovs_base${1:+/$1}; export ovs_dir
53
54	test -e ${ovs_dir}/cleanup || : > ${ovs_dir}/cleanup
55}
56
57ovs_sbx() {
58	if test "X$2" != X; then
59		(ovs_setenv $1; shift; "$@" >> ${ovs_dir}/debug.log)
60	else
61		ovs_setenv $1
62	fi
63}
64
65ovs_add_dp () {
66	info "Adding DP/Bridge IF: sbx:$1 dp:$2 {$3, $4, $5}"
67	sbxname="$1"
68	shift
69	ovs_sbx "$sbxname" python3 $ovs_base/ovs-dpctl.py add-dp $*
70	on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;"
71}
72
73usage() {
74	echo
75	echo "$0 [OPTIONS] [TEST]..."
76	echo "If no TEST argument is given, all tests will be run."
77	echo
78	echo "Options"
79	echo "  -t: capture traffic via tcpdump"
80	echo "  -v: verbose"
81	echo "  -p: pause on failure"
82	echo
83	echo "Available tests${tests}"
84	exit 1
85}
86
87# netlink_validation
88# - Create a dp
89# - check no warning with "old version" simulation
90test_netlink_checks () {
91	sbx_add "test_netlink_checks" || return 1
92
93	info "setting up new DP"
94	ovs_add_dp "test_netlink_checks" nv0 || return 1
95	# now try again
96	PRE_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
97	ovs_add_dp "test_netlink_checks" nv0 -V 0 || return 1
98	POST_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+")
99	if [ "$PRE_TEST" != "$POST_TEST" ]; then
100		info "failed - gen warning"
101		return 1
102	fi
103
104	return 0
105}
106
107run_test() {
108	(
109	tname="$1"
110	tdesc="$2"
111
112	if ! lsmod | grep openvswitch >/dev/null 2>&1; then
113		stdbuf -o0 printf "TEST: %-60s  [NOMOD]\n" "${tdesc}"
114		return $ksft_skip
115	fi
116
117	if python3 ovs-dpctl.py -h 2>&1 | \
118	     grep "Need to install the python" >/dev/null 2>&1; then
119		stdbuf -o0 printf "TEST: %-60s  [PYLIB]\n" "${tdesc}"
120		return $ksft_skip
121	fi
122	printf "TEST: %-60s  [START]\n" "${tname}"
123
124	unset IFS
125
126	eval test_${tname}
127	ret=$?
128
129	if [ $ret -eq 0 ]; then
130		printf "TEST: %-60s  [ OK ]\n" "${tdesc}"
131		ovs_exit_sig
132		rm -rf "$ovs_dir"
133	elif [ $ret -eq 1 ]; then
134		printf "TEST: %-60s  [FAIL]\n" "${tdesc}"
135		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
136			echo
137			echo "Pausing. Logs in $ovs_dir/. Hit enter to continue"
138			read a
139		fi
140		ovs_exit_sig
141		[ "${PAUSE_ON_FAIL}" = "yes" ] || rm -rf "$ovs_dir"
142		exit 1
143	elif [ $ret -eq $ksft_skip ]; then
144		printf "TEST: %-60s  [SKIP]\n" "${tdesc}"
145	elif [ $ret -eq 2 ]; then
146		rm -rf test_${tname}
147		run_test "$1" "$2"
148	fi
149
150	return $ret
151	)
152	ret=$?
153	case $ret in
154		0)
155			[ $all_skipped = true ] && [ $exitcode=$ksft_skip ] && exitcode=0
156			all_skipped=false
157		;;
158		$ksft_skip)
159			[ $all_skipped = true ] && exitcode=$ksft_skip
160		;;
161		*)
162			all_skipped=false
163			exitcode=1
164		;;
165	esac
166
167	return $ret
168}
169
170
171exitcode=0
172desc=0
173all_skipped=true
174
175while getopts :pvt o
176do
177	case $o in
178	p) PAUSE_ON_FAIL=yes;;
179	v) VERBOSE=1;;
180	t) if which tcpdump > /dev/null 2>&1; then
181		TRACING=1
182	   else
183		echo "=== tcpdump not available, tracing disabled"
184	   fi
185	   ;;
186	*) usage;;
187	esac
188done
189shift $(($OPTIND-1))
190
191IFS="
192"
193
194for arg do
195	# Check first that all requested tests are available before running any
196	command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; }
197done
198
199name=""
200desc=""
201for t in ${tests}; do
202	[ "${name}" = "" ]	&& name="${t}"	&& continue
203	[ "${desc}" = "" ]	&& desc="${t}"
204
205	run_this=1
206	for arg do
207		[ "${arg}" != "${arg#--*}" ] && continue
208		[ "${arg}" = "${name}" ] && run_this=1 && break
209		run_this=0
210	done
211	if [ $run_this -eq 1 ]; then
212		run_test "${name}" "${desc}"
213	fi
214	name=""
215	desc=""
216done
217
218exit ${exitcode}
219