1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Test traffic distribution when there are multiple paths between an IPv4 GRE 5# tunnel. The tunnel carries IPv4 and IPv6 traffic between multiple hosts. 6# Multiple routes are in the underlay network. With the default multipath 7# policy, SW2 will only look at the outer IP addresses, hence only a single 8# route would be used. 9# 10# +--------------------------------+ 11# | H1 | 12# | $h1 + | 13# | 198.51.100.{2-253}/24 | | 14# | 2001:db8:1::{2-fd}/64 | | 15# +-------------------------|------+ 16# | 17# +-------------------------|------------------+ 18# | SW1 | | 19# | $ol1 + | 20# | 198.51.100.1/24 | 21# | 2001:db8:1::1/64 | 22# | | 23# | + g1 (gre) | 24# | loc=192.0.2.1 | 25# | rem=192.0.2.2 --. | 26# | tos=inherit | | 27# | v | 28# | + $ul1 | 29# | | 192.0.2.17/28 | 30# +---------------------|----------------------+ 31# | 32# +---------------------|----------------------+ 33# | SW2 | | 34# | $ul21 + | 35# | 192.0.2.18/28 | | 36# | | | 37# ! __________________+___ | 38# | / \ | 39# | | | | 40# | + $ul22.111 (vlan) + $ul22.222 (vlan) | 41# | | 192.0.2.33/28 | 192.0.2.49/28 | 42# | | | | 43# +--|----------------------|------------------+ 44# | | 45# +--|----------------------|------------------+ 46# | | | | 47# | + $ul32.111 (vlan) + $ul32.222 (vlan) | 48# | | 192.0.2.34/28 | 192.0.2.50/28 | 49# | | | | 50# | \__________________+___/ | 51# | | | 52# | | | 53# | $ul31 + | 54# | 192.0.2.65/28 | SW3 | 55# +---------------------|----------------------+ 56# | 57# +---------------------|----------------------+ 58# | + $ul4 | 59# | ^ 192.0.2.66/28 | 60# | | | 61# | + g2 (gre) | | 62# | loc=192.0.2.2 | | 63# | rem=192.0.2.1 --' | 64# | tos=inherit | 65# | | 66# | $ol4 + | 67# | 203.0.113.1/24 | | 68# | 2001:db8:2::1/64 | SW4 | 69# +-------------------------|------------------+ 70# | 71# +-------------------------|------+ 72# | | | 73# | $h2 + | 74# | 203.0.113.{2-253}/24 | 75# | 2001:db8:2::{2-fd}/64 H2 | 76# +--------------------------------+ 77 78ALL_TESTS=" 79 ping_ipv4 80 ping_ipv6 81 custom_hash 82" 83 84NUM_NETIFS=10 85source lib.sh 86 87h1_create() 88{ 89 simple_if_init $h1 198.51.100.2/24 2001:db8:1::2/64 90 ip route add vrf v$h1 default via 198.51.100.1 dev $h1 91 ip -6 route add vrf v$h1 default via 2001:db8:1::1 dev $h1 92} 93 94h1_destroy() 95{ 96 ip -6 route del vrf v$h1 default 97 ip route del vrf v$h1 default 98 simple_if_fini $h1 198.51.100.2/24 2001:db8:1::2/64 99} 100 101sw1_create() 102{ 103 simple_if_init $ol1 198.51.100.1/24 2001:db8:1::1/64 104 __simple_if_init $ul1 v$ol1 192.0.2.17/28 105 106 tunnel_create g1 gre 192.0.2.1 192.0.2.2 tos inherit dev v$ol1 107 __simple_if_init g1 v$ol1 192.0.2.1/32 108 ip route add vrf v$ol1 192.0.2.2/32 via 192.0.2.18 109 110 ip route add vrf v$ol1 203.0.113.0/24 dev g1 111 ip -6 route add vrf v$ol1 2001:db8:2::/64 dev g1 112} 113 114sw1_destroy() 115{ 116 ip -6 route del vrf v$ol1 2001:db8:2::/64 117 ip route del vrf v$ol1 203.0.113.0/24 118 119 ip route del vrf v$ol1 192.0.2.2/32 120 __simple_if_fini g1 192.0.2.1/32 121 tunnel_destroy g1 122 123 __simple_if_fini $ul1 192.0.2.17/28 124 simple_if_fini $ol1 198.51.100.1/24 2001:db8:1::1/64 125} 126 127sw2_create() 128{ 129 simple_if_init $ul21 192.0.2.18/28 130 __simple_if_init $ul22 v$ul21 131 vlan_create $ul22 111 v$ul21 192.0.2.33/28 132 vlan_create $ul22 222 v$ul21 192.0.2.49/28 133 134 ip route add vrf v$ul21 192.0.2.1/32 via 192.0.2.17 135 ip route add vrf v$ul21 192.0.2.2/32 \ 136 nexthop via 192.0.2.34 \ 137 nexthop via 192.0.2.50 138} 139 140sw2_destroy() 141{ 142 ip route del vrf v$ul21 192.0.2.2/32 143 ip route del vrf v$ul21 192.0.2.1/32 144 145 vlan_destroy $ul22 222 146 vlan_destroy $ul22 111 147 __simple_if_fini $ul22 148 simple_if_fini $ul21 192.0.2.18/28 149} 150 151sw3_create() 152{ 153 simple_if_init $ul31 192.0.2.65/28 154 __simple_if_init $ul32 v$ul31 155 vlan_create $ul32 111 v$ul31 192.0.2.34/28 156 vlan_create $ul32 222 v$ul31 192.0.2.50/28 157 158 ip route add vrf v$ul31 192.0.2.2/32 via 192.0.2.66 159 ip route add vrf v$ul31 192.0.2.1/32 \ 160 nexthop via 192.0.2.33 \ 161 nexthop via 192.0.2.49 162 163 tc qdisc add dev $ul32 clsact 164 tc filter add dev $ul32 ingress pref 111 prot 802.1Q \ 165 flower vlan_id 111 action pass 166 tc filter add dev $ul32 ingress pref 222 prot 802.1Q \ 167 flower vlan_id 222 action pass 168} 169 170sw3_destroy() 171{ 172 tc qdisc del dev $ul32 clsact 173 174 ip route del vrf v$ul31 192.0.2.1/32 175 ip route del vrf v$ul31 192.0.2.2/32 176 177 vlan_destroy $ul32 222 178 vlan_destroy $ul32 111 179 __simple_if_fini $ul32 180 simple_if_fini $ul31 192.0.2.65/28 181} 182 183sw4_create() 184{ 185 simple_if_init $ol4 203.0.113.1/24 2001:db8:2::1/64 186 __simple_if_init $ul4 v$ol4 192.0.2.66/28 187 188 tunnel_create g2 gre 192.0.2.2 192.0.2.1 tos inherit dev v$ol4 189 __simple_if_init g2 v$ol4 192.0.2.2/32 190 ip route add vrf v$ol4 192.0.2.1/32 via 192.0.2.65 191 192 ip route add vrf v$ol4 198.51.100.0/24 dev g2 193 ip -6 route add vrf v$ol4 2001:db8:1::/64 dev g2 194} 195 196sw4_destroy() 197{ 198 ip -6 route del vrf v$ol4 2001:db8:1::/64 199 ip route del vrf v$ol4 198.51.100.0/24 200 201 ip route del vrf v$ol4 192.0.2.1/32 202 __simple_if_fini g2 192.0.2.2/32 203 tunnel_destroy g2 204 205 __simple_if_fini $ul4 192.0.2.66/28 206 simple_if_fini $ol4 203.0.113.1/24 2001:db8:2::1/64 207} 208 209h2_create() 210{ 211 simple_if_init $h2 203.0.113.2/24 2001:db8:2::2/64 212 ip route add vrf v$h2 default via 203.0.113.1 dev $h2 213 ip -6 route add vrf v$h2 default via 2001:db8:2::1 dev $h2 214} 215 216h2_destroy() 217{ 218 ip -6 route del vrf v$h2 default 219 ip route del vrf v$h2 default 220 simple_if_fini $h2 203.0.113.2/24 2001:db8:2::2/64 221} 222 223setup_prepare() 224{ 225 h1=${NETIFS[p1]} 226 227 ol1=${NETIFS[p2]} 228 ul1=${NETIFS[p3]} 229 230 ul21=${NETIFS[p4]} 231 ul22=${NETIFS[p5]} 232 233 ul32=${NETIFS[p6]} 234 ul31=${NETIFS[p7]} 235 236 ul4=${NETIFS[p8]} 237 ol4=${NETIFS[p9]} 238 239 h2=${NETIFS[p10]} 240 241 vrf_prepare 242 h1_create 243 sw1_create 244 sw2_create 245 sw3_create 246 sw4_create 247 h2_create 248 249 forwarding_enable 250} 251 252cleanup() 253{ 254 pre_cleanup 255 256 forwarding_restore 257 258 h2_destroy 259 sw4_destroy 260 sw3_destroy 261 sw2_destroy 262 sw1_destroy 263 h1_destroy 264 vrf_cleanup 265} 266 267ping_ipv4() 268{ 269 ping_test $h1 203.0.113.2 270} 271 272ping_ipv6() 273{ 274 ping6_test $h1 2001:db8:2::2 275} 276 277send_src_ipv4() 278{ 279 ip vrf exec v$h1 $MZ $h1 -q -p 64 \ 280 -A "198.51.100.2-198.51.100.253" -B 203.0.113.2 \ 281 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 282} 283 284send_dst_ipv4() 285{ 286 ip vrf exec v$h1 $MZ $h1 -q -p 64 \ 287 -A 198.51.100.2 -B "203.0.113.2-203.0.113.253" \ 288 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 289} 290 291send_src_udp4() 292{ 293 ip vrf exec v$h1 $MZ $h1 -q -p 64 \ 294 -A 198.51.100.2 -B 203.0.113.2 \ 295 -d 1msec -t udp "sp=0-32768,dp=30000" 296} 297 298send_dst_udp4() 299{ 300 ip vrf exec v$h1 $MZ $h1 -q -p 64 \ 301 -A 198.51.100.2 -B 203.0.113.2 \ 302 -d 1msec -t udp "sp=20000,dp=0-32768" 303} 304 305send_src_ipv6() 306{ 307 ip vrf exec v$h1 $MZ -6 $h1 -q -p 64 \ 308 -A "2001:db8:1::2-2001:db8:1::fd" -B 2001:db8:2::2 \ 309 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 310} 311 312send_dst_ipv6() 313{ 314 ip vrf exec v$h1 $MZ -6 $h1 -q -p 64 \ 315 -A 2001:db8:1::2 -B "2001:db8:2::2-2001:db8:2::fd" \ 316 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 317} 318 319send_flowlabel() 320{ 321 # Generate 16384 echo requests, each with a random flow label. 322 for _ in $(seq 1 16384); do 323 ip vrf exec v$h1 \ 324 $PING6 2001:db8:2::2 -F 0 -c 1 -q >/dev/null 2>&1 325 done 326} 327 328send_src_udp6() 329{ 330 ip vrf exec v$h1 $MZ -6 $h1 -q -p 64 \ 331 -A 2001:db8:1::2 -B 2001:db8:2::2 \ 332 -d 1msec -t udp "sp=0-32768,dp=30000" 333} 334 335send_dst_udp6() 336{ 337 ip vrf exec v$h1 $MZ -6 $h1 -q -p 64 \ 338 -A 2001:db8:1::2 -B 2001:db8:2::2 \ 339 -d 1msec -t udp "sp=20000,dp=0-32768" 340} 341 342custom_hash_test() 343{ 344 local field="$1"; shift 345 local balanced="$1"; shift 346 local send_flows="$@" 347 348 RET=0 349 350 local t0_111=$(tc_rule_stats_get $ul32 111 ingress) 351 local t0_222=$(tc_rule_stats_get $ul32 222 ingress) 352 353 $send_flows 354 355 local t1_111=$(tc_rule_stats_get $ul32 111 ingress) 356 local t1_222=$(tc_rule_stats_get $ul32 222 ingress) 357 358 local d111=$((t1_111 - t0_111)) 359 local d222=$((t1_222 - t0_222)) 360 361 local diff=$((d222 - d111)) 362 local sum=$((d111 + d222)) 363 364 local pct=$(echo "$diff / $sum * 100" | bc -l) 365 local is_balanced=$(echo "-20 <= $pct && $pct <= 20" | bc) 366 367 [[ ( $is_balanced -eq 1 && $balanced == "balanced" ) || 368 ( $is_balanced -eq 0 && $balanced == "unbalanced" ) ]] 369 check_err $? "Expected traffic to be $balanced, but it is not" 370 371 log_test "Multipath hash field: $field ($balanced)" 372 log_info "Packets sent on path1 / path2: $d111 / $d222" 373} 374 375custom_hash_v4() 376{ 377 log_info "Running IPv4 overlay custom multipath hash tests" 378 379 # Prevent the neighbour table from overflowing, as different neighbour 380 # entries will be created on $ol4 when using different destination IPs. 381 sysctl_set net.ipv4.neigh.default.gc_thresh1 1024 382 sysctl_set net.ipv4.neigh.default.gc_thresh2 1024 383 sysctl_set net.ipv4.neigh.default.gc_thresh3 1024 384 385 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0040 386 custom_hash_test "Inner source IP" "balanced" send_src_ipv4 387 custom_hash_test "Inner source IP" "unbalanced" send_dst_ipv4 388 389 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0080 390 custom_hash_test "Inner destination IP" "balanced" send_dst_ipv4 391 custom_hash_test "Inner destination IP" "unbalanced" send_src_ipv4 392 393 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0400 394 custom_hash_test "Inner source port" "balanced" send_src_udp4 395 custom_hash_test "Inner source port" "unbalanced" send_dst_udp4 396 397 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0800 398 custom_hash_test "Inner destination port" "balanced" send_dst_udp4 399 custom_hash_test "Inner destination port" "unbalanced" send_src_udp4 400 401 sysctl_restore net.ipv4.neigh.default.gc_thresh3 402 sysctl_restore net.ipv4.neigh.default.gc_thresh2 403 sysctl_restore net.ipv4.neigh.default.gc_thresh1 404} 405 406custom_hash_v6() 407{ 408 log_info "Running IPv6 overlay custom multipath hash tests" 409 410 # Prevent the neighbour table from overflowing, as different neighbour 411 # entries will be created on $ol4 when using different destination IPs. 412 sysctl_set net.ipv6.neigh.default.gc_thresh1 1024 413 sysctl_set net.ipv6.neigh.default.gc_thresh2 1024 414 sysctl_set net.ipv6.neigh.default.gc_thresh3 1024 415 416 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0040 417 custom_hash_test "Inner source IP" "balanced" send_src_ipv6 418 custom_hash_test "Inner source IP" "unbalanced" send_dst_ipv6 419 420 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0080 421 custom_hash_test "Inner destination IP" "balanced" send_dst_ipv6 422 custom_hash_test "Inner destination IP" "unbalanced" send_src_ipv6 423 424 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0200 425 custom_hash_test "Inner flowlabel" "balanced" send_flowlabel 426 custom_hash_test "Inner flowlabel" "unbalanced" send_src_ipv6 427 428 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0400 429 custom_hash_test "Inner source port" "balanced" send_src_udp6 430 custom_hash_test "Inner source port" "unbalanced" send_dst_udp6 431 432 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0800 433 custom_hash_test "Inner destination port" "balanced" send_dst_udp6 434 custom_hash_test "Inner destination port" "unbalanced" send_src_udp6 435 436 sysctl_restore net.ipv6.neigh.default.gc_thresh3 437 sysctl_restore net.ipv6.neigh.default.gc_thresh2 438 sysctl_restore net.ipv6.neigh.default.gc_thresh1 439} 440 441custom_hash() 442{ 443 # Test that when the hash policy is set to custom, traffic is 444 # distributed only according to the fields set in the 445 # fib_multipath_hash_fields sysctl. 446 # 447 # Each time set a different field and make sure traffic is only 448 # distributed when the field is changed in the packet stream. 449 450 sysctl_set net.ipv4.fib_multipath_hash_policy 3 451 452 custom_hash_v4 453 custom_hash_v6 454 455 sysctl_restore net.ipv4.fib_multipath_hash_policy 456} 457 458trap cleanup EXIT 459 460setup_prepare 461setup_wait 462tests_run 463 464exit $EXIT_STATUS 465