Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: forwarding: Add resilient hashing test

Verify that IPv4 and IPv6 multipath forwarding works correctly with
resilient nexthop groups and with different weights.

Test that when the idle timer is not zero, the resilient groups are not
rebalanced - because the nexthop buckets are considered active - and the
initial weights (1:1) are used.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
386e3792 557205f4

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