fib-onlink-tests.sh 12 KB

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