fib_tests.sh 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  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. set +e
  310. echo " Carrier down"
  311. $IP route get fibmatch 198.51.100.2 &> /dev/null
  312. log_test $? 0 "IPv4 fibmatch"
  313. $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
  314. log_test $? 0 "IPv6 fibmatch"
  315. $IP route get fibmatch 198.51.100.2 | \
  316. grep -q "linkdown"
  317. log_test $? 0 "IPv4 linkdown flag set"
  318. $IP -6 route get fibmatch 2001:db8:1::2 | \
  319. grep -q "linkdown"
  320. log_test $? 0 "IPv6 linkdown flag set"
  321. set -e
  322. $IP address add 192.0.2.1/24 dev dummy0
  323. $IP -6 address add 2001:db8:2::1/64 dev dummy0
  324. set +e
  325. echo " Second address added with carrier down"
  326. $IP route get fibmatch 192.0.2.2 &> /dev/null
  327. log_test $? 0 "IPv4 fibmatch"
  328. $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
  329. log_test $? 0 "IPv6 fibmatch"
  330. $IP route get fibmatch 192.0.2.2 | \
  331. grep -q "linkdown"
  332. log_test $? 0 "IPv4 linkdown flag set"
  333. $IP -6 route get fibmatch 2001:db8:2::2 | \
  334. grep -q "linkdown"
  335. log_test $? 0 "IPv6 linkdown flag set"
  336. cleanup
  337. }
  338. fib_carrier_test()
  339. {
  340. fib_carrier_local_test
  341. fib_carrier_unicast_test
  342. }
  343. ################################################################################
  344. # Tests on nexthop spec
  345. # run 'ip route add' with given spec
  346. add_rt()
  347. {
  348. local desc="$1"
  349. local erc=$2
  350. local vrf=$3
  351. local pfx=$4
  352. local gw=$5
  353. local dev=$6
  354. local cmd out rc
  355. [ "$vrf" = "-" ] && vrf="default"
  356. [ -n "$gw" ] && gw="via $gw"
  357. [ -n "$dev" ] && dev="dev $dev"
  358. cmd="$IP route add vrf $vrf $pfx $gw $dev"
  359. if [ "$VERBOSE" = "1" ]; then
  360. printf "\n COMMAND: $cmd\n"
  361. fi
  362. out=$(eval $cmd 2>&1)
  363. rc=$?
  364. if [ "$VERBOSE" = "1" -a -n "$out" ]; then
  365. echo " $out"
  366. fi
  367. log_test $rc $erc "$desc"
  368. }
  369. fib4_nexthop()
  370. {
  371. echo
  372. echo "IPv4 nexthop tests"
  373. echo "<<< write me >>>"
  374. }
  375. fib6_nexthop()
  376. {
  377. local lldummy=$(get_linklocal dummy0)
  378. local llv1=$(get_linklocal dummy0)
  379. if [ -z "$lldummy" ]; then
  380. echo "Failed to get linklocal address for dummy0"
  381. return 1
  382. fi
  383. if [ -z "$llv1" ]; then
  384. echo "Failed to get linklocal address for veth1"
  385. return 1
  386. fi
  387. echo
  388. echo "IPv6 nexthop tests"
  389. add_rt "Directly connected nexthop, unicast address" 0 \
  390. - 2001:db8:101::/64 2001:db8:1::2
  391. add_rt "Directly connected nexthop, unicast address with device" 0 \
  392. - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
  393. add_rt "Gateway is linklocal address" 0 \
  394. - 2001:db8:103::1/64 $llv1 "veth0"
  395. # fails because LL address requires a device
  396. add_rt "Gateway is linklocal address, no device" 2 \
  397. - 2001:db8:104::1/64 $llv1
  398. # local address can not be a gateway
  399. add_rt "Gateway can not be local unicast address" 2 \
  400. - 2001:db8:105::/64 2001:db8:1::1
  401. add_rt "Gateway can not be local unicast address, with device" 2 \
  402. - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
  403. add_rt "Gateway can not be a local linklocal address" 2 \
  404. - 2001:db8:107::1/64 $lldummy "dummy0"
  405. # VRF tests
  406. add_rt "Gateway can be local address in a VRF" 0 \
  407. - 2001:db8:108::/64 2001:db8:51::2
  408. add_rt "Gateway can be local address in a VRF, with device" 0 \
  409. - 2001:db8:109::/64 2001:db8:51::2 "veth0"
  410. add_rt "Gateway can be local linklocal address in a VRF" 0 \
  411. - 2001:db8:110::1/64 $llv1 "veth0"
  412. add_rt "Redirect to VRF lookup" 0 \
  413. - 2001:db8:111::/64 "" "red"
  414. add_rt "VRF route, gateway can be local address in default VRF" 0 \
  415. red 2001:db8:112::/64 2001:db8:51::1
  416. # local address in same VRF fails
  417. add_rt "VRF route, gateway can not be a local address" 2 \
  418. red 2001:db8:113::1/64 2001:db8:2::1
  419. add_rt "VRF route, gateway can not be a local addr with device" 2 \
  420. red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
  421. }
  422. # Default VRF:
  423. # dummy0 - 198.51.100.1/24 2001:db8:1::1/64
  424. # veth0 - 192.0.2.1/24 2001:db8:51::1/64
  425. #
  426. # VRF red:
  427. # dummy1 - 192.168.2.1/24 2001:db8:2::1/64
  428. # veth1 - 192.0.2.2/24 2001:db8:51::2/64
  429. #
  430. # [ dummy0 veth0 ]--[ veth1 dummy1 ]
  431. fib_nexthop_test()
  432. {
  433. setup
  434. set -e
  435. $IP -4 rule add pref 32765 table local
  436. $IP -4 rule del pref 0
  437. $IP -6 rule add pref 32765 table local
  438. $IP -6 rule del pref 0
  439. $IP link add red type vrf table 1
  440. $IP link set red up
  441. $IP -4 route add vrf red unreachable default metric 4278198272
  442. $IP -6 route add vrf red unreachable default metric 4278198272
  443. $IP link add veth0 type veth peer name veth1
  444. $IP link set dev veth0 up
  445. $IP address add 192.0.2.1/24 dev veth0
  446. $IP -6 address add 2001:db8:51::1/64 dev veth0
  447. $IP link set dev veth1 vrf red up
  448. $IP address add 192.0.2.2/24 dev veth1
  449. $IP -6 address add 2001:db8:51::2/64 dev veth1
  450. $IP link add dummy1 type dummy
  451. $IP link set dev dummy1 vrf red up
  452. $IP address add 192.168.2.1/24 dev dummy1
  453. $IP -6 address add 2001:db8:2::1/64 dev dummy1
  454. set +e
  455. sleep 1
  456. fib4_nexthop
  457. fib6_nexthop
  458. (
  459. $IP link del dev dummy1
  460. $IP link del veth0
  461. $IP link del red
  462. ) 2>/dev/null
  463. cleanup
  464. }
  465. ################################################################################
  466. # Tests on route add and replace
  467. run_cmd()
  468. {
  469. local cmd="$1"
  470. local out
  471. local stderr="2>/dev/null"
  472. if [ "$VERBOSE" = "1" ]; then
  473. printf " COMMAND: $cmd\n"
  474. stderr=
  475. fi
  476. out=$(eval $cmd $stderr)
  477. rc=$?
  478. if [ "$VERBOSE" = "1" -a -n "$out" ]; then
  479. echo " $out"
  480. fi
  481. [ "$VERBOSE" = "1" ] && echo
  482. return $rc
  483. }
  484. # add route for a prefix, flushing any existing routes first
  485. # expected to be the first step of a test
  486. add_route6()
  487. {
  488. local pfx="$1"
  489. local nh="$2"
  490. local out
  491. if [ "$VERBOSE" = "1" ]; then
  492. echo
  493. echo " ##################################################"
  494. echo
  495. fi
  496. run_cmd "$IP -6 ro flush ${pfx}"
  497. [ $? -ne 0 ] && exit 1
  498. out=$($IP -6 ro ls match ${pfx})
  499. if [ -n "$out" ]; then
  500. echo "Failed to flush routes for prefix used for tests."
  501. exit 1
  502. fi
  503. run_cmd "$IP -6 ro add ${pfx} ${nh}"
  504. if [ $? -ne 0 ]; then
  505. echo "Failed to add initial route for test."
  506. exit 1
  507. fi
  508. }
  509. # add initial route - used in replace route tests
  510. add_initial_route6()
  511. {
  512. add_route6 "2001:db8:104::/64" "$1"
  513. }
  514. check_route6()
  515. {
  516. local pfx="2001:db8:104::/64"
  517. local expected="$1"
  518. local out
  519. local rc=0
  520. out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
  521. [ "${out}" = "${expected}" ] && return 0
  522. if [ -z "${out}" ]; then
  523. if [ "$VERBOSE" = "1" ]; then
  524. printf "\nNo route entry found\n"
  525. printf "Expected:\n"
  526. printf " ${expected}\n"
  527. fi
  528. return 1
  529. fi
  530. # tricky way to convert output to 1-line without ip's
  531. # messy '\'; this drops all extra white space
  532. out=$(echo ${out})
  533. if [ "${out}" != "${expected}" ]; then
  534. rc=1
  535. if [ "${VERBOSE}" = "1" ]; then
  536. printf " Unexpected route entry. Have:\n"
  537. printf " ${out}\n"
  538. printf " Expected:\n"
  539. printf " ${expected}\n\n"
  540. fi
  541. fi
  542. return $rc
  543. }
  544. route_cleanup()
  545. {
  546. $IP li del red 2>/dev/null
  547. $IP li del dummy1 2>/dev/null
  548. $IP li del veth1 2>/dev/null
  549. $IP li del veth3 2>/dev/null
  550. cleanup &> /dev/null
  551. }
  552. route_setup()
  553. {
  554. route_cleanup
  555. setup
  556. [ "${VERBOSE}" = "1" ] && set -x
  557. set -e
  558. $IP li add red up type vrf table 101
  559. $IP li add veth1 type veth peer name veth2
  560. $IP li add veth3 type veth peer name veth4
  561. $IP li set veth1 up
  562. $IP li set veth3 up
  563. $IP li set veth2 vrf red up
  564. $IP li set veth4 vrf red up
  565. $IP li add dummy1 type dummy
  566. $IP li set dummy1 vrf red up
  567. $IP -6 addr add 2001:db8:101::1/64 dev veth1
  568. $IP -6 addr add 2001:db8:101::2/64 dev veth2
  569. $IP -6 addr add 2001:db8:103::1/64 dev veth3
  570. $IP -6 addr add 2001:db8:103::2/64 dev veth4
  571. $IP -6 addr add 2001:db8:104::1/64 dev dummy1
  572. $IP addr add 172.16.101.1/24 dev veth1
  573. $IP addr add 172.16.101.2/24 dev veth2
  574. $IP addr add 172.16.103.1/24 dev veth3
  575. $IP addr add 172.16.103.2/24 dev veth4
  576. $IP addr add 172.16.104.1/24 dev dummy1
  577. set +ex
  578. }
  579. # assumption is that basic add of a single path route works
  580. # otherwise just adding an address on an interface is broken
  581. ipv6_rt_add()
  582. {
  583. local rc
  584. echo
  585. echo "IPv6 route add / append tests"
  586. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  587. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  588. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
  589. log_test $? 2 "Attempt to add duplicate route - gw"
  590. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  591. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  592. run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
  593. log_test $? 2 "Attempt to add duplicate route - dev only"
  594. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  595. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  596. run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
  597. log_test $? 2 "Attempt to add duplicate route - reject route"
  598. # route append with same prefix adds a new route
  599. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  600. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  601. run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
  602. 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"
  603. log_test $? 0 "Append nexthop to existing route - gw"
  604. # insert mpath directly
  605. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop 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 "Add multipath route"
  608. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  609. run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  610. log_test $? 2 "Attempt to add duplicate multipath route"
  611. # insert of a second route without append but different metric
  612. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  613. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
  614. rc=$?
  615. if [ $rc -eq 0 ]; then
  616. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
  617. rc=$?
  618. fi
  619. log_test $rc 0 "Route add with different metrics"
  620. run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
  621. rc=$?
  622. if [ $rc -eq 0 ]; then
  623. 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"
  624. rc=$?
  625. fi
  626. log_test $rc 0 "Route delete with metric"
  627. }
  628. ipv6_rt_replace_single()
  629. {
  630. # single path with single path
  631. #
  632. add_initial_route6 "via 2001:db8:101::2"
  633. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
  634. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  635. log_test $? 0 "Single path with single path"
  636. # single path with multipath
  637. #
  638. add_initial_route6 "nexthop via 2001:db8:101::2"
  639. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
  640. 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"
  641. log_test $? 0 "Single path with multipath"
  642. # single path with single path using MULTIPATH attribute
  643. #
  644. add_initial_route6 "via 2001:db8:101::2"
  645. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
  646. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  647. log_test $? 0 "Single path with single path via multipath attribute"
  648. # route replace fails - invalid nexthop
  649. add_initial_route6 "via 2001:db8:101::2"
  650. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
  651. if [ $? -eq 0 ]; then
  652. # previous command is expected to fail so if it returns 0
  653. # that means the test failed.
  654. log_test 0 1 "Invalid nexthop"
  655. else
  656. check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
  657. log_test $? 0 "Invalid nexthop"
  658. fi
  659. # replace non-existent route
  660. # - note use of change versus replace since ip adds NLM_F_CREATE
  661. # for replace
  662. add_initial_route6 "via 2001:db8:101::2"
  663. run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
  664. log_test $? 2 "Single path - replace of non-existent route"
  665. }
  666. ipv6_rt_replace_mpath()
  667. {
  668. # multipath with multipath
  669. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  670. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  671. 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"
  672. log_test $? 0 "Multipath with multipath"
  673. # multipath with single
  674. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  675. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
  676. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  677. log_test $? 0 "Multipath with single path"
  678. # multipath with single
  679. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  680. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
  681. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  682. log_test $? 0 "Multipath with single path via multipath attribute"
  683. # route replace fails - invalid nexthop 1
  684. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  685. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
  686. 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"
  687. log_test $? 0 "Multipath - invalid first nexthop"
  688. # route replace fails - invalid nexthop 2
  689. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  690. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
  691. 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"
  692. log_test $? 0 "Multipath - invalid second nexthop"
  693. # multipath non-existent route
  694. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  695. run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  696. log_test $? 2 "Multipath - replace of non-existent route"
  697. }
  698. ipv6_rt_replace()
  699. {
  700. echo
  701. echo "IPv6 route replace tests"
  702. ipv6_rt_replace_single
  703. ipv6_rt_replace_mpath
  704. }
  705. ipv6_route_test()
  706. {
  707. route_setup
  708. ipv6_rt_add
  709. ipv6_rt_replace
  710. route_cleanup
  711. }
  712. ip_addr_metric_check()
  713. {
  714. ip addr help 2>&1 | grep -q metric
  715. if [ $? -ne 0 ]; then
  716. echo "iproute2 command does not support metric for addresses. Skipping test"
  717. return 1
  718. fi
  719. return 0
  720. }
  721. ipv6_addr_metric_test()
  722. {
  723. local rc
  724. echo
  725. echo "IPv6 prefix route tests"
  726. ip_addr_metric_check || return 1
  727. setup
  728. set -e
  729. $IP li add dummy1 type dummy
  730. $IP li add dummy2 type dummy
  731. $IP li set dummy1 up
  732. $IP li set dummy2 up
  733. # default entry is metric 256
  734. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
  735. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
  736. set +e
  737. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
  738. log_test $? 0 "Default metric"
  739. set -e
  740. run_cmd "$IP -6 addr flush dev dummy1"
  741. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
  742. set +e
  743. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
  744. log_test $? 0 "User specified metric on first device"
  745. set -e
  746. run_cmd "$IP -6 addr flush dev dummy2"
  747. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
  748. set +e
  749. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  750. log_test $? 0 "User specified metric on second device"
  751. run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
  752. rc=$?
  753. if [ $rc -eq 0 ]; then
  754. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  755. rc=$?
  756. fi
  757. log_test $rc 0 "Delete of address on first device"
  758. run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
  759. rc=$?
  760. if [ $rc -eq 0 ]; then
  761. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  762. rc=$?
  763. fi
  764. log_test $rc 0 "Modify metric of address"
  765. # verify prefix route removed on down
  766. run_cmd "ip netns exec testns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
  767. run_cmd "$IP li set dev dummy2 down"
  768. rc=$?
  769. if [ $rc -eq 0 ]; then
  770. check_route6 ""
  771. rc=$?
  772. fi
  773. log_test $rc 0 "Prefix route removed on link down"
  774. # verify prefix route re-inserted with assigned metric
  775. run_cmd "$IP li set dev dummy2 up"
  776. rc=$?
  777. if [ $rc -eq 0 ]; then
  778. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  779. rc=$?
  780. fi
  781. log_test $rc 0 "Prefix route with metric on link up"
  782. $IP li del dummy1
  783. $IP li del dummy2
  784. cleanup
  785. }
  786. # add route for a prefix, flushing any existing routes first
  787. # expected to be the first step of a test
  788. add_route()
  789. {
  790. local pfx="$1"
  791. local nh="$2"
  792. local out
  793. if [ "$VERBOSE" = "1" ]; then
  794. echo
  795. echo " ##################################################"
  796. echo
  797. fi
  798. run_cmd "$IP ro flush ${pfx}"
  799. [ $? -ne 0 ] && exit 1
  800. out=$($IP ro ls match ${pfx})
  801. if [ -n "$out" ]; then
  802. echo "Failed to flush routes for prefix used for tests."
  803. exit 1
  804. fi
  805. run_cmd "$IP ro add ${pfx} ${nh}"
  806. if [ $? -ne 0 ]; then
  807. echo "Failed to add initial route for test."
  808. exit 1
  809. fi
  810. }
  811. # add initial route - used in replace route tests
  812. add_initial_route()
  813. {
  814. add_route "172.16.104.0/24" "$1"
  815. }
  816. check_route()
  817. {
  818. local pfx="172.16.104.0/24"
  819. local expected="$1"
  820. local out
  821. local rc=0
  822. out=$($IP ro ls match ${pfx})
  823. [ "${out}" = "${expected}" ] && return 0
  824. if [ -z "${out}" ]; then
  825. if [ "$VERBOSE" = "1" ]; then
  826. printf "\nNo route entry found\n"
  827. printf "Expected:\n"
  828. printf " ${expected}\n"
  829. fi
  830. return 1
  831. fi
  832. # tricky way to convert output to 1-line without ip's
  833. # messy '\'; this drops all extra white space
  834. out=$(echo ${out})
  835. if [ "${out}" != "${expected}" ]; then
  836. rc=1
  837. if [ "${VERBOSE}" = "1" ]; then
  838. printf " Unexpected route entry. Have:\n"
  839. printf " ${out}\n"
  840. printf " Expected:\n"
  841. printf " ${expected}\n\n"
  842. fi
  843. fi
  844. return $rc
  845. }
  846. # assumption is that basic add of a single path route works
  847. # otherwise just adding an address on an interface is broken
  848. ipv4_rt_add()
  849. {
  850. local rc
  851. echo
  852. echo "IPv4 route add / append tests"
  853. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  854. add_route "172.16.104.0/24" "via 172.16.101.2"
  855. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
  856. log_test $? 2 "Attempt to add duplicate route - gw"
  857. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  858. add_route "172.16.104.0/24" "via 172.16.101.2"
  859. run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
  860. log_test $? 2 "Attempt to add duplicate route - dev only"
  861. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  862. add_route "172.16.104.0/24" "via 172.16.101.2"
  863. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  864. log_test $? 2 "Attempt to add duplicate route - reject route"
  865. # iproute2 prepend only sets NLM_F_CREATE
  866. # - adds a new route; does NOT convert existing route to ECMP
  867. add_route "172.16.104.0/24" "via 172.16.101.2"
  868. run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
  869. 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"
  870. log_test $? 0 "Add new nexthop for existing prefix"
  871. # route append with same prefix adds a new route
  872. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  873. add_route "172.16.104.0/24" "via 172.16.101.2"
  874. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  875. 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"
  876. log_test $? 0 "Append nexthop to existing route - gw"
  877. add_route "172.16.104.0/24" "via 172.16.101.2"
  878. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  879. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
  880. log_test $? 0 "Append nexthop to existing route - dev only"
  881. add_route "172.16.104.0/24" "via 172.16.101.2"
  882. run_cmd "$IP ro append unreachable 172.16.104.0/24"
  883. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
  884. log_test $? 0 "Append nexthop to existing route - reject route"
  885. run_cmd "$IP ro flush 172.16.104.0/24"
  886. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  887. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  888. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
  889. log_test $? 0 "Append nexthop to existing reject route - gw"
  890. run_cmd "$IP ro flush 172.16.104.0/24"
  891. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  892. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  893. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
  894. log_test $? 0 "Append nexthop to existing reject route - dev only"
  895. # insert mpath directly
  896. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  897. 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"
  898. log_test $? 0 "add multipath route"
  899. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  900. run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  901. log_test $? 2 "Attempt to add duplicate multipath route"
  902. # insert of a second route without append but different metric
  903. add_route "172.16.104.0/24" "via 172.16.101.2"
  904. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
  905. rc=$?
  906. if [ $rc -eq 0 ]; then
  907. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
  908. rc=$?
  909. fi
  910. log_test $rc 0 "Route add with different metrics"
  911. run_cmd "$IP ro del 172.16.104.0/24 metric 512"
  912. rc=$?
  913. if [ $rc -eq 0 ]; then
  914. 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"
  915. rc=$?
  916. fi
  917. log_test $rc 0 "Route delete with metric"
  918. }
  919. ipv4_rt_replace_single()
  920. {
  921. # single path with single path
  922. #
  923. add_initial_route "via 172.16.101.2"
  924. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
  925. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  926. log_test $? 0 "Single path with single path"
  927. # single path with multipath
  928. #
  929. add_initial_route "nexthop via 172.16.101.2"
  930. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
  931. 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"
  932. log_test $? 0 "Single path with multipath"
  933. # single path with reject
  934. #
  935. add_initial_route "nexthop via 172.16.101.2"
  936. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  937. check_route "unreachable 172.16.104.0/24"
  938. log_test $? 0 "Single path with reject route"
  939. # single path with single path using MULTIPATH attribute
  940. #
  941. add_initial_route "via 172.16.101.2"
  942. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
  943. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  944. log_test $? 0 "Single path with single path via multipath attribute"
  945. # route replace fails - invalid nexthop
  946. add_initial_route "via 172.16.101.2"
  947. run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
  948. if [ $? -eq 0 ]; then
  949. # previous command is expected to fail so if it returns 0
  950. # that means the test failed.
  951. log_test 0 1 "Invalid nexthop"
  952. else
  953. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
  954. log_test $? 0 "Invalid nexthop"
  955. fi
  956. # replace non-existent route
  957. # - note use of change versus replace since ip adds NLM_F_CREATE
  958. # for replace
  959. add_initial_route "via 172.16.101.2"
  960. run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
  961. log_test $? 2 "Single path - replace of non-existent route"
  962. }
  963. ipv4_rt_replace_mpath()
  964. {
  965. # multipath with multipath
  966. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  967. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  968. 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"
  969. log_test $? 0 "Multipath with multipath"
  970. # multipath with single
  971. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  972. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
  973. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  974. log_test $? 0 "Multipath with single path"
  975. # multipath with single
  976. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  977. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
  978. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  979. log_test $? 0 "Multipath with single path via multipath attribute"
  980. # multipath with reject
  981. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  982. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  983. check_route "unreachable 172.16.104.0/24"
  984. log_test $? 0 "Multipath with reject route"
  985. # route replace fails - invalid nexthop 1
  986. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  987. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
  988. 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"
  989. log_test $? 0 "Multipath - invalid first nexthop"
  990. # route replace fails - invalid nexthop 2
  991. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  992. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
  993. 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"
  994. log_test $? 0 "Multipath - invalid second nexthop"
  995. # multipath non-existent route
  996. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  997. run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  998. log_test $? 2 "Multipath - replace of non-existent route"
  999. }
  1000. ipv4_rt_replace()
  1001. {
  1002. echo
  1003. echo "IPv4 route replace tests"
  1004. ipv4_rt_replace_single
  1005. ipv4_rt_replace_mpath
  1006. }
  1007. ipv4_route_test()
  1008. {
  1009. route_setup
  1010. ipv4_rt_add
  1011. ipv4_rt_replace
  1012. route_cleanup
  1013. }
  1014. ipv4_addr_metric_test()
  1015. {
  1016. local rc
  1017. echo
  1018. echo "IPv4 prefix route tests"
  1019. ip_addr_metric_check || return 1
  1020. setup
  1021. set -e
  1022. $IP li add dummy1 type dummy
  1023. $IP li add dummy2 type dummy
  1024. $IP li set dummy1 up
  1025. $IP li set dummy2 up
  1026. # default entry is metric 256
  1027. run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
  1028. run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
  1029. set +e
  1030. 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"
  1031. log_test $? 0 "Default metric"
  1032. set -e
  1033. run_cmd "$IP addr flush dev dummy1"
  1034. run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
  1035. set +e
  1036. 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"
  1037. log_test $? 0 "User specified metric on first device"
  1038. set -e
  1039. run_cmd "$IP addr flush dev dummy2"
  1040. run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
  1041. set +e
  1042. 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"
  1043. log_test $? 0 "User specified metric on second device"
  1044. run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
  1045. rc=$?
  1046. if [ $rc -eq 0 ]; then
  1047. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
  1048. rc=$?
  1049. fi
  1050. log_test $rc 0 "Delete of address on first device"
  1051. run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
  1052. rc=$?
  1053. if [ $rc -eq 0 ]; then
  1054. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1055. rc=$?
  1056. fi
  1057. log_test $rc 0 "Modify metric of address"
  1058. # verify prefix route removed on down
  1059. run_cmd "$IP li set dev dummy2 down"
  1060. rc=$?
  1061. if [ $rc -eq 0 ]; then
  1062. check_route ""
  1063. rc=$?
  1064. fi
  1065. log_test $rc 0 "Prefix route removed on link down"
  1066. # verify prefix route re-inserted with assigned metric
  1067. run_cmd "$IP li set dev dummy2 up"
  1068. rc=$?
  1069. if [ $rc -eq 0 ]; then
  1070. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1071. rc=$?
  1072. fi
  1073. log_test $rc 0 "Prefix route with metric on link up"
  1074. $IP li del dummy1
  1075. $IP li del dummy2
  1076. cleanup
  1077. }
  1078. ################################################################################
  1079. # usage
  1080. usage()
  1081. {
  1082. cat <<EOF
  1083. usage: ${0##*/} OPTS
  1084. -t <test> Test(s) to run (default: all)
  1085. (options: $TESTS)
  1086. -p Pause on fail
  1087. -P Pause after each test before cleanup
  1088. -v verbose mode (show commands and output)
  1089. EOF
  1090. }
  1091. ################################################################################
  1092. # main
  1093. while getopts :t:pPhv o
  1094. do
  1095. case $o in
  1096. t) TESTS=$OPTARG;;
  1097. p) PAUSE_ON_FAIL=yes;;
  1098. P) PAUSE=yes;;
  1099. v) VERBOSE=$(($VERBOSE + 1));;
  1100. h) usage; exit 0;;
  1101. *) usage; exit 1;;
  1102. esac
  1103. done
  1104. PEER_CMD="ip netns exec ${PEER_NS}"
  1105. # make sure we don't pause twice
  1106. [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
  1107. if [ "$(id -u)" -ne 0 ];then
  1108. echo "SKIP: Need root privileges"
  1109. exit $ksft_skip;
  1110. fi
  1111. if [ ! -x "$(command -v ip)" ]; then
  1112. echo "SKIP: Could not run test without ip tool"
  1113. exit $ksft_skip
  1114. fi
  1115. ip route help 2>&1 | grep -q fibmatch
  1116. if [ $? -ne 0 ]; then
  1117. echo "SKIP: iproute2 too old, missing fibmatch"
  1118. exit $ksft_skip
  1119. fi
  1120. # start clean
  1121. cleanup &> /dev/null
  1122. for t in $TESTS
  1123. do
  1124. case $t in
  1125. fib_unreg_test|unregister) fib_unreg_test;;
  1126. fib_down_test|down) fib_down_test;;
  1127. fib_carrier_test|carrier) fib_carrier_test;;
  1128. fib_nexthop_test|nexthop) fib_nexthop_test;;
  1129. ipv6_route_test|ipv6_rt) ipv6_route_test;;
  1130. ipv4_route_test|ipv4_rt) ipv4_route_test;;
  1131. ipv6_addr_metric) ipv6_addr_metric_test;;
  1132. ipv4_addr_metric) ipv4_addr_metric_test;;
  1133. help) echo "Test names: $TESTS"; exit 0;;
  1134. esac
  1135. done
  1136. if [ "$TESTS" != "none" ]; then
  1137. printf "\nTests passed: %3d\n" ${nsuccess}
  1138. printf "Tests failed: %3d\n" ${nfail}
  1139. fi
  1140. exit $ret