# only if supported (or forced) and not disabled, see no-color.org if { [ -t 1 ] || [ "${SELFTESTS_MPTCP_LIB_COLOR_FORCE:-}" = "1" ]; } &&
[ "${NO_COLOR:-}" != "1" ]; then
readonly MPTCP_LIB_COLOR_RED="\E[1;31m"
readonly MPTCP_LIB_COLOR_GREEN="\E[1;32m"
readonly MPTCP_LIB_COLOR_YELLOW="\E[1;33m"
readonly MPTCP_LIB_COLOR_BLUE="\E[1;34m"
readonly MPTCP_LIB_COLOR_RESET="\E[0m" else
readonly MPTCP_LIB_COLOR_RED=
readonly MPTCP_LIB_COLOR_GREEN=
readonly MPTCP_LIB_COLOR_YELLOW=
readonly MPTCP_LIB_COLOR_BLUE=
readonly MPTCP_LIB_COLOR_RESET= fi
# SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY env var can be set not to ignore errors # from subtests marked as flaky
mptcp_lib_override_flaky() {
[ "${SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY:-}" = 1 ]
}
# $1-2: listener/connector ns ; $3 port ; $4-5 listener/connector stat file
mptcp_lib_pr_err_stats() {
local lns="${1}"
local cns="${2}"
local port="${3}"
local lstat="${4}"
local cstat="${5}"
echo -en "${MPTCP_LIB_COLOR_RED}"
{
printf "\nnetns %s (listener) socket stat for %d:\n""${lns}""${port}"
ip netns exec "${lns}" ss -Menitam -o "sport = :${port}" cat"${lstat}"
printf "\nnetns %s (connector) socket stat for %d:\n""${cns}""${port}"
ip netns exec "${cns}" ss -Menitam -o "dport = :${port}"
[ "${lstat}" != "${cstat}" ] && cat"${cstat}"
} 1>&2 echo -en "${MPTCP_LIB_COLOR_RESET}"
}
# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all # features using the last version of the kernel and the selftests to make sure # a test is not being skipped by mistake.
mptcp_lib_expect_all_features() {
[ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ]
}
# $1: msg
mptcp_lib_fail_if_expected_feature() { if mptcp_lib_expect_all_features; then echo"ERROR: missing feature: ${*}"
exit ${KSFT_FAIL} fi
return 1
}
# $1: file
mptcp_lib_has_file() {
local f="${1}"
if [ -f "${f}" ]; then
return 0 fi
mptcp_lib_fail_if_expected_feature "${f} file not found"
}
mptcp_lib_check_mptcp() { if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then
mptcp_lib_pr_skip "MPTCP support is not available"
exit ${KSFT_SKIP} fi
}
mptcp_lib_check_kallsyms() { if ! mptcp_lib_has_file "/proc/kallsyms"; then
mptcp_lib_pr_skip "CONFIG_KALLSYMS is missing"
exit ${KSFT_SKIP} fi
}
# Internal: use mptcp_lib_kallsyms_has() instead
__mptcp_lib_kallsyms_has() {
local sym="${1}"
mptcp_lib_check_kallsyms
grep -q " ${sym}" /proc/kallsyms
}
# $1: part of a symbol to look at, add '$' at the end for full name
mptcp_lib_kallsyms_has() {
local sym="${1}"
if __mptcp_lib_kallsyms_has "${sym}"; then
return 0 fi
mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
}
# $1: part of a symbol to look at, add '$' at the end for full name
mptcp_lib_kallsyms_doesnt_have() {
local sym="${1}"
if ! __mptcp_lib_kallsyms_has "${sym}"; then
return 0 fi
mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
}
# !!!AVOID USING THIS!!! # Features might not land in the expected version and features can be backported # # $1: kernel version, e.g. 6.3
mptcp_lib_kversion_ge() {
local exp_maj="${1%.*}"
local exp_min="${1#*.}"
local v maj min
# If the kernel has backported features, set this env var to 1: if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
return 0 fi
__mptcp_lib_result_check_duplicated() {
local subtest
for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do if [[ "${subtest}" == *" - ${KSFT_TEST}: ${*%% #*}" ]]; then
MPTCP_LIB_SUBTESTS_DUPLICATED=1
mptcp_lib_print_err "Duplicated entry: ${*}"
break fi done
}
__mptcp_lib_result_add() {
local result="${1}"
local time="time="
local ts_prev_ms
shift
local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1))
__mptcp_lib_result_check_duplicated "${*}"
# not to add two '#'
[[ "${*}" != *"#"* ]] && time="# ${time}"
# $1: test name
mptcp_lib_result_pass() {
__mptcp_lib_result_add "ok""${1}"
}
# $1: test name
mptcp_lib_result_fail() { if mptcp_lib_subtest_is_flaky; then # It might sound better to use 'not ok # TODO' or 'ok # SKIP', # but some CIs don't understand 'TODO' and treat SKIP as errors.
__mptcp_lib_result_add "ok""${1} # IGNORE Flaky" else
__mptcp_lib_result_add "not ok""${1}" fi
}
# $1: test name
mptcp_lib_result_skip() {
__mptcp_lib_result_add "ok""${1} # SKIP"
}
# $1: result code ; $2: test name
mptcp_lib_result_code() {
local ret="${1}"
local name="${2}"
case "${ret}" in "${KSFT_PASS}")
mptcp_lib_result_pass "${name}"
;; "${KSFT_FAIL}")
mptcp_lib_result_fail "${name}"
;; "${KSFT_SKIP}")
mptcp_lib_result_skip "${name}"
;;
*) echo"ERROR: wrong result code: ${ret}"
exit ${KSFT_FAIL}
;;
esac
}
mptcp_lib_result_print_all_tap() {
local subtest
if [ ${#MPTCP_LIB_SUBTESTS[@]} -eq 0 ] ||
[ "${SELFTESTS_MPTCP_LIB_NO_TAP:-}" = "1" ]; then
return fi
printf "\nTAP version 13\n"
printf "1..%d\n""${#MPTCP_LIB_SUBTESTS[@]}"
for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do
printf "%s\n""${subtest}" done
if [ "${MPTCP_LIB_SUBTESTS_DUPLICATED}" = 1 ] &&
mptcp_lib_expect_all_features; then
mptcp_lib_print_err "Duplicated test entries"
exit ${KSFT_FAIL} fi
}
# get the value of keyword $1 in the line marked by keyword $2
mptcp_lib_get_info_value() {
grep "${2}" 2>/dev/null |
sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q' # the ';q' at the end limits to the first matched entry.
}
# $1: file
mptcp_lib_print_file_err() {
ls -l "${1}" 1>&2 echo"Trailing bytes are: "
tail -c 32 "${1}" | od -x | head -n2
}
# $1: input file ; $2: output file ; $3: what kind of file
mptcp_lib_check_transfer() {
local in="${1}"
local out="${2}"
local what="${3}"
if ! cmp "$in""$out" > /dev/null 2>&1; then
mptcp_lib_pr_fail "$what does not match (in, out):"
mptcp_lib_print_file_err "$in"
mptcp_lib_print_file_err "$out"
return 1 fi
return 0
}
# $1: ns, $2: port
mptcp_lib_wait_local_port_listen() {
wait_local_port_listen "${@}""tcp"
}
mptcp_lib_check_output() {
local err="${1}"
local cmd="${2}"
local expected="${3}"
local cmd_ret=0
local out
if ! out=$(${cmd} 2>"${err}"); then
cmd_ret=${?} fi
if [ ${cmd_ret} -ne 0 ]; then
mptcp_lib_pr_fail "command execution '${cmd}' stderr" cat"${err}"
return 2 elif [ "${out}" = "${expected}" ]; then
return 0 else
mptcp_lib_pr_fail "expected '${expected}' got '${out}'"
return 1 fi
}
mptcp_lib_check_tools() {
local tool
for tool in "${@}"; do
case "${tool}" in "ip") if ! ip -Version &> /dev/null; then
mptcp_lib_pr_skip "Could not run test without ip tool"
exit ${KSFT_SKIP} fi
;; "tc") if ! tc -help &> /dev/null; then
mptcp_lib_pr_skip "Could not run test without tc tool"
exit ${KSFT_SKIP} fi
;; "ss") if ! ss -h | grep -q MPTCP; then
mptcp_lib_pr_skip "ss tool does not support MPTCP"
exit ${KSFT_SKIP} fi
;; "iptables"* | "ip6tables"*) if ! "${tool}" -V &> /dev/null; then
mptcp_lib_pr_skip "Could not run all tests without ${tool}"
exit ${KSFT_SKIP} fi
;;
*)
mptcp_lib_pr_fail "Internal error: unsupported tool: ${tool}"
exit ${KSFT_FAIL}
;;
esac done
}
mptcp_lib_ns_init() { if ! setup_ns "${@}"; then
mptcp_lib_pr_fail "Failed to setup namespaces ${*}"
exit ${KSFT_FAIL} fi
local netns for netns in "${@}"; do
ip netns exec "${!netns}" sysctl -q net.mptcp.enabled=1 done
}
mptcp_lib_ns_exit() {
cleanup_ns "${@}"
local netns for netns in "${@}"; do rm -f /tmp/"${netns}".{nstat,out} done
}
mptcp_lib_events() {
local ns="${1}"
local evts="${2}"
declare -n pid="${3}"
# shellcheck disable=SC2059 # the format is in a variable
printf "${MPTCP_LIB_TEST_FORMAT}""$((++MPTCP_LIB_TEST_COUNTER))""${*}"
}
# $1: var name ; $2: prev ret
mptcp_lib_check_expected_one() {
local var="${1}"
local exp="e_${var}"
local prev_ret="${2}"
if [ "${!var}" = "${!exp}" ]; then
return 0 fi
if [ "${prev_ret}" = "0" ]; then
mptcp_lib_pr_fail fi
mptcp_lib_print_err "Expected value for '${var}': '${!exp}', got '${!var}'."
return 1
}
# $@: all var names to check
mptcp_lib_check_expected() {
local rc=0
local var
for var in "${@}"; do
mptcp_lib_check_expected_one "${var}""${rc}" || rc=1 done
return "${rc}"
}
# shellcheck disable=SC2034 # Some variables are used below but indirectly
mptcp_lib_verify_listener_events() {
local evt=${1}
local e_type=${2}
local e_family=${3}
local e_saddr=${4}
local e_sport=${5}
local type
local family
local saddr
local sport
local rc=0
type=$(mptcp_lib_evts_get_info type "${evt}""${e_type}")
family=$(mptcp_lib_evts_get_info family "${evt}""${e_type}") if [ "${family}" ] && [ "${family}" = "${AF_INET6}" ]; then
saddr=$(mptcp_lib_evts_get_info saddr6 "${evt}""${e_type}") else
saddr=$(mptcp_lib_evts_get_info saddr4 "${evt}""${e_type}") fi
sport=$(mptcp_lib_evts_get_info sport "${evt}""${e_type}")
# format: <id>,<ip>,<flags>,<dev>
mptcp_lib_pm_nl_format_endpoints() {
local entry id ip flags dev port
for entry in "${@}"; do
IFS=, read -r id ip flags dev port <<< "${entry}" if mptcp_lib_is_ip_mptcp; then echo -n "${ip}"
[ -n "${port}" ] && echo -n " port ${port}" echo -n " id ${id}"
[ -n "${flags}" ] && echo -n " ${flags}"
[ -n "${dev}" ] && echo -n " dev ${dev}" echo" "# always a space at the end else echo -n "id ${id}" echo -n " flags ${flags//""/","}"
[ -n "${dev}" ] && echo -n " dev ${dev}" echo -n " ${ip}"
[ -n "${port}" ] && echo -n " ${port}" echo"" fi done
}
mptcp_lib_pm_nl_get_endpoint() {
local ns=${1}
local id=${2}
if mptcp_lib_is_ip_mptcp; then
ip -n "${ns}" mptcp endpoint show id "${id}" else
ip netns exec "${ns}" ./pm_nl_ctl get "${id}" fi
}
mptcp_lib_pm_nl_set_limits() {
local ns=${1}
local addrs=${2}
local subflows=${3}
if mptcp_lib_is_ip_mptcp; then
ip -n "${ns}" mptcp limits set add_addr_accepted "${addrs}" subflows "${subflows}" else
ip netns exec "${ns}" ./pm_nl_ctl limits "${addrs}""${subflows}" fi
}
mptcp_lib_pm_nl_add_endpoint() {
local ns=${1}
local addr=${2}
local flags dev id port
local nr=2
local p for p in "${@}"; do
case "${p}" in "flags" | "dev" | "id" | "port") eval"${p}"=\$"${nr}"
;;
esac
nr=$((nr + 1)) done
if mptcp_lib_is_ip_mptcp; then # shellcheck disable=SC2086 # blanks in flags, no double quote
ip -n "${ns}" mptcp endpoint add "${addr}" ${flags//","/" "} \
${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"} else
ip netns exec "${ns}" ./pm_nl_ctl add "${addr}" ${flags:+flags "${flags}"} \
${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"} fi
}
mptcp_lib_pm_nl_del_endpoint() {
local ns=${1}
local id=${2}
local addr=${3}
if mptcp_lib_is_ip_mptcp; then
[ "${id}" -ne 0 ] && addr=''
ip -n "${ns}" mptcp endpoint delete id "${id}" ${addr:+"${addr}"} else
ip netns exec "${ns}" ./pm_nl_ctl del"${id}""${addr}" fi
}
mptcp_lib_pm_nl_flush_endpoint() {
local ns=${1}
if mptcp_lib_is_ip_mptcp; then
ip -n "${ns}" mptcp endpoint flush else
ip netns exec "${ns}" ./pm_nl_ctl flush fi
}
mptcp_lib_pm_nl_show_endpoints() {
local ns=${1}
if mptcp_lib_is_ip_mptcp; then
ip -n "${ns}" mptcp endpoint show else
ip netns exec "${ns}" ./pm_nl_ctl dump fi
}
mptcp_lib_pm_nl_change_endpoint() {
local ns=${1}
local id=${2}
local flags=${3}
if mptcp_lib_is_ip_mptcp; then # shellcheck disable=SC2086 # blanks in flags, no double quote
ip -n "${ns}" mptcp endpoint change id "${id}" ${flags//","/" "} else
ip netns exec "${ns}" ./pm_nl_ctl set id "${id}" flags "${flags}" fi
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.