fib_tests.sh 39 KB

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