fib_tests.sh 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # This test is for checking IPv4 and IPv6 FIB behavior in response to
  4. # different events.
  5. ret=0
  6. # Kselftest framework requirement - SKIP code is 4.
  7. ksft_skip=4
  8. # all tests in this script. Can be overridden with -t option
  9. TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric"
  10. VERBOSE=0
  11. PAUSE_ON_FAIL=no
  12. PAUSE=no
  13. IP="ip -netns testns"
  14. log_test()
  15. {
  16. local rc=$1
  17. local expected=$2
  18. local msg="$3"
  19. if [ ${rc} -eq ${expected} ]; then
  20. printf " TEST: %-60s [ OK ]\n" "${msg}"
  21. nsuccess=$((nsuccess+1))
  22. else
  23. ret=1
  24. nfail=$((nfail+1))
  25. printf " TEST: %-60s [FAIL]\n" "${msg}"
  26. if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
  27. echo
  28. echo "hit enter to continue, 'q' to quit"
  29. read a
  30. [ "$a" = "q" ] && exit 1
  31. fi
  32. fi
  33. if [ "${PAUSE}" = "yes" ]; then
  34. echo
  35. echo "hit enter to continue, 'q' to quit"
  36. read a
  37. [ "$a" = "q" ] && exit 1
  38. fi
  39. }
  40. setup()
  41. {
  42. set -e
  43. ip netns add testns
  44. $IP link set dev lo up
  45. $IP link add dummy0 type dummy
  46. $IP link set dev dummy0 up
  47. $IP address add 198.51.100.1/24 dev dummy0
  48. $IP -6 address add 2001:db8:1::1/64 dev dummy0
  49. set +e
  50. }
  51. cleanup()
  52. {
  53. $IP link del dev dummy0 &> /dev/null
  54. ip netns del testns
  55. }
  56. get_linklocal()
  57. {
  58. local dev=$1
  59. local addr
  60. addr=$($IP -6 -br addr show dev ${dev} | \
  61. awk '{
  62. for (i = 3; i <= NF; ++i) {
  63. if ($i ~ /^fe80/)
  64. print $i
  65. }
  66. }'
  67. )
  68. addr=${addr/\/*}
  69. [ -z "$addr" ] && return 1
  70. echo $addr
  71. return 0
  72. }
  73. fib_unreg_unicast_test()
  74. {
  75. echo
  76. echo "Single path route test"
  77. setup
  78. echo " Start point"
  79. $IP route get fibmatch 198.51.100.2 &> /dev/null
  80. log_test $? 0 "IPv4 fibmatch"
  81. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  82. log_test $? 0 "IPv6 fibmatch"
  83. set -e
  84. $IP link del dev dummy0
  85. set +e
  86. echo " Nexthop device deleted"
  87. $IP route get fibmatch 198.51.100.2 &> /dev/null
  88. log_test $? 2 "IPv4 fibmatch - no route"
  89. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  90. log_test $? 2 "IPv6 fibmatch - no route"
  91. cleanup
  92. }
  93. fib_unreg_multipath_test()
  94. {
  95. echo
  96. echo "Multipath route test"
  97. setup
  98. set -e
  99. $IP link add dummy1 type dummy
  100. $IP link set dev dummy1 up
  101. $IP address add 192.0.2.1/24 dev dummy1
  102. $IP -6 address add 2001:db8:2::1/64 dev dummy1
  103. $IP route add 203.0.113.0/24 \
  104. nexthop via 198.51.100.2 dev dummy0 \
  105. nexthop via 192.0.2.2 dev dummy1
  106. $IP -6 route add 2001:db8:3::/64 \
  107. nexthop via 2001:db8:1::2 dev dummy0 \
  108. nexthop via 2001:db8:2::2 dev dummy1
  109. set +e
  110. echo " Start point"
  111. $IP route get fibmatch 203.0.113.1 &> /dev/null
  112. log_test $? 0 "IPv4 fibmatch"
  113. $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
  114. log_test $? 0 "IPv6 fibmatch"
  115. set -e
  116. $IP link del dev dummy0
  117. set +e
  118. echo " One nexthop device deleted"
  119. $IP route get fibmatch 203.0.113.1 &> /dev/null
  120. log_test $? 2 "IPv4 - multipath route removed on delete"
  121. $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
  122. # In IPv6 we do not flush the entire multipath route.
  123. log_test $? 0 "IPv6 - multipath down to single path"
  124. set -e
  125. $IP link del dev dummy1
  126. set +e
  127. echo " Second nexthop device deleted"
  128. $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
  129. log_test $? 2 "IPv6 - no route"
  130. cleanup
  131. }
  132. fib_unreg_test()
  133. {
  134. fib_unreg_unicast_test
  135. fib_unreg_multipath_test
  136. }
  137. fib_down_unicast_test()
  138. {
  139. echo
  140. echo "Single path, admin down"
  141. setup
  142. echo " Start point"
  143. $IP route get fibmatch 198.51.100.2 &> /dev/null
  144. log_test $? 0 "IPv4 fibmatch"
  145. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  146. log_test $? 0 "IPv6 fibmatch"
  147. set -e
  148. $IP link set dev dummy0 down
  149. set +e
  150. echo " Route deleted on down"
  151. $IP route get fibmatch 198.51.100.2 &> /dev/null
  152. log_test $? 2 "IPv4 fibmatch"
  153. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  154. log_test $? 2 "IPv6 fibmatch"
  155. cleanup
  156. }
  157. fib_down_multipath_test_do()
  158. {
  159. local down_dev=$1
  160. local up_dev=$2
  161. $IP route get fibmatch 203.0.113.1 \
  162. oif $down_dev &> /dev/null
  163. log_test $? 2 "IPv4 fibmatch on down device"
  164. $IP -6 route get fibmatch 2001:db8:3::1 \
  165. oif $down_dev &> /dev/null
  166. log_test $? 2 "IPv6 fibmatch on down device"
  167. $IP route get fibmatch 203.0.113.1 \
  168. oif $up_dev &> /dev/null
  169. log_test $? 0 "IPv4 fibmatch on up device"
  170. $IP -6 route get fibmatch 2001:db8:3::1 \
  171. oif $up_dev &> /dev/null
  172. log_test $? 0 "IPv6 fibmatch on up device"
  173. $IP route get fibmatch 203.0.113.1 | \
  174. grep $down_dev | grep -q "dead linkdown"
  175. log_test $? 0 "IPv4 flags on down device"
  176. $IP -6 route get fibmatch 2001:db8:3::1 | \
  177. grep $down_dev | grep -q "dead linkdown"
  178. log_test $? 0 "IPv6 flags on down device"
  179. $IP route get fibmatch 203.0.113.1 | \
  180. grep $up_dev | grep -q "dead linkdown"
  181. log_test $? 1 "IPv4 flags on up device"
  182. $IP -6 route get fibmatch 2001:db8:3::1 | \
  183. grep $up_dev | grep -q "dead linkdown"
  184. log_test $? 1 "IPv6 flags on up device"
  185. }
  186. fib_down_multipath_test()
  187. {
  188. echo
  189. echo "Admin down multipath"
  190. setup
  191. set -e
  192. $IP link add dummy1 type dummy
  193. $IP link set dev dummy1 up
  194. $IP address add 192.0.2.1/24 dev dummy1
  195. $IP -6 address add 2001:db8:2::1/64 dev dummy1
  196. $IP route add 203.0.113.0/24 \
  197. nexthop via 198.51.100.2 dev dummy0 \
  198. nexthop via 192.0.2.2 dev dummy1
  199. $IP -6 route add 2001:db8:3::/64 \
  200. nexthop via 2001:db8:1::2 dev dummy0 \
  201. nexthop via 2001:db8:2::2 dev dummy1
  202. set +e
  203. echo " Verify start point"
  204. $IP route get fibmatch 203.0.113.1 &> /dev/null
  205. log_test $? 0 "IPv4 fibmatch"
  206. $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
  207. log_test $? 0 "IPv6 fibmatch"
  208. set -e
  209. $IP link set dev dummy0 down
  210. set +e
  211. echo " One device down, one up"
  212. fib_down_multipath_test_do "dummy0" "dummy1"
  213. set -e
  214. $IP link set dev dummy0 up
  215. $IP link set dev dummy1 down
  216. set +e
  217. echo " Other device down and up"
  218. fib_down_multipath_test_do "dummy1" "dummy0"
  219. set -e
  220. $IP link set dev dummy0 down
  221. set +e
  222. echo " Both devices down"
  223. $IP route get fibmatch 203.0.113.1 &> /dev/null
  224. log_test $? 2 "IPv4 fibmatch"
  225. $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
  226. log_test $? 2 "IPv6 fibmatch"
  227. $IP link del dev dummy1
  228. cleanup
  229. }
  230. fib_down_test()
  231. {
  232. fib_down_unicast_test
  233. fib_down_multipath_test
  234. }
  235. # Local routes should not be affected when carrier changes.
  236. fib_carrier_local_test()
  237. {
  238. echo
  239. echo "Local carrier tests - single path"
  240. setup
  241. set -e
  242. $IP link set dev dummy0 carrier on
  243. set +e
  244. echo " Start point"
  245. $IP route get fibmatch 198.51.100.1 &> /dev/null
  246. log_test $? 0 "IPv4 fibmatch"
  247. $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
  248. log_test $? 0 "IPv6 fibmatch"
  249. $IP route get fibmatch 198.51.100.1 | \
  250. grep -q "linkdown"
  251. log_test $? 1 "IPv4 - no linkdown flag"
  252. $IP -6 route get fibmatch 2001:db8:1::1 | \
  253. grep -q "linkdown"
  254. log_test $? 1 "IPv6 - no linkdown flag"
  255. set -e
  256. $IP link set dev dummy0 carrier off
  257. sleep 1
  258. set +e
  259. echo " Carrier off on nexthop"
  260. $IP route get fibmatch 198.51.100.1 &> /dev/null
  261. log_test $? 0 "IPv4 fibmatch"
  262. $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
  263. log_test $? 0 "IPv6 fibmatch"
  264. $IP route get fibmatch 198.51.100.1 | \
  265. grep -q "linkdown"
  266. log_test $? 1 "IPv4 - linkdown flag set"
  267. $IP -6 route get fibmatch 2001:db8:1::1 | \
  268. grep -q "linkdown"
  269. log_test $? 1 "IPv6 - linkdown flag set"
  270. set -e
  271. $IP address add 192.0.2.1/24 dev dummy0
  272. $IP -6 address add 2001:db8:2::1/64 dev dummy0
  273. set +e
  274. echo " Route to local address with carrier down"
  275. $IP route get fibmatch 192.0.2.1 &> /dev/null
  276. log_test $? 0 "IPv4 fibmatch"
  277. $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
  278. log_test $? 0 "IPv6 fibmatch"
  279. $IP route get fibmatch 192.0.2.1 | \
  280. grep -q "linkdown"
  281. log_test $? 1 "IPv4 linkdown flag set"
  282. $IP -6 route get fibmatch 2001:db8:2::1 | \
  283. grep -q "linkdown"
  284. log_test $? 1 "IPv6 linkdown flag set"
  285. cleanup
  286. }
  287. fib_carrier_unicast_test()
  288. {
  289. ret=0
  290. echo
  291. echo "Single path route carrier test"
  292. setup
  293. set -e
  294. $IP link set dev dummy0 carrier on
  295. set +e
  296. echo " Start point"
  297. $IP route get fibmatch 198.51.100.2 &> /dev/null
  298. log_test $? 0 "IPv4 fibmatch"
  299. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  300. log_test $? 0 "IPv6 fibmatch"
  301. $IP route get fibmatch 198.51.100.2 | \
  302. grep -q "linkdown"
  303. log_test $? 1 "IPv4 no linkdown flag"
  304. $IP -6 route get fibmatch 2001:db8:1::2 | \
  305. grep -q "linkdown"
  306. log_test $? 1 "IPv6 no linkdown flag"
  307. set -e
  308. $IP link set dev dummy0 carrier off
  309. sleep 1
  310. set +e
  311. echo " Carrier down"
  312. $IP route get fibmatch 198.51.100.2 &> /dev/null
  313. log_test $? 0 "IPv4 fibmatch"
  314. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  315. log_test $? 0 "IPv6 fibmatch"
  316. $IP route get fibmatch 198.51.100.2 | \
  317. grep -q "linkdown"
  318. log_test $? 0 "IPv4 linkdown flag set"
  319. $IP -6 route get fibmatch 2001:db8:1::2 | \
  320. grep -q "linkdown"
  321. log_test $? 0 "IPv6 linkdown flag set"
  322. set -e
  323. $IP address add 192.0.2.1/24 dev dummy0
  324. $IP -6 address add 2001:db8:2::1/64 dev dummy0
  325. set +e
  326. echo " Second address added with carrier down"
  327. $IP route get fibmatch 192.0.2.2 &> /dev/null
  328. log_test $? 0 "IPv4 fibmatch"
  329. $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
  330. log_test $? 0 "IPv6 fibmatch"
  331. $IP route get fibmatch 192.0.2.2 | \
  332. grep -q "linkdown"
  333. log_test $? 0 "IPv4 linkdown flag set"
  334. $IP -6 route get fibmatch 2001:db8:2::2 | \
  335. grep -q "linkdown"
  336. log_test $? 0 "IPv6 linkdown flag set"
  337. cleanup
  338. }
  339. fib_carrier_test()
  340. {
  341. fib_carrier_local_test
  342. fib_carrier_unicast_test
  343. }
  344. ################################################################################
  345. # Tests on nexthop spec
  346. # run 'ip route add' with given spec
  347. add_rt()
  348. {
  349. local desc="$1"
  350. local erc=$2
  351. local vrf=$3
  352. local pfx=$4
  353. local gw=$5
  354. local dev=$6
  355. local cmd out rc
  356. [ "$vrf" = "-" ] && vrf="default"
  357. [ -n "$gw" ] && gw="via $gw"
  358. [ -n "$dev" ] && dev="dev $dev"
  359. cmd="$IP route add vrf $vrf $pfx $gw $dev"
  360. if [ "$VERBOSE" = "1" ]; then
  361. printf "\n COMMAND: $cmd\n"
  362. fi
  363. out=$(eval $cmd 2>&1)
  364. rc=$?
  365. if [ "$VERBOSE" = "1" -a -n "$out" ]; then
  366. echo " $out"
  367. fi
  368. log_test $rc $erc "$desc"
  369. }
  370. fib4_nexthop()
  371. {
  372. echo
  373. echo "IPv4 nexthop tests"
  374. echo "<<< write me >>>"
  375. }
  376. fib6_nexthop()
  377. {
  378. local lldummy=$(get_linklocal dummy0)
  379. local llv1=$(get_linklocal dummy0)
  380. if [ -z "$lldummy" ]; then
  381. echo "Failed to get linklocal address for dummy0"
  382. return 1
  383. fi
  384. if [ -z "$llv1" ]; then
  385. echo "Failed to get linklocal address for veth1"
  386. return 1
  387. fi
  388. echo
  389. echo "IPv6 nexthop tests"
  390. add_rt "Directly connected nexthop, unicast address" 0 \
  391. - 2001:db8:101::/64 2001:db8:1::2
  392. add_rt "Directly connected nexthop, unicast address with device" 0 \
  393. - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
  394. add_rt "Gateway is linklocal address" 0 \
  395. - 2001:db8:103::1/64 $llv1 "veth0"
  396. # fails because LL address requires a device
  397. add_rt "Gateway is linklocal address, no device" 2 \
  398. - 2001:db8:104::1/64 $llv1
  399. # local address can not be a gateway
  400. add_rt "Gateway can not be local unicast address" 2 \
  401. - 2001:db8:105::/64 2001:db8:1::1
  402. add_rt "Gateway can not be local unicast address, with device" 2 \
  403. - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
  404. add_rt "Gateway can not be a local linklocal address" 2 \
  405. - 2001:db8:107::1/64 $lldummy "dummy0"
  406. # VRF tests
  407. add_rt "Gateway can be local address in a VRF" 0 \
  408. - 2001:db8:108::/64 2001:db8:51::2
  409. add_rt "Gateway can be local address in a VRF, with device" 0 \
  410. - 2001:db8:109::/64 2001:db8:51::2 "veth0"
  411. add_rt "Gateway can be local linklocal address in a VRF" 0 \
  412. - 2001:db8:110::1/64 $llv1 "veth0"
  413. add_rt "Redirect to VRF lookup" 0 \
  414. - 2001:db8:111::/64 "" "red"
  415. add_rt "VRF route, gateway can be local address in default VRF" 0 \
  416. red 2001:db8:112::/64 2001:db8:51::1
  417. # local address in same VRF fails
  418. add_rt "VRF route, gateway can not be a local address" 2 \
  419. red 2001:db8:113::1/64 2001:db8:2::1
  420. add_rt "VRF route, gateway can not be a local addr with device" 2 \
  421. red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
  422. }
  423. # Default VRF:
  424. # dummy0 - 198.51.100.1/24 2001:db8:1::1/64
  425. # veth0 - 192.0.2.1/24 2001:db8:51::1/64
  426. #
  427. # VRF red:
  428. # dummy1 - 192.168.2.1/24 2001:db8:2::1/64
  429. # veth1 - 192.0.2.2/24 2001:db8:51::2/64
  430. #
  431. # [ dummy0 veth0 ]--[ veth1 dummy1 ]
  432. fib_nexthop_test()
  433. {
  434. setup
  435. set -e
  436. $IP -4 rule add pref 32765 table local
  437. $IP -4 rule del pref 0
  438. $IP -6 rule add pref 32765 table local
  439. $IP -6 rule del pref 0
  440. $IP link add red type vrf table 1
  441. $IP link set red up
  442. $IP -4 route add vrf red unreachable default metric 4278198272
  443. $IP -6 route add vrf red unreachable default metric 4278198272
  444. $IP link add veth0 type veth peer name veth1
  445. $IP link set dev veth0 up
  446. $IP address add 192.0.2.1/24 dev veth0
  447. $IP -6 address add 2001:db8:51::1/64 dev veth0
  448. $IP link set dev veth1 vrf red up
  449. $IP address add 192.0.2.2/24 dev veth1
  450. $IP -6 address add 2001:db8:51::2/64 dev veth1
  451. $IP link add dummy1 type dummy
  452. $IP link set dev dummy1 vrf red up
  453. $IP address add 192.168.2.1/24 dev dummy1
  454. $IP -6 address add 2001:db8:2::1/64 dev dummy1
  455. set +e
  456. sleep 1
  457. fib4_nexthop
  458. fib6_nexthop
  459. (
  460. $IP link del dev dummy1
  461. $IP link del veth0
  462. $IP link del red
  463. ) 2>/dev/null
  464. cleanup
  465. }
  466. ################################################################################
  467. # Tests on route add and replace
  468. run_cmd()
  469. {
  470. local cmd="$1"
  471. local out
  472. local stderr="2>/dev/null"
  473. if [ "$VERBOSE" = "1" ]; then
  474. printf " COMMAND: $cmd\n"
  475. stderr=
  476. fi
  477. out=$(eval $cmd $stderr)
  478. rc=$?
  479. if [ "$VERBOSE" = "1" -a -n "$out" ]; then
  480. echo " $out"
  481. fi
  482. [ "$VERBOSE" = "1" ] && echo
  483. return $rc
  484. }
  485. # add route for a prefix, flushing any existing routes first
  486. # expected to be the first step of a test
  487. add_route6()
  488. {
  489. local pfx="$1"
  490. local nh="$2"
  491. local out
  492. if [ "$VERBOSE" = "1" ]; then
  493. echo
  494. echo " ##################################################"
  495. echo
  496. fi
  497. run_cmd "$IP -6 ro flush ${pfx}"
  498. [ $? -ne 0 ] && exit 1
  499. out=$($IP -6 ro ls match ${pfx})
  500. if [ -n "$out" ]; then
  501. echo "Failed to flush routes for prefix used for tests."
  502. exit 1
  503. fi
  504. run_cmd "$IP -6 ro add ${pfx} ${nh}"
  505. if [ $? -ne 0 ]; then
  506. echo "Failed to add initial route for test."
  507. exit 1
  508. fi
  509. }
  510. # add initial route - used in replace route tests
  511. add_initial_route6()
  512. {
  513. add_route6 "2001:db8:104::/64" "$1"
  514. }
  515. check_route6()
  516. {
  517. local pfx="2001:db8:104::/64"
  518. local expected="$1"
  519. local out
  520. local rc=0
  521. out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
  522. [ "${out}" = "${expected}" ] && return 0
  523. if [ -z "${out}" ]; then
  524. if [ "$VERBOSE" = "1" ]; then
  525. printf "\nNo route entry found\n"
  526. printf "Expected:\n"
  527. printf " ${expected}\n"
  528. fi
  529. return 1
  530. fi
  531. # tricky way to convert output to 1-line without ip's
  532. # messy '\'; this drops all extra white space
  533. out=$(echo ${out})
  534. if [ "${out}" != "${expected}" ]; then
  535. rc=1
  536. if [ "${VERBOSE}" = "1" ]; then
  537. printf " Unexpected route entry. Have:\n"
  538. printf " ${out}\n"
  539. printf " Expected:\n"
  540. printf " ${expected}\n\n"
  541. fi
  542. fi
  543. return $rc
  544. }
  545. route_cleanup()
  546. {
  547. $IP li del red 2>/dev/null
  548. $IP li del dummy1 2>/dev/null
  549. $IP li del veth1 2>/dev/null
  550. $IP li del veth3 2>/dev/null
  551. cleanup &> /dev/null
  552. }
  553. route_setup()
  554. {
  555. route_cleanup
  556. setup
  557. [ "${VERBOSE}" = "1" ] && set -x
  558. set -e
  559. $IP li add red up type vrf table 101
  560. $IP li add veth1 type veth peer name veth2
  561. $IP li add veth3 type veth peer name veth4
  562. $IP li set veth1 up
  563. $IP li set veth3 up
  564. $IP li set veth2 vrf red up
  565. $IP li set veth4 vrf red up
  566. $IP li add dummy1 type dummy
  567. $IP li set dummy1 vrf red up
  568. $IP -6 addr add 2001:db8:101::1/64 dev veth1
  569. $IP -6 addr add 2001:db8:101::2/64 dev veth2
  570. $IP -6 addr add 2001:db8:103::1/64 dev veth3
  571. $IP -6 addr add 2001:db8:103::2/64 dev veth4
  572. $IP -6 addr add 2001:db8:104::1/64 dev dummy1
  573. $IP addr add 172.16.101.1/24 dev veth1
  574. $IP addr add 172.16.101.2/24 dev veth2
  575. $IP addr add 172.16.103.1/24 dev veth3
  576. $IP addr add 172.16.103.2/24 dev veth4
  577. $IP addr add 172.16.104.1/24 dev dummy1
  578. set +ex
  579. }
  580. # assumption is that basic add of a single path route works
  581. # otherwise just adding an address on an interface is broken
  582. ipv6_rt_add()
  583. {
  584. local rc
  585. echo
  586. echo "IPv6 route add / append tests"
  587. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  588. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  589. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
  590. log_test $? 2 "Attempt to add duplicate route - gw"
  591. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  592. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  593. run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
  594. log_test $? 2 "Attempt to add duplicate route - dev only"
  595. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  596. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  597. run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
  598. log_test $? 2 "Attempt to add duplicate route - reject route"
  599. # route append with same prefix adds a new route
  600. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  601. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  602. run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
  603. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
  604. log_test $? 0 "Append nexthop to existing route - gw"
  605. # insert mpath directly
  606. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  607. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
  608. log_test $? 0 "Add multipath route"
  609. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  610. run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  611. log_test $? 2 "Attempt to add duplicate multipath route"
  612. # insert of a second route without append but different metric
  613. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  614. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
  615. rc=$?
  616. if [ $rc -eq 0 ]; then
  617. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
  618. rc=$?
  619. fi
  620. log_test $rc 0 "Route add with different metrics"
  621. run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
  622. rc=$?
  623. if [ $rc -eq 0 ]; then
  624. check_route6 "2001:db8:104::/64 via 2001:db8:103::3 dev veth3 metric 256 2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
  625. rc=$?
  626. fi
  627. log_test $rc 0 "Route delete with metric"
  628. }
  629. ipv6_rt_replace_single()
  630. {
  631. # single path with single path
  632. #
  633. add_initial_route6 "via 2001:db8:101::2"
  634. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
  635. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  636. log_test $? 0 "Single path with single path"
  637. # single path with multipath
  638. #
  639. add_initial_route6 "nexthop via 2001:db8:101::2"
  640. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
  641. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
  642. log_test $? 0 "Single path with multipath"
  643. # single path with single path using MULTIPATH attribute
  644. #
  645. add_initial_route6 "via 2001:db8:101::2"
  646. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
  647. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  648. log_test $? 0 "Single path with single path via multipath attribute"
  649. # route replace fails - invalid nexthop
  650. add_initial_route6 "via 2001:db8:101::2"
  651. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
  652. if [ $? -eq 0 ]; then
  653. # previous command is expected to fail so if it returns 0
  654. # that means the test failed.
  655. log_test 0 1 "Invalid nexthop"
  656. else
  657. check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
  658. log_test $? 0 "Invalid nexthop"
  659. fi
  660. # replace non-existent route
  661. # - note use of change versus replace since ip adds NLM_F_CREATE
  662. # for replace
  663. add_initial_route6 "via 2001:db8:101::2"
  664. run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
  665. log_test $? 2 "Single path - replace of non-existent route"
  666. }
  667. ipv6_rt_replace_mpath()
  668. {
  669. # multipath with multipath
  670. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  671. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  672. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::3 dev veth3 weight 1"
  673. log_test $? 0 "Multipath with multipath"
  674. # multipath with single
  675. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  676. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
  677. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  678. log_test $? 0 "Multipath with single path"
  679. # multipath with single
  680. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  681. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
  682. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  683. log_test $? 0 "Multipath with single path via multipath attribute"
  684. # route replace fails - invalid nexthop 1
  685. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  686. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
  687. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
  688. log_test $? 0 "Multipath - invalid first nexthop"
  689. # route replace fails - invalid nexthop 2
  690. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  691. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
  692. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
  693. log_test $? 0 "Multipath - invalid second nexthop"
  694. # multipath non-existent route
  695. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  696. run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  697. log_test $? 2 "Multipath - replace of non-existent route"
  698. }
  699. ipv6_rt_replace()
  700. {
  701. echo
  702. echo "IPv6 route replace tests"
  703. ipv6_rt_replace_single
  704. ipv6_rt_replace_mpath
  705. }
  706. ipv6_route_test()
  707. {
  708. route_setup
  709. ipv6_rt_add
  710. ipv6_rt_replace
  711. route_cleanup
  712. }
  713. ip_addr_metric_check()
  714. {
  715. ip addr help 2>&1 | grep -q metric
  716. if [ $? -ne 0 ]; then
  717. echo "iproute2 command does not support metric for addresses. Skipping test"
  718. return 1
  719. fi
  720. return 0
  721. }
  722. ipv6_addr_metric_test()
  723. {
  724. local rc
  725. echo
  726. echo "IPv6 prefix route tests"
  727. ip_addr_metric_check || return 1
  728. setup
  729. set -e
  730. $IP li add dummy1 type dummy
  731. $IP li add dummy2 type dummy
  732. $IP li set dummy1 up
  733. $IP li set dummy2 up
  734. # default entry is metric 256
  735. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
  736. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
  737. set +e
  738. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
  739. log_test $? 0 "Default metric"
  740. set -e
  741. run_cmd "$IP -6 addr flush dev dummy1"
  742. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
  743. set +e
  744. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
  745. log_test $? 0 "User specified metric on first device"
  746. set -e
  747. run_cmd "$IP -6 addr flush dev dummy2"
  748. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
  749. set +e
  750. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  751. log_test $? 0 "User specified metric on second device"
  752. run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
  753. rc=$?
  754. if [ $rc -eq 0 ]; then
  755. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  756. rc=$?
  757. fi
  758. log_test $rc 0 "Delete of address on first device"
  759. run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
  760. rc=$?
  761. if [ $rc -eq 0 ]; then
  762. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  763. rc=$?
  764. fi
  765. log_test $rc 0 "Modify metric of address"
  766. # verify prefix route removed on down
  767. run_cmd "ip netns exec testns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
  768. run_cmd "$IP li set dev dummy2 down"
  769. rc=$?
  770. if [ $rc -eq 0 ]; then
  771. check_route6 ""
  772. rc=$?
  773. fi
  774. log_test $rc 0 "Prefix route removed on link down"
  775. # verify prefix route re-inserted with assigned metric
  776. run_cmd "$IP li set dev dummy2 up"
  777. rc=$?
  778. if [ $rc -eq 0 ]; then
  779. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  780. rc=$?
  781. fi
  782. log_test $rc 0 "Prefix route with metric on link up"
  783. $IP li del dummy1
  784. $IP li del dummy2
  785. cleanup
  786. }
  787. # add route for a prefix, flushing any existing routes first
  788. # expected to be the first step of a test
  789. add_route()
  790. {
  791. local pfx="$1"
  792. local nh="$2"
  793. local out
  794. if [ "$VERBOSE" = "1" ]; then
  795. echo
  796. echo " ##################################################"
  797. echo
  798. fi
  799. run_cmd "$IP ro flush ${pfx}"
  800. [ $? -ne 0 ] && exit 1
  801. out=$($IP ro ls match ${pfx})
  802. if [ -n "$out" ]; then
  803. echo "Failed to flush routes for prefix used for tests."
  804. exit 1
  805. fi
  806. run_cmd "$IP ro add ${pfx} ${nh}"
  807. if [ $? -ne 0 ]; then
  808. echo "Failed to add initial route for test."
  809. exit 1
  810. fi
  811. }
  812. # add initial route - used in replace route tests
  813. add_initial_route()
  814. {
  815. add_route "172.16.104.0/24" "$1"
  816. }
  817. check_route()
  818. {
  819. local pfx="172.16.104.0/24"
  820. local expected="$1"
  821. local out
  822. local rc=0
  823. out=$($IP ro ls match ${pfx})
  824. [ "${out}" = "${expected}" ] && return 0
  825. if [ -z "${out}" ]; then
  826. if [ "$VERBOSE" = "1" ]; then
  827. printf "\nNo route entry found\n"
  828. printf "Expected:\n"
  829. printf " ${expected}\n"
  830. fi
  831. return 1
  832. fi
  833. # tricky way to convert output to 1-line without ip's
  834. # messy '\'; this drops all extra white space
  835. out=$(echo ${out})
  836. if [ "${out}" != "${expected}" ]; then
  837. rc=1
  838. if [ "${VERBOSE}" = "1" ]; then
  839. printf " Unexpected route entry. Have:\n"
  840. printf " ${out}\n"
  841. printf " Expected:\n"
  842. printf " ${expected}\n\n"
  843. fi
  844. fi
  845. return $rc
  846. }
  847. # assumption is that basic add of a single path route works
  848. # otherwise just adding an address on an interface is broken
  849. ipv4_rt_add()
  850. {
  851. local rc
  852. echo
  853. echo "IPv4 route add / append tests"
  854. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  855. add_route "172.16.104.0/24" "via 172.16.101.2"
  856. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
  857. log_test $? 2 "Attempt to add duplicate route - gw"
  858. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  859. add_route "172.16.104.0/24" "via 172.16.101.2"
  860. run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
  861. log_test $? 2 "Attempt to add duplicate route - dev only"
  862. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  863. add_route "172.16.104.0/24" "via 172.16.101.2"
  864. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  865. log_test $? 2 "Attempt to add duplicate route - reject route"
  866. # iproute2 prepend only sets NLM_F_CREATE
  867. # - adds a new route; does NOT convert existing route to ECMP
  868. add_route "172.16.104.0/24" "via 172.16.101.2"
  869. run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
  870. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3 172.16.104.0/24 via 172.16.101.2 dev veth1"
  871. log_test $? 0 "Add new nexthop for existing prefix"
  872. # route append with same prefix adds a new route
  873. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  874. add_route "172.16.104.0/24" "via 172.16.101.2"
  875. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  876. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.2 dev veth3"
  877. log_test $? 0 "Append nexthop to existing route - gw"
  878. add_route "172.16.104.0/24" "via 172.16.101.2"
  879. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  880. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
  881. log_test $? 0 "Append nexthop to existing route - dev only"
  882. add_route "172.16.104.0/24" "via 172.16.101.2"
  883. run_cmd "$IP ro append unreachable 172.16.104.0/24"
  884. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
  885. log_test $? 0 "Append nexthop to existing route - reject route"
  886. run_cmd "$IP ro flush 172.16.104.0/24"
  887. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  888. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  889. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
  890. log_test $? 0 "Append nexthop to existing reject route - gw"
  891. run_cmd "$IP ro flush 172.16.104.0/24"
  892. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  893. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  894. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
  895. log_test $? 0 "Append nexthop to existing reject route - dev only"
  896. # insert mpath directly
  897. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  898. check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
  899. log_test $? 0 "add multipath route"
  900. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  901. run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  902. log_test $? 2 "Attempt to add duplicate multipath route"
  903. # insert of a second route without append but different metric
  904. add_route "172.16.104.0/24" "via 172.16.101.2"
  905. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
  906. rc=$?
  907. if [ $rc -eq 0 ]; then
  908. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
  909. rc=$?
  910. fi
  911. log_test $rc 0 "Route add with different metrics"
  912. run_cmd "$IP ro del 172.16.104.0/24 metric 512"
  913. rc=$?
  914. if [ $rc -eq 0 ]; then
  915. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.3 dev veth3 metric 256"
  916. rc=$?
  917. fi
  918. log_test $rc 0 "Route delete with metric"
  919. }
  920. ipv4_rt_replace_single()
  921. {
  922. # single path with single path
  923. #
  924. add_initial_route "via 172.16.101.2"
  925. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
  926. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  927. log_test $? 0 "Single path with single path"
  928. # single path with multipath
  929. #
  930. add_initial_route "nexthop via 172.16.101.2"
  931. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
  932. check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
  933. log_test $? 0 "Single path with multipath"
  934. # single path with reject
  935. #
  936. add_initial_route "nexthop via 172.16.101.2"
  937. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  938. check_route "unreachable 172.16.104.0/24"
  939. log_test $? 0 "Single path with reject route"
  940. # single path with single path using MULTIPATH attribute
  941. #
  942. add_initial_route "via 172.16.101.2"
  943. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
  944. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  945. log_test $? 0 "Single path with single path via multipath attribute"
  946. # route replace fails - invalid nexthop
  947. add_initial_route "via 172.16.101.2"
  948. run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
  949. if [ $? -eq 0 ]; then
  950. # previous command is expected to fail so if it returns 0
  951. # that means the test failed.
  952. log_test 0 1 "Invalid nexthop"
  953. else
  954. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
  955. log_test $? 0 "Invalid nexthop"
  956. fi
  957. # replace non-existent route
  958. # - note use of change versus replace since ip adds NLM_F_CREATE
  959. # for replace
  960. add_initial_route "via 172.16.101.2"
  961. run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
  962. log_test $? 2 "Single path - replace of non-existent route"
  963. }
  964. ipv4_rt_replace_mpath()
  965. {
  966. # multipath with multipath
  967. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  968. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  969. check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.3 dev veth3 weight 1"
  970. log_test $? 0 "Multipath with multipath"
  971. # multipath with single
  972. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  973. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
  974. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  975. log_test $? 0 "Multipath with single path"
  976. # multipath with single
  977. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  978. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
  979. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  980. log_test $? 0 "Multipath with single path via multipath attribute"
  981. # multipath with reject
  982. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  983. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  984. check_route "unreachable 172.16.104.0/24"
  985. log_test $? 0 "Multipath with reject route"
  986. # route replace fails - invalid nexthop 1
  987. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  988. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
  989. check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
  990. log_test $? 0 "Multipath - invalid first nexthop"
  991. # route replace fails - invalid nexthop 2
  992. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  993. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
  994. check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
  995. log_test $? 0 "Multipath - invalid second nexthop"
  996. # multipath non-existent route
  997. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  998. run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  999. log_test $? 2 "Multipath - replace of non-existent route"
  1000. }
  1001. ipv4_rt_replace()
  1002. {
  1003. echo
  1004. echo "IPv4 route replace tests"
  1005. ipv4_rt_replace_single
  1006. ipv4_rt_replace_mpath
  1007. }
  1008. ipv4_route_test()
  1009. {
  1010. route_setup
  1011. ipv4_rt_add
  1012. ipv4_rt_replace
  1013. route_cleanup
  1014. }
  1015. ipv4_addr_metric_test()
  1016. {
  1017. local rc
  1018. echo
  1019. echo "IPv4 prefix route tests"
  1020. ip_addr_metric_check || return 1
  1021. setup
  1022. set -e
  1023. $IP li add dummy1 type dummy
  1024. $IP li add dummy2 type dummy
  1025. $IP li set dummy1 up
  1026. $IP li set dummy2 up
  1027. # default entry is metric 256
  1028. run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
  1029. run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
  1030. set +e
  1031. check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2"
  1032. log_test $? 0 "Default metric"
  1033. set -e
  1034. run_cmd "$IP addr flush dev dummy1"
  1035. run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
  1036. set +e
  1037. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257"
  1038. log_test $? 0 "User specified metric on first device"
  1039. set -e
  1040. run_cmd "$IP addr flush dev dummy2"
  1041. run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
  1042. set +e
  1043. check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
  1044. log_test $? 0 "User specified metric on second device"
  1045. run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
  1046. rc=$?
  1047. if [ $rc -eq 0 ]; then
  1048. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
  1049. rc=$?
  1050. fi
  1051. log_test $rc 0 "Delete of address on first device"
  1052. run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
  1053. rc=$?
  1054. if [ $rc -eq 0 ]; then
  1055. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1056. rc=$?
  1057. fi
  1058. log_test $rc 0 "Modify metric of address"
  1059. # verify prefix route removed on down
  1060. run_cmd "$IP li set dev dummy2 down"
  1061. rc=$?
  1062. if [ $rc -eq 0 ]; then
  1063. check_route ""
  1064. rc=$?
  1065. fi
  1066. log_test $rc 0 "Prefix route removed on link down"
  1067. # verify prefix route re-inserted with assigned metric
  1068. run_cmd "$IP li set dev dummy2 up"
  1069. rc=$?
  1070. if [ $rc -eq 0 ]; then
  1071. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1072. rc=$?
  1073. fi
  1074. log_test $rc 0 "Prefix route with metric on link up"
  1075. $IP li del dummy1
  1076. $IP li del dummy2
  1077. cleanup
  1078. }
  1079. ################################################################################
  1080. # usage
  1081. usage()
  1082. {
  1083. cat <<EOF
  1084. usage: ${0##*/} OPTS
  1085. -t <test> Test(s) to run (default: all)
  1086. (options: $TESTS)
  1087. -p Pause on fail
  1088. -P Pause after each test before cleanup
  1089. -v verbose mode (show commands and output)
  1090. EOF
  1091. }
  1092. ################################################################################
  1093. # main
  1094. while getopts :t:pPhv o
  1095. do
  1096. case $o in
  1097. t) TESTS=$OPTARG;;
  1098. p) PAUSE_ON_FAIL=yes;;
  1099. P) PAUSE=yes;;
  1100. v) VERBOSE=$(($VERBOSE + 1));;
  1101. h) usage; exit 0;;
  1102. *) usage; exit 1;;
  1103. esac
  1104. done
  1105. PEER_CMD="ip netns exec ${PEER_NS}"
  1106. # make sure we don't pause twice
  1107. [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
  1108. if [ "$(id -u)" -ne 0 ];then
  1109. echo "SKIP: Need root privileges"
  1110. exit $ksft_skip;
  1111. fi
  1112. if [ ! -x "$(command -v ip)" ]; then
  1113. echo "SKIP: Could not run test without ip tool"
  1114. exit $ksft_skip
  1115. fi
  1116. ip route help 2>&1 | grep -q fibmatch
  1117. if [ $? -ne 0 ]; then
  1118. echo "SKIP: iproute2 too old, missing fibmatch"
  1119. exit $ksft_skip
  1120. fi
  1121. # start clean
  1122. cleanup &> /dev/null
  1123. for t in $TESTS
  1124. do
  1125. case $t in
  1126. fib_unreg_test|unregister) fib_unreg_test;;
  1127. fib_down_test|down) fib_down_test;;
  1128. fib_carrier_test|carrier) fib_carrier_test;;
  1129. fib_nexthop_test|nexthop) fib_nexthop_test;;
  1130. ipv6_route_test|ipv6_rt) ipv6_route_test;;
  1131. ipv4_route_test|ipv4_rt) ipv4_route_test;;
  1132. ipv6_addr_metric) ipv6_addr_metric_test;;
  1133. ipv4_addr_metric) ipv4_addr_metric_test;;
  1134. help) echo "Test names: $TESTS"; exit 0;;
  1135. esac
  1136. done
  1137. if [ "$TESTS" != "none" ]; then
  1138. printf "\nTests passed: %3d\n" ${nsuccess}
  1139. printf "Tests failed: %3d\n" ${nfail}
  1140. fi
  1141. exit $ret