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