1#!/bin/bash 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 <[email protected]> 9# 10# shellcheck disable=SC2154,SC2034,SC2016,SC2030,SC2031,SC2317 11# ^ Configuration and templates sourced with eval, counters reused in subshells 12 13source lib.sh 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[ -n "$NFT_CONCAT_RANGE_TESTS" ] && TESTS="${NFT_CONCAT_RANGE_TESTS}" 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 net_port_proto_match avx2_mismatch" 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 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 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 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 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 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 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 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 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 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 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 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 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 bash 367proto udp 368 369race_repeat 0 370 371perf_duration 0 372" 373 374TYPE_net_port_proto_match=" 375display net,port,proto 376type_spec ipv4_addr . inet_service . inet_proto 377chain_spec ip daddr . udp dport . meta l4proto 378dst addr4 port proto 379src 380start 1 381count 9 382src_delta 9 383tools sendip bash 384proto udp 385 386race_repeat 0 387 388perf_duration 0 389" 390 391TYPE_avx2_mismatch=" 392display avx2 false match 393type_spec inet_proto . ipv6_addr 394chain_spec meta l4proto . ip6 daddr 395dst proto addr6 396src 397start 1 398count 1 399src_delta 1 400tools ping 401proto icmp6 402 403race_repeat 0 404 405perf_duration 0 406" 407 408 409# Set template for all tests, types and rules are filled in depending on test 410set_template=' 411flush ruleset 412 413table inet filter { 414 counter test { 415 packets 0 bytes 0 416 } 417 418 set test { 419 type ${type_spec} 420 flags interval,timeout 421 } 422 423 chain input { 424 type filter hook prerouting priority 0; policy accept; 425 ${chain_spec} @test counter name \"test\" 426 } 427} 428 429table netdev perf { 430 counter test { 431 packets 0 bytes 0 432 } 433 434 counter match { 435 packets 0 bytes 0 436 } 437 438 set test { 439 type ${type_spec} 440 flags interval 441 } 442 443 set norange { 444 type ${type_spec} 445 } 446 447 set noconcat { 448 type ${type_spec%% *} 449 flags interval 450 } 451 452 chain test { 453 type filter hook ingress device veth_a priority 0; 454 } 455} 456' 457 458err_buf= 459info_buf= 460 461# Append string to error buffer 462err() { 463 err_buf="${err_buf}${1} 464" 465} 466 467# Append string to information buffer 468info() { 469 info_buf="${info_buf}${1} 470" 471} 472 473# Flush error buffer to stdout 474err_flush() { 475 printf "%s" "${err_buf}" 476 err_buf= 477} 478 479# Flush information buffer to stdout 480info_flush() { 481 printf "%s" "${info_buf}" 482 info_buf= 483} 484 485# Setup veth pair: this namespace receives traffic, B generates it 486setup_veth() { 487 ip netns add B 488 ip link add veth_a type veth peer name veth_b || return 1 489 490 ip link set veth_a up 491 ip link set veth_b netns B 492 493 ip -n B link set veth_b up 494 495 ip addr add dev veth_a 10.0.0.1 496 ip route add default dev veth_a 497 498 ip -6 addr add fe80::1/64 dev veth_a nodad 499 ip -6 addr add 2001:db8::1/64 dev veth_a nodad 500 ip -6 route add default dev veth_a 501 502 ip -n B route add default dev veth_b 503 504 ip -6 -n B addr add fe80::2/64 dev veth_b nodad 505 ip -6 -n B addr add 2001:db8::2/64 dev veth_b nodad 506 ip -6 -n B route add default dev veth_b 507 508 B() { 509 ip netns exec B "$@" >/dev/null 2>&1 510 } 511} 512 513# Fill in set template and initialise set 514setup_set() { 515 eval "echo \"${set_template}\"" | nft -f - 516} 517 518# Check that at least one of the needed tools is available 519check_tools() { 520 [ -z "${tools}" ] && return 0 521 522 __tools= 523 for tool in ${tools}; do 524 __tools="${__tools} ${tool}" 525 526 command -v "${tool}" >/dev/null && return 0 527 done 528 err "need one of:${__tools}, skipping" && return 1 529} 530 531# Set up function to send ICMP packets 532setup_send_icmp() { 533 send_icmp() { 534 B ping -c1 -W1 "${dst_addr4}" >/dev/null 2>&1 535 } 536} 537 538# Set up function to send ICMPv6 packets 539setup_send_icmp6() { 540 if command -v ping6 >/dev/null; then 541 send_icmp6() { 542 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 543 2>/dev/null 544 B ping6 -q -c1 -W1 "${dst_addr6}" 545 } 546 else 547 send_icmp6() { 548 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 549 2>/dev/null 550 B ping -q -6 -c1 -W1 "${dst_addr6}" 551 } 552 fi 553} 554 555# Set up function to send single UDP packets on IPv4 556setup_send_udp() { 557 if command -v sendip >/dev/null; then 558 send_udp() { 559 [ -n "${src_port}" ] && src_port="-us ${src_port}" 560 [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 561 [ -n "${src_addr4}" ] && src_addr4="-is ${src_addr4}" 562 563 # shellcheck disable=SC2086 # sendip needs split options 564 B sendip -p ipv4 -p udp ${src_addr4} ${src_port} \ 565 ${dst_port} "${dst_addr4}" 566 567 src_port= 568 dst_port= 569 src_addr4= 570 } 571 elif command -v socat -v >/dev/null; then 572 send_udp() { 573 if [ -n "${src_addr4}" ]; then 574 B ip addr add "${src_addr4}" dev veth_b 575 __socatbind=",bind=${src_addr4}" 576 if [ -n "${src_port}" ];then 577 __socatbind="${__socatbind}:${src_port}" 578 fi 579 fi 580 581 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 582 [ -z "${dst_port}" ] && dst_port=12345 583 584 echo "test4" | B socat -t 0.01 STDIN UDP4-DATAGRAM:"$dst_addr4":"$dst_port""${__socatbind}" 585 586 src_addr4= 587 src_port= 588 } 589 elif [ -z "$(bash -c 'type -p')" ]; then 590 send_udp() { 591 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 592 if [ -n "${src_addr4}" ]; then 593 B ip addr add "${src_addr4}/16" dev veth_b 594 B ip route add default dev veth_b 595 fi 596 597 B bash -c "echo > /dev/udp/${dst_addr4}/${dst_port}" 598 599 if [ -n "${src_addr4}" ]; then 600 B ip addr del "${src_addr4}/16" dev veth_b 601 fi 602 src_addr4= 603 } 604 else 605 return 1 606 fi 607} 608 609# Set up function to send single UDP packets on IPv6 610setup_send_udp6() { 611 if command -v sendip >/dev/null; then 612 send_udp6() { 613 [ -n "${src_port}" ] && src_port="-us ${src_port}" 614 [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 615 if [ -n "${src_addr6}" ]; then 616 src_addr6="-6s ${src_addr6}" 617 else 618 src_addr6="-6s 2001:db8::2" 619 fi 620 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 621 2>/dev/null 622 623 # shellcheck disable=SC2086 # this needs split options 624 B sendip -p ipv6 -p udp ${src_addr6} ${src_port} \ 625 ${dst_port} "${dst_addr6}" 626 627 src_port= 628 dst_port= 629 src_addr6= 630 } 631 elif command -v socat -v >/dev/null; then 632 send_udp6() { 633 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 634 2>/dev/null 635 636 __socatbind6= 637 638 if [ -n "${src_addr6}" ]; then 639 B ip addr add "${src_addr6}" dev veth_b nodad 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 [ -z "$(bash -c 'type -p')" ]; then 651 send_udp6() { 652 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 653 2>/dev/null 654 B ip addr add "${src_addr6}" dev veth_b nodad 655 B bash -c "echo > /dev/udp/${dst_addr6}/${dst_port}" 656 ip -6 addr del "${dst_addr6}" dev veth_a 2>/dev/null 657 } 658 else 659 return 1 660 fi 661} 662 663listener_ready() 664{ 665 port="$1" 666 ss -lnt -o "sport = :$port" | grep -q "$port" 667} 668 669# Set up function to send TCP traffic on IPv4 670setup_flood_tcp() { 671 if command -v iperf3 >/dev/null; then 672 flood_tcp() { 673 local n_port="${dst_port}" 674 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 675 if [ -n "${src_addr4}" ]; then 676 B ip addr add "${src_addr4}/16" dev veth_b 677 src_addr4="-B ${src_addr4}" 678 else 679 B ip addr add dev veth_b 10.0.0.2 680 src_addr4="-B 10.0.0.2" 681 fi 682 if [ -n "${src_port}" ]; then 683 src_port="--cport ${src_port}" 684 fi 685 B ip route add default dev veth_b 2>/dev/null 686 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 687 688 # shellcheck disable=SC2086 # this needs split options 689 iperf3 -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 690 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 691 692 # shellcheck disable=SC2086 # this needs split options 693 B iperf3 -c "${dst_addr4}" ${dst_port} ${src_port} \ 694 ${src_addr4} -l16 -t 1000 695 696 src_addr4= 697 src_port= 698 dst_port= 699 } 700 elif command -v iperf >/dev/null; then 701 flood_tcp() { 702 local n_port="${dst_port}" 703 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 704 if [ -n "${src_addr4}" ]; then 705 B ip addr add "${src_addr4}/16" dev veth_b 706 src_addr4="-B ${src_addr4}" 707 else 708 B ip addr add dev veth_b 10.0.0.2 2>/dev/null 709 src_addr4="-B 10.0.0.2" 710 fi 711 if [ -n "${src_port}" ]; then 712 src_addr4="${src_addr4}:${src_port}" 713 fi 714 B ip route add default dev veth_b 715 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 716 717 # shellcheck disable=SC2086 # this needs split options 718 iperf -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 719 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 720 721 # shellcheck disable=SC2086 # this needs split options 722 B iperf -c "${dst_addr4}" ${dst_port} ${src_addr4} \ 723 -l20 -t 1000 724 725 src_addr4= 726 src_port= 727 dst_port= 728 } 729 elif command -v netperf >/dev/null; then 730 flood_tcp() { 731 local n_port="${dst_port}" 732 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 733 if [ -n "${src_addr4}" ]; then 734 B ip addr add "${src_addr4}/16" dev veth_b 735 else 736 B ip addr add dev veth_b 10.0.0.2 737 src_addr4="10.0.0.2" 738 fi 739 if [ -n "${src_port}" ]; then 740 dst_port="${dst_port},${src_port}" 741 fi 742 B ip route add default dev veth_b 743 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 744 745 # shellcheck disable=SC2086 # this needs split options 746 netserver -4 ${dst_port} -L "${dst_addr4}" \ 747 >/dev/null 2>&1 748 busywait "$BUSYWAIT_TIMEOUT" listener_ready "${n_port}" 749 750 # shellcheck disable=SC2086 # this needs split options 751 B netperf -4 -H "${dst_addr4}" ${dst_port} \ 752 -L "${src_addr4}" -l 1000 -t TCP_STREAM 753 754 src_addr4= 755 src_port= 756 dst_port= 757 } 758 else 759 return 1 760 fi 761} 762 763# Set up function to send TCP traffic on IPv6 764setup_flood_tcp6() { 765 if command -v iperf3 >/dev/null; then 766 flood_tcp6() { 767 local n_port="${dst_port}" 768 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 769 if [ -n "${src_addr6}" ]; then 770 B ip addr add "${src_addr6}" dev veth_b nodad 771 src_addr6="-B ${src_addr6}" 772 else 773 src_addr6="-B 2001:db8::2" 774 fi 775 if [ -n "${src_port}" ]; then 776 src_port="--cport ${src_port}" 777 fi 778 B ip route add default dev veth_b 779 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 780 2>/dev/null 781 782 # shellcheck disable=SC2086 # this needs split options 783 iperf3 -s -DB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 784 busywait "$BUSYWAIT_TIMEOUT" listener_ready "${n_port}" 785 786 # shellcheck disable=SC2086 # this needs split options 787 B iperf3 -c "${dst_addr6}" ${dst_port} \ 788 ${src_port} ${src_addr6} -l16 -t 1000 789 790 src_addr6= 791 src_port= 792 dst_port= 793 } 794 elif command -v iperf >/dev/null; then 795 flood_tcp6() { 796 local n_port="${dst_port}" 797 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 798 if [ -n "${src_addr6}" ]; then 799 B ip addr add "${src_addr6}" dev veth_b nodad 800 src_addr6="-B ${src_addr6}" 801 else 802 src_addr6="-B 2001:db8::2" 803 fi 804 if [ -n "${src_port}" ]; then 805 src_addr6="${src_addr6}:${src_port}" 806 fi 807 B ip route add default dev veth_b 808 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 809 2>/dev/null 810 811 # shellcheck disable=SC2086 # this needs split options 812 iperf -s -VDB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 813 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 814 815 # shellcheck disable=SC2086 # this needs split options 816 B iperf -c "${dst_addr6}" -V ${dst_port} \ 817 ${src_addr6} -l1 -t 1000 818 819 src_addr6= 820 src_port= 821 dst_port= 822 } 823 elif command -v netperf >/dev/null; then 824 flood_tcp6() { 825 local n_port="${dst_port}" 826 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 827 if [ -n "${src_addr6}" ]; then 828 B ip addr add "${src_addr6}" dev veth_b nodad 829 else 830 src_addr6="2001:db8::2" 831 fi 832 if [ -n "${src_port}" ]; then 833 dst_port="${dst_port},${src_port}" 834 fi 835 B ip route add default dev veth_b 836 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 837 2>/dev/null 838 839 # shellcheck disable=SC2086 # this needs split options 840 netserver -6 ${dst_port} -L "${dst_addr6}" \ 841 >/dev/null 2>&1 842 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 843 844 # shellcheck disable=SC2086 # this needs split options 845 B netperf -6 -H "${dst_addr6}" ${dst_port} \ 846 -L "${src_addr6}" -l 1000 -t TCP_STREAM 847 848 src_addr6= 849 src_port= 850 dst_port= 851 } 852 else 853 return 1 854 fi 855} 856 857# Set up function to send UDP traffic on IPv4 858setup_flood_udp() { 859 if command -v iperf3 >/dev/null; then 860 flood_udp() { 861 local n_port="${dst_port}" 862 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 863 if [ -n "${src_addr4}" ]; then 864 B ip addr add "${src_addr4}/16" dev veth_b 865 src_addr4="-B ${src_addr4}" 866 else 867 B ip addr add dev veth_b 10.0.0.2 2>/dev/null 868 src_addr4="-B 10.0.0.2" 869 fi 870 if [ -n "${src_port}" ]; then 871 src_port="--cport ${src_port}" 872 fi 873 B ip route add default dev veth_b 874 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 875 876 # shellcheck disable=SC2086 # this needs split options 877 iperf3 -s -DB "${dst_addr4}" ${dst_port} 878 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 879 880 # shellcheck disable=SC2086 # this needs split options 881 B iperf3 -u -c "${dst_addr4}" -Z -b 100M -l16 -t1000 \ 882 ${dst_port} ${src_port} ${src_addr4} 883 884 src_addr4= 885 src_port= 886 dst_port= 887 } 888 elif command -v iperf >/dev/null; then 889 flood_udp() { 890 local n_port="${dst_port}" 891 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 892 if [ -n "${src_addr4}" ]; then 893 B ip addr add "${src_addr4}/16" dev veth_b 894 src_addr4="-B ${src_addr4}" 895 else 896 B ip addr add dev veth_b 10.0.0.2 897 src_addr4="-B 10.0.0.2" 898 fi 899 if [ -n "${src_port}" ]; then 900 src_addr4="${src_addr4}:${src_port}" 901 fi 902 B ip route add default dev veth_b 903 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 904 905 # shellcheck disable=SC2086 # this needs split options 906 iperf -u -sDB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 907 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 908 909 # shellcheck disable=SC2086 # this needs split options 910 B iperf -u -c "${dst_addr4}" -b 100M -l1 -t1000 \ 911 ${dst_port} ${src_addr4} 912 913 src_addr4= 914 src_port= 915 dst_port= 916 } 917 elif command -v netperf >/dev/null; then 918 flood_udp() { 919 local n_port="${dst_port}" 920 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 921 if [ -n "${src_addr4}" ]; then 922 B ip addr add "${src_addr4}/16" dev veth_b 923 else 924 B ip addr add dev veth_b 10.0.0.2 925 src_addr4="10.0.0.2" 926 fi 927 if [ -n "${src_port}" ]; then 928 dst_port="${dst_port},${src_port}" 929 fi 930 B ip route add default dev veth_b 931 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 932 933 # shellcheck disable=SC2086 # this needs split options 934 netserver -4 ${dst_port} -L "${dst_addr4}" \ 935 >/dev/null 2>&1 936 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 937 938 # shellcheck disable=SC2086 # this needs split options 939 B netperf -4 -H "${dst_addr4}" ${dst_port} \ 940 -L "${src_addr4}" -l 1000 -t UDP_STREAM 941 942 src_addr4= 943 src_port= 944 dst_port= 945 } 946 else 947 return 1 948 fi 949} 950 951# Find pktgen script and set up function to start pktgen injection 952setup_perf() { 953 for pktgen_script_path in ${PKTGEN_SCRIPT_PATHS} __notfound; do 954 command -v "${pktgen_script_path}" >/dev/null && break 955 done 956 [ "${pktgen_script_path}" = "__notfound" ] && return 1 957 958 perf_ipv4() { 959 ${pktgen_script_path} -s80 \ 960 -i veth_a -d "${dst_addr4}" -p "${dst_port}" \ 961 -m "${dst_mac}" \ 962 -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 963 perf_pid=$! 964 } 965 perf_ipv6() { 966 IP6=6 ${pktgen_script_path} -s100 \ 967 -i veth_a -d "${dst_addr6}" -p "${dst_port}" \ 968 -m "${dst_mac}" \ 969 -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 970 perf_pid=$! 971 } 972} 973 974# Clean up before each test 975cleanup() { 976 nft reset counter inet filter test >/dev/null 2>&1 977 nft flush ruleset >/dev/null 2>&1 978 ip link del dummy0 2>/dev/null 979 ip route del default 2>/dev/null 980 ip -6 route del default 2>/dev/null 981 ip netns pids B 2>/dev/null | xargs kill 2>/dev/null 982 ip netns del B 2>/dev/null 983 ip link del veth_a 2>/dev/null 984 timeout= 985 killall iperf3 2>/dev/null 986 killall iperf 2>/dev/null 987 killall netperf 2>/dev/null 988 killall netserver 2>/dev/null 989} 990 991cleanup_exit() { 992 cleanup 993 rm -f "$tmp" 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 ${ksft_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 ${ksft_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 ${ksft_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 $((RANDOM%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 ${ksft_skip} 1411 1412 timeout=3 1413 1414 [ "$KSFT_MACHINE_SLOW" = "yes" ] && timeout=8 1415 1416 range_size=1 1417 for i in $(seq "$start" $((start + count))); do 1418 end=$((start + range_size)) 1419 srcstart=$((start + src_delta)) 1420 srcend=$((end + src_delta)) 1421 1422 add "$(format)" || return 1 1423 1424 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1425 send_match "${j}" $((j + src_delta)) || return 1 1426 done 1427 1428 range_size=$((range_size + 1)) 1429 start=$((end + range_size)) 1430 done 1431 sleep $timeout 1432 for i in $(seq "$start" $((start + count))); do 1433 end=$((start + range_size)) 1434 srcstart=$((start + src_delta)) 1435 srcend=$((end + src_delta)) 1436 1437 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1438 send_nomatch "${j}" $((j + src_delta)) || return 1 1439 done 1440 1441 range_size=$((range_size + 1)) 1442 start=$((end + range_size)) 1443 done 1444} 1445 1446# Performance test template: 1447# - add concatenated ranged entries 1448# - add non-ranged concatenated entries (for hash set matching rate baseline) 1449# - add ranged entries with first field only (for rbhash baseline) 1450# - start pktgen injection directly on device rx path of this namespace 1451# - measure drop only rate, hash and rbtree baselines, then matching rate 1452test_performance() { 1453 chain_spec=${perf_spec} 1454 dst="${perf_dst}" 1455 src="${perf_src}" 1456 setup veth perf set || return ${ksft_skip} 1457 1458 first=${start} 1459 range_size=1 1460 for set in test norange noconcat; do 1461 start=${first} 1462 for i in $(seq "$start" $((start + perf_entries))); do 1463 end=$((start + range_size)) 1464 srcstart=$((start + src_delta)) 1465 srcend=$((end + src_delta)) 1466 1467 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1468 start=${end} 1469 end=$((end + 1)) 1470 elif [ "$start" -eq "$end" ]; then 1471 end=$((start + 1)) 1472 fi 1473 1474 add_perf ${set} 1475 1476 start=$((end + range_size)) 1477 done > "${tmp}" 1478 nft -f "${tmp}" 1479 done 1480 1481 perf $((end - 1)) "$srcstart" 1482 1483 sleep 2 1484 1485 nft add rule netdev perf test counter name \"test\" drop 1486 nft reset counter netdev perf test >/dev/null 2>&1 1487 sleep "${perf_duration}" 1488 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1489 info " baseline (drop from netdev hook): ${pps}pps" 1490 handle="$(nft -a list chain netdev perf test | grep counter)" 1491 handle="${handle##* }" 1492 nft delete rule netdev perf test handle "${handle}" 1493 1494 nft add rule "netdev perf test ${chain_spec} @norange \ 1495 counter name \"test\" drop" 1496 nft reset counter netdev perf test >/dev/null 2>&1 1497 sleep "${perf_duration}" 1498 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1499 info " baseline hash (non-ranged entries): ${pps}pps" 1500 handle="$(nft -a list chain netdev perf test | grep counter)" 1501 handle="${handle##* }" 1502 nft delete rule netdev perf test handle "${handle}" 1503 1504 nft add rule "netdev perf test ${chain_spec%%. *} @noconcat \ 1505 counter name \"test\" drop" 1506 nft reset counter netdev perf test >/dev/null 2>&1 1507 sleep "${perf_duration}" 1508 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1509 info " baseline rbtree (match on first field only): ${pps}pps" 1510 handle="$(nft -a list chain netdev perf test | grep counter)" 1511 handle="${handle##* }" 1512 nft delete rule netdev perf test handle "${handle}" 1513 1514 nft add rule "netdev perf test ${chain_spec} @test \ 1515 counter name \"test\" drop" 1516 nft reset counter netdev perf test >/dev/null 2>&1 1517 sleep "${perf_duration}" 1518 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1519 p5="$(printf %5s "${perf_entries}")" 1520 info " set with ${p5} full, ranged entries: ${pps}pps" 1521 kill "${perf_pid}" 1522} 1523 1524test_bug_flush_remove_add() { 1525 rounds=100 1526 [ "$KSFT_MACHINE_SLOW" = "yes" ] && rounds=10 1527 1528 set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }' 1529 elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }' 1530 elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }' 1531 for i in $(seq 1 $rounds); do 1532 nft add table t "$set_cmd" || return ${ksft_skip} 1533 nft add element t s "$elem1" 2>/dev/null || return 1 1534 nft flush set t s 2>/dev/null || return 1 1535 nft add element t s "$elem2" 2>/dev/null || return 1 1536 done 1537 nft flush ruleset 1538} 1539 1540# - add ranged element, check that packets match it 1541# - reload the set, check packets still match 1542test_bug_reload() { 1543 setup veth send_"${proto}" set || return ${ksft_skip} 1544 rstart=${start} 1545 1546 range_size=1 1547 for i in $(seq "${start}" $((start + count))); do 1548 end=$((start + range_size)) 1549 1550 # Avoid negative or zero-sized port ranges 1551 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1552 start=${end} 1553 end=$((end + 1)) 1554 fi 1555 srcstart=$((start + src_delta)) 1556 srcend=$((end + src_delta)) 1557 1558 add "$(format)" || return 1 1559 range_size=$((range_size + 1)) 1560 start=$((end + range_size)) 1561 done 1562 1563 # check kernel does allocate pcpu sctrach map 1564 # for reload with no elemet add/delete 1565 ( echo flush set inet filter test ; 1566 nft list set inet filter test ) | nft -f - 1567 1568 start=${rstart} 1569 range_size=1 1570 1571 for i in $(seq "${start}" $((start + count))); do 1572 end=$((start + range_size)) 1573 1574 # Avoid negative or zero-sized port ranges 1575 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1576 start=${end} 1577 end=$((end + 1)) 1578 fi 1579 srcstart=$((start + src_delta)) 1580 srcend=$((end + src_delta)) 1581 1582 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1583 send_match "${j}" $((j + src_delta)) || return 1 1584 done 1585 1586 range_size=$((range_size + 1)) 1587 start=$((end + range_size)) 1588 done 1589 1590 nft flush ruleset 1591} 1592 1593# - add ranged element, check that packets match it 1594# - delete element again, check it is gone 1595test_bug_net_port_proto_match() { 1596 setup veth send_"${proto}" set || return ${ksft_skip} 1597 rstart=${start} 1598 1599 range_size=1 1600 for i in $(seq 1 10); do 1601 for j in $(seq 1 20) ; do 1602 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1603 1604 nft "add element inet filter test { $elem }" || return 1 1605 nft "get element inet filter test { $elem }" | grep -q "$elem" 1606 if [ $? -ne 0 ];then 1607 local got=$(nft "get element inet filter test { $elem }") 1608 err "post-add: should have returned $elem but got $got" 1609 return 1 1610 fi 1611 done 1612 done 1613 1614 # recheck after set was filled 1615 for i in $(seq 1 10); do 1616 for j in $(seq 1 20) ; do 1617 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1618 1619 nft "get element inet filter test { $elem }" | grep -q "$elem" 1620 if [ $? -ne 0 ];then 1621 local got=$(nft "get element inet filter test { $elem }") 1622 err "post-fill: should have returned $elem but got $got" 1623 return 1 1624 fi 1625 done 1626 done 1627 1628 # random del and re-fetch 1629 for i in $(seq 1 10); do 1630 for j in $(seq 1 20) ; do 1631 local rnd=$((RANDOM%10)) 1632 local got="" 1633 1634 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1635 if [ $rnd -gt 0 ];then 1636 continue 1637 fi 1638 1639 nft "delete element inet filter test { $elem }" 1640 got=$(nft "get element inet filter test { $elem }" 2>/dev/null) 1641 if [ $? -eq 0 ];then 1642 err "post-delete: query for $elem returned $got instead of error." 1643 return 1 1644 fi 1645 done 1646 done 1647 1648 nft flush ruleset 1649} 1650 1651test_bug_avx2_mismatch() 1652{ 1653 setup veth send_"${proto}" set || return ${ksft_skip} 1654 1655 local a1="fe80:dead:01ff:0a02:0b03:6007:8009:a001" 1656 local a2="fe80:dead:01fe:0a02:0b03:6007:8009:a001" 1657 1658 nft "add element inet filter test { icmpv6 . $a1 }" 1659 1660 dst_addr6="$a2" 1661 send_icmp6 1662 1663 if [ "$(count_packets)" -gt "0" ]; then 1664 err "False match for $a2" 1665 return 1 1666 fi 1667} 1668 1669test_reported_issues() { 1670 eval test_bug_"${subtest}" 1671} 1672 1673# Run everything in a separate network namespace 1674[ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } 1675tmp="$(mktemp)" 1676trap cleanup_exit EXIT 1677 1678# Entry point for test runs 1679passed=0 1680for name in ${TESTS}; do 1681 printf "TEST: %s\n" "$(echo "$name" | tr '_' ' ')" 1682 if [ "${name}" = "reported_issues" ]; then 1683 SUBTESTS="${BUGS}" 1684 else 1685 SUBTESTS="${TYPES}" 1686 fi 1687 1688 for subtest in ${SUBTESTS}; do 1689 eval desc=\$TYPE_"${subtest}" 1690 IFS=' 1691' 1692 for __line in ${desc}; do 1693 # shellcheck disable=SC2086 1694 eval ${__line%% *}=\"${__line##* }\"; 1695 done 1696 IFS=' 1697' 1698 1699 if [ "${name}" = "concurrency" ] && \ 1700 [ "${race_repeat}" = "0" ]; then 1701 continue 1702 fi 1703 if [ "${name}" = "performance" ] && \ 1704 [ "${perf_duration}" = "0" ]; then 1705 continue 1706 fi 1707 1708 [ "$KSFT_MACHINE_SLOW" = "yes" ] && count=1 1709 1710 printf " %-32s " "${display}" 1711 tthen=$(date +%s) 1712 eval test_"${name}" 1713 ret=$? 1714 1715 tnow=$(date +%s) 1716 printf "%5ds%-30s" $((tnow-tthen)) 1717 1718 if [ $ret -eq 0 ]; then 1719 printf "[ OK ]\n" 1720 info_flush 1721 passed=$((passed + 1)) 1722 elif [ $ret -eq 1 ]; then 1723 printf "[FAIL]\n" 1724 err_flush 1725 exit 1 1726 elif [ $ret -eq ${ksft_skip} ]; then 1727 printf "[SKIP]\n" 1728 err_flush 1729 fi 1730 done 1731done 1732 1733[ ${passed} -eq 0 ] && exit ${ksft_skip} || exit 0 1734