1#! /bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4. "$(dirname "${0}")/../lib.sh" 5 6readonly KSFT_PASS=0 7readonly KSFT_FAIL=1 8readonly KSFT_SKIP=4 9 10# shellcheck disable=SC2155 # declare and assign separately 11readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}" 12 13# These variables are used in some selftests, read-only 14declare -rx MPTCP_LIB_EVENT_CREATED=1 # MPTCP_EVENT_CREATED 15declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2 # MPTCP_EVENT_ESTABLISHED 16declare -rx MPTCP_LIB_EVENT_CLOSED=3 # MPTCP_EVENT_CLOSED 17declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED 18declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED 19declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED 20declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED 21declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13 # MPTCP_EVENT_SUB_PRIORITY 22declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED 23declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED 24 25declare -rx MPTCP_LIB_AF_INET=2 26declare -rx MPTCP_LIB_AF_INET6=10 27 28MPTCP_LIB_SUBTESTS=() 29MPTCP_LIB_SUBTESTS_DUPLICATED=0 30MPTCP_LIB_SUBTEST_FLAKY=0 31MPTCP_LIB_SUBTESTS_LAST_TS_NS= 32MPTCP_LIB_TEST_COUNTER=0 33MPTCP_LIB_TEST_FORMAT="%02u %-50s" 34MPTCP_LIB_IP_MPTCP=0 35 36# only if supported (or forced) and not disabled, see no-color.org 37if { [ -t 1 ] || [ "${SELFTESTS_MPTCP_LIB_COLOR_FORCE:-}" = "1" ]; } && 38 [ "${NO_COLOR:-}" != "1" ]; then 39 readonly MPTCP_LIB_COLOR_RED="\E[1;31m" 40 readonly MPTCP_LIB_COLOR_GREEN="\E[1;32m" 41 readonly MPTCP_LIB_COLOR_YELLOW="\E[1;33m" 42 readonly MPTCP_LIB_COLOR_BLUE="\E[1;34m" 43 readonly MPTCP_LIB_COLOR_RESET="\E[0m" 44else 45 readonly MPTCP_LIB_COLOR_RED= 46 readonly MPTCP_LIB_COLOR_GREEN= 47 readonly MPTCP_LIB_COLOR_YELLOW= 48 readonly MPTCP_LIB_COLOR_BLUE= 49 readonly MPTCP_LIB_COLOR_RESET= 50fi 51 52# SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY env var can be set not to ignore errors 53# from subtests marked as flaky 54mptcp_lib_override_flaky() { 55 [ "${SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY:-}" = 1 ] 56} 57 58mptcp_lib_subtest_is_flaky() { 59 [ "${MPTCP_LIB_SUBTEST_FLAKY}" = 1 ] && ! mptcp_lib_override_flaky 60} 61 62# $1: color, $2: text 63mptcp_lib_print_color() { 64 echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}" 65} 66 67mptcp_lib_print_ok() { 68 mptcp_lib_print_color "${MPTCP_LIB_COLOR_GREEN}${*}" 69} 70 71mptcp_lib_print_warn() { 72 mptcp_lib_print_color "${MPTCP_LIB_COLOR_YELLOW}${*}" 73} 74 75mptcp_lib_print_info() { 76 mptcp_lib_print_color "${MPTCP_LIB_COLOR_BLUE}${*}" 77} 78 79mptcp_lib_print_err() { 80 mptcp_lib_print_color "${MPTCP_LIB_COLOR_RED}${*}" 81} 82 83# shellcheck disable=SC2120 # parameters are optional 84mptcp_lib_pr_ok() { 85 mptcp_lib_print_ok "[ OK ]${1:+ ${*}}" 86} 87 88mptcp_lib_pr_skip() { 89 mptcp_lib_print_warn "[SKIP]${1:+ ${*}}" 90} 91 92mptcp_lib_pr_fail() { 93 local title cmt 94 95 if mptcp_lib_subtest_is_flaky; then 96 title="IGNO" 97 cmt=" (flaky)" 98 else 99 title="FAIL" 100 fi 101 102 mptcp_lib_print_err "[${title}]${cmt}${1:+ ${*}}" 103} 104 105mptcp_lib_pr_info() { 106 mptcp_lib_print_info "INFO: ${*}" 107} 108 109mptcp_lib_pr_nstat() { 110 local ns="${1}" 111 local cache="/tmp/${ns}.out" 112 local hist="/tmp/${ns}.nstat" 113 114 if [ -f "${cache}" ]; then 115 awk '$2 != 0 { print " "$0 }' "${cache}" 116 else 117 NSTAT_HISTORY="${hist}" ip netns exec "${ns}" nstat -s | 118 grep Tcp 119 fi 120} 121 122# $1-2: listener/connector ns ; $3 port 123mptcp_lib_pr_err_stats() { 124 local lns="${1}" 125 local cns="${2}" 126 local port="${3}" 127 128 echo -en "${MPTCP_LIB_COLOR_RED}" 129 { 130 printf "\nnetns %s (listener) socket stat for %d:\n" "${lns}" "${port}" 131 ip netns exec "${lns}" ss -Menitam -o "sport = :${port}" 132 mptcp_lib_pr_nstat "${lns}" 133 134 printf "\nnetns %s (connector) socket stat for %d:\n" "${cns}" "${port}" 135 ip netns exec "${cns}" ss -Menitam -o "dport = :${port}" 136 [ "${lns}" != "${cns}" ] && mptcp_lib_pr_nstat "${cns}" 137 } 1>&2 138 echo -en "${MPTCP_LIB_COLOR_RESET}" 139} 140 141# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all 142# features using the last version of the kernel and the selftests to make sure 143# a test is not being skipped by mistake. 144mptcp_lib_expect_all_features() { 145 [ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ] 146} 147 148# $1: msg 149mptcp_lib_fail_if_expected_feature() { 150 if mptcp_lib_expect_all_features; then 151 echo "ERROR: missing feature: ${*}" 152 exit ${KSFT_FAIL} 153 fi 154 155 return 1 156} 157 158# $1: file 159mptcp_lib_has_file() { 160 local f="${1}" 161 162 if [ -f "${f}" ]; then 163 return 0 164 fi 165 166 mptcp_lib_fail_if_expected_feature "${f} file not found" 167} 168 169mptcp_lib_check_mptcp() { 170 if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then 171 mptcp_lib_pr_skip "MPTCP support is not available" 172 exit ${KSFT_SKIP} 173 fi 174} 175 176mptcp_lib_check_kallsyms() { 177 if ! mptcp_lib_has_file "/proc/kallsyms"; then 178 mptcp_lib_pr_skip "CONFIG_KALLSYMS is missing" 179 exit ${KSFT_SKIP} 180 fi 181} 182 183# Internal: use mptcp_lib_kallsyms_has() instead 184__mptcp_lib_kallsyms_has() { 185 local sym="${1}" 186 187 mptcp_lib_check_kallsyms 188 189 grep -q " ${sym}" /proc/kallsyms 190} 191 192# $1: part of a symbol to look at, add '$' at the end for full name 193mptcp_lib_kallsyms_has() { 194 local sym="${1}" 195 196 if __mptcp_lib_kallsyms_has "${sym}"; then 197 return 0 198 fi 199 200 mptcp_lib_fail_if_expected_feature "${sym} symbol not found" 201} 202 203# $1: part of a symbol to look at, add '$' at the end for full name 204mptcp_lib_kallsyms_doesnt_have() { 205 local sym="${1}" 206 207 if ! __mptcp_lib_kallsyms_has "${sym}"; then 208 return 0 209 fi 210 211 mptcp_lib_fail_if_expected_feature "${sym} symbol has been found" 212} 213 214# !!!AVOID USING THIS!!! 215# Features might not land in the expected version and features can be backported 216# 217# $1: kernel version, e.g. 6.3 218mptcp_lib_kversion_ge() { 219 local exp_maj="${1%.*}" 220 local exp_min="${1#*.}" 221 local v maj min 222 223 # If the kernel has backported features, set this env var to 1: 224 if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then 225 return 0 226 fi 227 228 v=$(uname -r | cut -d'.' -f1,2) 229 maj=${v%.*} 230 min=${v#*.} 231 232 if [ "${maj}" -gt "${exp_maj}" ] || 233 { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then 234 return 0 235 fi 236 237 mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}" 238} 239 240mptcp_lib_subtests_last_ts_reset() { 241 MPTCP_LIB_SUBTESTS_LAST_TS_NS="$(date +%s%N)" 242} 243mptcp_lib_subtests_last_ts_reset 244 245__mptcp_lib_result_check_duplicated() { 246 local subtest 247 248 for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do 249 if [[ "${subtest}" == *" - ${KSFT_TEST}: ${*%% #*}" ]]; then 250 MPTCP_LIB_SUBTESTS_DUPLICATED=1 251 mptcp_lib_print_err "Duplicated entry: ${*}" 252 break 253 fi 254 done 255} 256 257__mptcp_lib_result_add() { 258 local result="${1}" 259 local time="time=" 260 local ts_prev_ns 261 shift 262 263 local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1)) 264 265 __mptcp_lib_result_check_duplicated "${*}" 266 267 # not to add two '#' 268 [[ "${*}" != *"#"* ]] && time="# ${time}" 269 270 ts_prev_ns="${MPTCP_LIB_SUBTESTS_LAST_TS_NS}" 271 mptcp_lib_subtests_last_ts_reset 272 time+="$(((MPTCP_LIB_SUBTESTS_LAST_TS_NS - ts_prev_ns) / 1000000))ms" 273 274 MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${time}") 275} 276 277# $1: test name 278mptcp_lib_result_pass() { 279 __mptcp_lib_result_add "ok" "${1}" 280} 281 282# $1: test name 283mptcp_lib_result_fail() { 284 if mptcp_lib_subtest_is_flaky; then 285 # It might sound better to use 'not ok # TODO' or 'ok # SKIP', 286 # but some CIs don't understand 'TODO' and treat SKIP as errors. 287 __mptcp_lib_result_add "ok" "${1} # IGNORE Flaky" 288 else 289 __mptcp_lib_result_add "not ok" "${1}" 290 fi 291} 292 293# $1: test name 294mptcp_lib_result_skip() { 295 __mptcp_lib_result_add "ok" "${1} # SKIP" 296} 297 298# $1: result code ; $2: test name 299mptcp_lib_result_code() { 300 local ret="${1}" 301 local name="${2}" 302 303 case "${ret}" in 304 "${KSFT_PASS}") 305 mptcp_lib_result_pass "${name}" 306 ;; 307 "${KSFT_FAIL}") 308 mptcp_lib_result_fail "${name}" 309 ;; 310 "${KSFT_SKIP}") 311 mptcp_lib_result_skip "${name}" 312 ;; 313 *) 314 echo "ERROR: wrong result code: ${ret}" 315 exit ${KSFT_FAIL} 316 ;; 317 esac 318} 319 320mptcp_lib_result_print_all_tap() { 321 local subtest 322 323 if [ ${#MPTCP_LIB_SUBTESTS[@]} -eq 0 ] || 324 [ "${SELFTESTS_MPTCP_LIB_NO_TAP:-}" = "1" ]; then 325 return 326 fi 327 328 printf "\nTAP version 13\n" 329 printf "1..%d\n" "${#MPTCP_LIB_SUBTESTS[@]}" 330 331 for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do 332 printf "%s\n" "${subtest}" 333 done 334 335 if [ "${MPTCP_LIB_SUBTESTS_DUPLICATED}" = 1 ] && 336 mptcp_lib_expect_all_features; then 337 mptcp_lib_print_err "Duplicated test entries" 338 exit ${KSFT_FAIL} 339 fi 340} 341 342# get the value of keyword $1 in the line marked by keyword $2 343mptcp_lib_get_info_value() { 344 grep "${2}" 2>/dev/null | 345 sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q' 346 # the ';q' at the end limits to the first matched entry. 347} 348 349# $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]] 350mptcp_lib_evts_get_info() { 351 grep "${4:-}" "${2}" 2>/dev/null | 352 mptcp_lib_get_info_value "${1}" "^type:${3:-1}," 353} 354 355mptcp_lib_wait_timeout() { 356 local timeout_test="${1}" 357 local listener_ns="${2}" 358 local connector_ns="${3}" 359 local port="${4}" 360 shift 4 # rest are PIDs 361 362 sleep "${timeout_test}" 363 mptcp_lib_print_err "timeout" 364 mptcp_lib_pr_err_stats "${listener_ns}" "${connector_ns}" "${port}" 365 kill "${@}" 2>/dev/null 366} 367 368# $1: PID 369mptcp_lib_kill_wait() { 370 [ "${1}" -eq 0 ] && return 0 371 372 kill -SIGUSR1 "${1}" > /dev/null 2>&1 373 kill "${1}" > /dev/null 2>&1 374 wait "${1}" 2>/dev/null 375} 376 377# $1: PID 378mptcp_lib_pid_list_children() { 379 local curr="${1}" 380 # evoke 'ps' only once 381 local pids="${2:-"$(ps o pid,ppid)"}" 382 383 echo "${curr}" 384 385 local pid 386 for pid in $(echo "${pids}" | awk "\$2 == ${curr} { print \$1 }"); do 387 mptcp_lib_pid_list_children "${pid}" "${pids}" 388 done 389} 390 391# $1: PID 392mptcp_lib_kill_group_wait() { 393 # Some users might not have procps-ng: cannot use "kill -- -PID" 394 mptcp_lib_pid_list_children "${1}" | xargs -r kill &>/dev/null 395 wait "${1}" 2>/dev/null 396} 397 398# $1: IP address 399mptcp_lib_is_v6() { 400 [ -z "${1##*:*}" ] 401} 402 403mptcp_lib_nstat_init() { 404 local ns="${1}" 405 406 rm -f "/tmp/${ns}."{nstat,out} 407 NSTAT_HISTORY="/tmp/${ns}.nstat" ip netns exec "${ns}" nstat -n 408} 409 410mptcp_lib_nstat_get() { 411 local ns="${1}" 412 413 # filter out non-*TCP stats, and the rate (last column) 414 NSTAT_HISTORY="/tmp/${ns}.nstat" ip netns exec "${ns}" nstat -sz | 415 grep -o ".*Tcp\S\+\s\+[0-9]\+" > "/tmp/${ns}.out" 416} 417 418# $1: ns, $2: MIB counter 419# Get the counter from the cache (mptcp_lib_nstat_{init,get}()) if available. 420# If not, get the counter from nstat ignoring any cache, but using the history. 421mptcp_lib_get_counter() { 422 local ns="${1}" 423 local counter="${2}" 424 local cache="/tmp/${ns}.out" 425 local hist="/tmp/${ns}.nstat" 426 local count 427 428 if [[ -s "${cache}" && "${counter}" == *"Tcp"* ]]; then 429 count=$(awk "/^${counter} / {print \$2; exit}" "${cache}") 430 else 431 count=$(NSTAT_HISTORY="${hist}" ip netns exec "${ns}" \ 432 nstat -sz "${counter}" | 433 awk 'NR==1 {next} {print $2}') 434 fi 435 if [ -z "${count}" ]; then 436 mptcp_lib_fail_if_expected_feature "${counter} counter" 437 return 1 438 fi 439 440 echo "${count}" 441} 442 443mptcp_lib_make_file() { 444 local name="${1}" 445 local bs="${2}" 446 local size="${3}" 447 448 dd if=/dev/urandom of="${name}" bs="${bs}" count="${size}" 2> /dev/null 449 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "${name}" 450} 451 452# $1: file 453mptcp_lib_print_file_err() { 454 ls -l "${1}" 1>&2 455 echo "Trailing bytes are: " 456 tail -c 32 "${1}" | od -x | head -n2 457} 458 459# $1: input file ; $2: output file ; $3: what kind of file 460mptcp_lib_check_transfer() { 461 local in="${1}" 462 local out="${2}" 463 local what="${3}" 464 465 if ! cmp "$in" "$out" > /dev/null 2>&1; then 466 mptcp_lib_pr_fail "$what does not match (in, out):" 467 mptcp_lib_print_file_err "$in" 468 mptcp_lib_print_file_err "$out" 469 470 return 1 471 fi 472 473 return 0 474} 475 476# $1: ns, $2: port 477mptcp_lib_wait_local_port_listen() { 478 wait_local_port_listen "${@}" "tcp" 479} 480 481# $1: error file, $2: cmd, $3: expected msg, [$4: expected error] 482mptcp_lib_check_output() { 483 local err="${1}" 484 local cmd="${2}" 485 local expected="${3}" 486 local exp_error="${4:-0}" 487 local cmd_ret=0 488 local out 489 490 out=$(${cmd} 2>"${err}") || cmd_ret=1 491 492 if [ "${cmd_ret}" != "${exp_error}" ]; then 493 mptcp_lib_pr_fail "unexpected returned code for '${cmd}', info:" 494 if [ "${exp_error}" = 0 ]; then 495 cat "${err}" 496 else 497 echo "${out}" 498 fi 499 return 2 500 elif [ "${out}" = "${expected}" ]; then 501 return 0 502 else 503 mptcp_lib_pr_fail "expected '${expected}' got '${out}'" 504 return 1 505 fi 506} 507 508mptcp_lib_check_tools() { 509 local tool 510 511 for tool in "${@}"; do 512 case "${tool}" in 513 "ip") 514 if ! ip -Version &> /dev/null; then 515 mptcp_lib_pr_skip "Could not run test without ip tool" 516 exit ${KSFT_SKIP} 517 fi 518 ;; 519 "tc") 520 if ! tc -help &> /dev/null; then 521 mptcp_lib_pr_skip "Could not run test without tc tool" 522 exit ${KSFT_SKIP} 523 fi 524 ;; 525 "ss") 526 if ! ss -h | grep -q MPTCP; then 527 mptcp_lib_pr_skip "ss tool does not support MPTCP" 528 exit ${KSFT_SKIP} 529 fi 530 ;; 531 "iptables"* | "ip6tables"*) 532 if ! "${tool}" -V &> /dev/null; then 533 mptcp_lib_pr_skip "Could not run all tests without ${tool}" 534 exit ${KSFT_SKIP} 535 fi 536 ;; 537 *) 538 mptcp_lib_pr_fail "Internal error: unsupported tool: ${tool}" 539 exit ${KSFT_FAIL} 540 ;; 541 esac 542 done 543} 544 545mptcp_lib_ns_init() { 546 if ! setup_ns "${@}"; then 547 mptcp_lib_pr_fail "Failed to setup namespaces ${*}" 548 exit ${KSFT_FAIL} 549 fi 550 551 local netns 552 for netns in "${@}"; do 553 ip netns exec "${!netns}" sysctl -q net.mptcp.enabled=1 554 done 555} 556 557mptcp_lib_ns_exit() { 558 cleanup_ns "${@}" 559 560 local netns 561 for netns in "${@}"; do 562 rm -f /tmp/"${netns}".{nstat,out} 563 done 564} 565 566mptcp_lib_events() { 567 local ns="${1}" 568 local evts="${2}" 569 declare -n pid="${3}" 570 571 :>"${evts}" 572 573 mptcp_lib_kill_wait "${pid:-0}" 574 ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 & 575 pid=$! 576} 577 578mptcp_lib_print_title() { 579 : "${MPTCP_LIB_TEST_COUNTER:?}" 580 : "${MPTCP_LIB_TEST_FORMAT:?}" 581 582 # shellcheck disable=SC2059 # the format is in a variable 583 printf "${MPTCP_LIB_TEST_FORMAT}" "$((++MPTCP_LIB_TEST_COUNTER))" "${*}" 584} 585 586# $1: var name ; $2: prev ret 587mptcp_lib_check_expected_one() { 588 local var="${1}" 589 local exp="e_${var}" 590 local prev_ret="${2}" 591 592 if [ "${!var}" = "${!exp}" ]; then 593 return 0 594 fi 595 596 if [ "${prev_ret}" = "0" ]; then 597 mptcp_lib_pr_fail 598 fi 599 600 mptcp_lib_print_err "Expected value for '${var}': '${!exp}', got '${!var}'." 601 return 1 602} 603 604# $@: all var names to check 605mptcp_lib_check_expected() { 606 local rc=0 607 local var 608 609 for var in "${@}"; do 610 mptcp_lib_check_expected_one "${var}" "${rc}" || rc=1 611 done 612 613 return "${rc}" 614} 615 616# shellcheck disable=SC2034 # Some variables are used below but indirectly 617mptcp_lib_verify_listener_events() { 618 local evt=${1} 619 local e_type=${2} 620 local e_family=${3} 621 local e_saddr=${4} 622 local e_sport=${5} 623 local type 624 local family 625 local saddr 626 local sport 627 local rc=0 628 629 type=$(mptcp_lib_evts_get_info type "${evt}" "${e_type}") 630 family=$(mptcp_lib_evts_get_info family "${evt}" "${e_type}") 631 if [ "${family}" ] && [ "${family}" = "${AF_INET6}" ]; then 632 saddr=$(mptcp_lib_evts_get_info saddr6 "${evt}" "${e_type}") 633 else 634 saddr=$(mptcp_lib_evts_get_info saddr4 "${evt}" "${e_type}") 635 fi 636 sport=$(mptcp_lib_evts_get_info sport "${evt}" "${e_type}") 637 638 mptcp_lib_check_expected "type" "family" "saddr" "sport" || rc="${?}" 639 return "${rc}" 640} 641 642mptcp_lib_set_ip_mptcp() { 643 MPTCP_LIB_IP_MPTCP=1 644} 645 646mptcp_lib_is_ip_mptcp() { 647 [ "${MPTCP_LIB_IP_MPTCP}" = "1" ] 648} 649 650# format: <id>,<ip>,<flags>,<dev> 651mptcp_lib_pm_nl_format_endpoints() { 652 local entry id ip flags dev port 653 654 for entry in "${@}"; do 655 IFS=, read -r id ip flags dev port <<< "${entry}" 656 if mptcp_lib_is_ip_mptcp; then 657 echo -n "${ip}" 658 [ -n "${port}" ] && echo -n " port ${port}" 659 echo -n " id ${id}" 660 [ -n "${flags}" ] && echo -n " ${flags}" 661 [ -n "${dev}" ] && echo -n " dev ${dev}" 662 echo " " # always a space at the end 663 else 664 echo -n "id ${id}" 665 echo -n " flags ${flags//" "/","}" 666 [ -n "${dev}" ] && echo -n " dev ${dev}" 667 echo -n " ${ip}" 668 [ -n "${port}" ] && echo -n " ${port}" 669 echo "" 670 fi 671 done 672} 673 674mptcp_lib_pm_nl_get_endpoint() { 675 local ns=${1} 676 local id=${2} 677 678 if mptcp_lib_is_ip_mptcp; then 679 ip -n "${ns}" mptcp endpoint show id "${id}" 680 else 681 ip netns exec "${ns}" ./pm_nl_ctl get "${id}" 682 fi 683} 684 685mptcp_lib_pm_nl_set_limits() { 686 local ns=${1} 687 local addrs=${2} 688 local subflows=${3} 689 690 if mptcp_lib_is_ip_mptcp; then 691 ip -n "${ns}" mptcp limits set add_addr_accepted "${addrs}" subflows "${subflows}" 692 else 693 ip netns exec "${ns}" ./pm_nl_ctl limits "${addrs}" "${subflows}" 694 fi 695} 696 697mptcp_lib_pm_nl_add_endpoint() { 698 local ns=${1} 699 local addr=${2} 700 local flags dev id port 701 local nr=2 702 703 local p 704 for p in "${@}"; do 705 case "${p}" in 706 "flags" | "dev" | "id" | "port") 707 eval "${p}"=\$"${nr}" 708 ;; 709 esac 710 711 nr=$((nr + 1)) 712 done 713 714 if mptcp_lib_is_ip_mptcp; then 715 # shellcheck disable=SC2086 # blanks in flags, no double quote 716 ip -n "${ns}" mptcp endpoint add "${addr}" ${flags//","/" "} \ 717 ${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"} 718 else 719 ip netns exec "${ns}" ./pm_nl_ctl add "${addr}" ${flags:+flags "${flags}"} \ 720 ${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"} 721 fi 722} 723 724mptcp_lib_pm_nl_del_endpoint() { 725 local ns=${1} 726 local id=${2} 727 local addr=${3} 728 729 if mptcp_lib_is_ip_mptcp; then 730 [ "${id}" -ne 0 ] && addr='' 731 ip -n "${ns}" mptcp endpoint delete id "${id}" ${addr:+"${addr}"} 732 else 733 ip netns exec "${ns}" ./pm_nl_ctl del "${id}" "${addr}" 734 fi 735} 736 737mptcp_lib_pm_nl_flush_endpoint() { 738 local ns=${1} 739 740 if mptcp_lib_is_ip_mptcp; then 741 ip -n "${ns}" mptcp endpoint flush 742 else 743 ip netns exec "${ns}" ./pm_nl_ctl flush 744 fi 745} 746 747mptcp_lib_pm_nl_show_endpoints() { 748 local ns=${1} 749 750 if mptcp_lib_is_ip_mptcp; then 751 ip -n "${ns}" mptcp endpoint show 752 else 753 ip netns exec "${ns}" ./pm_nl_ctl dump 754 fi 755} 756 757mptcp_lib_pm_nl_change_endpoint() { 758 local ns=${1} 759 local id=${2} 760 local flags=${3} 761 762 if mptcp_lib_is_ip_mptcp; then 763 # shellcheck disable=SC2086 # blanks in flags, no double quote 764 ip -n "${ns}" mptcp endpoint change id "${id}" ${flags//","/" "} 765 else 766 ip netns exec "${ns}" ./pm_nl_ctl set id "${id}" flags "${flags}" 767 fi 768} 769