xref: /openbmc/linux/tools/testing/selftests/net/mptcp/mptcp_lib.sh (revision 09138ba68c1487a42c400485e999386a74911dbc)
1d83013bdSMatthieu Baerts#! /bin/bash
2d83013bdSMatthieu Baerts# SPDX-License-Identifier: GPL-2.0
3d83013bdSMatthieu Baerts
4c4192967SMatthieu Baertsreadonly KSFT_PASS=0
5d83013bdSMatthieu Baertsreadonly KSFT_FAIL=1
6d83013bdSMatthieu Baertsreadonly KSFT_SKIP=4
79466df1aSMatthieu Baerts
89466df1aSMatthieu Baerts# shellcheck disable=SC2155 # declare and assign separately
92decb7d9SMatthieu Baerts (NGI0)readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}"
10c4192967SMatthieu Baerts
11a17d1419SGeliang Tang# These variables are used in some selftests, read-only
12*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_CREATED=1           # MPTCP_EVENT_CREATED
13*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2       # MPTCP_EVENT_ESTABLISHED
14*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_CLOSED=3            # MPTCP_EVENT_CLOSED
15*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6         # MPTCP_EVENT_ANNOUNCED
16*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_REMOVED=7           # MPTCP_EVENT_REMOVED
17*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10  # MPTCP_EVENT_SUB_ESTABLISHED
18*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11       # MPTCP_EVENT_SUB_CLOSED
19*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13     # MPTCP_EVENT_SUB_PRIORITY
20*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED
21*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16  # MPTCP_EVENT_LISTENER_CLOSED
22*a417ef47SMatthieu Baerts (NGI0)
23*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_AF_INET=2
24*a417ef47SMatthieu Baerts (NGI0)declare -rx MPTCP_LIB_AF_INET6=10
25*a417ef47SMatthieu Baerts (NGI0)
26c4192967SMatthieu BaertsMPTCP_LIB_SUBTESTS=()
27d83013bdSMatthieu Baerts
289466df1aSMatthieu Baerts# only if supported (or forced) and not disabled, see no-color.org
299466df1aSMatthieu Baertsif { [ -t 1 ] || [ "${SELFTESTS_MPTCP_LIB_COLOR_FORCE:-}" = "1" ]; } &&
309466df1aSMatthieu Baerts   [ "${NO_COLOR:-}" != "1" ]; then
319466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_RED="\E[1;31m"
329466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_GREEN="\E[1;32m"
339466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_YELLOW="\E[1;33m"
349466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_BLUE="\E[1;34m"
359466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_RESET="\E[0m"
369466df1aSMatthieu Baertselse
379466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_RED=
389466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_GREEN=
399466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_YELLOW=
409466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_BLUE=
419466df1aSMatthieu Baerts	readonly MPTCP_LIB_COLOR_RESET=
429466df1aSMatthieu Baertsfi
439466df1aSMatthieu Baerts
449466df1aSMatthieu Baerts# $1: color, $2: text
459466df1aSMatthieu Baertsmptcp_lib_print_color() {
469466df1aSMatthieu Baerts	echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}"
479466df1aSMatthieu Baerts}
489466df1aSMatthieu Baerts
499466df1aSMatthieu Baertsmptcp_lib_print_ok() {
509466df1aSMatthieu Baerts	mptcp_lib_print_color "${MPTCP_LIB_COLOR_GREEN}${*}"
519466df1aSMatthieu Baerts}
529466df1aSMatthieu Baerts
539466df1aSMatthieu Baertsmptcp_lib_print_warn() {
549466df1aSMatthieu Baerts	mptcp_lib_print_color "${MPTCP_LIB_COLOR_YELLOW}${*}"
559466df1aSMatthieu Baerts}
569466df1aSMatthieu Baerts
579466df1aSMatthieu Baertsmptcp_lib_print_info() {
589466df1aSMatthieu Baerts	mptcp_lib_print_color "${MPTCP_LIB_COLOR_BLUE}${*}"
599466df1aSMatthieu Baerts}
609466df1aSMatthieu Baerts
619466df1aSMatthieu Baertsmptcp_lib_print_err() {
629466df1aSMatthieu Baerts	mptcp_lib_print_color "${MPTCP_LIB_COLOR_RED}${*}"
639466df1aSMatthieu Baerts}
649466df1aSMatthieu Baerts
65d83013bdSMatthieu Baerts# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all
66d83013bdSMatthieu Baerts# features using the last version of the kernel and the selftests to make sure
67d83013bdSMatthieu Baerts# a test is not being skipped by mistake.
68d83013bdSMatthieu Baertsmptcp_lib_expect_all_features() {
69d83013bdSMatthieu Baerts	[ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ]
70d83013bdSMatthieu Baerts}
71d83013bdSMatthieu Baerts
72d83013bdSMatthieu Baerts# $1: msg
73d83013bdSMatthieu Baertsmptcp_lib_fail_if_expected_feature() {
74d83013bdSMatthieu Baerts	if mptcp_lib_expect_all_features; then
75d83013bdSMatthieu Baerts		echo "ERROR: missing feature: ${*}"
76d83013bdSMatthieu Baerts		exit ${KSFT_FAIL}
77d83013bdSMatthieu Baerts	fi
78d83013bdSMatthieu Baerts
79d83013bdSMatthieu Baerts	return 1
80d83013bdSMatthieu Baerts}
81d83013bdSMatthieu Baerts
82d83013bdSMatthieu Baerts# $1: file
83d83013bdSMatthieu Baertsmptcp_lib_has_file() {
84d83013bdSMatthieu Baerts	local f="${1}"
85d83013bdSMatthieu Baerts
86d83013bdSMatthieu Baerts	if [ -f "${f}" ]; then
87d83013bdSMatthieu Baerts		return 0
88d83013bdSMatthieu Baerts	fi
89d83013bdSMatthieu Baerts
90d83013bdSMatthieu Baerts	mptcp_lib_fail_if_expected_feature "${f} file not found"
91d83013bdSMatthieu Baerts}
92d83013bdSMatthieu Baerts
93d83013bdSMatthieu Baertsmptcp_lib_check_mptcp() {
94d83013bdSMatthieu Baerts	if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then
95d83013bdSMatthieu Baerts		echo "SKIP: MPTCP support is not available"
96d83013bdSMatthieu Baerts		exit ${KSFT_SKIP}
97d83013bdSMatthieu Baerts	fi
98d83013bdSMatthieu Baerts}
9967300482SMatthieu Baerts
10067300482SMatthieu Baertsmptcp_lib_check_kallsyms() {
10167300482SMatthieu Baerts	if ! mptcp_lib_has_file "/proc/kallsyms"; then
10267300482SMatthieu Baerts		echo "SKIP: CONFIG_KALLSYMS is missing"
10367300482SMatthieu Baerts		exit ${KSFT_SKIP}
10467300482SMatthieu Baerts	fi
10567300482SMatthieu Baerts}
10667300482SMatthieu Baerts
10767300482SMatthieu Baerts# Internal: use mptcp_lib_kallsyms_has() instead
10867300482SMatthieu Baerts__mptcp_lib_kallsyms_has() {
10967300482SMatthieu Baerts	local sym="${1}"
11067300482SMatthieu Baerts
11167300482SMatthieu Baerts	mptcp_lib_check_kallsyms
11267300482SMatthieu Baerts
11367300482SMatthieu Baerts	grep -q " ${sym}" /proc/kallsyms
11467300482SMatthieu Baerts}
11567300482SMatthieu Baerts
11667300482SMatthieu Baerts# $1: part of a symbol to look at, add '$' at the end for full name
11767300482SMatthieu Baertsmptcp_lib_kallsyms_has() {
11867300482SMatthieu Baerts	local sym="${1}"
11967300482SMatthieu Baerts
12067300482SMatthieu Baerts	if __mptcp_lib_kallsyms_has "${sym}"; then
12167300482SMatthieu Baerts		return 0
12267300482SMatthieu Baerts	fi
12367300482SMatthieu Baerts
12467300482SMatthieu Baerts	mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
12567300482SMatthieu Baerts}
12667300482SMatthieu Baerts
12767300482SMatthieu Baerts# $1: part of a symbol to look at, add '$' at the end for full name
12867300482SMatthieu Baertsmptcp_lib_kallsyms_doesnt_have() {
12967300482SMatthieu Baerts	local sym="${1}"
13067300482SMatthieu Baerts
13167300482SMatthieu Baerts	if ! __mptcp_lib_kallsyms_has "${sym}"; then
13267300482SMatthieu Baerts		return 0
13367300482SMatthieu Baerts	fi
13467300482SMatthieu Baerts
13567300482SMatthieu Baerts	mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
13667300482SMatthieu Baerts}
137b1a6a38aSMatthieu Baerts
138b1a6a38aSMatthieu Baerts# !!!AVOID USING THIS!!!
139b1a6a38aSMatthieu Baerts# Features might not land in the expected version and features can be backported
140b1a6a38aSMatthieu Baerts#
141b1a6a38aSMatthieu Baerts# $1: kernel version, e.g. 6.3
142b1a6a38aSMatthieu Baertsmptcp_lib_kversion_ge() {
143b1a6a38aSMatthieu Baerts	local exp_maj="${1%.*}"
144b1a6a38aSMatthieu Baerts	local exp_min="${1#*.}"
145b1a6a38aSMatthieu Baerts	local v maj min
146b1a6a38aSMatthieu Baerts
147b1a6a38aSMatthieu Baerts	# If the kernel has backported features, set this env var to 1:
148b1a6a38aSMatthieu Baerts	if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
149b1a6a38aSMatthieu Baerts		return 0
150b1a6a38aSMatthieu Baerts	fi
151b1a6a38aSMatthieu Baerts
152b1a6a38aSMatthieu Baerts	v=$(uname -r | cut -d'.' -f1,2)
153b1a6a38aSMatthieu Baerts	maj=${v%.*}
154b1a6a38aSMatthieu Baerts	min=${v#*.}
155b1a6a38aSMatthieu Baerts
156b1a6a38aSMatthieu Baerts	if   [ "${maj}" -gt "${exp_maj}" ] ||
157b1a6a38aSMatthieu Baerts	   { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
158b1a6a38aSMatthieu Baerts		return 0
159b1a6a38aSMatthieu Baerts	fi
160b1a6a38aSMatthieu Baerts
161b1a6a38aSMatthieu Baerts	mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
162b1a6a38aSMatthieu Baerts}
163c4192967SMatthieu Baerts
164c4192967SMatthieu Baerts__mptcp_lib_result_add() {
165c4192967SMatthieu Baerts	local result="${1}"
166c4192967SMatthieu Baerts	shift
167c4192967SMatthieu Baerts
168c4192967SMatthieu Baerts	local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1))
169c4192967SMatthieu Baerts
170c4192967SMatthieu Baerts	MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*}")
171c4192967SMatthieu Baerts}
172c4192967SMatthieu Baerts
173c4192967SMatthieu Baerts# $1: test name
174c4192967SMatthieu Baertsmptcp_lib_result_pass() {
175c4192967SMatthieu Baerts	__mptcp_lib_result_add "ok" "${1}"
176c4192967SMatthieu Baerts}
177c4192967SMatthieu Baerts
178c4192967SMatthieu Baerts# $1: test name
179c4192967SMatthieu Baertsmptcp_lib_result_fail() {
180c4192967SMatthieu Baerts	__mptcp_lib_result_add "not ok" "${1}"
181c4192967SMatthieu Baerts}
182c4192967SMatthieu Baerts
183c4192967SMatthieu Baerts# $1: test name
184c4192967SMatthieu Baertsmptcp_lib_result_skip() {
185c4192967SMatthieu Baerts	__mptcp_lib_result_add "ok" "${1} # SKIP"
186c4192967SMatthieu Baerts}
187c4192967SMatthieu Baerts
188c4192967SMatthieu Baerts# $1: result code ; $2: test name
189c4192967SMatthieu Baertsmptcp_lib_result_code() {
190c4192967SMatthieu Baerts	local ret="${1}"
191c4192967SMatthieu Baerts	local name="${2}"
192c4192967SMatthieu Baerts
193c4192967SMatthieu Baerts	case "${ret}" in
194c4192967SMatthieu Baerts		"${KSFT_PASS}")
195c4192967SMatthieu Baerts			mptcp_lib_result_pass "${name}"
196c4192967SMatthieu Baerts			;;
197c4192967SMatthieu Baerts		"${KSFT_FAIL}")
198c4192967SMatthieu Baerts			mptcp_lib_result_fail "${name}"
199c4192967SMatthieu Baerts			;;
200c4192967SMatthieu Baerts		"${KSFT_SKIP}")
201c4192967SMatthieu Baerts			mptcp_lib_result_skip "${name}"
202c4192967SMatthieu Baerts			;;
203c4192967SMatthieu Baerts		*)
204c4192967SMatthieu Baerts			echo "ERROR: wrong result code: ${ret}"
205c4192967SMatthieu Baerts			exit ${KSFT_FAIL}
206c4192967SMatthieu Baerts			;;
207c4192967SMatthieu Baerts	esac
208c4192967SMatthieu Baerts}
209c4192967SMatthieu Baerts
210c4192967SMatthieu Baertsmptcp_lib_result_print_all_tap() {
211c4192967SMatthieu Baerts	local subtest
212c4192967SMatthieu Baerts
213c4192967SMatthieu Baerts	if [ ${#MPTCP_LIB_SUBTESTS[@]} -eq 0 ] ||
214c4192967SMatthieu Baerts	   [ "${SELFTESTS_MPTCP_LIB_NO_TAP:-}" = "1" ]; then
215c4192967SMatthieu Baerts		return
216c4192967SMatthieu Baerts	fi
217c4192967SMatthieu Baerts
218c4192967SMatthieu Baerts	printf "\nTAP version 13\n"
219c4192967SMatthieu Baerts	printf "1..%d\n" "${#MPTCP_LIB_SUBTESTS[@]}"
220c4192967SMatthieu Baerts
221c4192967SMatthieu Baerts	for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do
222c4192967SMatthieu Baerts		printf "%s\n" "${subtest}"
223c4192967SMatthieu Baerts	done
224c4192967SMatthieu Baerts}
2251fdb37a6SGeliang Tang
226ae1fa39dSGeliang Tang# get the value of keyword $1 in the line marked by keyword $2
227ae1fa39dSGeliang Tangmptcp_lib_get_info_value() {
228ae1fa39dSGeliang Tang	grep "${2}" | sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q'
229ae1fa39dSGeliang Tang}
230ae1fa39dSGeliang Tang
231ece1aaecSGeliang Tang# $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]]
232ae1fa39dSGeliang Tangmptcp_lib_evts_get_info() {
233ece1aaecSGeliang Tang	grep "${4:-}" "${2}" | mptcp_lib_get_info_value "${1}" "^type:${3:-1},"
234ae1fa39dSGeliang Tang}
235ae1fa39dSGeliang Tang
2361fdb37a6SGeliang Tang# $1: PID
2371fdb37a6SGeliang Tangmptcp_lib_kill_wait() {
2381fdb37a6SGeliang Tang	[ "${1}" -eq 0 ] && return 0
2391fdb37a6SGeliang Tang
2401fdb37a6SGeliang Tang	kill -SIGUSR1 "${1}" > /dev/null 2>&1
2411fdb37a6SGeliang Tang	kill "${1}" > /dev/null 2>&1
2421fdb37a6SGeliang Tang	wait "${1}" 2>/dev/null
2431fdb37a6SGeliang Tang}
244697128a3SGeliang Tang
2458e7f31bfSGeliang Tang# $1: IP address
2468e7f31bfSGeliang Tangmptcp_lib_is_v6() {
2478e7f31bfSGeliang Tang	[ -z "${1##*:*}" ]
2488e7f31bfSGeliang Tang}
2498e7f31bfSGeliang Tang
250697128a3SGeliang Tang# $1: ns, $2: MIB counter
251697128a3SGeliang Tangmptcp_lib_get_counter() {
252697128a3SGeliang Tang	local ns="${1}"
253697128a3SGeliang Tang	local counter="${2}"
254697128a3SGeliang Tang	local count
255697128a3SGeliang Tang
256697128a3SGeliang Tang	count=$(ip netns exec "${ns}" nstat -asz "${counter}" |
257697128a3SGeliang Tang		awk 'NR==1 {next} {print $2}')
258697128a3SGeliang Tang	if [ -z "${count}" ]; then
259697128a3SGeliang Tang		mptcp_lib_fail_if_expected_feature "${counter} counter"
260697128a3SGeliang Tang		return 1
261697128a3SGeliang Tang	fi
262697128a3SGeliang Tang
263697128a3SGeliang Tang	echo "${count}"
264697128a3SGeliang Tang}
265b66609e9SGeliang Tang
266b66609e9SGeliang Tangmptcp_lib_events() {
267b66609e9SGeliang Tang	local ns="${1}"
268b66609e9SGeliang Tang	local evts="${2}"
269b66609e9SGeliang Tang	declare -n pid="${3}"
270b66609e9SGeliang Tang
271b66609e9SGeliang Tang	:>"${evts}"
272b66609e9SGeliang Tang
273b66609e9SGeliang Tang	mptcp_lib_kill_wait "${pid:-0}"
274b66609e9SGeliang Tang	ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 &
275b66609e9SGeliang Tang	pid=$!
276b66609e9SGeliang Tang}
277