router_multipath.sh 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. ALL_TESTS="ping_ipv4 ping_ipv6 multipath_test"
  4. NUM_NETIFS=8
  5. source lib.sh
  6. h1_create()
  7. {
  8. vrf_create "vrf-h1"
  9. ip link set dev $h1 master vrf-h1
  10. ip link set dev vrf-h1 up
  11. ip link set dev $h1 up
  12. ip address add 192.0.2.2/24 dev $h1
  13. ip address add 2001:db8:1::2/64 dev $h1
  14. ip route add 198.51.100.0/24 vrf vrf-h1 nexthop via 192.0.2.1
  15. ip route add 2001:db8:2::/64 vrf vrf-h1 nexthop via 2001:db8:1::1
  16. }
  17. h1_destroy()
  18. {
  19. ip route del 2001:db8:2::/64 vrf vrf-h1
  20. ip route del 198.51.100.0/24 vrf vrf-h1
  21. ip address del 2001:db8:1::2/64 dev $h1
  22. ip address del 192.0.2.2/24 dev $h1
  23. ip link set dev $h1 down
  24. vrf_destroy "vrf-h1"
  25. }
  26. h2_create()
  27. {
  28. vrf_create "vrf-h2"
  29. ip link set dev $h2 master vrf-h2
  30. ip link set dev vrf-h2 up
  31. ip link set dev $h2 up
  32. ip address add 198.51.100.2/24 dev $h2
  33. ip address add 2001:db8:2::2/64 dev $h2
  34. ip route add 192.0.2.0/24 vrf vrf-h2 nexthop via 198.51.100.1
  35. ip route add 2001:db8:1::/64 vrf vrf-h2 nexthop via 2001:db8:2::1
  36. }
  37. h2_destroy()
  38. {
  39. ip route del 2001:db8:1::/64 vrf vrf-h2
  40. ip route del 192.0.2.0/24 vrf vrf-h2
  41. ip address del 2001:db8:2::2/64 dev $h2
  42. ip address del 198.51.100.2/24 dev $h2
  43. ip link set dev $h2 down
  44. vrf_destroy "vrf-h2"
  45. }
  46. router1_create()
  47. {
  48. vrf_create "vrf-r1"
  49. ip link set dev $rp11 master vrf-r1
  50. ip link set dev $rp12 master vrf-r1
  51. ip link set dev $rp13 master vrf-r1
  52. ip link set dev vrf-r1 up
  53. ip link set dev $rp11 up
  54. ip link set dev $rp12 up
  55. ip link set dev $rp13 up
  56. ip address add 192.0.2.1/24 dev $rp11
  57. ip address add 2001:db8:1::1/64 dev $rp11
  58. ip address add 169.254.2.12/24 dev $rp12
  59. ip address add fe80:2::12/64 dev $rp12
  60. ip address add 169.254.3.13/24 dev $rp13
  61. ip address add fe80:3::13/64 dev $rp13
  62. ip route add 198.51.100.0/24 vrf vrf-r1 \
  63. nexthop via 169.254.2.22 dev $rp12 \
  64. nexthop via 169.254.3.23 dev $rp13
  65. ip route add 2001:db8:2::/64 vrf vrf-r1 \
  66. nexthop via fe80:2::22 dev $rp12 \
  67. nexthop via fe80:3::23 dev $rp13
  68. }
  69. router1_destroy()
  70. {
  71. ip route del 2001:db8:2::/64 vrf vrf-r1
  72. ip route del 198.51.100.0/24 vrf vrf-r1
  73. ip address del fe80:3::13/64 dev $rp13
  74. ip address del 169.254.3.13/24 dev $rp13
  75. ip address del fe80:2::12/64 dev $rp12
  76. ip address del 169.254.2.12/24 dev $rp12
  77. ip address del 2001:db8:1::1/64 dev $rp11
  78. ip address del 192.0.2.1/24 dev $rp11
  79. ip link set dev $rp13 down
  80. ip link set dev $rp12 down
  81. ip link set dev $rp11 down
  82. vrf_destroy "vrf-r1"
  83. }
  84. router2_create()
  85. {
  86. vrf_create "vrf-r2"
  87. ip link set dev $rp21 master vrf-r2
  88. ip link set dev $rp22 master vrf-r2
  89. ip link set dev $rp23 master vrf-r2
  90. ip link set dev vrf-r2 up
  91. ip link set dev $rp21 up
  92. ip link set dev $rp22 up
  93. ip link set dev $rp23 up
  94. ip address add 198.51.100.1/24 dev $rp21
  95. ip address add 2001:db8:2::1/64 dev $rp21
  96. ip address add 169.254.2.22/24 dev $rp22
  97. ip address add fe80:2::22/64 dev $rp22
  98. ip address add 169.254.3.23/24 dev $rp23
  99. ip address add fe80:3::23/64 dev $rp23
  100. ip route add 192.0.2.0/24 vrf vrf-r2 \
  101. nexthop via 169.254.2.12 dev $rp22 \
  102. nexthop via 169.254.3.13 dev $rp23
  103. ip route add 2001:db8:1::/64 vrf vrf-r2 \
  104. nexthop via fe80:2::12 dev $rp22 \
  105. nexthop via fe80:3::13 dev $rp23
  106. }
  107. router2_destroy()
  108. {
  109. ip route del 2001:db8:1::/64 vrf vrf-r2
  110. ip route del 192.0.2.0/24 vrf vrf-r2
  111. ip address del fe80:3::23/64 dev $rp23
  112. ip address del 169.254.3.23/24 dev $rp23
  113. ip address del fe80:2::22/64 dev $rp22
  114. ip address del 169.254.2.22/24 dev $rp22
  115. ip address del 2001:db8:2::1/64 dev $rp21
  116. ip address del 198.51.100.1/24 dev $rp21
  117. ip link set dev $rp23 down
  118. ip link set dev $rp22 down
  119. ip link set dev $rp21 down
  120. vrf_destroy "vrf-r2"
  121. }
  122. multipath_eval()
  123. {
  124. local desc="$1"
  125. local weight_rp12=$2
  126. local weight_rp13=$3
  127. local packets_rp12=$4
  128. local packets_rp13=$5
  129. local weights_ratio packets_ratio diff
  130. RET=0
  131. if [[ "$packets_rp12" -eq "0" || "$packets_rp13" -eq "0" ]]; then
  132. check_err 1 "Packet difference is 0"
  133. log_test "Multipath"
  134. log_info "Expected ratio $weights_ratio"
  135. return
  136. fi
  137. if [[ "$weight_rp12" -gt "$weight_rp13" ]]; then
  138. weights_ratio=$(echo "scale=2; $weight_rp12 / $weight_rp13" \
  139. | bc -l)
  140. packets_ratio=$(echo "scale=2; $packets_rp12 / $packets_rp13" \
  141. | bc -l)
  142. else
  143. weights_ratio=$(echo "scale=2; $weight_rp13 / $weight_rp12" | \
  144. bc -l)
  145. packets_ratio=$(echo "scale=2; $packets_rp13 / $packets_rp12" | \
  146. bc -l)
  147. fi
  148. diff=$(echo $weights_ratio - $packets_ratio | bc -l)
  149. diff=${diff#-}
  150. test "$(echo "$diff / $weights_ratio > 0.15" | bc -l)" -eq 0
  151. check_err $? "Too large discrepancy between expected and measured ratios"
  152. log_test "$desc"
  153. log_info "Expected ratio $weights_ratio Measured ratio $packets_ratio"
  154. }
  155. multipath4_test()
  156. {
  157. local desc="$1"
  158. local weight_rp12=$2
  159. local weight_rp13=$3
  160. local t0_rp12 t0_rp13 t1_rp12 t1_rp13
  161. local packets_rp12 packets_rp13
  162. # Transmit multiple flows from h1 to h2 and make sure they are
  163. # distributed between both multipath links (rp12 and rp13)
  164. # according to the configured weights.
  165. sysctl_set net.ipv4.fib_multipath_hash_policy 1
  166. ip route replace 198.51.100.0/24 vrf vrf-r1 \
  167. nexthop via 169.254.2.22 dev $rp12 weight $weight_rp12 \
  168. nexthop via 169.254.3.23 dev $rp13 weight $weight_rp13
  169. t0_rp12=$(link_stats_tx_packets_get $rp12)
  170. t0_rp13=$(link_stats_tx_packets_get $rp13)
  171. ip vrf exec vrf-h1 $MZ -q -p 64 -A 192.0.2.2 -B 198.51.100.2 \
  172. -d 1msec -t udp "sp=1024,dp=0-32768"
  173. t1_rp12=$(link_stats_tx_packets_get $rp12)
  174. t1_rp13=$(link_stats_tx_packets_get $rp13)
  175. let "packets_rp12 = $t1_rp12 - $t0_rp12"
  176. let "packets_rp13 = $t1_rp13 - $t0_rp13"
  177. multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
  178. # Restore settings.
  179. ip route replace 198.51.100.0/24 vrf vrf-r1 \
  180. nexthop via 169.254.2.22 dev $rp12 \
  181. nexthop via 169.254.3.23 dev $rp13
  182. sysctl_restore net.ipv4.fib_multipath_hash_policy
  183. }
  184. multipath6_l4_test()
  185. {
  186. local desc="$1"
  187. local weight_rp12=$2
  188. local weight_rp13=$3
  189. local t0_rp12 t0_rp13 t1_rp12 t1_rp13
  190. local packets_rp12 packets_rp13
  191. # Transmit multiple flows from h1 to h2 and make sure they are
  192. # distributed between both multipath links (rp12 and rp13)
  193. # according to the configured weights.
  194. sysctl_set net.ipv6.fib_multipath_hash_policy 1
  195. ip route replace 2001:db8:2::/64 vrf vrf-r1 \
  196. nexthop via fe80:2::22 dev $rp12 weight $weight_rp12 \
  197. nexthop via fe80:3::23 dev $rp13 weight $weight_rp13
  198. t0_rp12=$(link_stats_tx_packets_get $rp12)
  199. t0_rp13=$(link_stats_tx_packets_get $rp13)
  200. $MZ $h1 -6 -q -p 64 -A 2001:db8:1::2 -B 2001:db8:2::2 \
  201. -d 1msec -t udp "sp=1024,dp=0-32768"
  202. t1_rp12=$(link_stats_tx_packets_get $rp12)
  203. t1_rp13=$(link_stats_tx_packets_get $rp13)
  204. let "packets_rp12 = $t1_rp12 - $t0_rp12"
  205. let "packets_rp13 = $t1_rp13 - $t0_rp13"
  206. multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
  207. ip route replace 2001:db8:2::/64 vrf vrf-r1 \
  208. nexthop via fe80:2::22 dev $rp12 \
  209. nexthop via fe80:3::23 dev $rp13
  210. sysctl_restore net.ipv6.fib_multipath_hash_policy
  211. }
  212. multipath6_test()
  213. {
  214. local desc="$1"
  215. local weight_rp12=$2
  216. local weight_rp13=$3
  217. local t0_rp12 t0_rp13 t1_rp12 t1_rp13
  218. local packets_rp12 packets_rp13
  219. ip route replace 2001:db8:2::/64 vrf vrf-r1 \
  220. nexthop via fe80:2::22 dev $rp12 weight $weight_rp12 \
  221. nexthop via fe80:3::23 dev $rp13 weight $weight_rp13
  222. t0_rp12=$(link_stats_tx_packets_get $rp12)
  223. t0_rp13=$(link_stats_tx_packets_get $rp13)
  224. # Generate 16384 echo requests, each with a random flow label.
  225. for _ in $(seq 1 16384); do
  226. ip vrf exec vrf-h1 $PING6 2001:db8:2::2 -F 0 -c 1 -q &> /dev/null
  227. done
  228. t1_rp12=$(link_stats_tx_packets_get $rp12)
  229. t1_rp13=$(link_stats_tx_packets_get $rp13)
  230. let "packets_rp12 = $t1_rp12 - $t0_rp12"
  231. let "packets_rp13 = $t1_rp13 - $t0_rp13"
  232. multipath_eval "$desc" $weight_rp12 $weight_rp13 $packets_rp12 $packets_rp13
  233. ip route replace 2001:db8:2::/64 vrf vrf-r1 \
  234. nexthop via fe80:2::22 dev $rp12 \
  235. nexthop via fe80:3::23 dev $rp13
  236. }
  237. multipath_test()
  238. {
  239. log_info "Running IPv4 multipath tests"
  240. multipath4_test "ECMP" 1 1
  241. multipath4_test "Weighted MP 2:1" 2 1
  242. multipath4_test "Weighted MP 11:45" 11 45
  243. log_info "Running IPv6 multipath tests"
  244. multipath6_test "ECMP" 1 1
  245. multipath6_test "Weighted MP 2:1" 2 1
  246. multipath6_test "Weighted MP 11:45" 11 45
  247. log_info "Running IPv6 L4 hash multipath tests"
  248. multipath6_l4_test "ECMP" 1 1
  249. multipath6_l4_test "Weighted MP 2:1" 2 1
  250. multipath6_l4_test "Weighted MP 11:45" 11 45
  251. }
  252. setup_prepare()
  253. {
  254. h1=${NETIFS[p1]}
  255. rp11=${NETIFS[p2]}
  256. rp12=${NETIFS[p3]}
  257. rp22=${NETIFS[p4]}
  258. rp13=${NETIFS[p5]}
  259. rp23=${NETIFS[p6]}
  260. rp21=${NETIFS[p7]}
  261. h2=${NETIFS[p8]}
  262. vrf_prepare
  263. h1_create
  264. h2_create
  265. router1_create
  266. router2_create
  267. forwarding_enable
  268. }
  269. cleanup()
  270. {
  271. pre_cleanup
  272. forwarding_restore
  273. router2_destroy
  274. router1_destroy
  275. h2_destroy
  276. h1_destroy
  277. vrf_cleanup
  278. }
  279. ping_ipv4()
  280. {
  281. ping_test $h1 198.51.100.2
  282. }
  283. ping_ipv6()
  284. {
  285. ping6_test $h1 2001:db8:2::2
  286. }
  287. trap cleanup EXIT
  288. setup_prepare
  289. setup_wait
  290. tests_run
  291. exit $EXIT_STATUS