675 lines
15 KiB
Bash
675 lines
15 KiB
Bash
#! /bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
. "$(dirname "${0}")/../lib.sh"
|
|
. "$(dirname "${0}")/../net_helper.sh"
|
|
|
|
readonly KSFT_PASS=0
|
|
readonly KSFT_FAIL=1
|
|
readonly KSFT_SKIP=4
|
|
|
|
# shellcheck disable=SC2155 # declare and assign separately
|
|
readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}"
|
|
|
|
# These variables are used in some selftests, read-only
|
|
declare -rx MPTCP_LIB_EVENT_CREATED=1 # MPTCP_EVENT_CREATED
|
|
declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2 # MPTCP_EVENT_ESTABLISHED
|
|
declare -rx MPTCP_LIB_EVENT_CLOSED=3 # MPTCP_EVENT_CLOSED
|
|
declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
|
|
declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED
|
|
declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED
|
|
declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED
|
|
declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13 # MPTCP_EVENT_SUB_PRIORITY
|
|
declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED
|
|
declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED
|
|
|
|
declare -rx MPTCP_LIB_AF_INET=2
|
|
declare -rx MPTCP_LIB_AF_INET6=10
|
|
|
|
MPTCP_LIB_SUBTESTS=()
|
|
MPTCP_LIB_SUBTESTS_DUPLICATED=0
|
|
MPTCP_LIB_SUBTEST_FLAKY=0
|
|
MPTCP_LIB_SUBTESTS_LAST_TS_MS=
|
|
MPTCP_LIB_TEST_COUNTER=0
|
|
MPTCP_LIB_TEST_FORMAT="%02u %-50s"
|
|
MPTCP_LIB_IP_MPTCP=0
|
|
|
|
# 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 ]
|
|
}
|
|
|
|
mptcp_lib_subtest_is_flaky() {
|
|
[ "${MPTCP_LIB_SUBTEST_FLAKY}" = 1 ] && ! mptcp_lib_override_flaky
|
|
}
|
|
|
|
# $1: color, $2: text
|
|
mptcp_lib_print_color() {
|
|
echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}"
|
|
}
|
|
|
|
mptcp_lib_print_ok() {
|
|
mptcp_lib_print_color "${MPTCP_LIB_COLOR_GREEN}${*}"
|
|
}
|
|
|
|
mptcp_lib_print_warn() {
|
|
mptcp_lib_print_color "${MPTCP_LIB_COLOR_YELLOW}${*}"
|
|
}
|
|
|
|
mptcp_lib_print_info() {
|
|
mptcp_lib_print_color "${MPTCP_LIB_COLOR_BLUE}${*}"
|
|
}
|
|
|
|
mptcp_lib_print_err() {
|
|
mptcp_lib_print_color "${MPTCP_LIB_COLOR_RED}${*}"
|
|
}
|
|
|
|
# shellcheck disable=SC2120 # parameters are optional
|
|
mptcp_lib_pr_ok() {
|
|
mptcp_lib_print_ok "[ OK ]${1:+ ${*}}"
|
|
}
|
|
|
|
mptcp_lib_pr_skip() {
|
|
mptcp_lib_print_warn "[SKIP]${1:+ ${*}}"
|
|
}
|
|
|
|
mptcp_lib_pr_fail() {
|
|
local title cmt
|
|
|
|
if mptcp_lib_subtest_is_flaky; then
|
|
title="IGNO"
|
|
cmt=" (flaky)"
|
|
else
|
|
title="FAIL"
|
|
fi
|
|
|
|
mptcp_lib_print_err "[${title}]${cmt}${1:+ ${*}}"
|
|
}
|
|
|
|
mptcp_lib_pr_info() {
|
|
mptcp_lib_print_info "INFO: ${*}"
|
|
}
|
|
|
|
# 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
|
|
|
|
v=$(uname -r | cut -d'.' -f1,2)
|
|
maj=${v%.*}
|
|
min=${v#*.}
|
|
|
|
if [ "${maj}" -gt "${exp_maj}" ] ||
|
|
{ [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
|
|
return 0
|
|
fi
|
|
|
|
mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
|
|
}
|
|
|
|
mptcp_lib_subtests_last_ts_reset() {
|
|
MPTCP_LIB_SUBTESTS_LAST_TS_MS="$(date +%s%3N)"
|
|
}
|
|
mptcp_lib_subtests_last_ts_reset
|
|
|
|
__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}"
|
|
|
|
ts_prev_ms="${MPTCP_LIB_SUBTESTS_LAST_TS_MS}"
|
|
mptcp_lib_subtests_last_ts_reset
|
|
time+="$((MPTCP_LIB_SUBTESTS_LAST_TS_MS - ts_prev_ms))ms"
|
|
|
|
MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${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}" | sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q'
|
|
}
|
|
|
|
# $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]]
|
|
mptcp_lib_evts_get_info() {
|
|
grep "${4:-}" "${2}" | mptcp_lib_get_info_value "${1}" "^type:${3:-1},"
|
|
}
|
|
|
|
# $1: PID
|
|
mptcp_lib_kill_wait() {
|
|
[ "${1}" -eq 0 ] && return 0
|
|
|
|
kill -SIGUSR1 "${1}" > /dev/null 2>&1
|
|
kill "${1}" > /dev/null 2>&1
|
|
wait "${1}" 2>/dev/null
|
|
}
|
|
|
|
# $1: IP address
|
|
mptcp_lib_is_v6() {
|
|
[ -z "${1##*:*}" ]
|
|
}
|
|
|
|
# $1: ns, $2: MIB counter
|
|
mptcp_lib_get_counter() {
|
|
local ns="${1}"
|
|
local counter="${2}"
|
|
local count
|
|
|
|
count=$(ip netns exec "${ns}" nstat -asz "${counter}" |
|
|
awk 'NR==1 {next} {print $2}')
|
|
if [ -z "${count}" ]; then
|
|
mptcp_lib_fail_if_expected_feature "${counter} counter"
|
|
return 1
|
|
fi
|
|
|
|
echo "${count}"
|
|
}
|
|
|
|
mptcp_lib_make_file() {
|
|
local name="${1}"
|
|
local bs="${2}"
|
|
local size="${3}"
|
|
|
|
dd if=/dev/urandom of="${name}" bs="${bs}" count="${size}" 2> /dev/null
|
|
echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "${name}"
|
|
}
|
|
|
|
# $1: file
|
|
mptcp_lib_print_file_err() {
|
|
ls -l "${1}" 1>&2
|
|
echo "Trailing bytes are: "
|
|
tail -c 27 "${1}"
|
|
}
|
|
|
|
# $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
|
|
ip netns exec "${!netns}" sysctl -q net.ipv4.conf.all.rp_filter=0
|
|
ip netns exec "${!netns}" sysctl -q net.ipv4.conf.default.rp_filter=0
|
|
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}"
|
|
|
|
:>"${evts}"
|
|
|
|
mptcp_lib_kill_wait "${pid:-0}"
|
|
ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 &
|
|
pid=$!
|
|
}
|
|
|
|
mptcp_lib_print_title() {
|
|
: "${MPTCP_LIB_TEST_COUNTER:?}"
|
|
: "${MPTCP_LIB_TEST_FORMAT:?}"
|
|
|
|
# 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}")
|
|
|
|
mptcp_lib_check_expected "type" "family" "saddr" "sport" || rc="${?}"
|
|
return "${rc}"
|
|
}
|
|
|
|
mptcp_lib_set_ip_mptcp() {
|
|
MPTCP_LIB_IP_MPTCP=1
|
|
}
|
|
|
|
mptcp_lib_is_ip_mptcp() {
|
|
[ "${MPTCP_LIB_IP_MPTCP}" = "1" ]
|
|
}
|
|
|
|
# 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
|
|
}
|