fib_tests.sh 41 KB

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