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