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

selftests: forwarding: Add test for custom multipath hash with IPv4 GRE

Test that when the hash policy is set to custom, traffic is distributed
only according to the inner fields set in the fib_multipath_hash_fields
sysctl.

Each time set a different field and make sure traffic is only
distributed when the field is changed in the packet stream.

The test only verifies the behavior of IPv4/IPv6 overlays on top of an
IPv4 underlay network. A subsequent patch will do the same with an IPv6
underlay network.

Example output:

# ./gre_custom_multipath_hash.sh
TEST: ping [ OK ]
TEST: ping6 [ OK ]
INFO: Running IPv4 overlay custom multipath hash tests
TEST: Multipath hash field: Inner source IP (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 6601 / 6001
TEST: Multipath hash field: Inner source IP (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 0 / 12600
TEST: Multipath hash field: Inner destination IP (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 6802 / 5802
TEST: Multipath hash field: Inner destination IP (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 12601 / 1
TEST: Multipath hash field: Inner source port (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 16430 / 16344
TEST: Multipath hash field: Inner source port (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 0 / 32772
TEST: Multipath hash field: Inner destination port (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 16430 / 16343
TEST: Multipath hash field: Inner destination port (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 0 / 32772
INFO: Running IPv6 overlay custom multipath hash tests
TEST: Multipath hash field: Inner source IP (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 6702 / 5900
TEST: Multipath hash field: Inner source IP (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 0 / 12601
TEST: Multipath hash field: Inner destination IP (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 5751 / 6851
TEST: Multipath hash field: Inner destination IP (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 12602 / 1
TEST: Multipath hash field: Inner flowlabel (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 8364 / 8065
TEST: Multipath hash field: Inner flowlabel (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 12601 / 0
TEST: Multipath hash field: Inner source port (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 16425 / 16349
TEST: Multipath hash field: Inner source port (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 1 / 32770
TEST: Multipath hash field: Inner destination port (balanced) [ OK ]
INFO: Packets sent on path1 / path2: 16425 / 16349
TEST: Multipath hash field: Inner destination port (unbalanced) [ OK ]
INFO: Packets sent on path1 / path2: 2 / 32770

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
185b0c19 511e8db5

+456
+456
tools/testing/selftests/net/forwarding/gre_custom_multipath_hash.sh
··· 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 + 78 + ALL_TESTS=" 79 + ping_ipv4 80 + ping_ipv6 81 + custom_hash 82 + " 83 + 84 + NUM_NETIFS=10 85 + source lib.sh 86 + 87 + h1_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 + 94 + h1_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 + 101 + sw1_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 + 114 + sw1_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 + 127 + sw2_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 + 140 + sw2_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 + 151 + sw3_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 + 170 + sw3_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 + 183 + sw4_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 + 196 + sw4_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 + 209 + h2_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 + 216 + h2_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 + 223 + setup_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 + 252 + cleanup() 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 + 267 + ping_ipv4() 268 + { 269 + ping_test $h1 203.0.113.2 270 + } 271 + 272 + ping_ipv6() 273 + { 274 + ping6_test $h1 2001:db8:2::2 275 + } 276 + 277 + send_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 + 283 + send_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 + 289 + send_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 + 295 + send_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 + 301 + send_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 + 307 + send_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 + 313 + send_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 + 322 + send_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 + 328 + send_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 + 334 + custom_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 + 367 + custom_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 + 398 + custom_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 + 433 + custom_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 + 450 + trap cleanup EXIT 451 + 452 + setup_prepare 453 + setup_wait 454 + tests_run 455 + 456 + exit $EXIT_STATUS