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