fib_tests.sh 39 KB

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