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

selftests: netfilter: Introduce tests for sets with range concatenation

This test covers functionality and stability of the newly added
nftables set implementation supporting concatenation of ranged
fields.

For some selected set expression types, test:
- correctness, by checking that packets match or don't
- concurrency, by attempting races between insertion, deletion, lookup
- timeout feature, checking that packets don't match expired entries

and (roughly) estimate matching rates, comparing to baselines for
simple drop on netdev ingress hook and for hash and rbtrees sets.

In order to send packets, this needs one of sendip, netcat or bash.
To flood with traffic, iperf3, iperf and netperf are supported. For
performance measurements, this relies on the sample pktgen script
pktgen_bench_xmit_mode_netif_receive.sh.

If none of the tools suitable for a given test are available, specific
tests will be skipped.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Stefano Brivio and committed by
Pablo Neira Ayuso
611973c1 3c4287f6

+1483 -1
+2 -1
tools/testing/selftests/netfilter/Makefile
··· 2 2 # Makefile for netfilter selftests 3 3 4 4 TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \ 5 - conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh 5 + conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \ 6 + nft_concat_range.sh 6 7 7 8 include ../lib.mk
+1481
tools/testing/selftests/netfilter/nft_concat_range.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # nft_concat_range.sh - Tests for sets with concatenation of ranged fields 5 + # 6 + # Copyright (c) 2019 Red Hat GmbH 7 + # 8 + # Author: Stefano Brivio <sbrivio@redhat.com> 9 + # 10 + # shellcheck disable=SC2154,SC2034,SC2016,SC2030,SC2031 11 + # ^ Configuration and templates sourced with eval, counters reused in subshells 12 + 13 + KSELFTEST_SKIP=4 14 + 15 + # Available test groups: 16 + # - correctness: check that packets match given entries, and only those 17 + # - concurrency: attempt races between insertion, deletion and lookup 18 + # - timeout: check that packets match entries until they expire 19 + # - performance: estimate matching rate, compare with rbtree and hash baselines 20 + TESTS="correctness concurrency timeout" 21 + [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance" 22 + 23 + # Set types, defined by TYPE_ variables below 24 + TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto 25 + net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port 26 + net_port_mac_proto_net" 27 + 28 + # List of possible paths to pktgen script from kernel tree for performance tests 29 + PKTGEN_SCRIPT_PATHS=" 30 + ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh 31 + pktgen/pktgen_bench_xmit_mode_netif_receive.sh" 32 + 33 + # Definition of set types: 34 + # display display text for test report 35 + # type_spec nftables set type specifier 36 + # chain_spec nftables type specifier for rules mapping to set 37 + # dst call sequence of format_*() functions for destination fields 38 + # src call sequence of format_*() functions for source fields 39 + # start initial integer used to generate addresses and ports 40 + # count count of entries to generate and match 41 + # src_delta number summed to destination generator for source fields 42 + # tools list of tools for correctness and timeout tests, any can be used 43 + # proto L4 protocol of test packets 44 + # 45 + # race_repeat race attempts per thread, 0 disables concurrency test for type 46 + # flood_tools list of tools for concurrency tests, any can be used 47 + # flood_proto L4 protocol of test packets for concurrency tests 48 + # flood_spec nftables type specifier for concurrency tests 49 + # 50 + # perf_duration duration of single pktgen injection test 51 + # perf_spec nftables type specifier for performance tests 52 + # perf_dst format_*() functions for destination fields in performance test 53 + # perf_src format_*() functions for source fields in performance test 54 + # perf_entries number of set entries for performance test 55 + # perf_proto L3 protocol of test packets 56 + TYPE_net_port=" 57 + display net,port 58 + type_spec ipv4_addr . inet_service 59 + chain_spec ip daddr . udp dport 60 + dst addr4 port 61 + src 62 + start 1 63 + count 5 64 + src_delta 2000 65 + tools sendip nc bash 66 + proto udp 67 + 68 + race_repeat 3 69 + flood_tools iperf3 iperf netperf 70 + flood_proto udp 71 + flood_spec ip daddr . udp dport 72 + 73 + perf_duration 5 74 + perf_spec ip daddr . udp dport 75 + perf_dst addr4 port 76 + perf_src 77 + perf_entries 1000 78 + perf_proto ipv4 79 + " 80 + 81 + TYPE_port_net=" 82 + display port,net 83 + type_spec inet_service . ipv4_addr 84 + chain_spec udp dport . ip daddr 85 + dst port addr4 86 + src 87 + start 1 88 + count 5 89 + src_delta 2000 90 + tools sendip nc bash 91 + proto udp 92 + 93 + race_repeat 3 94 + flood_tools iperf3 iperf netperf 95 + flood_proto udp 96 + flood_spec udp dport . ip daddr 97 + 98 + perf_duration 5 99 + perf_spec udp dport . ip daddr 100 + perf_dst port addr4 101 + perf_src 102 + perf_entries 100 103 + perf_proto ipv4 104 + " 105 + 106 + TYPE_net6_port=" 107 + display net6,port 108 + type_spec ipv6_addr . inet_service 109 + chain_spec ip6 daddr . udp dport 110 + dst addr6 port 111 + src 112 + start 10 113 + count 5 114 + src_delta 2000 115 + tools sendip nc bash 116 + proto udp6 117 + 118 + race_repeat 3 119 + flood_tools iperf3 iperf netperf 120 + flood_proto tcp6 121 + flood_spec ip6 daddr . udp dport 122 + 123 + perf_duration 5 124 + perf_spec ip6 daddr . udp dport 125 + perf_dst addr6 port 126 + perf_src 127 + perf_entries 1000 128 + perf_proto ipv6 129 + " 130 + 131 + TYPE_port_proto=" 132 + display port,proto 133 + type_spec inet_service . inet_proto 134 + chain_spec udp dport . meta l4proto 135 + dst port proto 136 + src 137 + start 1 138 + count 5 139 + src_delta 2000 140 + tools sendip nc bash 141 + proto udp 142 + 143 + race_repeat 0 144 + 145 + perf_duration 5 146 + perf_spec udp dport . meta l4proto 147 + perf_dst port proto 148 + perf_src 149 + perf_entries 30000 150 + perf_proto ipv4 151 + " 152 + 153 + TYPE_net6_port_mac=" 154 + display net6,port,mac 155 + type_spec ipv6_addr . inet_service . ether_addr 156 + chain_spec ip6 daddr . udp dport . ether saddr 157 + dst addr6 port 158 + src mac 159 + start 10 160 + count 5 161 + src_delta 2000 162 + tools sendip nc bash 163 + proto udp6 164 + 165 + race_repeat 0 166 + 167 + perf_duration 5 168 + perf_spec ip6 daddr . udp dport . ether daddr 169 + perf_dst addr6 port mac 170 + perf_src 171 + perf_entries 10 172 + perf_proto ipv6 173 + " 174 + 175 + TYPE_net6_port_mac_proto=" 176 + display net6,port,mac,proto 177 + type_spec ipv6_addr . inet_service . ether_addr . inet_proto 178 + chain_spec ip6 daddr . udp dport . ether saddr . meta l4proto 179 + dst addr6 port 180 + src mac proto 181 + start 10 182 + count 5 183 + src_delta 2000 184 + tools sendip nc bash 185 + proto udp6 186 + 187 + race_repeat 0 188 + 189 + perf_duration 5 190 + perf_spec ip6 daddr . udp dport . ether daddr . meta l4proto 191 + perf_dst addr6 port mac proto 192 + perf_src 193 + perf_entries 1000 194 + perf_proto ipv6 195 + " 196 + 197 + TYPE_net_port_net=" 198 + display net,port,net 199 + type_spec ipv4_addr . inet_service . ipv4_addr 200 + chain_spec ip daddr . udp dport . ip saddr 201 + dst addr4 port 202 + src addr4 203 + start 1 204 + count 5 205 + src_delta 2000 206 + tools sendip nc bash 207 + proto udp 208 + 209 + race_repeat 3 210 + flood_tools iperf3 iperf netperf 211 + flood_proto tcp 212 + flood_spec ip daddr . udp dport . ip saddr 213 + 214 + perf_duration 0 215 + " 216 + 217 + TYPE_net6_port_net6_port=" 218 + display net6,port,net6,port 219 + type_spec ipv6_addr . inet_service . ipv6_addr . inet_service 220 + chain_spec ip6 daddr . udp dport . ip6 saddr . udp sport 221 + dst addr6 port 222 + src addr6 port 223 + start 10 224 + count 5 225 + src_delta 2000 226 + tools sendip nc 227 + proto udp6 228 + 229 + race_repeat 3 230 + flood_tools iperf3 iperf netperf 231 + flood_proto tcp6 232 + flood_spec ip6 daddr . tcp dport . ip6 saddr . tcp sport 233 + 234 + perf_duration 0 235 + " 236 + 237 + TYPE_net_port_mac_proto_net=" 238 + display net,port,mac,proto,net 239 + type_spec ipv4_addr . inet_service . ether_addr . inet_proto . ipv4_addr 240 + chain_spec ip daddr . udp dport . ether saddr . meta l4proto . ip saddr 241 + dst addr4 port 242 + src mac proto addr4 243 + start 1 244 + count 5 245 + src_delta 2000 246 + tools sendip nc bash 247 + proto udp 248 + 249 + race_repeat 0 250 + 251 + perf_duration 0 252 + " 253 + 254 + TYPE_net_mac=" 255 + display net,mac 256 + type_spec ipv4_addr . ether_addr 257 + chain_spec ip daddr . ether saddr 258 + dst addr4 259 + src mac 260 + start 1 261 + count 5 262 + src_delta 2000 263 + tools sendip nc bash 264 + proto udp 265 + 266 + race_repeat 0 267 + 268 + perf_duration 5 269 + perf_spec ip daddr . ether daddr 270 + perf_dst addr4 mac 271 + perf_src 272 + perf_entries 1000 273 + perf_proto ipv4 274 + " 275 + 276 + TYPE_net_mac_icmp=" 277 + display net,mac - ICMP 278 + type_spec ipv4_addr . ether_addr 279 + chain_spec ip daddr . ether saddr 280 + dst addr4 281 + src mac 282 + start 1 283 + count 5 284 + src_delta 2000 285 + tools ping 286 + proto icmp 287 + 288 + race_repeat 0 289 + 290 + perf_duration 0 291 + " 292 + 293 + TYPE_net6_mac_icmp=" 294 + display net6,mac - ICMPv6 295 + type_spec ipv6_addr . ether_addr 296 + chain_spec ip6 daddr . ether saddr 297 + dst addr6 298 + src mac 299 + start 10 300 + count 50 301 + src_delta 2000 302 + tools ping 303 + proto icmp6 304 + 305 + race_repeat 0 306 + 307 + perf_duration 0 308 + " 309 + 310 + TYPE_net_port_proto_net=" 311 + display net,port,proto,net 312 + type_spec ipv4_addr . inet_service . inet_proto . ipv4_addr 313 + chain_spec ip daddr . udp dport . meta l4proto . ip saddr 314 + dst addr4 port proto 315 + src addr4 316 + start 1 317 + count 5 318 + src_delta 2000 319 + tools sendip nc 320 + proto udp 321 + 322 + race_repeat 3 323 + flood_tools iperf3 iperf netperf 324 + flood_proto tcp 325 + flood_spec ip daddr . tcp dport . meta l4proto . ip saddr 326 + 327 + perf_duration 0 328 + " 329 + 330 + # Set template for all tests, types and rules are filled in depending on test 331 + set_template=' 332 + flush ruleset 333 + 334 + table inet filter { 335 + counter test { 336 + packets 0 bytes 0 337 + } 338 + 339 + set test { 340 + type ${type_spec} 341 + flags interval,timeout 342 + } 343 + 344 + chain input { 345 + type filter hook prerouting priority 0; policy accept; 346 + ${chain_spec} @test counter name \"test\" 347 + } 348 + } 349 + 350 + table netdev perf { 351 + counter test { 352 + packets 0 bytes 0 353 + } 354 + 355 + counter match { 356 + packets 0 bytes 0 357 + } 358 + 359 + set test { 360 + type ${type_spec} 361 + flags interval 362 + } 363 + 364 + set norange { 365 + type ${type_spec} 366 + } 367 + 368 + set noconcat { 369 + type ${type_spec%% *} 370 + flags interval 371 + } 372 + 373 + chain test { 374 + type filter hook ingress device veth_a priority 0; 375 + } 376 + } 377 + ' 378 + 379 + err_buf= 380 + info_buf= 381 + 382 + # Append string to error buffer 383 + err() { 384 + err_buf="${err_buf}${1} 385 + " 386 + } 387 + 388 + # Append string to information buffer 389 + info() { 390 + info_buf="${info_buf}${1} 391 + " 392 + } 393 + 394 + # Flush error buffer to stdout 395 + err_flush() { 396 + printf "%s" "${err_buf}" 397 + err_buf= 398 + } 399 + 400 + # Flush information buffer to stdout 401 + info_flush() { 402 + printf "%s" "${info_buf}" 403 + info_buf= 404 + } 405 + 406 + # Setup veth pair: this namespace receives traffic, B generates it 407 + setup_veth() { 408 + ip netns add B 409 + ip link add veth_a type veth peer name veth_b || return 1 410 + 411 + ip link set veth_a up 412 + ip link set veth_b netns B 413 + 414 + ip -n B link set veth_b up 415 + 416 + ip addr add dev veth_a 10.0.0.1 417 + ip route add default dev veth_a 418 + 419 + ip -6 addr add fe80::1/64 dev veth_a nodad 420 + ip -6 addr add 2001:db8::1/64 dev veth_a nodad 421 + ip -6 route add default dev veth_a 422 + 423 + ip -n B route add default dev veth_b 424 + 425 + ip -6 -n B addr add fe80::2/64 dev veth_b nodad 426 + ip -6 -n B addr add 2001:db8::2/64 dev veth_b nodad 427 + ip -6 -n B route add default dev veth_b 428 + 429 + B() { 430 + ip netns exec B "$@" >/dev/null 2>&1 431 + } 432 + 433 + sleep 2 434 + } 435 + 436 + # Fill in set template and initialise set 437 + setup_set() { 438 + eval "echo \"${set_template}\"" | nft -f - 439 + } 440 + 441 + # Check that at least one of the needed tools is available 442 + check_tools() { 443 + __tools= 444 + for tool in ${tools}; do 445 + if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \ 446 + ! nc -u -w0 1.1.1.1 1 2>/dev/null; then 447 + # Some GNU netcat builds might not support IPv6 448 + __tools="${__tools} netcat-openbsd" 449 + continue 450 + fi 451 + __tools="${__tools} ${tool}" 452 + 453 + command -v "${tool}" >/dev/null && return 0 454 + done 455 + err "need one of:${__tools}, skipping" && return 1 456 + } 457 + 458 + # Set up function to send ICMP packets 459 + setup_send_icmp() { 460 + send_icmp() { 461 + B ping -c1 -W1 "${dst_addr4}" >/dev/null 2>&1 462 + } 463 + } 464 + 465 + # Set up function to send ICMPv6 packets 466 + setup_send_icmp6() { 467 + if command -v ping6 >/dev/null; then 468 + send_icmp6() { 469 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 470 + 2>/dev/null 471 + B ping6 -q -c1 -W1 "${dst_addr6}" 472 + } 473 + else 474 + send_icmp6() { 475 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 476 + 2>/dev/null 477 + B ping -q -6 -c1 -W1 "${dst_addr6}" 478 + } 479 + fi 480 + } 481 + 482 + # Set up function to send single UDP packets on IPv4 483 + setup_send_udp() { 484 + if command -v sendip >/dev/null; then 485 + send_udp() { 486 + [ -n "${src_port}" ] && src_port="-us ${src_port}" 487 + [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 488 + [ -n "${src_addr4}" ] && src_addr4="-is ${src_addr4}" 489 + 490 + # shellcheck disable=SC2086 # sendip needs split options 491 + B sendip -p ipv4 -p udp ${src_addr4} ${src_port} \ 492 + ${dst_port} "${dst_addr4}" 493 + 494 + src_port= 495 + dst_port= 496 + src_addr4= 497 + } 498 + elif command -v nc >/dev/null; then 499 + if nc -u -w0 1.1.1.1 1 2>/dev/null; then 500 + # OpenBSD netcat 501 + nc_opt="-w0" 502 + else 503 + # GNU netcat 504 + nc_opt="-q0" 505 + fi 506 + 507 + send_udp() { 508 + if [ -n "${src_addr4}" ]; then 509 + B ip addr add "${src_addr4}" dev veth_b 510 + __src_addr4="-s ${src_addr4}" 511 + fi 512 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 513 + [ -n "${src_port}" ] && src_port="-p ${src_port}" 514 + 515 + echo "" | B nc -u "${nc_opt}" "${__src_addr4}" \ 516 + "${src_port}" "${dst_addr4}" "${dst_port}" 517 + 518 + src_addr4= 519 + src_port= 520 + } 521 + elif [ -z "$(bash -c 'type -p')" ]; then 522 + send_udp() { 523 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 524 + if [ -n "${src_addr4}" ]; then 525 + B ip addr add "${src_addr4}/16" dev veth_b 526 + B ip route add default dev veth_b 527 + fi 528 + 529 + B bash -c "echo > /dev/udp/${dst_addr4}/${dst_port}" 530 + 531 + if [ -n "${src_addr4}" ]; then 532 + B ip addr del "${src_addr4}/16" dev veth_b 533 + fi 534 + src_addr4= 535 + } 536 + else 537 + return 1 538 + fi 539 + } 540 + 541 + # Set up function to send single UDP packets on IPv6 542 + setup_send_udp6() { 543 + if command -v sendip >/dev/null; then 544 + send_udp6() { 545 + [ -n "${src_port}" ] && src_port="-us ${src_port}" 546 + [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 547 + if [ -n "${src_addr6}" ]; then 548 + src_addr6="-6s ${src_addr6}" 549 + else 550 + src_addr6="-6s 2001:db8::2" 551 + fi 552 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 553 + 2>/dev/null 554 + 555 + # shellcheck disable=SC2086 # this needs split options 556 + B sendip -p ipv6 -p udp ${src_addr6} ${src_port} \ 557 + ${dst_port} "${dst_addr6}" 558 + 559 + src_port= 560 + dst_port= 561 + src_addr6= 562 + } 563 + elif command -v nc >/dev/null && nc -u -w0 1.1.1.1 1 2>/dev/null; then 564 + # GNU netcat might not work with IPv6, try next tool 565 + send_udp6() { 566 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 567 + 2>/dev/null 568 + if [ -n "${src_addr6}" ]; then 569 + B ip addr add "${src_addr6}" dev veth_b nodad 570 + else 571 + src_addr6="2001:db8::2" 572 + fi 573 + [ -n "${src_port}" ] && src_port="-p ${src_port}" 574 + 575 + # shellcheck disable=SC2086 # this needs split options 576 + echo "" | B nc -u w0 "-s${src_addr6}" ${src_port} \ 577 + ${dst_addr6} ${dst_port} 578 + 579 + src_addr6= 580 + src_port= 581 + } 582 + elif [ -z "$(bash -c 'type -p')" ]; then 583 + send_udp6() { 584 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 585 + 2>/dev/null 586 + B ip addr add "${src_addr6}" dev veth_b nodad 587 + B bash -c "echo > /dev/udp/${dst_addr6}/${dst_port}" 588 + ip -6 addr del "${dst_addr6}" dev veth_a 2>/dev/null 589 + } 590 + else 591 + return 1 592 + fi 593 + } 594 + 595 + # Set up function to send TCP traffic on IPv4 596 + setup_flood_tcp() { 597 + if command -v iperf3 >/dev/null; then 598 + flood_tcp() { 599 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 600 + if [ -n "${src_addr4}" ]; then 601 + B ip addr add "${src_addr4}/16" dev veth_b 602 + src_addr4="-B ${src_addr4}" 603 + else 604 + B ip addr add dev veth_b 10.0.0.2 605 + src_addr4="-B 10.0.0.2" 606 + fi 607 + if [ -n "${src_port}" ]; then 608 + src_port="--cport ${src_port}" 609 + fi 610 + B ip route add default dev veth_b 2>/dev/null 611 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 612 + 613 + # shellcheck disable=SC2086 # this needs split options 614 + iperf3 -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 615 + sleep 2 616 + 617 + # shellcheck disable=SC2086 # this needs split options 618 + B iperf3 -c "${dst_addr4}" ${dst_port} ${src_port} \ 619 + ${src_addr4} -l16 -t 1000 620 + 621 + src_addr4= 622 + src_port= 623 + dst_port= 624 + } 625 + elif command -v iperf >/dev/null; then 626 + flood_tcp() { 627 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 628 + if [ -n "${src_addr4}" ]; then 629 + B ip addr add "${src_addr4}/16" dev veth_b 630 + src_addr4="-B ${src_addr4}" 631 + else 632 + B ip addr add dev veth_b 10.0.0.2 2>/dev/null 633 + src_addr4="-B 10.0.0.2" 634 + fi 635 + if [ -n "${src_port}" ]; then 636 + src_addr4="${src_addr4}:${src_port}" 637 + fi 638 + B ip route add default dev veth_b 639 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 640 + 641 + # shellcheck disable=SC2086 # this needs split options 642 + iperf -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 643 + sleep 2 644 + 645 + # shellcheck disable=SC2086 # this needs split options 646 + B iperf -c "${dst_addr4}" ${dst_port} ${src_addr4} \ 647 + -l20 -t 1000 648 + 649 + src_addr4= 650 + src_port= 651 + dst_port= 652 + } 653 + elif command -v netperf >/dev/null; then 654 + flood_tcp() { 655 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 656 + if [ -n "${src_addr4}" ]; then 657 + B ip addr add "${src_addr4}/16" dev veth_b 658 + else 659 + B ip addr add dev veth_b 10.0.0.2 660 + src_addr4="10.0.0.2" 661 + fi 662 + if [ -n "${src_port}" ]; then 663 + dst_port="${dst_port},${src_port}" 664 + fi 665 + B ip route add default dev veth_b 666 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 667 + 668 + # shellcheck disable=SC2086 # this needs split options 669 + netserver -4 ${dst_port} -L "${dst_addr4}" \ 670 + >/dev/null 2>&1 671 + sleep 2 672 + 673 + # shellcheck disable=SC2086 # this needs split options 674 + B netperf -4 -H "${dst_addr4}" ${dst_port} \ 675 + -L "${src_addr4}" -l 1000 -t TCP_STREAM 676 + 677 + src_addr4= 678 + src_port= 679 + dst_port= 680 + } 681 + else 682 + return 1 683 + fi 684 + } 685 + 686 + # Set up function to send TCP traffic on IPv6 687 + setup_flood_tcp6() { 688 + if command -v iperf3 >/dev/null; then 689 + flood_tcp6() { 690 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 691 + if [ -n "${src_addr6}" ]; then 692 + B ip addr add "${src_addr6}" dev veth_b nodad 693 + src_addr6="-B ${src_addr6}" 694 + else 695 + src_addr6="-B 2001:db8::2" 696 + fi 697 + if [ -n "${src_port}" ]; then 698 + src_port="--cport ${src_port}" 699 + fi 700 + B ip route add default dev veth_b 701 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 702 + 2>/dev/null 703 + 704 + # shellcheck disable=SC2086 # this needs split options 705 + iperf3 -s -DB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 706 + sleep 2 707 + 708 + # shellcheck disable=SC2086 # this needs split options 709 + B iperf3 -c "${dst_addr6}" ${dst_port} \ 710 + ${src_port} ${src_addr6} -l16 -t 1000 711 + 712 + src_addr6= 713 + src_port= 714 + dst_port= 715 + } 716 + elif command -v iperf >/dev/null; then 717 + flood_tcp6() { 718 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 719 + if [ -n "${src_addr6}" ]; then 720 + B ip addr add "${src_addr6}" dev veth_b nodad 721 + src_addr6="-B ${src_addr6}" 722 + else 723 + src_addr6="-B 2001:db8::2" 724 + fi 725 + if [ -n "${src_port}" ]; then 726 + src_addr6="${src_addr6}:${src_port}" 727 + fi 728 + B ip route add default dev veth_b 729 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 730 + 2>/dev/null 731 + 732 + # shellcheck disable=SC2086 # this needs split options 733 + iperf -s -VDB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 734 + sleep 2 735 + 736 + # shellcheck disable=SC2086 # this needs split options 737 + B iperf -c "${dst_addr6}" -V ${dst_port} \ 738 + ${src_addr6} -l1 -t 1000 739 + 740 + src_addr6= 741 + src_port= 742 + dst_port= 743 + } 744 + elif command -v netperf >/dev/null; then 745 + flood_tcp6() { 746 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 747 + if [ -n "${src_addr6}" ]; then 748 + B ip addr add "${src_addr6}" dev veth_b nodad 749 + else 750 + src_addr6="2001:db8::2" 751 + fi 752 + if [ -n "${src_port}" ]; then 753 + dst_port="${dst_port},${src_port}" 754 + fi 755 + B ip route add default dev veth_b 756 + ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 757 + 2>/dev/null 758 + 759 + # shellcheck disable=SC2086 # this needs split options 760 + netserver -6 ${dst_port} -L "${dst_addr6}" \ 761 + >/dev/null 2>&1 762 + sleep 2 763 + 764 + # shellcheck disable=SC2086 # this needs split options 765 + B netperf -6 -H "${dst_addr6}" ${dst_port} \ 766 + -L "${src_addr6}" -l 1000 -t TCP_STREAM 767 + 768 + src_addr6= 769 + src_port= 770 + dst_port= 771 + } 772 + else 773 + return 1 774 + fi 775 + } 776 + 777 + # Set up function to send UDP traffic on IPv4 778 + setup_flood_udp() { 779 + if command -v iperf3 >/dev/null; then 780 + flood_udp() { 781 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 782 + if [ -n "${src_addr4}" ]; then 783 + B ip addr add "${src_addr4}/16" dev veth_b 784 + src_addr4="-B ${src_addr4}" 785 + else 786 + B ip addr add dev veth_b 10.0.0.2 2>/dev/null 787 + src_addr4="-B 10.0.0.2" 788 + fi 789 + if [ -n "${src_port}" ]; then 790 + src_port="--cport ${src_port}" 791 + fi 792 + B ip route add default dev veth_b 793 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 794 + 795 + # shellcheck disable=SC2086 # this needs split options 796 + iperf3 -s -DB "${dst_addr4}" ${dst_port} 797 + sleep 2 798 + 799 + # shellcheck disable=SC2086 # this needs split options 800 + B iperf3 -u -c "${dst_addr4}" -Z -b 100M -l16 -t1000 \ 801 + ${dst_port} ${src_port} ${src_addr4} 802 + 803 + src_addr4= 804 + src_port= 805 + dst_port= 806 + } 807 + elif command -v iperf >/dev/null; then 808 + flood_udp() { 809 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 810 + if [ -n "${src_addr4}" ]; then 811 + B ip addr add "${src_addr4}/16" dev veth_b 812 + src_addr4="-B ${src_addr4}" 813 + else 814 + B ip addr add dev veth_b 10.0.0.2 815 + src_addr4="-B 10.0.0.2" 816 + fi 817 + if [ -n "${src_port}" ]; then 818 + src_addr4="${src_addr4}:${src_port}" 819 + fi 820 + B ip route add default dev veth_b 821 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 822 + 823 + # shellcheck disable=SC2086 # this needs split options 824 + iperf -u -sDB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 825 + sleep 2 826 + 827 + # shellcheck disable=SC2086 # this needs split options 828 + B iperf -u -c "${dst_addr4}" -b 100M -l1 -t1000 \ 829 + ${dst_port} ${src_addr4} 830 + 831 + src_addr4= 832 + src_port= 833 + dst_port= 834 + } 835 + elif command -v netperf >/dev/null; then 836 + flood_udp() { 837 + [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 838 + if [ -n "${src_addr4}" ]; then 839 + B ip addr add "${src_addr4}/16" dev veth_b 840 + else 841 + B ip addr add dev veth_b 10.0.0.2 842 + src_addr4="10.0.0.2" 843 + fi 844 + if [ -n "${src_port}" ]; then 845 + dst_port="${dst_port},${src_port}" 846 + fi 847 + B ip route add default dev veth_b 848 + ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 849 + 850 + # shellcheck disable=SC2086 # this needs split options 851 + netserver -4 ${dst_port} -L "${dst_addr4}" \ 852 + >/dev/null 2>&1 853 + sleep 2 854 + 855 + # shellcheck disable=SC2086 # this needs split options 856 + B netperf -4 -H "${dst_addr4}" ${dst_port} \ 857 + -L "${src_addr4}" -l 1000 -t UDP_STREAM 858 + 859 + src_addr4= 860 + src_port= 861 + dst_port= 862 + } 863 + else 864 + return 1 865 + fi 866 + } 867 + 868 + # Find pktgen script and set up function to start pktgen injection 869 + setup_perf() { 870 + for pktgen_script_path in ${PKTGEN_SCRIPT_PATHS} __notfound; do 871 + command -v "${pktgen_script_path}" >/dev/null && break 872 + done 873 + [ "${pktgen_script_path}" = "__notfound" ] && return 1 874 + 875 + perf_ipv4() { 876 + ${pktgen_script_path} -s80 \ 877 + -i veth_a -d "${dst_addr4}" -p "${dst_port}" \ 878 + -m "${dst_mac}" \ 879 + -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 880 + perf_pid=$! 881 + } 882 + perf_ipv6() { 883 + IP6=6 ${pktgen_script_path} -s100 \ 884 + -i veth_a -d "${dst_addr6}" -p "${dst_port}" \ 885 + -m "${dst_mac}" \ 886 + -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 887 + perf_pid=$! 888 + } 889 + } 890 + 891 + # Clean up before each test 892 + cleanup() { 893 + nft reset counter inet filter test >/dev/null 2>&1 894 + nft flush ruleset >/dev/null 2>&1 895 + ip link del dummy0 2>/dev/null 896 + ip route del default 2>/dev/null 897 + ip -6 route del default 2>/dev/null 898 + ip netns del B 2>/dev/null 899 + ip link del veth_a 2>/dev/null 900 + timeout= 901 + killall iperf3 2>/dev/null 902 + killall iperf 2>/dev/null 903 + killall netperf 2>/dev/null 904 + killall netserver 2>/dev/null 905 + rm -f ${tmp} 906 + sleep 2 907 + } 908 + 909 + # Entry point for setup functions 910 + setup() { 911 + if [ "$(id -u)" -ne 0 ]; then 912 + echo " need to run as root" 913 + exit ${KSELFTEST_SKIP} 914 + fi 915 + 916 + cleanup 917 + check_tools || return 1 918 + for arg do 919 + if ! eval setup_"${arg}"; then 920 + err " ${arg} not supported" 921 + return 1 922 + fi 923 + done 924 + } 925 + 926 + # Format integer into IPv4 address, summing 10.0.0.5 (arbitrary) to it 927 + format_addr4() { 928 + a=$((${1} + 16777216 * 10 + 5)) 929 + printf "%i.%i.%i.%i" \ 930 + "$((a / 16777216))" "$((a % 16777216 / 65536))" \ 931 + "$((a % 65536 / 256))" "$((a % 256))" 932 + } 933 + 934 + # Format integer into IPv6 address, summing 2001:db8:: to it 935 + format_addr6() { 936 + printf "2001:db8::%04x:%04x" "$((${1} / 65536))" "$((${1} % 65536))" 937 + } 938 + 939 + # Format integer into EUI-48 address, summing 00:01:00:00:00:00 to it 940 + format_mac() { 941 + printf "00:01:%02x:%02x:%02x:%02x" \ 942 + "$((${1} / 16777216))" "$((${1} % 16777216 / 65536))" \ 943 + "$((${1} % 65536 / 256))" "$((${1} % 256))" 944 + } 945 + 946 + # Format integer into port, avoid 0 port 947 + format_port() { 948 + printf "%i" "$((${1} % 65534 + 1))" 949 + } 950 + 951 + # Drop suffixed '6' from L4 protocol, if any 952 + format_proto() { 953 + printf "%s" "${proto}" | tr -d 6 954 + } 955 + 956 + # Format destination and source fields into nft concatenated type 957 + format() { 958 + __start= 959 + __end= 960 + __expr="{ " 961 + 962 + for f in ${dst}; do 963 + [ "${__expr}" != "{ " ] && __expr="${__expr} . " 964 + 965 + __start="$(eval format_"${f}" "${start}")" 966 + __end="$(eval format_"${f}" "${end}")" 967 + 968 + if [ "${f}" = "proto" ]; then 969 + __expr="${__expr}${__start}" 970 + else 971 + __expr="${__expr}${__start}-${__end}" 972 + fi 973 + done 974 + for f in ${src}; do 975 + __expr="${__expr} . " 976 + __start="$(eval format_"${f}" "${srcstart}")" 977 + __end="$(eval format_"${f}" "${srcend}")" 978 + 979 + if [ "${f}" = "proto" ]; then 980 + __expr="${__expr}${__start}" 981 + else 982 + __expr="${__expr}${__start}-${__end}" 983 + fi 984 + done 985 + 986 + if [ -n "${timeout}" ]; then 987 + echo "${__expr} timeout ${timeout}s }" 988 + else 989 + echo "${__expr} }" 990 + fi 991 + } 992 + 993 + # Format destination and source fields into nft type, start element only 994 + format_norange() { 995 + __expr="{ " 996 + 997 + for f in ${dst}; do 998 + [ "${__expr}" != "{ " ] && __expr="${__expr} . " 999 + 1000 + __expr="${__expr}$(eval format_"${f}" "${start}")" 1001 + done 1002 + for f in ${src}; do 1003 + __expr="${__expr} . $(eval format_"${f}" "${start}")" 1004 + done 1005 + 1006 + echo "${__expr} }" 1007 + } 1008 + 1009 + # Format first destination field into nft type 1010 + format_noconcat() { 1011 + for f in ${dst}; do 1012 + __start="$(eval format_"${f}" "${start}")" 1013 + __end="$(eval format_"${f}" "${end}")" 1014 + 1015 + if [ "${f}" = "proto" ]; then 1016 + echo "{ ${__start} }" 1017 + else 1018 + echo "{ ${__start}-${__end} }" 1019 + fi 1020 + return 1021 + done 1022 + } 1023 + 1024 + # Add single entry to 'test' set in 'inet filter' table 1025 + add() { 1026 + if ! nft add element inet filter test "${1}"; then 1027 + err "Failed to add ${1} given ruleset:" 1028 + err "$(nft list ruleset -a)" 1029 + return 1 1030 + fi 1031 + } 1032 + 1033 + # Format and output entries for sets in 'netdev perf' table 1034 + add_perf() { 1035 + if [ "${1}" = "test" ]; then 1036 + echo "add element netdev perf test $(format)" 1037 + elif [ "${1}" = "norange" ]; then 1038 + echo "add element netdev perf norange $(format_norange)" 1039 + elif [ "${1}" = "noconcat" ]; then 1040 + echo "add element netdev perf noconcat $(format_noconcat)" 1041 + fi 1042 + } 1043 + 1044 + # Add single entry to 'norange' set in 'netdev perf' table 1045 + add_perf_norange() { 1046 + if ! nft add element netdev perf norange "${1}"; then 1047 + err "Failed to add ${1} given ruleset:" 1048 + err "$(nft list ruleset -a)" 1049 + return 1 1050 + fi 1051 + } 1052 + 1053 + # Add single entry to 'noconcat' set in 'netdev perf' table 1054 + add_perf_noconcat() { 1055 + if ! nft add element netdev perf noconcat "${1}"; then 1056 + err "Failed to add ${1} given ruleset:" 1057 + err "$(nft list ruleset -a)" 1058 + return 1 1059 + fi 1060 + } 1061 + 1062 + # Delete single entry from set 1063 + del() { 1064 + if ! nft delete element inet filter test "${1}"; then 1065 + err "Failed to delete ${1} given ruleset:" 1066 + err "$(nft list ruleset -a)" 1067 + return 1 1068 + fi 1069 + } 1070 + 1071 + # Return packet count from 'test' counter in 'inet filter' table 1072 + count_packets() { 1073 + found=0 1074 + for token in $(nft list counter inet filter test); do 1075 + [ ${found} -eq 1 ] && echo "${token}" && return 1076 + [ "${token}" = "packets" ] && found=1 1077 + done 1078 + } 1079 + 1080 + # Return packet count from 'test' counter in 'netdev perf' table 1081 + count_perf_packets() { 1082 + found=0 1083 + for token in $(nft list counter netdev perf test); do 1084 + [ ${found} -eq 1 ] && echo "${token}" && return 1085 + [ "${token}" = "packets" ] && found=1 1086 + done 1087 + } 1088 + 1089 + # Set MAC addresses, send traffic according to specifier 1090 + flood() { 1091 + ip link set veth_a address "$(format_mac "${1}")" 1092 + ip -n B link set veth_b address "$(format_mac "${2}")" 1093 + 1094 + for f in ${dst}; do 1095 + eval dst_"$f"=\$\(format_\$f "${1}"\) 1096 + done 1097 + for f in ${src}; do 1098 + eval src_"$f"=\$\(format_\$f "${2}"\) 1099 + done 1100 + eval flood_\$proto 1101 + } 1102 + 1103 + # Set MAC addresses, start pktgen injection 1104 + perf() { 1105 + dst_mac="$(format_mac "${1}")" 1106 + ip link set veth_a address "${dst_mac}" 1107 + 1108 + for f in ${dst}; do 1109 + eval dst_"$f"=\$\(format_\$f "${1}"\) 1110 + done 1111 + for f in ${src}; do 1112 + eval src_"$f"=\$\(format_\$f "${2}"\) 1113 + done 1114 + eval perf_\$perf_proto 1115 + } 1116 + 1117 + # Set MAC addresses, send single packet, check that it matches, reset counter 1118 + send_match() { 1119 + ip link set veth_a address "$(format_mac "${1}")" 1120 + ip -n B link set veth_b address "$(format_mac "${2}")" 1121 + 1122 + for f in ${dst}; do 1123 + eval dst_"$f"=\$\(format_\$f "${1}"\) 1124 + done 1125 + for f in ${src}; do 1126 + eval src_"$f"=\$\(format_\$f "${2}"\) 1127 + done 1128 + eval send_\$proto 1129 + if [ "$(count_packets)" != "1" ]; then 1130 + err "${proto} packet to:" 1131 + err " $(for f in ${dst}; do 1132 + eval format_\$f "${1}"; printf ' '; done)" 1133 + err "from:" 1134 + err " $(for f in ${src}; do 1135 + eval format_\$f "${2}"; printf ' '; done)" 1136 + err "should have matched ruleset:" 1137 + err "$(nft list ruleset -a)" 1138 + return 1 1139 + fi 1140 + nft reset counter inet filter test >/dev/null 1141 + } 1142 + 1143 + # Set MAC addresses, send single packet, check that it doesn't match 1144 + send_nomatch() { 1145 + ip link set veth_a address "$(format_mac "${1}")" 1146 + ip -n B link set veth_b address "$(format_mac "${2}")" 1147 + 1148 + for f in ${dst}; do 1149 + eval dst_"$f"=\$\(format_\$f "${1}"\) 1150 + done 1151 + for f in ${src}; do 1152 + eval src_"$f"=\$\(format_\$f "${2}"\) 1153 + done 1154 + eval send_\$proto 1155 + if [ "$(count_packets)" != "0" ]; then 1156 + err "${proto} packet to:" 1157 + err " $(for f in ${dst}; do 1158 + eval format_\$f "${1}"; printf ' '; done)" 1159 + err "from:" 1160 + err " $(for f in ${src}; do 1161 + eval format_\$f "${2}"; printf ' '; done)" 1162 + err "should not have matched ruleset:" 1163 + err "$(nft list ruleset -a)" 1164 + return 1 1165 + fi 1166 + } 1167 + 1168 + # Correctness test template: 1169 + # - add ranged element, check that packets match it 1170 + # - check that packets outside range don't match it 1171 + # - remove some elements, check that packets don't match anymore 1172 + test_correctness() { 1173 + setup veth send_"${proto}" set || return ${KSELFTEST_SKIP} 1174 + 1175 + range_size=1 1176 + for i in $(seq "${start}" $((start + count))); do 1177 + end=$((start + range_size)) 1178 + 1179 + # Avoid negative or zero-sized port ranges 1180 + if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1181 + start=${end} 1182 + end=$((end + 1)) 1183 + fi 1184 + srcstart=$((start + src_delta)) 1185 + srcend=$((end + src_delta)) 1186 + 1187 + add "$(format)" || return 1 1188 + for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do 1189 + send_match "${j}" $((j + src_delta)) || return 1 1190 + done 1191 + send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1 1192 + 1193 + # Delete elements now and then 1194 + if [ $((i % 3)) -eq 0 ]; then 1195 + del "$(format)" || return 1 1196 + for j in $(seq ${start} \ 1197 + $((range_size / 2 + 1)) ${end}); do 1198 + send_nomatch "${j}" $((j + src_delta)) \ 1199 + || return 1 1200 + done 1201 + fi 1202 + 1203 + range_size=$((range_size + 1)) 1204 + start=$((end + range_size)) 1205 + done 1206 + } 1207 + 1208 + # Concurrency test template: 1209 + # - add all the elements 1210 + # - start a thread for each physical thread that: 1211 + # - adds all the elements 1212 + # - flushes the set 1213 + # - adds all the elements 1214 + # - flushes the entire ruleset 1215 + # - adds the set back 1216 + # - adds all the elements 1217 + # - delete all the elements 1218 + test_concurrency() { 1219 + proto=${flood_proto} 1220 + tools=${flood_tools} 1221 + chain_spec=${flood_spec} 1222 + setup veth flood_"${proto}" set || return ${KSELFTEST_SKIP} 1223 + 1224 + range_size=1 1225 + cstart=${start} 1226 + flood_pids= 1227 + for i in $(seq ${start} $((start + count))); do 1228 + end=$((start + range_size)) 1229 + srcstart=$((start + src_delta)) 1230 + srcend=$((end + src_delta)) 1231 + 1232 + add "$(format)" || return 1 1233 + 1234 + flood "${i}" $((i + src_delta)) & flood_pids="${flood_pids} $!" 1235 + 1236 + range_size=$((range_size + 1)) 1237 + start=$((end + range_size)) 1238 + done 1239 + 1240 + sleep 10 1241 + 1242 + pids= 1243 + for c in $(seq 1 "$(nproc)"); do ( 1244 + for r in $(seq 1 "${race_repeat}"); do 1245 + range_size=1 1246 + 1247 + # $start needs to be local to this subshell 1248 + # shellcheck disable=SC2030 1249 + start=${cstart} 1250 + for i in $(seq ${start} $((start + count))); do 1251 + end=$((start + range_size)) 1252 + srcstart=$((start + src_delta)) 1253 + srcend=$((end + src_delta)) 1254 + 1255 + add "$(format)" 2>/dev/null 1256 + 1257 + range_size=$((range_size + 1)) 1258 + start=$((end + range_size)) 1259 + done 1260 + 1261 + nft flush inet filter test 2>/dev/null 1262 + 1263 + range_size=1 1264 + start=${cstart} 1265 + for i in $(seq ${start} $((start + count))); do 1266 + end=$((start + range_size)) 1267 + srcstart=$((start + src_delta)) 1268 + srcend=$((end + src_delta)) 1269 + 1270 + add "$(format)" 2>/dev/null 1271 + 1272 + range_size=$((range_size + 1)) 1273 + start=$((end + range_size)) 1274 + done 1275 + 1276 + nft flush ruleset 1277 + setup set 2>/dev/null 1278 + 1279 + range_size=1 1280 + start=${cstart} 1281 + for i in $(seq ${start} $((start + count))); do 1282 + end=$((start + range_size)) 1283 + srcstart=$((start + src_delta)) 1284 + srcend=$((end + src_delta)) 1285 + 1286 + add "$(format)" 2>/dev/null 1287 + 1288 + range_size=$((range_size + 1)) 1289 + start=$((end + range_size)) 1290 + done 1291 + 1292 + range_size=1 1293 + start=${cstart} 1294 + for i in $(seq ${start} $((start + count))); do 1295 + end=$((start + range_size)) 1296 + srcstart=$((start + src_delta)) 1297 + srcend=$((end + src_delta)) 1298 + 1299 + del "$(format)" 2>/dev/null 1300 + 1301 + range_size=$((range_size + 1)) 1302 + start=$((end + range_size)) 1303 + done 1304 + done 1305 + ) & pids="${pids} $!" 1306 + done 1307 + 1308 + # shellcheck disable=SC2046,SC2086 # word splitting wanted here 1309 + wait $(for pid in ${pids}; do echo ${pid}; done) 1310 + # shellcheck disable=SC2046,SC2086 1311 + kill $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null 1312 + # shellcheck disable=SC2046,SC2086 1313 + wait $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null 1314 + 1315 + return 0 1316 + } 1317 + 1318 + # Timeout test template: 1319 + # - add all the elements with 3s timeout while checking that packets match 1320 + # - wait 3s after the last insertion, check that packets don't match any entry 1321 + test_timeout() { 1322 + setup veth send_"${proto}" set || return ${KSELFTEST_SKIP} 1323 + 1324 + timeout=3 1325 + range_size=1 1326 + for i in $(seq "${start}" $((start + count))); do 1327 + end=$((start + range_size)) 1328 + srcstart=$((start + src_delta)) 1329 + srcend=$((end + src_delta)) 1330 + 1331 + add "$(format)" || return 1 1332 + 1333 + for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do 1334 + send_match "${j}" $((j + src_delta)) || return 1 1335 + done 1336 + 1337 + range_size=$((range_size + 1)) 1338 + start=$((end + range_size)) 1339 + done 1340 + sleep 3 1341 + for i in $(seq ${start} $((start + count))); do 1342 + end=$((start + range_size)) 1343 + srcstart=$((start + src_delta)) 1344 + srcend=$((end + src_delta)) 1345 + 1346 + for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do 1347 + send_nomatch "${j}" $((j + src_delta)) || return 1 1348 + done 1349 + 1350 + range_size=$((range_size + 1)) 1351 + start=$((end + range_size)) 1352 + done 1353 + } 1354 + 1355 + # Performance test template: 1356 + # - add concatenated ranged entries 1357 + # - add non-ranged concatenated entries (for hash set matching rate baseline) 1358 + # - add ranged entries with first field only (for rbhash baseline) 1359 + # - start pktgen injection directly on device rx path of this namespace 1360 + # - measure drop only rate, hash and rbtree baselines, then matching rate 1361 + test_performance() { 1362 + chain_spec=${perf_spec} 1363 + dst="${perf_dst}" 1364 + src="${perf_src}" 1365 + setup veth perf set || return ${KSELFTEST_SKIP} 1366 + 1367 + first=${start} 1368 + range_size=1 1369 + for set in test norange noconcat; do 1370 + start=${first} 1371 + for i in $(seq ${start} $((start + perf_entries))); do 1372 + end=$((start + range_size)) 1373 + srcstart=$((start + src_delta)) 1374 + srcend=$((end + src_delta)) 1375 + 1376 + if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1377 + start=${end} 1378 + end=$((end + 1)) 1379 + elif [ ${start} -eq ${end} ]; then 1380 + end=$((start + 1)) 1381 + fi 1382 + 1383 + add_perf ${set} 1384 + 1385 + start=$((end + range_size)) 1386 + done > "${tmp}" 1387 + nft -f "${tmp}" 1388 + done 1389 + 1390 + perf $((end - 1)) ${srcstart} 1391 + 1392 + sleep 2 1393 + 1394 + nft add rule netdev perf test counter name \"test\" drop 1395 + nft reset counter netdev perf test >/dev/null 2>&1 1396 + sleep "${perf_duration}" 1397 + pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1398 + info " baseline (drop from netdev hook): ${pps}pps" 1399 + handle="$(nft -a list chain netdev perf test | grep counter)" 1400 + handle="${handle##* }" 1401 + nft delete rule netdev perf test handle "${handle}" 1402 + 1403 + nft add rule "netdev perf test ${chain_spec} @norange \ 1404 + counter name \"test\" drop" 1405 + nft reset counter netdev perf test >/dev/null 2>&1 1406 + sleep "${perf_duration}" 1407 + pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1408 + info " baseline hash (non-ranged entries): ${pps}pps" 1409 + handle="$(nft -a list chain netdev perf test | grep counter)" 1410 + handle="${handle##* }" 1411 + nft delete rule netdev perf test handle "${handle}" 1412 + 1413 + nft add rule "netdev perf test ${chain_spec%%. *} @noconcat \ 1414 + counter name \"test\" drop" 1415 + nft reset counter netdev perf test >/dev/null 2>&1 1416 + sleep "${perf_duration}" 1417 + pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1418 + info " baseline rbtree (match on first field only): ${pps}pps" 1419 + handle="$(nft -a list chain netdev perf test | grep counter)" 1420 + handle="${handle##* }" 1421 + nft delete rule netdev perf test handle "${handle}" 1422 + 1423 + nft add rule "netdev perf test ${chain_spec} @test \ 1424 + counter name \"test\" drop" 1425 + nft reset counter netdev perf test >/dev/null 2>&1 1426 + sleep "${perf_duration}" 1427 + pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1428 + p5="$(printf %5s "${perf_entries}")" 1429 + info " set with ${p5} full, ranged entries: ${pps}pps" 1430 + kill "${perf_pid}" 1431 + } 1432 + 1433 + # Run everything in a separate network namespace 1434 + [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } 1435 + tmp="$(mktemp)" 1436 + trap cleanup EXIT 1437 + 1438 + # Entry point for test runs 1439 + passed=0 1440 + for name in ${TESTS}; do 1441 + printf "TEST: %s\n" "${name}" 1442 + for type in ${TYPES}; do 1443 + eval desc=\$TYPE_"${type}" 1444 + IFS=' 1445 + ' 1446 + for __line in ${desc}; do 1447 + # shellcheck disable=SC2086 1448 + eval ${__line%% *}=\"${__line##* }\"; 1449 + done 1450 + IFS=' 1451 + ' 1452 + 1453 + if [ "${name}" = "concurrency" ] && \ 1454 + [ "${race_repeat}" = "0" ]; then 1455 + continue 1456 + fi 1457 + if [ "${name}" = "performance" ] && \ 1458 + [ "${perf_duration}" = "0" ]; then 1459 + continue 1460 + fi 1461 + 1462 + printf " %-60s " "${display}" 1463 + eval test_"${name}" 1464 + ret=$? 1465 + 1466 + if [ $ret -eq 0 ]; then 1467 + printf "[ OK ]\n" 1468 + info_flush 1469 + passed=$((passed + 1)) 1470 + elif [ $ret -eq 1 ]; then 1471 + printf "[FAIL]\n" 1472 + err_flush 1473 + exit 1 1474 + elif [ $ret -eq ${KSELFTEST_SKIP} ]; then 1475 + printf "[SKIP]\n" 1476 + err_flush 1477 + fi 1478 + done 1479 + done 1480 + 1481 + [ ${passed} -eq 0 ] && exit ${KSELFTEST_SKIP}