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