| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Test qdisc offload indication |
| |
| |
| ALL_TESTS=" |
| test_root |
| test_port_tbf |
| test_etsprio |
| test_etsprio_port_tbf |
| " |
| NUM_NETIFS=1 |
| lib_dir=$(dirname $0)/../../../net/forwarding |
| source $lib_dir/lib.sh |
| |
| check_not_offloaded() |
| { |
| local handle=$1; shift |
| local h |
| local offloaded |
| |
| h=$(qdisc_stats_get $h1 "$handle" .handle) |
| [[ $h == '"'$handle'"' ]] |
| check_err $? "Qdisc with handle $handle does not exist" |
| |
| offloaded=$(qdisc_stats_get $h1 "$handle" .offloaded) |
| [[ $offloaded == true ]] |
| check_fail $? "Qdisc with handle $handle offloaded, but should not be" |
| } |
| |
| check_all_offloaded() |
| { |
| local handle=$1; shift |
| |
| if [[ ! -z $handle ]]; then |
| local offloaded=$(qdisc_stats_get $h1 "$handle" .offloaded) |
| [[ $offloaded == true ]] |
| check_err $? "Qdisc with handle $handle not offloaded" |
| fi |
| |
| local unoffloaded=$(tc q sh dev $h1 invisible | |
| grep -v offloaded | |
| sed s/root/parent\ root/ | |
| cut -d' ' -f 5) |
| [[ -z $unoffloaded ]] |
| check_err $? "Qdiscs with following parents not offloaded: $unoffloaded" |
| |
| pre_cleanup |
| } |
| |
| with_ets() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle \ |
| ets bands 8 priomap 7 6 5 4 3 2 1 0 |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_prio() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle \ |
| prio bands 8 priomap 7 6 5 4 3 2 1 0 |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_red() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle \ |
| red limit 1000000 min 200000 max 300000 probability 0.5 avpkt 1500 |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_tbf() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle \ |
| tbf rate 400Mbit burst 128K limit 1M |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_pfifo() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle pfifo limit 100K |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_bfifo() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle bfifo limit 100K |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_drr() |
| { |
| local handle=$1; shift |
| local locus=$1; shift |
| |
| tc qdisc add dev $h1 $locus handle $handle drr |
| "$@" |
| tc qdisc del dev $h1 $locus |
| } |
| |
| with_qdiscs() |
| { |
| local handle=$1; shift |
| local parent=$1; shift |
| local kind=$1; shift |
| local next_handle=$((handle * 2)) |
| local locus; |
| |
| if [[ $kind == "--" ]]; then |
| local cmd=$1; shift |
| $cmd $(printf %x: $parent) "$@" |
| else |
| if ((parent == 0)); then |
| locus=root |
| else |
| locus=$(printf "parent %x:1" $parent) |
| fi |
| |
| with_$kind $(printf %x: $handle) "$locus" \ |
| with_qdiscs $next_handle $handle "$@" |
| fi |
| } |
| |
| get_name() |
| { |
| local parent=$1; shift |
| local name=$(echo "" "${@^^}" | tr ' ' -) |
| |
| if ((parent != 0)); then |
| kind=$(qdisc_stats_get $h1 $parent: .kind) |
| kind=${kind%\"} |
| kind=${kind#\"} |
| name="-${kind^^}$name" |
| fi |
| |
| echo root$name |
| } |
| |
| do_test_offloaded() |
| { |
| local handle=$1; shift |
| local parent=$1; shift |
| |
| RET=0 |
| with_qdiscs $handle $parent "$@" -- check_all_offloaded |
| log_test $(get_name $parent "$@")" offloaded" |
| } |
| |
| do_test_nooffload() |
| { |
| local handle=$1; shift |
| local parent=$1; shift |
| |
| local name=$(echo "${@^^}" | tr ' ' -) |
| local kind |
| |
| RET=0 |
| with_qdiscs $handle $parent "$@" -- check_not_offloaded |
| log_test $(get_name $parent "$@")" not offloaded" |
| } |
| |
| do_test_combinations() |
| { |
| local handle=$1; shift |
| local parent=$1; shift |
| |
| local cont |
| local leaf |
| local fifo |
| |
| for cont in "" ets prio; do |
| for leaf in "" red tbf "red tbf" "tbf red"; do |
| for fifo in "" pfifo bfifo; do |
| if [[ -z "$cont$leaf$fifo" ]]; then |
| continue |
| fi |
| do_test_offloaded $handle $parent \ |
| $cont $leaf $fifo |
| done |
| done |
| done |
| |
| for cont in ets prio; do |
| for leaf in red tbf; do |
| do_test_nooffload $handle $parent $cont red tbf $leaf |
| do_test_nooffload $handle $parent $cont tbf red $leaf |
| done |
| for leaf in "red red" "tbf tbf"; do |
| do_test_nooffload $handle $parent $cont $leaf |
| done |
| done |
| |
| do_test_nooffload $handle $parent drr |
| } |
| |
| test_root() |
| { |
| do_test_combinations 1 0 |
| } |
| |
| test_port_tbf() |
| { |
| with_tbf 1: root \ |
| do_test_combinations 8 1 |
| } |
| |
| do_test_etsprio() |
| { |
| local parent=$1; shift |
| local tbfpfx=$1; shift |
| local cont |
| |
| for cont in ets prio; do |
| RET=0 |
| with_$cont 8: "$parent" \ |
| with_red 11: "parent 8:1" \ |
| with_red 12: "parent 8:2" \ |
| with_tbf 13: "parent 8:3" \ |
| with_tbf 14: "parent 8:4" \ |
| check_all_offloaded |
| log_test "root$tbfpfx-ETS-{RED,TBF} offloaded" |
| |
| RET=0 |
| with_$cont 8: "$parent" \ |
| with_red 81: "parent 8:1" \ |
| with_tbf 811: "parent 81:1" \ |
| with_tbf 84: "parent 8:4" \ |
| with_red 841: "parent 84:1" \ |
| check_all_offloaded |
| log_test "root$tbfpfx-ETS-{RED-TBF,TBF-RED} offloaded" |
| |
| RET=0 |
| with_$cont 8: "$parent" \ |
| with_red 81: "parent 8:1" \ |
| with_tbf 811: "parent 81:1" \ |
| with_bfifo 8111: "parent 811:1" \ |
| with_tbf 82: "parent 8:2" \ |
| with_red 821: "parent 82:1" \ |
| with_bfifo 8211: "parent 821:1" \ |
| check_all_offloaded |
| log_test "root$tbfpfx-ETS-{RED-TBF-bFIFO,TBF-RED-bFIFO} offloaded" |
| done |
| } |
| |
| test_etsprio() |
| { |
| do_test_etsprio root "" |
| } |
| |
| test_etsprio_port_tbf() |
| { |
| with_tbf 1: root \ |
| do_test_etsprio "parent 1:1" "-TBF" |
| } |
| |
| cleanup() |
| { |
| tc qdisc del dev $h1 root &>/dev/null |
| } |
| |
| trap cleanup EXIT |
| h1=${NETIFS[p1]} |
| tests_run |
| |
| exit $EXIT_STATUS |