gre_custom_multipath_hash.sh (12600B)
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 $MZ $h1 -q -p 64 -A "198.51.100.2-198.51.100.253" -B 203.0.113.2 \ 280 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 281} 282 283send_dst_ipv4() 284{ 285 $MZ $h1 -q -p 64 -A 198.51.100.2 -B "203.0.113.2-203.0.113.253" \ 286 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 287} 288 289send_src_udp4() 290{ 291 $MZ $h1 -q -p 64 -A 198.51.100.2 -B 203.0.113.2 \ 292 -d 1msec -t udp "sp=0-32768,dp=30000" 293} 294 295send_dst_udp4() 296{ 297 $MZ $h1 -q -p 64 -A 198.51.100.2 -B 203.0.113.2 \ 298 -d 1msec -t udp "sp=20000,dp=0-32768" 299} 300 301send_src_ipv6() 302{ 303 $MZ -6 $h1 -q -p 64 -A "2001:db8:1::2-2001:db8:1::fd" -B 2001:db8:2::2 \ 304 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 305} 306 307send_dst_ipv6() 308{ 309 $MZ -6 $h1 -q -p 64 -A 2001:db8:1::2 -B "2001:db8:2::2-2001:db8:2::fd" \ 310 -d 1msec -c 50 -t udp "sp=20000,dp=30000" 311} 312 313send_flowlabel() 314{ 315 # Generate 16384 echo requests, each with a random flow label. 316 for _ in $(seq 1 16384); do 317 ip vrf exec v$h1 \ 318 $PING6 2001:db8:2::2 -F 0 -c 1 -q >/dev/null 2>&1 319 done 320} 321 322send_src_udp6() 323{ 324 $MZ -6 $h1 -q -p 64 -A 2001:db8:1::2 -B 2001:db8:2::2 \ 325 -d 1msec -t udp "sp=0-32768,dp=30000" 326} 327 328send_dst_udp6() 329{ 330 $MZ -6 $h1 -q -p 64 -A 2001:db8:1::2 -B 2001:db8:2::2 \ 331 -d 1msec -t udp "sp=20000,dp=0-32768" 332} 333 334custom_hash_test() 335{ 336 local field="$1"; shift 337 local balanced="$1"; shift 338 local send_flows="$@" 339 340 RET=0 341 342 local t0_111=$(tc_rule_stats_get $ul32 111 ingress) 343 local t0_222=$(tc_rule_stats_get $ul32 222 ingress) 344 345 $send_flows 346 347 local t1_111=$(tc_rule_stats_get $ul32 111 ingress) 348 local t1_222=$(tc_rule_stats_get $ul32 222 ingress) 349 350 local d111=$((t1_111 - t0_111)) 351 local d222=$((t1_222 - t0_222)) 352 353 local diff=$((d222 - d111)) 354 local sum=$((d111 + d222)) 355 356 local pct=$(echo "$diff / $sum * 100" | bc -l) 357 local is_balanced=$(echo "-20 <= $pct && $pct <= 20" | bc) 358 359 [[ ( $is_balanced -eq 1 && $balanced == "balanced" ) || 360 ( $is_balanced -eq 0 && $balanced == "unbalanced" ) ]] 361 check_err $? "Expected traffic to be $balanced, but it is not" 362 363 log_test "Multipath hash field: $field ($balanced)" 364 log_info "Packets sent on path1 / path2: $d111 / $d222" 365} 366 367custom_hash_v4() 368{ 369 log_info "Running IPv4 overlay custom multipath hash tests" 370 371 # Prevent the neighbour table from overflowing, as different neighbour 372 # entries will be created on $ol4 when using different destination IPs. 373 sysctl_set net.ipv4.neigh.default.gc_thresh1 1024 374 sysctl_set net.ipv4.neigh.default.gc_thresh2 1024 375 sysctl_set net.ipv4.neigh.default.gc_thresh3 1024 376 377 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0040 378 custom_hash_test "Inner source IP" "balanced" send_src_ipv4 379 custom_hash_test "Inner source IP" "unbalanced" send_dst_ipv4 380 381 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0080 382 custom_hash_test "Inner destination IP" "balanced" send_dst_ipv4 383 custom_hash_test "Inner destination IP" "unbalanced" send_src_ipv4 384 385 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0400 386 custom_hash_test "Inner source port" "balanced" send_src_udp4 387 custom_hash_test "Inner source port" "unbalanced" send_dst_udp4 388 389 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0800 390 custom_hash_test "Inner destination port" "balanced" send_dst_udp4 391 custom_hash_test "Inner destination port" "unbalanced" send_src_udp4 392 393 sysctl_restore net.ipv4.neigh.default.gc_thresh3 394 sysctl_restore net.ipv4.neigh.default.gc_thresh2 395 sysctl_restore net.ipv4.neigh.default.gc_thresh1 396} 397 398custom_hash_v6() 399{ 400 log_info "Running IPv6 overlay custom multipath hash tests" 401 402 # Prevent the neighbour table from overflowing, as different neighbour 403 # entries will be created on $ol4 when using different destination IPs. 404 sysctl_set net.ipv6.neigh.default.gc_thresh1 1024 405 sysctl_set net.ipv6.neigh.default.gc_thresh2 1024 406 sysctl_set net.ipv6.neigh.default.gc_thresh3 1024 407 408 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0040 409 custom_hash_test "Inner source IP" "balanced" send_src_ipv6 410 custom_hash_test "Inner source IP" "unbalanced" send_dst_ipv6 411 412 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0080 413 custom_hash_test "Inner destination IP" "balanced" send_dst_ipv6 414 custom_hash_test "Inner destination IP" "unbalanced" send_src_ipv6 415 416 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0200 417 custom_hash_test "Inner flowlabel" "balanced" send_flowlabel 418 custom_hash_test "Inner flowlabel" "unbalanced" send_src_ipv6 419 420 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0400 421 custom_hash_test "Inner source port" "balanced" send_src_udp6 422 custom_hash_test "Inner source port" "unbalanced" send_dst_udp6 423 424 sysctl_set net.ipv4.fib_multipath_hash_fields 0x0800 425 custom_hash_test "Inner destination port" "balanced" send_dst_udp6 426 custom_hash_test "Inner destination port" "unbalanced" send_src_udp6 427 428 sysctl_restore net.ipv6.neigh.default.gc_thresh3 429 sysctl_restore net.ipv6.neigh.default.gc_thresh2 430 sysctl_restore net.ipv6.neigh.default.gc_thresh1 431} 432 433custom_hash() 434{ 435 # Test that when the hash policy is set to custom, traffic is 436 # distributed only according to the fields set in the 437 # fib_multipath_hash_fields sysctl. 438 # 439 # Each time set a different field and make sure traffic is only 440 # distributed when the field is changed in the packet stream. 441 442 sysctl_set net.ipv4.fib_multipath_hash_policy 3 443 444 custom_hash_v4 445 custom_hash_v6 446 447 sysctl_restore net.ipv4.fib_multipath_hash_policy 448} 449 450trap cleanup EXIT 451 452setup_prepare 453setup_wait 454tests_run 455 456exit $EXIT_STATUS