mptcp_lib.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. #! /bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. . "$(dirname "${0}")/../lib.sh"
  4. . "$(dirname "${0}")/../net_helper.sh"
  5. readonly KSFT_PASS=0
  6. readonly KSFT_FAIL=1
  7. readonly KSFT_SKIP=4
  8. # shellcheck disable=SC2155 # declare and assign separately
  9. readonly KSFT_TEST="${MPTCP_LIB_KSFT_TEST:-$(basename "${0}" .sh)}"
  10. # These variables are used in some selftests, read-only
  11. declare -rx MPTCP_LIB_EVENT_CREATED=1 # MPTCP_EVENT_CREATED
  12. declare -rx MPTCP_LIB_EVENT_ESTABLISHED=2 # MPTCP_EVENT_ESTABLISHED
  13. declare -rx MPTCP_LIB_EVENT_CLOSED=3 # MPTCP_EVENT_CLOSED
  14. declare -rx MPTCP_LIB_EVENT_ANNOUNCED=6 # MPTCP_EVENT_ANNOUNCED
  15. declare -rx MPTCP_LIB_EVENT_REMOVED=7 # MPTCP_EVENT_REMOVED
  16. declare -rx MPTCP_LIB_EVENT_SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED
  17. declare -rx MPTCP_LIB_EVENT_SUB_CLOSED=11 # MPTCP_EVENT_SUB_CLOSED
  18. declare -rx MPTCP_LIB_EVENT_SUB_PRIORITY=13 # MPTCP_EVENT_SUB_PRIORITY
  19. declare -rx MPTCP_LIB_EVENT_LISTENER_CREATED=15 # MPTCP_EVENT_LISTENER_CREATED
  20. declare -rx MPTCP_LIB_EVENT_LISTENER_CLOSED=16 # MPTCP_EVENT_LISTENER_CLOSED
  21. declare -rx MPTCP_LIB_AF_INET=2
  22. declare -rx MPTCP_LIB_AF_INET6=10
  23. MPTCP_LIB_SUBTESTS=()
  24. MPTCP_LIB_SUBTESTS_DUPLICATED=0
  25. MPTCP_LIB_SUBTEST_FLAKY=0
  26. MPTCP_LIB_SUBTESTS_LAST_TS_MS=
  27. MPTCP_LIB_TEST_COUNTER=0
  28. MPTCP_LIB_TEST_FORMAT="%02u %-50s"
  29. MPTCP_LIB_IP_MPTCP=0
  30. # only if supported (or forced) and not disabled, see no-color.org
  31. if { [ -t 1 ] || [ "${SELFTESTS_MPTCP_LIB_COLOR_FORCE:-}" = "1" ]; } &&
  32. [ "${NO_COLOR:-}" != "1" ]; then
  33. readonly MPTCP_LIB_COLOR_RED="\E[1;31m"
  34. readonly MPTCP_LIB_COLOR_GREEN="\E[1;32m"
  35. readonly MPTCP_LIB_COLOR_YELLOW="\E[1;33m"
  36. readonly MPTCP_LIB_COLOR_BLUE="\E[1;34m"
  37. readonly MPTCP_LIB_COLOR_RESET="\E[0m"
  38. else
  39. readonly MPTCP_LIB_COLOR_RED=
  40. readonly MPTCP_LIB_COLOR_GREEN=
  41. readonly MPTCP_LIB_COLOR_YELLOW=
  42. readonly MPTCP_LIB_COLOR_BLUE=
  43. readonly MPTCP_LIB_COLOR_RESET=
  44. fi
  45. # SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY env var can be set not to ignore errors
  46. # from subtests marked as flaky
  47. mptcp_lib_override_flaky() {
  48. [ "${SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY:-}" = 1 ]
  49. }
  50. mptcp_lib_subtest_is_flaky() {
  51. [ "${MPTCP_LIB_SUBTEST_FLAKY}" = 1 ] && ! mptcp_lib_override_flaky
  52. }
  53. # $1: color, $2: text
  54. mptcp_lib_print_color() {
  55. echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}"
  56. }
  57. mptcp_lib_print_ok() {
  58. mptcp_lib_print_color "${MPTCP_LIB_COLOR_GREEN}${*}"
  59. }
  60. mptcp_lib_print_warn() {
  61. mptcp_lib_print_color "${MPTCP_LIB_COLOR_YELLOW}${*}"
  62. }
  63. mptcp_lib_print_info() {
  64. mptcp_lib_print_color "${MPTCP_LIB_COLOR_BLUE}${*}"
  65. }
  66. mptcp_lib_print_err() {
  67. mptcp_lib_print_color "${MPTCP_LIB_COLOR_RED}${*}"
  68. }
  69. # shellcheck disable=SC2120 # parameters are optional
  70. mptcp_lib_pr_ok() {
  71. mptcp_lib_print_ok "[ OK ]${1:+ ${*}}"
  72. }
  73. mptcp_lib_pr_skip() {
  74. mptcp_lib_print_warn "[SKIP]${1:+ ${*}}"
  75. }
  76. mptcp_lib_pr_fail() {
  77. local title cmt
  78. if mptcp_lib_subtest_is_flaky; then
  79. title="IGNO"
  80. cmt=" (flaky)"
  81. else
  82. title="FAIL"
  83. fi
  84. mptcp_lib_print_err "[${title}]${cmt}${1:+ ${*}}"
  85. }
  86. mptcp_lib_pr_info() {
  87. mptcp_lib_print_info "INFO: ${*}"
  88. }
  89. # SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all
  90. # features using the last version of the kernel and the selftests to make sure
  91. # a test is not being skipped by mistake.
  92. mptcp_lib_expect_all_features() {
  93. [ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ]
  94. }
  95. # $1: msg
  96. mptcp_lib_fail_if_expected_feature() {
  97. if mptcp_lib_expect_all_features; then
  98. echo "ERROR: missing feature: ${*}"
  99. exit ${KSFT_FAIL}
  100. fi
  101. return 1
  102. }
  103. # $1: file
  104. mptcp_lib_has_file() {
  105. local f="${1}"
  106. if [ -f "${f}" ]; then
  107. return 0
  108. fi
  109. mptcp_lib_fail_if_expected_feature "${f} file not found"
  110. }
  111. mptcp_lib_check_mptcp() {
  112. if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then
  113. mptcp_lib_pr_skip "MPTCP support is not available"
  114. exit ${KSFT_SKIP}
  115. fi
  116. }
  117. mptcp_lib_check_kallsyms() {
  118. if ! mptcp_lib_has_file "/proc/kallsyms"; then
  119. mptcp_lib_pr_skip "CONFIG_KALLSYMS is missing"
  120. exit ${KSFT_SKIP}
  121. fi
  122. }
  123. # Internal: use mptcp_lib_kallsyms_has() instead
  124. __mptcp_lib_kallsyms_has() {
  125. local sym="${1}"
  126. mptcp_lib_check_kallsyms
  127. grep -q " ${sym}" /proc/kallsyms
  128. }
  129. # $1: part of a symbol to look at, add '$' at the end for full name
  130. mptcp_lib_kallsyms_has() {
  131. local sym="${1}"
  132. if __mptcp_lib_kallsyms_has "${sym}"; then
  133. return 0
  134. fi
  135. mptcp_lib_fail_if_expected_feature "${sym} symbol not found"
  136. }
  137. # $1: part of a symbol to look at, add '$' at the end for full name
  138. mptcp_lib_kallsyms_doesnt_have() {
  139. local sym="${1}"
  140. if ! __mptcp_lib_kallsyms_has "${sym}"; then
  141. return 0
  142. fi
  143. mptcp_lib_fail_if_expected_feature "${sym} symbol has been found"
  144. }
  145. # !!!AVOID USING THIS!!!
  146. # Features might not land in the expected version and features can be backported
  147. #
  148. # $1: kernel version, e.g. 6.3
  149. mptcp_lib_kversion_ge() {
  150. local exp_maj="${1%.*}"
  151. local exp_min="${1#*.}"
  152. local v maj min
  153. # If the kernel has backported features, set this env var to 1:
  154. if [ "${SELFTESTS_MPTCP_LIB_NO_KVERSION_CHECK:-}" = "1" ]; then
  155. return 0
  156. fi
  157. v=$(uname -r | cut -d'.' -f1,2)
  158. maj=${v%.*}
  159. min=${v#*.}
  160. if [ "${maj}" -gt "${exp_maj}" ] ||
  161. { [ "${maj}" -eq "${exp_maj}" ] && [ "${min}" -ge "${exp_min}" ]; }; then
  162. return 0
  163. fi
  164. mptcp_lib_fail_if_expected_feature "kernel version ${1} lower than ${v}"
  165. }
  166. mptcp_lib_subtests_last_ts_reset() {
  167. MPTCP_LIB_SUBTESTS_LAST_TS_MS="$(date +%s%3N)"
  168. }
  169. mptcp_lib_subtests_last_ts_reset
  170. __mptcp_lib_result_check_duplicated() {
  171. local subtest
  172. for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do
  173. if [[ "${subtest}" == *" - ${KSFT_TEST}: ${*%% #*}" ]]; then
  174. MPTCP_LIB_SUBTESTS_DUPLICATED=1
  175. mptcp_lib_print_err "Duplicated entry: ${*}"
  176. break
  177. fi
  178. done
  179. }
  180. __mptcp_lib_result_add() {
  181. local result="${1}"
  182. local time="time="
  183. local ts_prev_ms
  184. shift
  185. local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1))
  186. __mptcp_lib_result_check_duplicated "${*}"
  187. # not to add two '#'
  188. [[ "${*}" != *"#"* ]] && time="# ${time}"
  189. ts_prev_ms="${MPTCP_LIB_SUBTESTS_LAST_TS_MS}"
  190. mptcp_lib_subtests_last_ts_reset
  191. time+="$((MPTCP_LIB_SUBTESTS_LAST_TS_MS - ts_prev_ms))ms"
  192. MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${time}")
  193. }
  194. # $1: test name
  195. mptcp_lib_result_pass() {
  196. __mptcp_lib_result_add "ok" "${1}"
  197. }
  198. # $1: test name
  199. mptcp_lib_result_fail() {
  200. if mptcp_lib_subtest_is_flaky; then
  201. # It might sound better to use 'not ok # TODO' or 'ok # SKIP',
  202. # but some CIs don't understand 'TODO' and treat SKIP as errors.
  203. __mptcp_lib_result_add "ok" "${1} # IGNORE Flaky"
  204. else
  205. __mptcp_lib_result_add "not ok" "${1}"
  206. fi
  207. }
  208. # $1: test name
  209. mptcp_lib_result_skip() {
  210. __mptcp_lib_result_add "ok" "${1} # SKIP"
  211. }
  212. # $1: result code ; $2: test name
  213. mptcp_lib_result_code() {
  214. local ret="${1}"
  215. local name="${2}"
  216. case "${ret}" in
  217. "${KSFT_PASS}")
  218. mptcp_lib_result_pass "${name}"
  219. ;;
  220. "${KSFT_FAIL}")
  221. mptcp_lib_result_fail "${name}"
  222. ;;
  223. "${KSFT_SKIP}")
  224. mptcp_lib_result_skip "${name}"
  225. ;;
  226. *)
  227. echo "ERROR: wrong result code: ${ret}"
  228. exit ${KSFT_FAIL}
  229. ;;
  230. esac
  231. }
  232. mptcp_lib_result_print_all_tap() {
  233. local subtest
  234. if [ ${#MPTCP_LIB_SUBTESTS[@]} -eq 0 ] ||
  235. [ "${SELFTESTS_MPTCP_LIB_NO_TAP:-}" = "1" ]; then
  236. return
  237. fi
  238. printf "\nTAP version 13\n"
  239. printf "1..%d\n" "${#MPTCP_LIB_SUBTESTS[@]}"
  240. for subtest in "${MPTCP_LIB_SUBTESTS[@]}"; do
  241. printf "%s\n" "${subtest}"
  242. done
  243. if [ "${MPTCP_LIB_SUBTESTS_DUPLICATED}" = 1 ] &&
  244. mptcp_lib_expect_all_features; then
  245. mptcp_lib_print_err "Duplicated test entries"
  246. exit ${KSFT_FAIL}
  247. fi
  248. }
  249. # get the value of keyword $1 in the line marked by keyword $2
  250. mptcp_lib_get_info_value() {
  251. grep "${2}" | sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q'
  252. }
  253. # $1: info name ; $2: evts_ns ; [$3: event type; [$4: addr]]
  254. mptcp_lib_evts_get_info() {
  255. grep "${4:-}" "${2}" | mptcp_lib_get_info_value "${1}" "^type:${3:-1},"
  256. }
  257. # $1: PID
  258. mptcp_lib_kill_wait() {
  259. [ "${1}" -eq 0 ] && return 0
  260. kill -SIGUSR1 "${1}" > /dev/null 2>&1
  261. kill "${1}" > /dev/null 2>&1
  262. wait "${1}" 2>/dev/null
  263. }
  264. # $1: IP address
  265. mptcp_lib_is_v6() {
  266. [ -z "${1##*:*}" ]
  267. }
  268. # $1: ns, $2: MIB counter
  269. mptcp_lib_get_counter() {
  270. local ns="${1}"
  271. local counter="${2}"
  272. local count
  273. count=$(ip netns exec "${ns}" nstat -asz "${counter}" |
  274. awk 'NR==1 {next} {print $2}')
  275. if [ -z "${count}" ]; then
  276. mptcp_lib_fail_if_expected_feature "${counter} counter"
  277. return 1
  278. fi
  279. echo "${count}"
  280. }
  281. mptcp_lib_make_file() {
  282. local name="${1}"
  283. local bs="${2}"
  284. local size="${3}"
  285. dd if=/dev/urandom of="${name}" bs="${bs}" count="${size}" 2> /dev/null
  286. echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "${name}"
  287. }
  288. # $1: file
  289. mptcp_lib_print_file_err() {
  290. ls -l "${1}" 1>&2
  291. echo "Trailing bytes are: "
  292. tail -c 27 "${1}"
  293. }
  294. # $1: input file ; $2: output file ; $3: what kind of file
  295. mptcp_lib_check_transfer() {
  296. local in="${1}"
  297. local out="${2}"
  298. local what="${3}"
  299. if ! cmp "$in" "$out" > /dev/null 2>&1; then
  300. mptcp_lib_pr_fail "$what does not match (in, out):"
  301. mptcp_lib_print_file_err "$in"
  302. mptcp_lib_print_file_err "$out"
  303. return 1
  304. fi
  305. return 0
  306. }
  307. # $1: ns, $2: port
  308. mptcp_lib_wait_local_port_listen() {
  309. wait_local_port_listen "${@}" "tcp"
  310. }
  311. mptcp_lib_check_output() {
  312. local err="${1}"
  313. local cmd="${2}"
  314. local expected="${3}"
  315. local cmd_ret=0
  316. local out
  317. if ! out=$(${cmd} 2>"${err}"); then
  318. cmd_ret=${?}
  319. fi
  320. if [ ${cmd_ret} -ne 0 ]; then
  321. mptcp_lib_pr_fail "command execution '${cmd}' stderr"
  322. cat "${err}"
  323. return 2
  324. elif [ "${out}" = "${expected}" ]; then
  325. return 0
  326. else
  327. mptcp_lib_pr_fail "expected '${expected}' got '${out}'"
  328. return 1
  329. fi
  330. }
  331. mptcp_lib_check_tools() {
  332. local tool
  333. for tool in "${@}"; do
  334. case "${tool}" in
  335. "ip")
  336. if ! ip -Version &> /dev/null; then
  337. mptcp_lib_pr_skip "Could not run test without ip tool"
  338. exit ${KSFT_SKIP}
  339. fi
  340. ;;
  341. "tc")
  342. if ! tc -help &> /dev/null; then
  343. mptcp_lib_pr_skip "Could not run test without tc tool"
  344. exit ${KSFT_SKIP}
  345. fi
  346. ;;
  347. "ss")
  348. if ! ss -h | grep -q MPTCP; then
  349. mptcp_lib_pr_skip "ss tool does not support MPTCP"
  350. exit ${KSFT_SKIP}
  351. fi
  352. ;;
  353. "iptables"* | "ip6tables"*)
  354. if ! "${tool}" -V &> /dev/null; then
  355. mptcp_lib_pr_skip "Could not run all tests without ${tool}"
  356. exit ${KSFT_SKIP}
  357. fi
  358. ;;
  359. *)
  360. mptcp_lib_pr_fail "Internal error: unsupported tool: ${tool}"
  361. exit ${KSFT_FAIL}
  362. ;;
  363. esac
  364. done
  365. }
  366. mptcp_lib_ns_init() {
  367. if ! setup_ns "${@}"; then
  368. mptcp_lib_pr_fail "Failed to setup namespaces ${*}"
  369. exit ${KSFT_FAIL}
  370. fi
  371. local netns
  372. for netns in "${@}"; do
  373. ip netns exec "${!netns}" sysctl -q net.mptcp.enabled=1
  374. ip netns exec "${!netns}" sysctl -q net.ipv4.conf.all.rp_filter=0
  375. ip netns exec "${!netns}" sysctl -q net.ipv4.conf.default.rp_filter=0
  376. done
  377. }
  378. mptcp_lib_ns_exit() {
  379. cleanup_ns "${@}"
  380. local netns
  381. for netns in "${@}"; do
  382. rm -f /tmp/"${netns}".{nstat,out}
  383. done
  384. }
  385. mptcp_lib_events() {
  386. local ns="${1}"
  387. local evts="${2}"
  388. declare -n pid="${3}"
  389. :>"${evts}"
  390. mptcp_lib_kill_wait "${pid:-0}"
  391. ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 &
  392. pid=$!
  393. }
  394. mptcp_lib_print_title() {
  395. : "${MPTCP_LIB_TEST_COUNTER:?}"
  396. : "${MPTCP_LIB_TEST_FORMAT:?}"
  397. # shellcheck disable=SC2059 # the format is in a variable
  398. printf "${MPTCP_LIB_TEST_FORMAT}" "$((++MPTCP_LIB_TEST_COUNTER))" "${*}"
  399. }
  400. # $1: var name ; $2: prev ret
  401. mptcp_lib_check_expected_one() {
  402. local var="${1}"
  403. local exp="e_${var}"
  404. local prev_ret="${2}"
  405. if [ "${!var}" = "${!exp}" ]; then
  406. return 0
  407. fi
  408. if [ "${prev_ret}" = "0" ]; then
  409. mptcp_lib_pr_fail
  410. fi
  411. mptcp_lib_print_err "Expected value for '${var}': '${!exp}', got '${!var}'."
  412. return 1
  413. }
  414. # $@: all var names to check
  415. mptcp_lib_check_expected() {
  416. local rc=0
  417. local var
  418. for var in "${@}"; do
  419. mptcp_lib_check_expected_one "${var}" "${rc}" || rc=1
  420. done
  421. return "${rc}"
  422. }
  423. # shellcheck disable=SC2034 # Some variables are used below but indirectly
  424. mptcp_lib_verify_listener_events() {
  425. local evt=${1}
  426. local e_type=${2}
  427. local e_family=${3}
  428. local e_saddr=${4}
  429. local e_sport=${5}
  430. local type
  431. local family
  432. local saddr
  433. local sport
  434. local rc=0
  435. type=$(mptcp_lib_evts_get_info type "${evt}" "${e_type}")
  436. family=$(mptcp_lib_evts_get_info family "${evt}" "${e_type}")
  437. if [ "${family}" ] && [ "${family}" = "${AF_INET6}" ]; then
  438. saddr=$(mptcp_lib_evts_get_info saddr6 "${evt}" "${e_type}")
  439. else
  440. saddr=$(mptcp_lib_evts_get_info saddr4 "${evt}" "${e_type}")
  441. fi
  442. sport=$(mptcp_lib_evts_get_info sport "${evt}" "${e_type}")
  443. mptcp_lib_check_expected "type" "family" "saddr" "sport" || rc="${?}"
  444. return "${rc}"
  445. }
  446. mptcp_lib_set_ip_mptcp() {
  447. MPTCP_LIB_IP_MPTCP=1
  448. }
  449. mptcp_lib_is_ip_mptcp() {
  450. [ "${MPTCP_LIB_IP_MPTCP}" = "1" ]
  451. }
  452. # format: <id>,<ip>,<flags>,<dev>
  453. mptcp_lib_pm_nl_format_endpoints() {
  454. local entry id ip flags dev port
  455. for entry in "${@}"; do
  456. IFS=, read -r id ip flags dev port <<< "${entry}"
  457. if mptcp_lib_is_ip_mptcp; then
  458. echo -n "${ip}"
  459. [ -n "${port}" ] && echo -n " port ${port}"
  460. echo -n " id ${id}"
  461. [ -n "${flags}" ] && echo -n " ${flags}"
  462. [ -n "${dev}" ] && echo -n " dev ${dev}"
  463. echo " " # always a space at the end
  464. else
  465. echo -n "id ${id}"
  466. echo -n " flags ${flags//" "/","}"
  467. [ -n "${dev}" ] && echo -n " dev ${dev}"
  468. echo -n " ${ip}"
  469. [ -n "${port}" ] && echo -n " ${port}"
  470. echo ""
  471. fi
  472. done
  473. }
  474. mptcp_lib_pm_nl_get_endpoint() {
  475. local ns=${1}
  476. local id=${2}
  477. if mptcp_lib_is_ip_mptcp; then
  478. ip -n "${ns}" mptcp endpoint show id "${id}"
  479. else
  480. ip netns exec "${ns}" ./pm_nl_ctl get "${id}"
  481. fi
  482. }
  483. mptcp_lib_pm_nl_set_limits() {
  484. local ns=${1}
  485. local addrs=${2}
  486. local subflows=${3}
  487. if mptcp_lib_is_ip_mptcp; then
  488. ip -n "${ns}" mptcp limits set add_addr_accepted "${addrs}" subflows "${subflows}"
  489. else
  490. ip netns exec "${ns}" ./pm_nl_ctl limits "${addrs}" "${subflows}"
  491. fi
  492. }
  493. mptcp_lib_pm_nl_add_endpoint() {
  494. local ns=${1}
  495. local addr=${2}
  496. local flags dev id port
  497. local nr=2
  498. local p
  499. for p in "${@}"; do
  500. case "${p}" in
  501. "flags" | "dev" | "id" | "port")
  502. eval "${p}"=\$"${nr}"
  503. ;;
  504. esac
  505. nr=$((nr + 1))
  506. done
  507. if mptcp_lib_is_ip_mptcp; then
  508. # shellcheck disable=SC2086 # blanks in flags, no double quote
  509. ip -n "${ns}" mptcp endpoint add "${addr}" ${flags//","/" "} \
  510. ${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"}
  511. else
  512. ip netns exec "${ns}" ./pm_nl_ctl add "${addr}" ${flags:+flags "${flags}"} \
  513. ${dev:+dev "${dev}"} ${id:+id "${id}"} ${port:+port "${port}"}
  514. fi
  515. }
  516. mptcp_lib_pm_nl_del_endpoint() {
  517. local ns=${1}
  518. local id=${2}
  519. local addr=${3}
  520. if mptcp_lib_is_ip_mptcp; then
  521. [ "${id}" -ne 0 ] && addr=''
  522. ip -n "${ns}" mptcp endpoint delete id "${id}" ${addr:+"${addr}"}
  523. else
  524. ip netns exec "${ns}" ./pm_nl_ctl del "${id}" "${addr}"
  525. fi
  526. }
  527. mptcp_lib_pm_nl_flush_endpoint() {
  528. local ns=${1}
  529. if mptcp_lib_is_ip_mptcp; then
  530. ip -n "${ns}" mptcp endpoint flush
  531. else
  532. ip netns exec "${ns}" ./pm_nl_ctl flush
  533. fi
  534. }
  535. mptcp_lib_pm_nl_show_endpoints() {
  536. local ns=${1}
  537. if mptcp_lib_is_ip_mptcp; then
  538. ip -n "${ns}" mptcp endpoint show
  539. else
  540. ip netns exec "${ns}" ./pm_nl_ctl dump
  541. fi
  542. }
  543. mptcp_lib_pm_nl_change_endpoint() {
  544. local ns=${1}
  545. local id=${2}
  546. local flags=${3}
  547. if mptcp_lib_is_ip_mptcp; then
  548. # shellcheck disable=SC2086 # blanks in flags, no double quote
  549. ip -n "${ns}" mptcp endpoint change id "${id}" ${flags//","/" "}
  550. else
  551. ip netns exec "${ns}" ./pm_nl_ctl set id "${id}" flags "${flags}"
  552. fi
  553. }