mptcp_lib.sh 17 KB

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