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. 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. # iproute2 prepend only sets NLM_F_CREATE
  599. # - adds a new route; does NOT convert existing route to ECMP
  600. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  601. run_cmd "$IP -6 ro prepend 2001:db8:104::/64 via 2001:db8:103::2"
  602. check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024 2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  603. log_test $? 0 "Add new route for existing prefix (w/o NLM_F_EXCL)"
  604. # route append with same prefix adds a new route
  605. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  606. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  607. run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
  608. 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"
  609. log_test $? 0 "Append nexthop to existing route - gw"
  610. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  611. run_cmd "$IP -6 ro append 2001:db8:104::/64 dev veth3"
  612. check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop dev veth3 weight 1"
  613. log_test $? 0 "Append nexthop to existing route - dev only"
  614. # multipath route can not have a nexthop that is a reject route
  615. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  616. run_cmd "$IP -6 ro append unreachable 2001:db8:104::/64"
  617. log_test $? 2 "Append nexthop to existing route - reject route"
  618. # reject route can not be converted to multipath route
  619. run_cmd "$IP -6 ro flush 2001:db8:104::/64"
  620. run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
  621. run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
  622. log_test $? 2 "Append nexthop to existing reject route - gw"
  623. run_cmd "$IP -6 ro flush 2001:db8:104::/64"
  624. run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
  625. run_cmd "$IP -6 ro append 2001:db8:104::/64 dev veth3"
  626. log_test $? 2 "Append nexthop to existing reject route - dev only"
  627. # insert mpath directly
  628. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  629. 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"
  630. log_test $? 0 "Add multipath route"
  631. add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  632. run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  633. log_test $? 2 "Attempt to add duplicate multipath route"
  634. # insert of a second route without append but different metric
  635. add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
  636. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
  637. rc=$?
  638. if [ $rc -eq 0 ]; then
  639. run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
  640. rc=$?
  641. fi
  642. log_test $rc 0 "Route add with different metrics"
  643. run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
  644. rc=$?
  645. if [ $rc -eq 0 ]; then
  646. 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"
  647. rc=$?
  648. fi
  649. log_test $rc 0 "Route delete with metric"
  650. }
  651. ipv6_rt_replace_single()
  652. {
  653. # single path with single path
  654. #
  655. add_initial_route6 "via 2001:db8:101::2"
  656. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
  657. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  658. log_test $? 0 "Single path with single path"
  659. # single path with multipath
  660. #
  661. add_initial_route6 "nexthop via 2001:db8:101::2"
  662. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
  663. 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"
  664. log_test $? 0 "Single path with multipath"
  665. # single path with reject
  666. #
  667. add_initial_route6 "nexthop via 2001:db8:101::2"
  668. run_cmd "$IP -6 ro replace unreachable 2001:db8:104::/64"
  669. check_route6 "unreachable 2001:db8:104::/64 dev lo metric 1024"
  670. log_test $? 0 "Single path with reject route"
  671. # single path with single path using MULTIPATH attribute
  672. #
  673. add_initial_route6 "via 2001:db8:101::2"
  674. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
  675. check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
  676. log_test $? 0 "Single path with single path via multipath attribute"
  677. # route replace fails - invalid nexthop
  678. add_initial_route6 "via 2001:db8:101::2"
  679. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
  680. if [ $? -eq 0 ]; then
  681. # previous command is expected to fail so if it returns 0
  682. # that means the test failed.
  683. log_test 0 1 "Invalid nexthop"
  684. else
  685. check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
  686. log_test $? 0 "Invalid nexthop"
  687. fi
  688. # replace non-existent route
  689. # - note use of change versus replace since ip adds NLM_F_CREATE
  690. # for replace
  691. add_initial_route6 "via 2001:db8:101::2"
  692. run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
  693. log_test $? 2 "Single path - replace of non-existent route"
  694. }
  695. ipv6_rt_replace_mpath()
  696. {
  697. # multipath with multipath
  698. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  699. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  700. 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"
  701. log_test $? 0 "Multipath with multipath"
  702. # multipath with single
  703. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  704. run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
  705. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  706. log_test $? 0 "Multipath with single path"
  707. # multipath with single
  708. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  709. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
  710. check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
  711. log_test $? 0 "Multipath with single path via multipath attribute"
  712. # multipath with reject
  713. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  714. run_cmd "$IP -6 ro replace unreachable 2001:db8:104::/64"
  715. check_route6 "unreachable 2001:db8:104::/64 dev lo metric 1024"
  716. log_test $? 0 "Multipath with reject route"
  717. # route replace fails - invalid nexthop 1
  718. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  719. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
  720. 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"
  721. log_test $? 0 "Multipath - invalid first nexthop"
  722. # route replace fails - invalid nexthop 2
  723. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  724. run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
  725. 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"
  726. log_test $? 0 "Multipath - invalid second nexthop"
  727. # multipath non-existent route
  728. add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
  729. run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
  730. log_test $? 2 "Multipath - replace of non-existent route"
  731. }
  732. ipv6_rt_replace()
  733. {
  734. echo
  735. echo "IPv6 route replace tests"
  736. ipv6_rt_replace_single
  737. ipv6_rt_replace_mpath
  738. }
  739. ipv6_route_test()
  740. {
  741. route_setup
  742. ipv6_rt_add
  743. ipv6_rt_replace
  744. route_cleanup
  745. }
  746. ip_addr_metric_check()
  747. {
  748. ip addr help 2>&1 | grep -q metric
  749. if [ $? -ne 0 ]; then
  750. echo "iproute2 command does not support metric for addresses. Skipping test"
  751. return 1
  752. fi
  753. return 0
  754. }
  755. ipv6_addr_metric_test()
  756. {
  757. local rc
  758. echo
  759. echo "IPv6 prefix route tests"
  760. ip_addr_metric_check || return 1
  761. setup
  762. set -e
  763. $IP li add dummy1 type dummy
  764. $IP li add dummy2 type dummy
  765. $IP li set dummy1 up
  766. $IP li set dummy2 up
  767. # default entry is metric 256
  768. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
  769. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
  770. set +e
  771. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
  772. log_test $? 0 "Default metric"
  773. set -e
  774. run_cmd "$IP -6 addr flush dev dummy1"
  775. run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
  776. set +e
  777. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
  778. log_test $? 0 "User specified metric on first device"
  779. set -e
  780. run_cmd "$IP -6 addr flush dev dummy2"
  781. run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
  782. set +e
  783. check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  784. log_test $? 0 "User specified metric on second device"
  785. run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
  786. rc=$?
  787. if [ $rc -eq 0 ]; then
  788. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
  789. rc=$?
  790. fi
  791. log_test $rc 0 "Delete of address on first device"
  792. run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
  793. rc=$?
  794. if [ $rc -eq 0 ]; then
  795. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  796. rc=$?
  797. fi
  798. log_test $rc 0 "Modify metric of address"
  799. # verify prefix route removed on down
  800. run_cmd "ip netns exec testns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
  801. run_cmd "$IP li set dev dummy2 down"
  802. rc=$?
  803. if [ $rc -eq 0 ]; then
  804. check_route6 ""
  805. rc=$?
  806. fi
  807. log_test $rc 0 "Prefix route removed on link down"
  808. # verify prefix route re-inserted with assigned metric
  809. run_cmd "$IP li set dev dummy2 up"
  810. rc=$?
  811. if [ $rc -eq 0 ]; then
  812. check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
  813. rc=$?
  814. fi
  815. log_test $rc 0 "Prefix route with metric on link up"
  816. $IP li del dummy1
  817. $IP li del dummy2
  818. cleanup
  819. }
  820. # add route for a prefix, flushing any existing routes first
  821. # expected to be the first step of a test
  822. add_route()
  823. {
  824. local pfx="$1"
  825. local nh="$2"
  826. local out
  827. if [ "$VERBOSE" = "1" ]; then
  828. echo
  829. echo " ##################################################"
  830. echo
  831. fi
  832. run_cmd "$IP ro flush ${pfx}"
  833. [ $? -ne 0 ] && exit 1
  834. out=$($IP ro ls match ${pfx})
  835. if [ -n "$out" ]; then
  836. echo "Failed to flush routes for prefix used for tests."
  837. exit 1
  838. fi
  839. run_cmd "$IP ro add ${pfx} ${nh}"
  840. if [ $? -ne 0 ]; then
  841. echo "Failed to add initial route for test."
  842. exit 1
  843. fi
  844. }
  845. # add initial route - used in replace route tests
  846. add_initial_route()
  847. {
  848. add_route "172.16.104.0/24" "$1"
  849. }
  850. check_route()
  851. {
  852. local pfx="172.16.104.0/24"
  853. local expected="$1"
  854. local out
  855. local rc=0
  856. out=$($IP ro ls match ${pfx})
  857. [ "${out}" = "${expected}" ] && return 0
  858. if [ -z "${out}" ]; then
  859. if [ "$VERBOSE" = "1" ]; then
  860. printf "\nNo route entry found\n"
  861. printf "Expected:\n"
  862. printf " ${expected}\n"
  863. fi
  864. return 1
  865. fi
  866. # tricky way to convert output to 1-line without ip's
  867. # messy '\'; this drops all extra white space
  868. out=$(echo ${out})
  869. if [ "${out}" != "${expected}" ]; then
  870. rc=1
  871. if [ "${VERBOSE}" = "1" ]; then
  872. printf " Unexpected route entry. Have:\n"
  873. printf " ${out}\n"
  874. printf " Expected:\n"
  875. printf " ${expected}\n\n"
  876. fi
  877. fi
  878. return $rc
  879. }
  880. # assumption is that basic add of a single path route works
  881. # otherwise just adding an address on an interface is broken
  882. ipv4_rt_add()
  883. {
  884. local rc
  885. echo
  886. echo "IPv4 route add / append tests"
  887. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  888. add_route "172.16.104.0/24" "via 172.16.101.2"
  889. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
  890. log_test $? 2 "Attempt to add duplicate route - gw"
  891. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  892. add_route "172.16.104.0/24" "via 172.16.101.2"
  893. run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
  894. log_test $? 2 "Attempt to add duplicate route - dev only"
  895. # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
  896. add_route "172.16.104.0/24" "via 172.16.101.2"
  897. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  898. log_test $? 2 "Attempt to add duplicate route - reject route"
  899. # iproute2 prepend only sets NLM_F_CREATE
  900. # - adds a new route; does NOT convert existing route to ECMP
  901. add_route "172.16.104.0/24" "via 172.16.101.2"
  902. run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
  903. 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"
  904. log_test $? 0 "Add new nexthop for existing prefix"
  905. # route append with same prefix adds a new route
  906. # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
  907. add_route "172.16.104.0/24" "via 172.16.101.2"
  908. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  909. 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"
  910. log_test $? 0 "Append nexthop to existing route - gw"
  911. add_route "172.16.104.0/24" "via 172.16.101.2"
  912. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  913. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
  914. log_test $? 0 "Append nexthop to existing route - dev only"
  915. add_route "172.16.104.0/24" "via 172.16.101.2"
  916. run_cmd "$IP ro append unreachable 172.16.104.0/24"
  917. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
  918. log_test $? 0 "Append nexthop to existing route - reject route"
  919. run_cmd "$IP ro flush 172.16.104.0/24"
  920. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  921. run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
  922. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
  923. log_test $? 0 "Append nexthop to existing reject route - gw"
  924. run_cmd "$IP ro flush 172.16.104.0/24"
  925. run_cmd "$IP ro add unreachable 172.16.104.0/24"
  926. run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
  927. check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
  928. log_test $? 0 "Append nexthop to existing reject route - dev only"
  929. # insert mpath directly
  930. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  931. 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"
  932. log_test $? 0 "add multipath route"
  933. add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  934. run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  935. log_test $? 2 "Attempt to add duplicate multipath route"
  936. # insert of a second route without append but different metric
  937. add_route "172.16.104.0/24" "via 172.16.101.2"
  938. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
  939. rc=$?
  940. if [ $rc -eq 0 ]; then
  941. run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
  942. rc=$?
  943. fi
  944. log_test $rc 0 "Route add with different metrics"
  945. run_cmd "$IP ro del 172.16.104.0/24 metric 512"
  946. rc=$?
  947. if [ $rc -eq 0 ]; then
  948. 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"
  949. rc=$?
  950. fi
  951. log_test $rc 0 "Route delete with metric"
  952. }
  953. ipv4_rt_replace_single()
  954. {
  955. # single path with single path
  956. #
  957. add_initial_route "via 172.16.101.2"
  958. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
  959. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  960. log_test $? 0 "Single path with single path"
  961. # single path with multipath
  962. #
  963. add_initial_route "nexthop via 172.16.101.2"
  964. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
  965. 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"
  966. log_test $? 0 "Single path with multipath"
  967. # single path with reject
  968. #
  969. add_initial_route "nexthop via 172.16.101.2"
  970. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  971. check_route "unreachable 172.16.104.0/24"
  972. log_test $? 0 "Single path with reject route"
  973. # single path with single path using MULTIPATH attribute
  974. #
  975. add_initial_route "via 172.16.101.2"
  976. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
  977. check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
  978. log_test $? 0 "Single path with single path via multipath attribute"
  979. # route replace fails - invalid nexthop
  980. add_initial_route "via 172.16.101.2"
  981. run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
  982. if [ $? -eq 0 ]; then
  983. # previous command is expected to fail so if it returns 0
  984. # that means the test failed.
  985. log_test 0 1 "Invalid nexthop"
  986. else
  987. check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
  988. log_test $? 0 "Invalid nexthop"
  989. fi
  990. # replace non-existent route
  991. # - note use of change versus replace since ip adds NLM_F_CREATE
  992. # for replace
  993. add_initial_route "via 172.16.101.2"
  994. run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
  995. log_test $? 2 "Single path - replace of non-existent route"
  996. }
  997. ipv4_rt_replace_mpath()
  998. {
  999. # multipath with multipath
  1000. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1001. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  1002. 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"
  1003. log_test $? 0 "Multipath with multipath"
  1004. # multipath with single
  1005. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1006. run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
  1007. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  1008. log_test $? 0 "Multipath with single path"
  1009. # multipath with single
  1010. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1011. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
  1012. check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
  1013. log_test $? 0 "Multipath with single path via multipath attribute"
  1014. # multipath with reject
  1015. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1016. run_cmd "$IP ro replace unreachable 172.16.104.0/24"
  1017. check_route "unreachable 172.16.104.0/24"
  1018. log_test $? 0 "Multipath with reject route"
  1019. # route replace fails - invalid nexthop 1
  1020. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1021. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
  1022. 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"
  1023. log_test $? 0 "Multipath - invalid first nexthop"
  1024. # route replace fails - invalid nexthop 2
  1025. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1026. run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
  1027. 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"
  1028. log_test $? 0 "Multipath - invalid second nexthop"
  1029. # multipath non-existent route
  1030. add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
  1031. run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
  1032. log_test $? 2 "Multipath - replace of non-existent route"
  1033. }
  1034. ipv4_rt_replace()
  1035. {
  1036. echo
  1037. echo "IPv4 route replace tests"
  1038. ipv4_rt_replace_single
  1039. ipv4_rt_replace_mpath
  1040. }
  1041. ipv4_route_test()
  1042. {
  1043. route_setup
  1044. ipv4_rt_add
  1045. ipv4_rt_replace
  1046. route_cleanup
  1047. }
  1048. ipv4_addr_metric_test()
  1049. {
  1050. local rc
  1051. echo
  1052. echo "IPv4 prefix route tests"
  1053. ip_addr_metric_check || return 1
  1054. setup
  1055. set -e
  1056. $IP li add dummy1 type dummy
  1057. $IP li add dummy2 type dummy
  1058. $IP li set dummy1 up
  1059. $IP li set dummy2 up
  1060. # default entry is metric 256
  1061. run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
  1062. run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
  1063. set +e
  1064. 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"
  1065. log_test $? 0 "Default metric"
  1066. set -e
  1067. run_cmd "$IP addr flush dev dummy1"
  1068. run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
  1069. set +e
  1070. 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"
  1071. log_test $? 0 "User specified metric on first device"
  1072. set -e
  1073. run_cmd "$IP addr flush dev dummy2"
  1074. run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
  1075. set +e
  1076. 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"
  1077. log_test $? 0 "User specified metric on second device"
  1078. run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
  1079. rc=$?
  1080. if [ $rc -eq 0 ]; then
  1081. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
  1082. rc=$?
  1083. fi
  1084. log_test $rc 0 "Delete of address on first device"
  1085. run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
  1086. rc=$?
  1087. if [ $rc -eq 0 ]; then
  1088. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1089. rc=$?
  1090. fi
  1091. log_test $rc 0 "Modify metric of address"
  1092. # verify prefix route removed on down
  1093. run_cmd "$IP li set dev dummy2 down"
  1094. rc=$?
  1095. if [ $rc -eq 0 ]; then
  1096. check_route ""
  1097. rc=$?
  1098. fi
  1099. log_test $rc 0 "Prefix route removed on link down"
  1100. # verify prefix route re-inserted with assigned metric
  1101. run_cmd "$IP li set dev dummy2 up"
  1102. rc=$?
  1103. if [ $rc -eq 0 ]; then
  1104. check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
  1105. rc=$?
  1106. fi
  1107. log_test $rc 0 "Prefix route with metric on link up"
  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