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