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 <sbrivio@redhat.com> 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" 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# Set template for all tests, types and rules are filled in depending on test 391set_template=' 392flush ruleset 393 394table inet filter { 395 counter test { 396 packets 0 bytes 0 397 } 398 399 set test { 400 type ${type_spec} 401 flags interval,timeout 402 } 403 404 chain input { 405 type filter hook prerouting priority 0; policy accept; 406 ${chain_spec} @test counter name \"test\" 407 } 408} 409 410table netdev perf { 411 counter test { 412 packets 0 bytes 0 413 } 414 415 counter match { 416 packets 0 bytes 0 417 } 418 419 set test { 420 type ${type_spec} 421 flags interval 422 } 423 424 set norange { 425 type ${type_spec} 426 } 427 428 set noconcat { 429 type ${type_spec%% *} 430 flags interval 431 } 432 433 chain test { 434 type filter hook ingress device veth_a priority 0; 435 } 436} 437' 438 439err_buf= 440info_buf= 441 442# Append string to error buffer 443err() { 444 err_buf="${err_buf}${1} 445" 446} 447 448# Append string to information buffer 449info() { 450 info_buf="${info_buf}${1} 451" 452} 453 454# Flush error buffer to stdout 455err_flush() { 456 printf "%s" "${err_buf}" 457 err_buf= 458} 459 460# Flush information buffer to stdout 461info_flush() { 462 printf "%s" "${info_buf}" 463 info_buf= 464} 465 466# Setup veth pair: this namespace receives traffic, B generates it 467setup_veth() { 468 ip netns add B 469 ip link add veth_a type veth peer name veth_b || return 1 470 471 ip link set veth_a up 472 ip link set veth_b netns B 473 474 ip -n B link set veth_b up 475 476 ip addr add dev veth_a 10.0.0.1 477 ip route add default dev veth_a 478 479 ip -6 addr add fe80::1/64 dev veth_a nodad 480 ip -6 addr add 2001:db8::1/64 dev veth_a nodad 481 ip -6 route add default dev veth_a 482 483 ip -n B route add default dev veth_b 484 485 ip -6 -n B addr add fe80::2/64 dev veth_b nodad 486 ip -6 -n B addr add 2001:db8::2/64 dev veth_b nodad 487 ip -6 -n B route add default dev veth_b 488 489 B() { 490 ip netns exec B "$@" >/dev/null 2>&1 491 } 492} 493 494# Fill in set template and initialise set 495setup_set() { 496 eval "echo \"${set_template}\"" | nft -f - 497} 498 499# Check that at least one of the needed tools is available 500check_tools() { 501 [ -z "${tools}" ] && return 0 502 503 __tools= 504 for tool in ${tools}; do 505 __tools="${__tools} ${tool}" 506 507 command -v "${tool}" >/dev/null && return 0 508 done 509 err "need one of:${__tools}, skipping" && return 1 510} 511 512# Set up function to send ICMP packets 513setup_send_icmp() { 514 send_icmp() { 515 B ping -c1 -W1 "${dst_addr4}" >/dev/null 2>&1 516 } 517} 518 519# Set up function to send ICMPv6 packets 520setup_send_icmp6() { 521 if command -v ping6 >/dev/null; then 522 send_icmp6() { 523 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 524 2>/dev/null 525 B ping6 -q -c1 -W1 "${dst_addr6}" 526 } 527 else 528 send_icmp6() { 529 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 530 2>/dev/null 531 B ping -q -6 -c1 -W1 "${dst_addr6}" 532 } 533 fi 534} 535 536# Set up function to send single UDP packets on IPv4 537setup_send_udp() { 538 if command -v sendip >/dev/null; then 539 send_udp() { 540 [ -n "${src_port}" ] && src_port="-us ${src_port}" 541 [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 542 [ -n "${src_addr4}" ] && src_addr4="-is ${src_addr4}" 543 544 # shellcheck disable=SC2086 # sendip needs split options 545 B sendip -p ipv4 -p udp ${src_addr4} ${src_port} \ 546 ${dst_port} "${dst_addr4}" 547 548 src_port= 549 dst_port= 550 src_addr4= 551 } 552 elif command -v socat -v >/dev/null; then 553 send_udp() { 554 if [ -n "${src_addr4}" ]; then 555 B ip addr add "${src_addr4}" dev veth_b 556 __socatbind=",bind=${src_addr4}" 557 if [ -n "${src_port}" ];then 558 __socatbind="${__socatbind}:${src_port}" 559 fi 560 fi 561 562 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 563 [ -z "${dst_port}" ] && dst_port=12345 564 565 echo "test4" | B socat -t 0.01 STDIN UDP4-DATAGRAM:"$dst_addr4":"$dst_port""${__socatbind}" 566 567 src_addr4= 568 src_port= 569 } 570 elif [ -z "$(bash -c 'type -p')" ]; then 571 send_udp() { 572 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 573 if [ -n "${src_addr4}" ]; then 574 B ip addr add "${src_addr4}/16" dev veth_b 575 B ip route add default dev veth_b 576 fi 577 578 B bash -c "echo > /dev/udp/${dst_addr4}/${dst_port}" 579 580 if [ -n "${src_addr4}" ]; then 581 B ip addr del "${src_addr4}/16" dev veth_b 582 fi 583 src_addr4= 584 } 585 else 586 return 1 587 fi 588} 589 590# Set up function to send single UDP packets on IPv6 591setup_send_udp6() { 592 if command -v sendip >/dev/null; then 593 send_udp6() { 594 [ -n "${src_port}" ] && src_port="-us ${src_port}" 595 [ -n "${dst_port}" ] && dst_port="-ud ${dst_port}" 596 if [ -n "${src_addr6}" ]; then 597 src_addr6="-6s ${src_addr6}" 598 else 599 src_addr6="-6s 2001:db8::2" 600 fi 601 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 602 2>/dev/null 603 604 # shellcheck disable=SC2086 # this needs split options 605 B sendip -p ipv6 -p udp ${src_addr6} ${src_port} \ 606 ${dst_port} "${dst_addr6}" 607 608 src_port= 609 dst_port= 610 src_addr6= 611 } 612 elif command -v socat -v >/dev/null; then 613 send_udp6() { 614 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 615 2>/dev/null 616 617 __socatbind6= 618 619 if [ -n "${src_addr6}" ]; then 620 B ip addr add "${src_addr6}" dev veth_b nodad 621 622 __socatbind6=",bind=[${src_addr6}]" 623 624 if [ -n "${src_port}" ] ;then 625 __socatbind6="${__socatbind6}:${src_port}" 626 fi 627 fi 628 629 echo "test6" | B socat -t 0.01 STDIN UDP6-DATAGRAM:["$dst_addr6"]:"$dst_port""${__socatbind6}" 630 } 631 elif [ -z "$(bash -c 'type -p')" ]; then 632 send_udp6() { 633 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 634 2>/dev/null 635 B ip addr add "${src_addr6}" dev veth_b nodad 636 B bash -c "echo > /dev/udp/${dst_addr6}/${dst_port}" 637 ip -6 addr del "${dst_addr6}" dev veth_a 2>/dev/null 638 } 639 else 640 return 1 641 fi 642} 643 644listener_ready() 645{ 646 port="$1" 647 ss -lnt -o "sport = :$port" | grep -q "$port" 648} 649 650# Set up function to send TCP traffic on IPv4 651setup_flood_tcp() { 652 if command -v iperf3 >/dev/null; then 653 flood_tcp() { 654 local n_port="${dst_port}" 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 src_addr4="-B ${src_addr4}" 659 else 660 B ip addr add dev veth_b 10.0.0.2 661 src_addr4="-B 10.0.0.2" 662 fi 663 if [ -n "${src_port}" ]; then 664 src_port="--cport ${src_port}" 665 fi 666 B ip route add default dev veth_b 2>/dev/null 667 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 668 669 # shellcheck disable=SC2086 # this needs split options 670 iperf3 -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 671 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 672 673 # shellcheck disable=SC2086 # this needs split options 674 B iperf3 -c "${dst_addr4}" ${dst_port} ${src_port} \ 675 ${src_addr4} -l16 -t 1000 676 677 src_addr4= 678 src_port= 679 dst_port= 680 } 681 elif command -v iperf >/dev/null; then 682 flood_tcp() { 683 local n_port="${dst_port}" 684 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 685 if [ -n "${src_addr4}" ]; then 686 B ip addr add "${src_addr4}/16" dev veth_b 687 src_addr4="-B ${src_addr4}" 688 else 689 B ip addr add dev veth_b 10.0.0.2 2>/dev/null 690 src_addr4="-B 10.0.0.2" 691 fi 692 if [ -n "${src_port}" ]; then 693 src_addr4="${src_addr4}:${src_port}" 694 fi 695 B ip route add default dev veth_b 696 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 697 698 # shellcheck disable=SC2086 # this needs split options 699 iperf -s -DB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 700 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 701 702 # shellcheck disable=SC2086 # this needs split options 703 B iperf -c "${dst_addr4}" ${dst_port} ${src_addr4} \ 704 -l20 -t 1000 705 706 src_addr4= 707 src_port= 708 dst_port= 709 } 710 elif command -v netperf >/dev/null; then 711 flood_tcp() { 712 local n_port="${dst_port}" 713 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 714 if [ -n "${src_addr4}" ]; then 715 B ip addr add "${src_addr4}/16" dev veth_b 716 else 717 B ip addr add dev veth_b 10.0.0.2 718 src_addr4="10.0.0.2" 719 fi 720 if [ -n "${src_port}" ]; then 721 dst_port="${dst_port},${src_port}" 722 fi 723 B ip route add default dev veth_b 724 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 725 726 # shellcheck disable=SC2086 # this needs split options 727 netserver -4 ${dst_port} -L "${dst_addr4}" \ 728 >/dev/null 2>&1 729 busywait "$BUSYWAIT_TIMEOUT" listener_ready "${n_port}" 730 731 # shellcheck disable=SC2086 # this needs split options 732 B netperf -4 -H "${dst_addr4}" ${dst_port} \ 733 -L "${src_addr4}" -l 1000 -t TCP_STREAM 734 735 src_addr4= 736 src_port= 737 dst_port= 738 } 739 else 740 return 1 741 fi 742} 743 744# Set up function to send TCP traffic on IPv6 745setup_flood_tcp6() { 746 if command -v iperf3 >/dev/null; then 747 flood_tcp6() { 748 local n_port="${dst_port}" 749 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 750 if [ -n "${src_addr6}" ]; then 751 B ip addr add "${src_addr6}" dev veth_b nodad 752 src_addr6="-B ${src_addr6}" 753 else 754 src_addr6="-B 2001:db8::2" 755 fi 756 if [ -n "${src_port}" ]; then 757 src_port="--cport ${src_port}" 758 fi 759 B ip route add default dev veth_b 760 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 761 2>/dev/null 762 763 # shellcheck disable=SC2086 # this needs split options 764 iperf3 -s -DB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 765 busywait "$BUSYWAIT_TIMEOUT" listener_ready "${n_port}" 766 767 # shellcheck disable=SC2086 # this needs split options 768 B iperf3 -c "${dst_addr6}" ${dst_port} \ 769 ${src_port} ${src_addr6} -l16 -t 1000 770 771 src_addr6= 772 src_port= 773 dst_port= 774 } 775 elif command -v iperf >/dev/null; then 776 flood_tcp6() { 777 local n_port="${dst_port}" 778 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 779 if [ -n "${src_addr6}" ]; then 780 B ip addr add "${src_addr6}" dev veth_b nodad 781 src_addr6="-B ${src_addr6}" 782 else 783 src_addr6="-B 2001:db8::2" 784 fi 785 if [ -n "${src_port}" ]; then 786 src_addr6="${src_addr6}:${src_port}" 787 fi 788 B ip route add default dev veth_b 789 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 790 2>/dev/null 791 792 # shellcheck disable=SC2086 # this needs split options 793 iperf -s -VDB "${dst_addr6}" ${dst_port} >/dev/null 2>&1 794 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 795 796 # shellcheck disable=SC2086 # this needs split options 797 B iperf -c "${dst_addr6}" -V ${dst_port} \ 798 ${src_addr6} -l1 -t 1000 799 800 src_addr6= 801 src_port= 802 dst_port= 803 } 804 elif command -v netperf >/dev/null; then 805 flood_tcp6() { 806 local n_port="${dst_port}" 807 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 808 if [ -n "${src_addr6}" ]; then 809 B ip addr add "${src_addr6}" dev veth_b nodad 810 else 811 src_addr6="2001:db8::2" 812 fi 813 if [ -n "${src_port}" ]; then 814 dst_port="${dst_port},${src_port}" 815 fi 816 B ip route add default dev veth_b 817 ip -6 addr add "${dst_addr6}" dev veth_a nodad \ 818 2>/dev/null 819 820 # shellcheck disable=SC2086 # this needs split options 821 netserver -6 ${dst_port} -L "${dst_addr6}" \ 822 >/dev/null 2>&1 823 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 824 825 # shellcheck disable=SC2086 # this needs split options 826 B netperf -6 -H "${dst_addr6}" ${dst_port} \ 827 -L "${src_addr6}" -l 1000 -t TCP_STREAM 828 829 src_addr6= 830 src_port= 831 dst_port= 832 } 833 else 834 return 1 835 fi 836} 837 838# Set up function to send UDP traffic on IPv4 839setup_flood_udp() { 840 if command -v iperf3 >/dev/null; then 841 flood_udp() { 842 local n_port="${dst_port}" 843 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 844 if [ -n "${src_addr4}" ]; then 845 B ip addr add "${src_addr4}/16" dev veth_b 846 src_addr4="-B ${src_addr4}" 847 else 848 B ip addr add dev veth_b 10.0.0.2 2>/dev/null 849 src_addr4="-B 10.0.0.2" 850 fi 851 if [ -n "${src_port}" ]; then 852 src_port="--cport ${src_port}" 853 fi 854 B ip route add default dev veth_b 855 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 856 857 # shellcheck disable=SC2086 # this needs split options 858 iperf3 -s -DB "${dst_addr4}" ${dst_port} 859 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 860 861 # shellcheck disable=SC2086 # this needs split options 862 B iperf3 -u -c "${dst_addr4}" -Z -b 100M -l16 -t1000 \ 863 ${dst_port} ${src_port} ${src_addr4} 864 865 src_addr4= 866 src_port= 867 dst_port= 868 } 869 elif command -v iperf >/dev/null; then 870 flood_udp() { 871 local n_port="${dst_port}" 872 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 873 if [ -n "${src_addr4}" ]; then 874 B ip addr add "${src_addr4}/16" dev veth_b 875 src_addr4="-B ${src_addr4}" 876 else 877 B ip addr add dev veth_b 10.0.0.2 878 src_addr4="-B 10.0.0.2" 879 fi 880 if [ -n "${src_port}" ]; then 881 src_addr4="${src_addr4}:${src_port}" 882 fi 883 B ip route add default dev veth_b 884 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 885 886 # shellcheck disable=SC2086 # this needs split options 887 iperf -u -sDB "${dst_addr4}" ${dst_port} >/dev/null 2>&1 888 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 889 890 # shellcheck disable=SC2086 # this needs split options 891 B iperf -u -c "${dst_addr4}" -b 100M -l1 -t1000 \ 892 ${dst_port} ${src_addr4} 893 894 src_addr4= 895 src_port= 896 dst_port= 897 } 898 elif command -v netperf >/dev/null; then 899 flood_udp() { 900 local n_port="${dst_port}" 901 [ -n "${dst_port}" ] && dst_port="-p ${dst_port}" 902 if [ -n "${src_addr4}" ]; then 903 B ip addr add "${src_addr4}/16" dev veth_b 904 else 905 B ip addr add dev veth_b 10.0.0.2 906 src_addr4="10.0.0.2" 907 fi 908 if [ -n "${src_port}" ]; then 909 dst_port="${dst_port},${src_port}" 910 fi 911 B ip route add default dev veth_b 912 ip addr add "${dst_addr4}" dev veth_a 2>/dev/null 913 914 # shellcheck disable=SC2086 # this needs split options 915 netserver -4 ${dst_port} -L "${dst_addr4}" \ 916 >/dev/null 2>&1 917 busywait "$BUSYWAIT_TIMEOUT" listener_ready "$n_port" 918 919 # shellcheck disable=SC2086 # this needs split options 920 B netperf -4 -H "${dst_addr4}" ${dst_port} \ 921 -L "${src_addr4}" -l 1000 -t UDP_STREAM 922 923 src_addr4= 924 src_port= 925 dst_port= 926 } 927 else 928 return 1 929 fi 930} 931 932# Find pktgen script and set up function to start pktgen injection 933setup_perf() { 934 for pktgen_script_path in ${PKTGEN_SCRIPT_PATHS} __notfound; do 935 command -v "${pktgen_script_path}" >/dev/null && break 936 done 937 [ "${pktgen_script_path}" = "__notfound" ] && return 1 938 939 perf_ipv4() { 940 ${pktgen_script_path} -s80 \ 941 -i veth_a -d "${dst_addr4}" -p "${dst_port}" \ 942 -m "${dst_mac}" \ 943 -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 944 perf_pid=$! 945 } 946 perf_ipv6() { 947 IP6=6 ${pktgen_script_path} -s100 \ 948 -i veth_a -d "${dst_addr6}" -p "${dst_port}" \ 949 -m "${dst_mac}" \ 950 -t $(($(nproc) / 5 + 1)) -b10000 -n0 2>/dev/null & 951 perf_pid=$! 952 } 953} 954 955# Clean up before each test 956cleanup() { 957 nft reset counter inet filter test >/dev/null 2>&1 958 nft flush ruleset >/dev/null 2>&1 959 ip link del dummy0 2>/dev/null 960 ip route del default 2>/dev/null 961 ip -6 route del default 2>/dev/null 962 ip netns pids B 2>/dev/null | xargs kill 2>/dev/null 963 ip netns del B 2>/dev/null 964 ip link del veth_a 2>/dev/null 965 timeout= 966 killall iperf3 2>/dev/null 967 killall iperf 2>/dev/null 968 killall netperf 2>/dev/null 969 killall netserver 2>/dev/null 970} 971 972cleanup_exit() { 973 cleanup 974 rm -f "$tmp" 975} 976 977# Entry point for setup functions 978setup() { 979 if [ "$(id -u)" -ne 0 ]; then 980 echo " need to run as root" 981 exit ${ksft_skip} 982 fi 983 984 cleanup 985 check_tools || return 1 986 for arg do 987 if ! eval setup_"${arg}"; then 988 err " ${arg} not supported" 989 return 1 990 fi 991 done 992} 993 994# Format integer into IPv4 address, summing 10.0.0.5 (arbitrary) to it 995format_addr4() { 996 a=$((${1} + 16777216 * 10 + 5)) 997 printf "%i.%i.%i.%i" \ 998 "$((a / 16777216))" "$((a % 16777216 / 65536))" \ 999 "$((a % 65536 / 256))" "$((a % 256))" 1000} 1001 1002# Format integer into IPv6 address, summing 2001:db8:: to it 1003format_addr6() { 1004 printf "2001:db8::%04x:%04x" "$((${1} / 65536))" "$((${1} % 65536))" 1005} 1006 1007# Format integer into EUI-48 address, summing 00:01:00:00:00:00 to it 1008format_mac() { 1009 printf "00:01:%02x:%02x:%02x:%02x" \ 1010 "$((${1} / 16777216))" "$((${1} % 16777216 / 65536))" \ 1011 "$((${1} % 65536 / 256))" "$((${1} % 256))" 1012} 1013 1014# Format integer into port, avoid 0 port 1015format_port() { 1016 printf "%i" "$((${1} % 65534 + 1))" 1017} 1018 1019# Drop suffixed '6' from L4 protocol, if any 1020format_proto() { 1021 printf "%s" "${proto}" | tr -d 6 1022} 1023 1024# Format destination and source fields into nft concatenated type 1025format() { 1026 __start= 1027 __end= 1028 __expr="{ " 1029 1030 for f in ${dst}; do 1031 [ "${__expr}" != "{ " ] && __expr="${__expr} . " 1032 1033 __start="$(eval format_"${f}" "${start}")" 1034 __end="$(eval format_"${f}" "${end}")" 1035 1036 if [ "${f}" = "proto" ]; then 1037 __expr="${__expr}${__start}" 1038 else 1039 __expr="${__expr}${__start}-${__end}" 1040 fi 1041 done 1042 for f in ${src}; do 1043 [ "${__expr}" != "{ " ] && __expr="${__expr} . " 1044 1045 __start="$(eval format_"${f}" "${srcstart}")" 1046 __end="$(eval format_"${f}" "${srcend}")" 1047 1048 if [ "${f}" = "proto" ]; then 1049 __expr="${__expr}${__start}" 1050 else 1051 __expr="${__expr}${__start}-${__end}" 1052 fi 1053 done 1054 1055 if [ -n "${timeout}" ]; then 1056 echo "${__expr} timeout ${timeout}s }" 1057 else 1058 echo "${__expr} }" 1059 fi 1060} 1061 1062# Format destination and source fields into nft type, start element only 1063format_norange() { 1064 __expr="{ " 1065 1066 for f in ${dst}; do 1067 [ "${__expr}" != "{ " ] && __expr="${__expr} . " 1068 1069 __expr="${__expr}$(eval format_"${f}" "${start}")" 1070 done 1071 for f in ${src}; do 1072 __expr="${__expr} . $(eval format_"${f}" "${start}")" 1073 done 1074 1075 echo "${__expr} }" 1076} 1077 1078# Format first destination field into nft type 1079format_noconcat() { 1080 for f in ${dst}; do 1081 __start="$(eval format_"${f}" "${start}")" 1082 __end="$(eval format_"${f}" "${end}")" 1083 1084 if [ "${f}" = "proto" ]; then 1085 echo "{ ${__start} }" 1086 else 1087 echo "{ ${__start}-${__end} }" 1088 fi 1089 return 1090 done 1091} 1092 1093# Add single entry to 'test' set in 'inet filter' table 1094add() { 1095 if ! nft add element inet filter test "${1}"; then 1096 err "Failed to add ${1} given ruleset:" 1097 err "$(nft -a list ruleset)" 1098 return 1 1099 fi 1100} 1101 1102# Format and output entries for sets in 'netdev perf' table 1103add_perf() { 1104 if [ "${1}" = "test" ]; then 1105 echo "add element netdev perf test $(format)" 1106 elif [ "${1}" = "norange" ]; then 1107 echo "add element netdev perf norange $(format_norange)" 1108 elif [ "${1}" = "noconcat" ]; then 1109 echo "add element netdev perf noconcat $(format_noconcat)" 1110 fi 1111} 1112 1113# Add single entry to 'norange' set in 'netdev perf' table 1114add_perf_norange() { 1115 if ! nft add element netdev perf norange "${1}"; then 1116 err "Failed to add ${1} given ruleset:" 1117 err "$(nft -a list ruleset)" 1118 return 1 1119 fi 1120} 1121 1122# Add single entry to 'noconcat' set in 'netdev perf' table 1123add_perf_noconcat() { 1124 if ! nft add element netdev perf noconcat "${1}"; then 1125 err "Failed to add ${1} given ruleset:" 1126 err "$(nft -a list ruleset)" 1127 return 1 1128 fi 1129} 1130 1131# Delete single entry from set 1132del() { 1133 if ! nft delete element inet filter test "${1}"; then 1134 err "Failed to delete ${1} given ruleset:" 1135 err "$(nft -a list ruleset)" 1136 return 1 1137 fi 1138} 1139 1140# Return packet count from 'test' counter in 'inet filter' table 1141count_packets() { 1142 found=0 1143 for token in $(nft list counter inet filter test); do 1144 [ ${found} -eq 1 ] && echo "${token}" && return 1145 [ "${token}" = "packets" ] && found=1 1146 done 1147} 1148 1149# Return packet count from 'test' counter in 'netdev perf' table 1150count_perf_packets() { 1151 found=0 1152 for token in $(nft list counter netdev perf test); do 1153 [ ${found} -eq 1 ] && echo "${token}" && return 1154 [ "${token}" = "packets" ] && found=1 1155 done 1156} 1157 1158# Set MAC addresses, send traffic according to specifier 1159flood() { 1160 ip link set veth_a address "$(format_mac "${1}")" 1161 ip -n B link set veth_b address "$(format_mac "${2}")" 1162 1163 for f in ${dst}; do 1164 eval dst_"$f"=\$\(format_\$f "${1}"\) 1165 done 1166 for f in ${src}; do 1167 eval src_"$f"=\$\(format_\$f "${2}"\) 1168 done 1169 eval flood_\$proto 1170} 1171 1172# Set MAC addresses, start pktgen injection 1173perf() { 1174 dst_mac="$(format_mac "${1}")" 1175 ip link set veth_a address "${dst_mac}" 1176 1177 for f in ${dst}; do 1178 eval dst_"$f"=\$\(format_\$f "${1}"\) 1179 done 1180 for f in ${src}; do 1181 eval src_"$f"=\$\(format_\$f "${2}"\) 1182 done 1183 eval perf_\$perf_proto 1184} 1185 1186# Set MAC addresses, send single packet, check that it matches, reset counter 1187send_match() { 1188 ip link set veth_a address "$(format_mac "${1}")" 1189 ip -n B link set veth_b address "$(format_mac "${2}")" 1190 1191 for f in ${dst}; do 1192 eval dst_"$f"=\$\(format_\$f "${1}"\) 1193 done 1194 for f in ${src}; do 1195 eval src_"$f"=\$\(format_\$f "${2}"\) 1196 done 1197 eval send_\$proto 1198 if [ "$(count_packets)" != "1" ]; then 1199 err "${proto} packet to:" 1200 err " $(for f in ${dst}; do 1201 eval format_\$f "${1}"; printf ' '; done)" 1202 err "from:" 1203 err " $(for f in ${src}; do 1204 eval format_\$f "${2}"; printf ' '; done)" 1205 err "should have matched ruleset:" 1206 err "$(nft -a list ruleset)" 1207 return 1 1208 fi 1209 nft reset counter inet filter test >/dev/null 1210} 1211 1212# Set MAC addresses, send single packet, check that it doesn't match 1213send_nomatch() { 1214 ip link set veth_a address "$(format_mac "${1}")" 1215 ip -n B link set veth_b address "$(format_mac "${2}")" 1216 1217 for f in ${dst}; do 1218 eval dst_"$f"=\$\(format_\$f "${1}"\) 1219 done 1220 for f in ${src}; do 1221 eval src_"$f"=\$\(format_\$f "${2}"\) 1222 done 1223 eval send_\$proto 1224 if [ "$(count_packets)" != "0" ]; then 1225 err "${proto} packet to:" 1226 err " $(for f in ${dst}; do 1227 eval format_\$f "${1}"; printf ' '; done)" 1228 err "from:" 1229 err " $(for f in ${src}; do 1230 eval format_\$f "${2}"; printf ' '; done)" 1231 err "should not have matched ruleset:" 1232 err "$(nft -a list ruleset)" 1233 return 1 1234 fi 1235} 1236 1237# Correctness test template: 1238# - add ranged element, check that packets match it 1239# - check that packets outside range don't match it 1240# - remove some elements, check that packets don't match anymore 1241test_correctness() { 1242 setup veth send_"${proto}" set || return ${ksft_skip} 1243 1244 range_size=1 1245 for i in $(seq "${start}" $((start + count))); do 1246 end=$((start + range_size)) 1247 1248 # Avoid negative or zero-sized port ranges 1249 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1250 start=${end} 1251 end=$((end + 1)) 1252 fi 1253 srcstart=$((start + src_delta)) 1254 srcend=$((end + src_delta)) 1255 1256 add "$(format)" || return 1 1257 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1258 send_match "${j}" $((j + src_delta)) || return 1 1259 done 1260 send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1 1261 1262 # Delete elements now and then 1263 if [ $((i % 3)) -eq 0 ]; then 1264 del "$(format)" || return 1 1265 for j in $(seq "$start" \ 1266 $((range_size / 2 + 1)) ${end}); do 1267 send_nomatch "${j}" $((j + src_delta)) \ 1268 || return 1 1269 done 1270 fi 1271 1272 range_size=$((range_size + 1)) 1273 start=$((end + range_size)) 1274 done 1275} 1276 1277# Concurrency test template: 1278# - add all the elements 1279# - start a thread for each physical thread that: 1280# - adds all the elements 1281# - flushes the set 1282# - adds all the elements 1283# - flushes the entire ruleset 1284# - adds the set back 1285# - adds all the elements 1286# - delete all the elements 1287test_concurrency() { 1288 proto=${flood_proto} 1289 tools=${flood_tools} 1290 chain_spec=${flood_spec} 1291 setup veth flood_"${proto}" set || return ${ksft_skip} 1292 1293 range_size=1 1294 cstart=${start} 1295 flood_pids= 1296 for i in $(seq "$start" $((start + count))); do 1297 end=$((start + range_size)) 1298 srcstart=$((start + src_delta)) 1299 srcend=$((end + src_delta)) 1300 1301 add "$(format)" || return 1 1302 1303 flood "${i}" $((i + src_delta)) & flood_pids="${flood_pids} $!" 1304 1305 range_size=$((range_size + 1)) 1306 start=$((end + range_size)) 1307 done 1308 1309 sleep $((RANDOM%10)) 1310 1311 pids= 1312 for c in $(seq 1 "$(nproc)"); do ( 1313 for r in $(seq 1 "${race_repeat}"); do 1314 range_size=1 1315 1316 # $start needs to be local to this subshell 1317 # shellcheck disable=SC2030 1318 start=${cstart} 1319 for i in $(seq "$start" $((start + count))); do 1320 end=$((start + range_size)) 1321 srcstart=$((start + src_delta)) 1322 srcend=$((end + src_delta)) 1323 1324 add "$(format)" 2>/dev/null 1325 1326 range_size=$((range_size + 1)) 1327 start=$((end + range_size)) 1328 done 1329 1330 nft flush inet filter test 2>/dev/null 1331 1332 range_size=1 1333 start=${cstart} 1334 for i in $(seq "$start" $((start + count))); do 1335 end=$((start + range_size)) 1336 srcstart=$((start + src_delta)) 1337 srcend=$((end + src_delta)) 1338 1339 add "$(format)" 2>/dev/null 1340 1341 range_size=$((range_size + 1)) 1342 start=$((end + range_size)) 1343 done 1344 1345 nft flush ruleset 1346 setup set 2>/dev/null 1347 1348 range_size=1 1349 start=${cstart} 1350 for i in $(seq "$start" $((start + count))); do 1351 end=$((start + range_size)) 1352 srcstart=$((start + src_delta)) 1353 srcend=$((end + src_delta)) 1354 1355 add "$(format)" 2>/dev/null 1356 1357 range_size=$((range_size + 1)) 1358 start=$((end + range_size)) 1359 done 1360 1361 range_size=1 1362 start=${cstart} 1363 for i in $(seq "$start" $((start + count))); do 1364 end=$((start + range_size)) 1365 srcstart=$((start + src_delta)) 1366 srcend=$((end + src_delta)) 1367 1368 del "$(format)" 2>/dev/null 1369 1370 range_size=$((range_size + 1)) 1371 start=$((end + range_size)) 1372 done 1373 done 1374 ) & pids="${pids} $!" 1375 done 1376 1377 # shellcheck disable=SC2046,SC2086 # word splitting wanted here 1378 wait $(for pid in ${pids}; do echo ${pid}; done) 1379 # shellcheck disable=SC2046,SC2086 1380 kill $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null 1381 # shellcheck disable=SC2046,SC2086 1382 wait $(for pid in ${flood_pids}; do echo ${pid}; done) 2>/dev/null 1383 1384 return 0 1385} 1386 1387# Timeout test template: 1388# - add all the elements with 3s timeout while checking that packets match 1389# - wait 3s after the last insertion, check that packets don't match any entry 1390test_timeout() { 1391 setup veth send_"${proto}" set || return ${ksft_skip} 1392 1393 timeout=3 1394 1395 [ "$KSFT_MACHINE_SLOW" = "yes" ] && timeout=8 1396 1397 range_size=1 1398 for i in $(seq "$start" $((start + count))); do 1399 end=$((start + range_size)) 1400 srcstart=$((start + src_delta)) 1401 srcend=$((end + src_delta)) 1402 1403 add "$(format)" || return 1 1404 1405 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1406 send_match "${j}" $((j + src_delta)) || return 1 1407 done 1408 1409 range_size=$((range_size + 1)) 1410 start=$((end + range_size)) 1411 done 1412 sleep $timeout 1413 for i in $(seq "$start" $((start + count))); do 1414 end=$((start + range_size)) 1415 srcstart=$((start + src_delta)) 1416 srcend=$((end + src_delta)) 1417 1418 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1419 send_nomatch "${j}" $((j + src_delta)) || return 1 1420 done 1421 1422 range_size=$((range_size + 1)) 1423 start=$((end + range_size)) 1424 done 1425} 1426 1427# Performance test template: 1428# - add concatenated ranged entries 1429# - add non-ranged concatenated entries (for hash set matching rate baseline) 1430# - add ranged entries with first field only (for rbhash baseline) 1431# - start pktgen injection directly on device rx path of this namespace 1432# - measure drop only rate, hash and rbtree baselines, then matching rate 1433test_performance() { 1434 chain_spec=${perf_spec} 1435 dst="${perf_dst}" 1436 src="${perf_src}" 1437 setup veth perf set || return ${ksft_skip} 1438 1439 first=${start} 1440 range_size=1 1441 for set in test norange noconcat; do 1442 start=${first} 1443 for i in $(seq "$start" $((start + perf_entries))); do 1444 end=$((start + range_size)) 1445 srcstart=$((start + src_delta)) 1446 srcend=$((end + src_delta)) 1447 1448 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1449 start=${end} 1450 end=$((end + 1)) 1451 elif [ "$start" -eq "$end" ]; then 1452 end=$((start + 1)) 1453 fi 1454 1455 add_perf ${set} 1456 1457 start=$((end + range_size)) 1458 done > "${tmp}" 1459 nft -f "${tmp}" 1460 done 1461 1462 perf $((end - 1)) "$srcstart" 1463 1464 sleep 2 1465 1466 nft add rule netdev perf test counter name \"test\" drop 1467 nft reset counter netdev perf test >/dev/null 2>&1 1468 sleep "${perf_duration}" 1469 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1470 info " baseline (drop from netdev hook): ${pps}pps" 1471 handle="$(nft -a list chain netdev perf test | grep counter)" 1472 handle="${handle##* }" 1473 nft delete rule netdev perf test handle "${handle}" 1474 1475 nft add rule "netdev perf test ${chain_spec} @norange \ 1476 counter name \"test\" drop" 1477 nft reset counter netdev perf test >/dev/null 2>&1 1478 sleep "${perf_duration}" 1479 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1480 info " baseline hash (non-ranged entries): ${pps}pps" 1481 handle="$(nft -a list chain netdev perf test | grep counter)" 1482 handle="${handle##* }" 1483 nft delete rule netdev perf test handle "${handle}" 1484 1485 nft add rule "netdev perf test ${chain_spec%%. *} @noconcat \ 1486 counter name \"test\" drop" 1487 nft reset counter netdev perf test >/dev/null 2>&1 1488 sleep "${perf_duration}" 1489 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1490 info " baseline rbtree (match on first field only): ${pps}pps" 1491 handle="$(nft -a list chain netdev perf test | grep counter)" 1492 handle="${handle##* }" 1493 nft delete rule netdev perf test handle "${handle}" 1494 1495 nft add rule "netdev perf test ${chain_spec} @test \ 1496 counter name \"test\" drop" 1497 nft reset counter netdev perf test >/dev/null 2>&1 1498 sleep "${perf_duration}" 1499 pps="$(printf %10s $(($(count_perf_packets) / perf_duration)))" 1500 p5="$(printf %5s "${perf_entries}")" 1501 info " set with ${p5} full, ranged entries: ${pps}pps" 1502 kill "${perf_pid}" 1503} 1504 1505test_bug_flush_remove_add() { 1506 rounds=100 1507 [ "$KSFT_MACHINE_SLOW" = "yes" ] && rounds=10 1508 1509 set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }' 1510 elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }' 1511 elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }' 1512 for i in $(seq 1 $rounds); do 1513 nft add table t "$set_cmd" || return ${ksft_skip} 1514 nft add element t s "$elem1" 2>/dev/null || return 1 1515 nft flush set t s 2>/dev/null || return 1 1516 nft add element t s "$elem2" 2>/dev/null || return 1 1517 done 1518 nft flush ruleset 1519} 1520 1521# - add ranged element, check that packets match it 1522# - reload the set, check packets still match 1523test_bug_reload() { 1524 setup veth send_"${proto}" set || return ${ksft_skip} 1525 rstart=${start} 1526 1527 range_size=1 1528 for i in $(seq "${start}" $((start + count))); do 1529 end=$((start + range_size)) 1530 1531 # Avoid negative or zero-sized port ranges 1532 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1533 start=${end} 1534 end=$((end + 1)) 1535 fi 1536 srcstart=$((start + src_delta)) 1537 srcend=$((end + src_delta)) 1538 1539 add "$(format)" || return 1 1540 range_size=$((range_size + 1)) 1541 start=$((end + range_size)) 1542 done 1543 1544 # check kernel does allocate pcpu sctrach map 1545 # for reload with no elemet add/delete 1546 ( echo flush set inet filter test ; 1547 nft list set inet filter test ) | nft -f - 1548 1549 start=${rstart} 1550 range_size=1 1551 1552 for i in $(seq "${start}" $((start + count))); do 1553 end=$((start + range_size)) 1554 1555 # Avoid negative or zero-sized port ranges 1556 if [ $((end / 65534)) -gt $((start / 65534)) ]; then 1557 start=${end} 1558 end=$((end + 1)) 1559 fi 1560 srcstart=$((start + src_delta)) 1561 srcend=$((end + src_delta)) 1562 1563 for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do 1564 send_match "${j}" $((j + src_delta)) || return 1 1565 done 1566 1567 range_size=$((range_size + 1)) 1568 start=$((end + range_size)) 1569 done 1570 1571 nft flush ruleset 1572} 1573 1574# - add ranged element, check that packets match it 1575# - delete element again, check it is gone 1576test_bug_net_port_proto_match() { 1577 setup veth send_"${proto}" set || return ${ksft_skip} 1578 rstart=${start} 1579 1580 range_size=1 1581 for i in $(seq 1 10); do 1582 for j in $(seq 1 20) ; do 1583 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1584 1585 nft "add element inet filter test { $elem }" || return 1 1586 nft "get element inet filter test { $elem }" | grep -q "$elem" 1587 if [ $? -ne 0 ];then 1588 local got=$(nft "get element inet filter test { $elem }") 1589 err "post-add: should have returned $elem but got $got" 1590 return 1 1591 fi 1592 done 1593 done 1594 1595 # recheck after set was filled 1596 for i in $(seq 1 10); do 1597 for j in $(seq 1 20) ; do 1598 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1599 1600 nft "get element inet filter test { $elem }" | grep -q "$elem" 1601 if [ $? -ne 0 ];then 1602 local got=$(nft "get element inet filter test { $elem }") 1603 err "post-fill: should have returned $elem but got $got" 1604 return 1 1605 fi 1606 done 1607 done 1608 1609 # random del and re-fetch 1610 for i in $(seq 1 10); do 1611 for j in $(seq 1 20) ; do 1612 local rnd=$((RANDOM%10)) 1613 local got="" 1614 1615 elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))") 1616 if [ $rnd -gt 0 ];then 1617 continue 1618 fi 1619 1620 nft "delete element inet filter test { $elem }" 1621 got=$(nft "get element inet filter test { $elem }" 2>/dev/null) 1622 if [ $? -eq 0 ];then 1623 err "post-delete: query for $elem returned $got instead of error." 1624 return 1 1625 fi 1626 done 1627 done 1628 1629 nft flush ruleset 1630} 1631 1632test_reported_issues() { 1633 eval test_bug_"${subtest}" 1634} 1635 1636# Run everything in a separate network namespace 1637[ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; } 1638tmp="$(mktemp)" 1639trap cleanup_exit EXIT 1640 1641# Entry point for test runs 1642passed=0 1643for name in ${TESTS}; do 1644 printf "TEST: %s\n" "$(echo "$name" | tr '_' ' ')" 1645 if [ "${name}" = "reported_issues" ]; then 1646 SUBTESTS="${BUGS}" 1647 else 1648 SUBTESTS="${TYPES}" 1649 fi 1650 1651 for subtest in ${SUBTESTS}; do 1652 eval desc=\$TYPE_"${subtest}" 1653 IFS=' 1654' 1655 for __line in ${desc}; do 1656 # shellcheck disable=SC2086 1657 eval ${__line%% *}=\"${__line##* }\"; 1658 done 1659 IFS=' 1660' 1661 1662 if [ "${name}" = "concurrency" ] && \ 1663 [ "${race_repeat}" = "0" ]; then 1664 continue 1665 fi 1666 if [ "${name}" = "performance" ] && \ 1667 [ "${perf_duration}" = "0" ]; then 1668 continue 1669 fi 1670 1671 [ "$KSFT_MACHINE_SLOW" = "yes" ] && count=1 1672 1673 printf " %-32s " "${display}" 1674 tthen=$(date +%s) 1675 eval test_"${name}" 1676 ret=$? 1677 1678 tnow=$(date +%s) 1679 printf "%5ds%-30s" $((tnow-tthen)) 1680 1681 if [ $ret -eq 0 ]; then 1682 printf "[ OK ]\n" 1683 info_flush 1684 passed=$((passed + 1)) 1685 elif [ $ret -eq 1 ]; then 1686 printf "[FAIL]\n" 1687 err_flush 1688 exit 1 1689 elif [ $ret -eq ${ksft_skip} ]; then 1690 printf "[SKIP]\n" 1691 err_flush 1692 fi 1693 done 1694done 1695 1696[ ${passed} -eq 0 ] && exit ${ksft_skip} || exit 0 1697