| #!/bin/bash | |
| # SPDX-License-Identifier: GPL-2.0 | |
| #shellcheck disable=SC2034 # SC does not see the global variables | |
| #shellcheck disable=SC2317,SC2329 # unused functions | |
| ALL_TESTS=" | |
| test_eth_ctrl_stats | |
| test_eth_mac_stats | |
| test_pause_stats | |
| " | |
| : "${DRIVER_TEST_CONFORMANT:=yes}" | |
| STABLE_MAC_ADDRS=yes | |
| NUM_NETIFS=2 | |
| lib_dir=$(dirname "$0") | |
| # shellcheck source=./../../../net/forwarding/lib.sh | |
| source "$lib_dir"/../../../net/forwarding/lib.sh | |
| # shellcheck source=./../../../kselftest/ktap_helpers.sh | |
| source "$lib_dir"/../../../kselftest/ktap_helpers.sh | |
| UINT32_MAX=$((2**32 - 1)) | |
| SUBTESTS=0 | |
| TEST_NAME=$(basename "$0" .sh) | |
| traffic_test() | |
| { | |
| local iface=$1; shift | |
| local neigh=$1; shift | |
| local num_tx=$1; shift | |
| local pkt_format="$1"; shift | |
| local -a counters=("$@") | |
| local int grp cnt target exact_check | |
| local before after delta | |
| local num_rx=$((num_tx * 2)) | |
| local xfail_message | |
| local src="aggregate" | |
| local i | |
| for i in "${!counters[@]}"; do | |
| read -r int grp cnt target exact_check xfail_message \ | |
| <<< "${counters[$i]}" | |
| before[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src") | |
| done | |
| # shellcheck disable=SC2086 # needs split options | |
| run_on "$iface" "$MZ" "$iface" -q -d 10usec -c "$num_tx" $pkt_format | |
| # shellcheck disable=SC2086 # needs split options | |
| run_on "$neigh" "$MZ" "$neigh" -q -d 10usec -c "$num_rx" $pkt_format | |
| hw_stats_settle "$int" | |
| for i in "${!counters[@]}"; do | |
| read -r int grp cnt target exact_check xfail_message \ | |
| <<< "${counters[$i]}" | |
| after[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src") | |
| if [[ "${after[$i]}" == "null" ]]; then | |
| ktap_test_skip "$TEST_NAME.$grp-$cnt" | |
| continue; | |
| fi | |
| delta=$((after[i] - before[i])) | |
| if [ "$exact_check" -ne 0 ]; then | |
| [ "$delta" -eq "$target" ] | |
| else | |
| [ "$delta" -ge "$target" ] && \ | |
| [ "$delta" -le "$UINT32_MAX" ] | |
| fi | |
| err="$?" | |
| if [[ $err != 0 ]] && [[ -n $xfail_message ]]; then | |
| ktap_print_msg "$xfail_message" | |
| ktap_test_xfail "$TEST_NAME.$grp-$cnt" | |
| continue; | |
| fi | |
| if [[ $err != 0 ]]; then | |
| ktap_print_msg "$grp-$cnt is not valid on $int (expected $target, got $delta)" | |
| ktap_test_fail "$TEST_NAME.$grp-$cnt" | |
| else | |
| ktap_test_pass "$TEST_NAME.$grp-$cnt" | |
| fi | |
| done | |
| } | |
| test_eth_ctrl_stats() | |
| { | |
| local pkt_format="-a own -b bcast 88:08 -p 64" | |
| local num_pkts=1000 | |
| local -a counters | |
| counters=("$h1 eth-ctrl MACControlFramesTransmitted $num_pkts 0") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 eth-ctrl MACControlFramesReceived $num_pkts 0") | |
| traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \ | |
| "${counters[@]}" | |
| } | |
| SUBTESTS=$((SUBTESTS + 2)) | |
| test_eth_mac_stats() | |
| { | |
| local pkt_size=100 | |
| local pkt_size_fcs=$((pkt_size + 4)) | |
| local bcast_pkt_format="-a own -b bcast -p $pkt_size" | |
| local mcast_pkt_format="-a own -b 01:00:5E:00:00:01 -p $pkt_size" | |
| local num_pkts=2000 | |
| local octets=$((pkt_size_fcs * num_pkts)) | |
| local -a counters error_cnt collision_cnt | |
| # Error counters should be exactly zero | |
| counters=("$h1 eth-mac FrameCheckSequenceErrors 0 1" | |
| "$h1 eth-mac AlignmentErrors 0 1" | |
| "$h1 eth-mac FramesLostDueToIntMACXmitError 0 1" | |
| "$h1 eth-mac CarrierSenseErrors 0 1" | |
| "$h1 eth-mac FramesLostDueToIntMACRcvError 0 1" | |
| "$h1 eth-mac InRangeLengthErrors 0 1" | |
| "$h1 eth-mac OutOfRangeLengthField 0 1" | |
| "$h1 eth-mac FrameTooLongErrors 0 1" | |
| "$h1 eth-mac FramesAbortedDueToXSColls 0 1") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ | |
| "${counters[@]}" | |
| # Collision related counters should also be zero | |
| counters=("$h1 eth-mac SingleCollisionFrames 0 1" | |
| "$h1 eth-mac MultipleCollisionFrames 0 1" | |
| "$h1 eth-mac FramesWithDeferredXmissions 0 1" | |
| "$h1 eth-mac LateCollisions 0 1" | |
| "$h1 eth-mac FramesWithExcessiveDeferral 0 1") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 eth-mac BroadcastFramesXmittedOK $num_pkts 0" | |
| "$h1 eth-mac OctetsTransmittedOK $octets 0") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 eth-mac BroadcastFramesReceivedOK $num_pkts 0" | |
| "$h1 eth-mac OctetsReceivedOK $octets 0") | |
| traffic_test "$h2" "$h1" "$num_pkts" "$bcast_pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 eth-mac FramesTransmittedOK $num_pkts 0" | |
| "$h1 eth-mac MulticastFramesXmittedOK $num_pkts 0") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$mcast_pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 eth-mac FramesReceivedOK $num_pkts 0" | |
| "$h1 eth-mac MulticastFramesReceivedOK $num_pkts 0") | |
| traffic_test "$h2" "$h1" "$num_pkts" "$mcast_pkt_format" \ | |
| "${counters[@]}" | |
| } | |
| SUBTESTS=$((SUBTESTS + 22)) | |
| test_pause_stats() | |
| { | |
| local pkt_format="-a own -b 01:80:c2:00:00:01 88:08:00:01:00:01" | |
| local xfail_message="software sent pause frames not detected" | |
| local num_pkts=2000 | |
| local -a counters | |
| local int | |
| local i | |
| # Check that there is pause frame support | |
| for ((i = 1; i <= NUM_NETIFS; ++i)); do | |
| int="${NETIFS[p$i]}" | |
| if ! run_on "$int" ethtool -I --json -a "$int" > /dev/null 2>&1; then | |
| ktap_test_skip "$TEST_NAME.tx_pause_frames" | |
| ktap_test_skip "$TEST_NAME.rx_pause_frames" | |
| return | |
| fi | |
| done | |
| counters=("$h1 pause tx_pause_frames $num_pkts 0 $xfail_message") | |
| traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \ | |
| "${counters[@]}" | |
| counters=("$h1 pause rx_pause_frames $num_pkts 0") | |
| traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \ | |
| "${counters[@]}" | |
| } | |
| SUBTESTS=$((SUBTESTS + 2)) | |
| setup_prepare() | |
| { | |
| local iface | |
| h1=${NETIFS[p1]} | |
| h2=${NETIFS[p2]} | |
| h2_mac=$(mac_get "$h2") | |
| } | |
| ktap_print_header | |
| ktap_set_plan $SUBTESTS | |
| check_ethtool_counter_group_support | |
| trap cleanup EXIT | |
| setup_prepare | |
| setup_wait | |
| tests_run | |
| ktap_finished |