1#! /bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4readonly KSFT_PASS=0 5readonly KSFT_FAIL=1 6readonly KSFT_SKIP=4 7 8# shellcheck disable=SC2155 # declare and assign separately 9readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}" 10 11# These variables are used in some selftests, read-only 12declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED 13declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED 14declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED 15declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED 16declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED 17declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED 18 19declare -rx MPTCP_LIB_AF_INET=2 20declare -rx MPTCP_LIB_AF_INET6=10 21 22# These variables are used in some selftests, read-only 23declare -rx MPTCP_LIB_EVENT_CREATED=1 # MPTCP_EVENT_CREATED 24declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2 # MPTCP_EVENT_ESTABLISHED 25declare -rx MPTCP_LIB_EVENT_CLOSED=3 # MPTCP_EVENT_CLOSED 26declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED 27declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED 28declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED 29declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED 30declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13 # MPTCP_EVENT_SUB_PRIORITY 31declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED 32declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED 33 34declare -rx MPTCP_LIB_AF_INET=2 35declare -rx MPTCP_LIB_AF_INET6=10 36 37MPTCP_LIB_SUBTESTS=() 38 39# only if supported (or forced) and not disabled, see no-color.org 40if { [ -t 1 ] || [ "${SELFTESTS_MPTCP_LIB_COLOR_FORCE:-}" = "1" ]; } && 41 [ "${NO_COLOR:-}" != "1" ]; then 42 readonly MPTCP_LIB_COLOR_RED="\E[1;31m" 43 readonly MPTCP_LIB_COLOR_GREEN="\E[1;32m" 44 readonly MPTCP_LIB_COLOR_YELLOW="\E[1;33m" 45 readonly MPTCP_LIB_COLOR_BLUE="\E[1;34m" 46 readonly MPTCP_LIB_COLOR_RESET="\E[0m" 47else 48 readonly MPTCP_LIB_COLOR_RED= 49 readonly MPTCP_LIB_COLOR_GREEN= 50 readonly MPTCP_LIB_COLOR_YELLOW= 51 readonly MPTCP_LIB_COLOR_BLUE= 52 readonly MPTCP_LIB_COLOR_RESET= 53fi 54 55# $1: color, $2: text 56mptcp_lib_print_color() { 57 echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}" 58} 59 60mptcp_lib_print_ok() { 61 mptcp_lib_print_color "${MPTCP_LIB_COLOR_GREEN}${*}" 62} 63 64mptcp_lib_print_warn() { 65 mptcp_lib_print_color "${MPTCP_LIB_COLOR_YELLOW}${*}" 66} 67 68mptcp_lib_print_info() { 69 mptcp_lib_print_color "${MPTCP_LIB_COLOR_BLUE}${*}" 70} 71 72mptcp_lib_print_err() { 73 mptcp_lib_print_color "${MPTCP_LIB_COLOR_RED}${*}" 74} 75 76# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all 77# features using the last version of the kernel and the selftests to make sure 78# a test is not being skipped by mistake. 79mptcp_lib_expect_all_features() { 80 [ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ] 81} 82 83# $1: msg 84mptcp_lib_fail_if_expected_feature() { 85 if mptcp_lib_expect_all_features; then 86 echo "ERROR: missing feature: ${*}" 87 exit ${KSFT_FAIL} 88 fi 89 90 return 1 91} 92 93# $1: file 94mptcp_lib_has_file() { 95 local f="${1}" 96 97 if [ -f "${f}" ]; then 98 return 0 99 fi 100 101 mptcp_lib_fail_if_expected_feature "${f} file not found" 102} 103 104mptcp_lib_check_mptcp() { 105 if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then 106 echo "SKIP: MPTCP support is not available" 107 exit ${KSFT_SKIP} 108 fi 109} 110 111mptcp_lib_check_kallsyms() { 112 if ! mptcp_lib_has_file "/proc/kallsyms"; then 113 echo "SKIP: CONFIG_KALLSYMS is missing" 114 exit ${KSFT_SKIP} 115 fi 116} 117 118# Internal: use mptcp_lib_kallsyms_has() instead 119__mptcp_lib_kallsyms_has() { 120 local sym="${1}" 121 122 mptcp_lib_check_kallsyms 123 124 grep -q " ${sym}" /proc/kallsyms 125} 126 127# $1: part of a symbol to look at, add '$' at the end for full name 128mptcp_lib_kallsyms_has() { 129 local sym="${1}" 130 131 if __mptcp_lib_kallsyms_has "${sym}"; then 132 return 0 133 fi 134 135 mptcp_lib_fail_if_expected_feature "${sym} symbol not found" 136} 137 138# $1: part of a symbol to look at, add '$' at the end for full name 139mptcp_lib_kallsyms_doesnt_have() { 140 local sym="${1}" 141 142 if ! __mptcp_lib_kallsyms_has "${sym}"; then 143 return 0 144 fi 145 146 mptcp_lib_fail_if_expected_feature "${sym} symbol has been found" 147} 148 149# !!!AVOID USING THIS!!! 150# Features might not land in the expected version and features can be backported 151# 152# $1: kernel version, e.g. 6.3 153mptcp_lib_kversion_ge() { 154 local exp_maj="${1%.*}" 155 local exp_min="${1#*.}" 156 local v maj min 157 158 # If the kernel has backported features, set this env var to 1: 159 if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then 160 return 0 161 fi 162 163 v=$(uname -r | cut -d'.' -f1,2) 164 maj=${v%.*} 165 min=${v#*.} 166 167 if [ "${maj}" -gt "${exp_maj}" ] || 168 { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then 169 return 0 170 fi 171 172 mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}" 173} 174 175__mptcp_lib_result_add() { 176 local result="${1}" 177 shift 178 179 local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1)) 180 181 MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*}") 182} 183 184# $1: test name 185mptcp_lib_result_pass() { 186 __mptcp_lib_result_add "ok" "${1}" 187} 188 189# $1: test name 190mptcp_lib_result_fail() { 191 __mptcp_lib_result_add "not ok" "${1}" 192} 193 194# $1: test name 195mptcp_lib_result_skip() { 196 __mptcp_lib_result_add "ok" "${1} # SKIP" 197} 198 199# $1: result code ; $2: test name 200mptcp_lib_result_code() { 201 local ret="${1}" 202 local name="${2}" 203 204 case "${ret}" in 205 "${KSFT_PASS}") 206 mptcp_lib_result_pass "${name}" 207 ;; 208 "${KSFT_FAIL}") 209 mptcp_lib_result_fail "${name}" 210 ;; 211 "${KSFT_SKIP}") 212 mptcp_lib_result_skip "${name}" 213 ;; 214 *) 215 echo "ERROR: wrong result code: ${ret}" 216 exit ${KSFT_FAIL} 217 ;; 218 esac 219} 220 221mptcp_lib_result_print_all_tap() { 222 local subtest 223 224 if [ ${#MPTCP_LIB_SUBTESTS[@]} -eq 0 ] || 225 [ "${SELFTESTS_MPTCP_LIB_NO_TAP:-}" = "1" ]; then 226 return 227 fi 228 229 printf "\nTAP version 13\n" 230 printf "1..%d\n" "${#MPTCP_LIB_SUBTESTS[@]}" 231 232 for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do 233 printf "%s\n" "${subtest}" 234 done 235} 236 237# get the value of keyword $1 in the line marked by keyword $2 238mptcp_lib_get_info_value() { 239 grep "${2}" | sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q' 240} 241 242# $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]] 243mptcp_lib_evts_get_info() { 244 grep "${4:-}" "${2}" | mptcp_lib_get_info_value "${1}" "^type:${3:-1}," 245} 246 247# $1: PID 248mptcp_lib_kill_wait() { 249 [ "${1}" -eq 0 ] && return 0 250 251 kill -SIGUSR1 "${1}" > /dev/null 2>&1 252 kill "${1}" > /dev/null 2>&1 253 wait "${1}" 2>/dev/null 254} 255 256# $1: IP address 257mptcp_lib_is_v6() { 258 [ -z "${1##*:*}" ] 259} 260 261# $1: ns, $2: MIB counter 262mptcp_lib_get_counter() { 263 local ns="${1}" 264 local counter="${2}" 265 local count 266 267 count=$(ip netns exec "${ns}" nstat -asz "${counter}" | 268 awk 'NR==1 {next} {print $2}') 269 if [ -z "${count}" ]; then 270 mptcp_lib_fail_if_expected_feature "${counter} counter" 271 return 1 272 fi 273 274 echo "${count}" 275} 276 277mptcp_lib_events() { 278 local ns="${1}" 279 local evts="${2}" 280 declare -n pid="${3}" 281 282 :>"${evts}" 283 284 mptcp_lib_kill_wait "${pid:-0}" 285 ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 & 286 pid=$! 287} 288