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