fib-onlink-tests.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # IPv4 and IPv6 onlink tests
  4. source lib.sh
  5. PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
  6. VERBOSE=0
  7. # Network interfaces
  8. # - odd in current namespace; even in peer ns
  9. declare -A NETIFS
  10. # default VRF
  11. NETIFS[p1]=veth1
  12. NETIFS[p2]=veth2
  13. NETIFS[p3]=veth3
  14. NETIFS[p4]=veth4
  15. # VRF
  16. NETIFS[p5]=veth5
  17. NETIFS[p6]=veth6
  18. NETIFS[p7]=veth7
  19. NETIFS[p8]=veth8
  20. # /24 network
  21. declare -A V4ADDRS
  22. V4ADDRS[p1]=169.254.1.1
  23. V4ADDRS[p2]=169.254.1.2
  24. V4ADDRS[p3]=169.254.3.1
  25. V4ADDRS[p4]=169.254.3.2
  26. V4ADDRS[p5]=169.254.5.1
  27. V4ADDRS[p6]=169.254.5.2
  28. V4ADDRS[p7]=169.254.7.1
  29. V4ADDRS[p8]=169.254.7.2
  30. # /64 network
  31. declare -A V6ADDRS
  32. V6ADDRS[p1]=2001:db8:101::1
  33. V6ADDRS[p2]=2001:db8:101::2
  34. V6ADDRS[p3]=2001:db8:301::1
  35. V6ADDRS[p4]=2001:db8:301::2
  36. V6ADDRS[p5]=2001:db8:501::1
  37. V6ADDRS[p6]=2001:db8:501::2
  38. V6ADDRS[p7]=2001:db8:701::1
  39. V6ADDRS[p8]=2001:db8:701::2
  40. # Test networks:
  41. # [1] = default table
  42. # [2] = VRF
  43. #
  44. # /32 host routes
  45. declare -A TEST_NET4
  46. TEST_NET4[1]=169.254.101
  47. TEST_NET4[2]=169.254.102
  48. # /128 host routes
  49. declare -A TEST_NET6
  50. TEST_NET6[1]=2001:db8:101
  51. TEST_NET6[2]=2001:db8:102
  52. # connected gateway
  53. CONGW[1]=169.254.1.254
  54. CONGW[2]=169.254.3.254
  55. CONGW[3]=169.254.5.254
  56. # recursive gateway
  57. RECGW4[1]=169.254.11.254
  58. RECGW4[2]=169.254.12.254
  59. RECGW6[1]=2001:db8:11::64
  60. RECGW6[2]=2001:db8:12::64
  61. # for v4 mapped to v6
  62. declare -A TEST_NET4IN6IN6
  63. TEST_NET4IN6[1]=10.1.1.254
  64. TEST_NET4IN6[2]=10.2.1.254
  65. # mcast addresses
  66. MCAST4=233.252.0.1
  67. MCAST6=ff02::1
  68. VRF=lisa
  69. VRF_TABLE=1101
  70. PBR_TABLE=101
  71. ################################################################################
  72. # utilities
  73. log_test()
  74. {
  75. local rc=$1
  76. local expected=$2
  77. local msg="$3"
  78. if [ ${rc} -eq ${expected} ]; then
  79. nsuccess=$((nsuccess+1))
  80. printf " TEST: %-50s [ OK ]\n" "${msg}"
  81. else
  82. nfail=$((nfail+1))
  83. printf " TEST: %-50s [FAIL]\n" "${msg}"
  84. if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
  85. echo
  86. echo "hit enter to continue, 'q' to quit"
  87. read a
  88. [ "$a" = "q" ] && exit 1
  89. fi
  90. fi
  91. }
  92. log_section()
  93. {
  94. echo
  95. echo "######################################################################"
  96. echo "TEST SECTION: $*"
  97. echo "######################################################################"
  98. }
  99. log_subsection()
  100. {
  101. echo
  102. echo "#########################################"
  103. echo "TEST SUBSECTION: $*"
  104. }
  105. run_cmd()
  106. {
  107. local cmd="$1"
  108. local out
  109. local rc
  110. if [ "$VERBOSE" = "1" ]; then
  111. printf " COMMAND: $cmd\n"
  112. fi
  113. out=$(eval $cmd 2>&1)
  114. rc=$?
  115. if [ "$VERBOSE" = "1" -a -n "$out" ]; then
  116. echo " $out"
  117. fi
  118. [ "$VERBOSE" = "1" ] && echo
  119. return $rc
  120. }
  121. get_linklocal()
  122. {
  123. local dev=$1
  124. local pfx
  125. local addr
  126. addr=$(${pfx} ${IP} -6 -br addr show dev ${dev} | \
  127. awk '{
  128. for (i = 3; i <= NF; ++i) {
  129. if ($i ~ /^fe80/)
  130. print $i
  131. }
  132. }'
  133. )
  134. addr=${addr/\/*}
  135. [ -z "$addr" ] && return 1
  136. echo $addr
  137. return 0
  138. }
  139. ################################################################################
  140. #
  141. setup()
  142. {
  143. echo
  144. echo "########################################"
  145. echo "Configuring interfaces"
  146. set -e
  147. # create namespaces
  148. setup_ns ns1
  149. IP="ip -netns $ns1"
  150. setup_ns ns2
  151. # add vrf table
  152. ${IP} li add ${VRF} type vrf table ${VRF_TABLE}
  153. ${IP} li set ${VRF} up
  154. ${IP} ro add table ${VRF_TABLE} unreachable default metric 8192
  155. ${IP} -6 ro add table ${VRF_TABLE} unreachable default metric 8192
  156. # create test interfaces
  157. ${IP} li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
  158. ${IP} li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
  159. ${IP} li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
  160. ${IP} li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
  161. # enslave vrf interfaces
  162. for n in 5 7; do
  163. ${IP} li set ${NETIFS[p${n}]} vrf ${VRF}
  164. done
  165. # add addresses
  166. for n in 1 3 5 7; do
  167. ${IP} li set ${NETIFS[p${n}]} up
  168. ${IP} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
  169. ${IP} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
  170. done
  171. # move peer interfaces to namespace and add addresses
  172. for n in 2 4 6 8; do
  173. ${IP} li set ${NETIFS[p${n}]} netns ${ns2} up
  174. ip -netns $ns2 addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
  175. ip -netns $ns2 addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
  176. done
  177. ${IP} -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
  178. ${IP} -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
  179. set +e
  180. }
  181. ################################################################################
  182. # IPv4 tests
  183. #
  184. run_ip()
  185. {
  186. local table="$1"
  187. local prefix="$2"
  188. local gw="$3"
  189. local dev="$4"
  190. local exp_rc="$5"
  191. local desc="$6"
  192. # dev arg may be empty
  193. [ -n "${dev}" ] && dev="dev ${dev}"
  194. run_cmd "${IP} ro add table ${table} ${prefix}/32 via ${gw} ${dev} onlink"
  195. log_test $? ${exp_rc} "${desc}"
  196. }
  197. run_ip_mpath()
  198. {
  199. local table="$1"
  200. local prefix="$2"
  201. local nh1="$3"
  202. local nh2="$4"
  203. local exp_rc="$5"
  204. local desc="$6"
  205. # dev arg may be empty
  206. [ -n "${dev}" ] && dev="dev ${dev}"
  207. run_cmd "${IP} ro add table ${table} ${prefix}/32 \
  208. nexthop via ${nh1} nexthop via ${nh2}"
  209. log_test $? ${exp_rc} "${desc}"
  210. }
  211. valid_onlink_ipv4()
  212. {
  213. # - unicast connected, unicast recursive
  214. #
  215. log_subsection "default VRF - main table"
  216. run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
  217. run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
  218. run_ip 254 ${TEST_NET4[1]}.9 ${CONGW[1]} ${NETIFS[p3]} 0 \
  219. "nexthop device mismatch"
  220. log_subsection "VRF ${VRF}"
  221. run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
  222. run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
  223. run_ip ${VRF_TABLE} ${TEST_NET4[2]}.10 ${CONGW[3]} ${NETIFS[p7]} 0 \
  224. "nexthop device mismatch"
  225. log_subsection "VRF device, PBR table"
  226. run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
  227. run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
  228. # multipath version
  229. #
  230. log_subsection "default VRF - main table - multipath"
  231. run_ip_mpath 254 ${TEST_NET4[1]}.5 \
  232. "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
  233. "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
  234. 0 "unicast connected - multipath"
  235. run_ip_mpath 254 ${TEST_NET4[1]}.6 \
  236. "${RECGW4[1]} dev ${NETIFS[p1]} onlink" \
  237. "${RECGW4[2]} dev ${NETIFS[p3]} onlink" \
  238. 0 "unicast recursive - multipath"
  239. run_ip_mpath 254 ${TEST_NET4[1]}.7 \
  240. "${CONGW[1]} dev ${NETIFS[p1]}" \
  241. "${CONGW[2]} dev ${NETIFS[p3]} onlink" \
  242. 0 "unicast connected - multipath onlink first only"
  243. run_ip_mpath 254 ${TEST_NET4[1]}.8 \
  244. "${CONGW[1]} dev ${NETIFS[p1]} onlink" \
  245. "${CONGW[2]} dev ${NETIFS[p3]}" \
  246. 0 "unicast connected - multipath onlink second only"
  247. }
  248. invalid_onlink_ipv4()
  249. {
  250. run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
  251. "Invalid gw - local unicast address"
  252. run_ip 254 ${TEST_NET4[1]}.12 ${MCAST4} ${NETIFS[p1]} 2 \
  253. "Invalid gw - multicast address"
  254. run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
  255. "Invalid gw - local unicast address, VRF"
  256. run_ip ${VRF_TABLE} ${TEST_NET4[2]}.12 ${MCAST4} ${NETIFS[p5]} 2 \
  257. "Invalid gw - multicast address, VRF"
  258. run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
  259. }
  260. ################################################################################
  261. # IPv6 tests
  262. #
  263. run_ip6()
  264. {
  265. local table="$1"
  266. local prefix="$2"
  267. local gw="$3"
  268. local dev="$4"
  269. local exp_rc="$5"
  270. local desc="$6"
  271. # dev arg may be empty
  272. [ -n "${dev}" ] && dev="dev ${dev}"
  273. run_cmd "${IP} -6 ro add table ${table} ${prefix}/128 via ${gw} ${dev} onlink"
  274. log_test $? ${exp_rc} "${desc}"
  275. }
  276. run_ip6_mpath()
  277. {
  278. local table="$1"
  279. local prefix="$2"
  280. local opts="$3"
  281. local nh1="$4"
  282. local nh2="$5"
  283. local exp_rc="$6"
  284. local desc="$7"
  285. run_cmd "${IP} -6 ro add table ${table} ${prefix}/128 ${opts} \
  286. nexthop via ${nh1} nexthop via ${nh2}"
  287. log_test $? ${exp_rc} "${desc}"
  288. }
  289. valid_onlink_ipv6()
  290. {
  291. # - unicast connected, unicast recursive, v4-mapped
  292. #
  293. log_subsection "default VRF - main table"
  294. run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
  295. run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
  296. run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
  297. run_ip6 254 ${TEST_NET6[1]}::a ${V6ADDRS[p1]/::*}::64 ${NETIFS[p3]} 0 \
  298. "nexthop device mismatch"
  299. log_subsection "VRF ${VRF}"
  300. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
  301. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
  302. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
  303. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::b ${V6ADDRS[p5]/::*}::64 \
  304. ${NETIFS[p7]} 0 "nexthop device mismatch"
  305. log_subsection "VRF device, PBR table"
  306. run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
  307. run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
  308. run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
  309. # multipath version
  310. #
  311. log_subsection "default VRF - main table - multipath"
  312. run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \
  313. "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
  314. "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
  315. 0 "unicast connected - multipath onlink"
  316. run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \
  317. "${RECGW6[1]} dev ${NETIFS[p1]}" \
  318. "${RECGW6[2]} dev ${NETIFS[p3]}" \
  319. 0 "unicast recursive - multipath onlink"
  320. run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \
  321. "::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \
  322. "::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \
  323. 0 "v4-mapped - multipath onlink"
  324. run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \
  325. "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
  326. "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
  327. 0 "unicast connected - multipath onlink both nexthops"
  328. run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \
  329. "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
  330. "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
  331. 0 "unicast connected - multipath onlink first only"
  332. run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \
  333. "${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
  334. "${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
  335. 0 "unicast connected - multipath onlink second only"
  336. }
  337. invalid_onlink_ipv6()
  338. {
  339. local lladdr
  340. lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
  341. run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
  342. "Invalid gw - local unicast address"
  343. run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
  344. "Invalid gw - local linklocal address"
  345. run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
  346. "Invalid gw - multicast address"
  347. lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
  348. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
  349. "Invalid gw - local unicast address, VRF"
  350. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
  351. "Invalid gw - local linklocal address, VRF"
  352. run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
  353. "Invalid gw - multicast address, VRF"
  354. run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
  355. "No nexthop device given"
  356. }
  357. run_onlink_tests()
  358. {
  359. log_section "IPv4 onlink"
  360. log_subsection "Valid onlink commands"
  361. valid_onlink_ipv4
  362. log_subsection "Invalid onlink commands"
  363. invalid_onlink_ipv4
  364. log_section "IPv6 onlink"
  365. log_subsection "Valid onlink commands"
  366. valid_onlink_ipv6
  367. log_subsection "Invalid onlink commands"
  368. invalid_onlink_ipv6
  369. }
  370. ################################################################################
  371. # usage
  372. usage()
  373. {
  374. cat <<EOF
  375. usage: ${0##*/} OPTS
  376. -p Pause on fail
  377. -v verbose mode (show commands and output)
  378. EOF
  379. }
  380. ################################################################################
  381. # main
  382. nsuccess=0
  383. nfail=0
  384. while getopts :t:pPhv o
  385. do
  386. case $o in
  387. p) PAUSE_ON_FAIL=yes;;
  388. v) VERBOSE=$(($VERBOSE + 1));;
  389. h) usage; exit 0;;
  390. *) usage; exit 1;;
  391. esac
  392. done
  393. setup
  394. run_onlink_tests
  395. cleanup_ns ${ns1} ${ns2}
  396. if [ "$TESTS" != "none" ]; then
  397. printf "\nTests passed: %3d\n" ${nsuccess}
  398. printf "Tests failed: %3d\n" ${nfail}
  399. fi