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 upcall_interfaces ovs: test the upcall interfaces" 16 17info() { 18 [ $VERBOSE = 0 ] || echo $* 19} 20 21ovs_base=`pwd` 22sbxs= 23sbx_add () { 24 info "adding sandbox '$1'" 25 26 sbxs="$sbxs $1" 27 28 NO_BIN=0 29 30 # Create sandbox. 31 local d="$ovs_base"/$1 32 if [ -e $d ]; then 33 info "removing $d" 34 rm -rf "$d" 35 fi 36 mkdir "$d" || return 1 37 ovs_setenv $1 38} 39 40ovs_exit_sig() { 41 [ -e ${ovs_dir}/cleanup ] && . "$ovs_dir/cleanup" 42} 43 44on_exit() { 45 echo "$1" > ${ovs_dir}/cleanup.tmp 46 cat ${ovs_dir}/cleanup >> ${ovs_dir}/cleanup.tmp 47 mv ${ovs_dir}/cleanup.tmp ${ovs_dir}/cleanup 48} 49 50ovs_setenv() { 51 sandbox=$1 52 53 ovs_dir=$ovs_base${1:+/$1}; export ovs_dir 54 55 test -e ${ovs_dir}/cleanup || : > ${ovs_dir}/cleanup 56} 57 58ovs_sbx() { 59 if test "X$2" != X; then 60 (ovs_setenv $1; shift; "$@" >> ${ovs_dir}/debug.log) 61 else 62 ovs_setenv $1 63 fi 64} 65 66ovs_add_dp () { 67 info "Adding DP/Bridge IF: sbx:$1 dp:$2 {$3, $4, $5}" 68 sbxname="$1" 69 shift 70 ovs_sbx "$sbxname" python3 $ovs_base/ovs-dpctl.py add-dp $* 71 on_exit "ovs_sbx $sbxname python3 $ovs_base/ovs-dpctl.py del-dp $1;" 72} 73 74ovs_add_if () { 75 info "Adding IF to DP: br:$2 if:$3" 76 if [ "$4" != "-u" ]; then 77 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" \ 78 || return 1 79 else 80 python3 $ovs_base/ovs-dpctl.py add-if \ 81 -u "$2" "$3" >$ovs_dir/$3.out 2>$ovs_dir/$3.err & 82 pid=$! 83 on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null" 84 fi 85} 86 87ovs_del_if () { 88 info "Deleting IF from DP: br:$2 if:$3" 89 ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py del-if "$2" "$3" || return 1 90} 91 92ovs_netns_spawn_daemon() { 93 sbx=$1 94 shift 95 netns=$1 96 shift 97 info "spawning cmd: $*" 98 ip netns exec $netns $* >> $ovs_dir/stdout 2>> $ovs_dir/stderr & 99 pid=$! 100 ovs_sbx "$sbx" on_exit "kill -TERM $pid 2>/dev/null" 101} 102 103ovs_add_netns_and_veths () { 104 info "Adding netns attached: sbx:$1 dp:$2 {$3, $4, $5}" 105 ovs_sbx "$1" ip netns add "$3" || return 1 106 on_exit "ovs_sbx $1 ip netns del $3" 107 ovs_sbx "$1" ip link add "$4" type veth peer name "$5" || return 1 108 on_exit "ovs_sbx $1 ip link del $4 >/dev/null 2>&1" 109 ovs_sbx "$1" ip link set "$4" up || return 1 110 ovs_sbx "$1" ip link set "$5" netns "$3" || return 1 111 ovs_sbx "$1" ip netns exec "$3" ip link set "$5" up || return 1 112 113 if [ "$6" != "" ]; then 114 ovs_sbx "$1" ip netns exec "$3" ip addr add "$6" dev "$5" \ 115 || return 1 116 fi 117 118 if [ "$7" != "-u" ]; then 119 ovs_add_if "$1" "$2" "$4" || return 1 120 else 121 ovs_add_if "$1" "$2" "$4" -u || return 1 122 fi 123 124 [ $TRACING -eq 1 ] && ovs_netns_spawn_daemon "$1" "$ns" \ 125 tcpdump -i any -s 65535 126 127 return 0 128} 129 130usage() { 131 echo 132 echo "$0 [OPTIONS] [TEST]..." 133 echo "If no TEST argument is given, all tests will be run." 134 echo 135 echo "Options" 136 echo " -t: capture traffic via tcpdump" 137 echo " -v: verbose" 138 echo " -p: pause on failure" 139 echo 140 echo "Available tests${tests}" 141 exit 1 142} 143 144# netlink_validation 145# - Create a dp 146# - check no warning with "old version" simulation 147test_netlink_checks () { 148 sbx_add "test_netlink_checks" || return 1 149 150 info "setting up new DP" 151 ovs_add_dp "test_netlink_checks" nv0 || return 1 152 # now try again 153 PRE_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+") 154 ovs_add_dp "test_netlink_checks" nv0 -V 0 || return 1 155 POST_TEST=$(dmesg | grep -E "RIP: [0-9a-fA-Fx]+:ovs_dp_cmd_new\+") 156 if [ "$PRE_TEST" != "$POST_TEST" ]; then 157 info "failed - gen warning" 158 return 1 159 fi 160 161 ovs_add_netns_and_veths "test_netlink_checks" nv0 left left0 l0 || \ 162 return 1 163 ovs_add_netns_and_veths "test_netlink_checks" nv0 right right0 r0 || \ 164 return 1 165 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ 166 wc -l) == 3 ] || \ 167 return 1 168 ovs_del_if "test_netlink_checks" nv0 right0 || return 1 169 [ $(python3 $ovs_base/ovs-dpctl.py show nv0 | grep port | \ 170 wc -l) == 2 ] || \ 171 return 1 172 173 return 0 174} 175 176test_upcall_interfaces() { 177 sbx_add "test_upcall_interfaces" || return 1 178 179 info "setting up new DP" 180 ovs_add_dp "test_upcall_interfaces" ui0 -V 2:1 || return 1 181 182 ovs_add_netns_and_veths "test_upcall_interfaces" ui0 upc left0 l0 \ 183 172.31.110.1/24 -u || return 1 184 185 sleep 1 186 info "sending arping" 187 ip netns exec upc arping -I l0 172.31.110.20 -c 1 \ 188 >$ovs_dir/arping.stdout 2>$ovs_dir/arping.stderr 189 190 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 191 return 0 192} 193 194run_test() { 195 ( 196 tname="$1" 197 tdesc="$2" 198 199 if ! lsmod | grep openvswitch >/dev/null 2>&1; then 200 stdbuf -o0 printf "TEST: %-60s [NOMOD]\n" "${tdesc}" 201 return $ksft_skip 202 fi 203 204 if python3 ovs-dpctl.py -h 2>&1 | \ 205 grep "Need to install the python" >/dev/null 2>&1; then 206 stdbuf -o0 printf "TEST: %-60s [PYLIB]\n" "${tdesc}" 207 return $ksft_skip 208 fi 209 printf "TEST: %-60s [START]\n" "${tname}" 210 211 unset IFS 212 213 eval test_${tname} 214 ret=$? 215 216 if [ $ret -eq 0 ]; then 217 printf "TEST: %-60s [ OK ]\n" "${tdesc}" 218 ovs_exit_sig 219 rm -rf "$ovs_dir" 220 elif [ $ret -eq 1 ]; then 221 printf "TEST: %-60s [FAIL]\n" "${tdesc}" 222 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 223 echo 224 echo "Pausing. Logs in $ovs_dir/. Hit enter to continue" 225 read a 226 fi 227 ovs_exit_sig 228 [ "${PAUSE_ON_FAIL}" = "yes" ] || rm -rf "$ovs_dir" 229 exit 1 230 elif [ $ret -eq $ksft_skip ]; then 231 printf "TEST: %-60s [SKIP]\n" "${tdesc}" 232 elif [ $ret -eq 2 ]; then 233 rm -rf test_${tname} 234 run_test "$1" "$2" 235 fi 236 237 return $ret 238 ) 239 ret=$? 240 case $ret in 241 0) 242 [ $all_skipped = true ] && [ $exitcode=$ksft_skip ] && exitcode=0 243 all_skipped=false 244 ;; 245 $ksft_skip) 246 [ $all_skipped = true ] && exitcode=$ksft_skip 247 ;; 248 *) 249 all_skipped=false 250 exitcode=1 251 ;; 252 esac 253 254 return $ret 255} 256 257 258exitcode=0 259desc=0 260all_skipped=true 261 262while getopts :pvt o 263do 264 case $o in 265 p) PAUSE_ON_FAIL=yes;; 266 v) VERBOSE=1;; 267 t) if which tcpdump > /dev/null 2>&1; then 268 TRACING=1 269 else 270 echo "=== tcpdump not available, tracing disabled" 271 fi 272 ;; 273 *) usage;; 274 esac 275done 276shift $(($OPTIND-1)) 277 278IFS=" 279" 280 281for arg do 282 # Check first that all requested tests are available before running any 283 command -v > /dev/null "test_${arg}" || { echo "=== Test ${arg} not found"; usage; } 284done 285 286name="" 287desc="" 288for t in ${tests}; do 289 [ "${name}" = "" ] && name="${t}" && continue 290 [ "${desc}" = "" ] && desc="${t}" 291 292 run_this=1 293 for arg do 294 [ "${arg}" != "${arg#--*}" ] && continue 295 [ "${arg}" = "${name}" ] && run_this=1 && break 296 run_this=0 297 done 298 if [ $run_this -eq 1 ]; then 299 run_test "${name}" "${desc}" 300 fi 301 name="" 302 desc="" 303done 304 305exit ${exitcode} 306