1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3#shellcheck disable=SC2034 # SC does not see the global variables 4#shellcheck disable=SC2317,SC2329 # unused functions 5 6ALL_TESTS=" 7 test_eth_ctrl_stats 8 test_eth_mac_stats 9 test_pause_stats 10" 11: "${DRIVER_TEST_CONFORMANT:=yes}" 12STABLE_MAC_ADDRS=yes 13NUM_NETIFS=2 14lib_dir=$(dirname "$0") 15# shellcheck source=./../../../net/forwarding/lib.sh 16source "$lib_dir"/../../../net/forwarding/lib.sh 17# shellcheck source=./../../../kselftest/ktap_helpers.sh 18source "$lib_dir"/../../../kselftest/ktap_helpers.sh 19 20UINT32_MAX=$((2**32 - 1)) 21SUBTESTS=0 22TEST_NAME=$(basename "$0" .sh) 23 24traffic_test() 25{ 26 local iface=$1; shift 27 local neigh=$1; shift 28 local num_tx=$1; shift 29 local pkt_format="$1"; shift 30 local -a counters=("$@") 31 local int grp cnt target exact_check 32 local before after delta 33 local num_rx=$((num_tx * 2)) 34 local xfail_message 35 local src="aggregate" 36 local i 37 38 for i in "${!counters[@]}"; do 39 read -r int grp cnt target exact_check xfail_message \ 40 <<< "${counters[$i]}" 41 42 before[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src") 43 done 44 45 # shellcheck disable=SC2086 # needs split options 46 run_on "$iface" "$MZ" "$iface" -q -d 10usec -c "$num_tx" $pkt_format 47 48 # shellcheck disable=SC2086 # needs split options 49 run_on "$neigh" "$MZ" "$neigh" -q -d 10usec -c "$num_rx" $pkt_format 50 51 hw_stats_settle "$int" 52 53 for i in "${!counters[@]}"; do 54 read -r int grp cnt target exact_check xfail_message \ 55 <<< "${counters[$i]}" 56 57 after[i]=$(ethtool_std_stats_get "$int" "$grp" "$cnt" "$src") 58 if [[ "${after[$i]}" == "null" ]]; then 59 ktap_test_skip "$TEST_NAME.$grp-$cnt" 60 continue; 61 fi 62 63 delta=$((after[i] - before[i])) 64 65 if [ "$exact_check" -ne 0 ]; then 66 [ "$delta" -eq "$target" ] 67 else 68 [ "$delta" -ge "$target" ] && \ 69 [ "$delta" -le "$UINT32_MAX" ] 70 fi 71 err="$?" 72 73 if [[ $err != 0 ]] && [[ -n $xfail_message ]]; then 74 ktap_print_msg "$xfail_message" 75 ktap_test_xfail "$TEST_NAME.$grp-$cnt" 76 continue; 77 fi 78 79 if [[ $err != 0 ]]; then 80 ktap_print_msg "$grp-$cnt is not valid on $int (expected $target, got $delta)" 81 ktap_test_fail "$TEST_NAME.$grp-$cnt" 82 else 83 ktap_test_pass "$TEST_NAME.$grp-$cnt" 84 fi 85 done 86} 87 88test_eth_ctrl_stats() 89{ 90 local pkt_format="-a own -b bcast 88:08 -p 64" 91 local num_pkts=1000 92 local -a counters 93 94 counters=("$h1 eth-ctrl MACControlFramesTransmitted $num_pkts 0") 95 traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \ 96 "${counters[@]}" 97 98 counters=("$h1 eth-ctrl MACControlFramesReceived $num_pkts 0") 99 traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \ 100 "${counters[@]}" 101} 102SUBTESTS=$((SUBTESTS + 2)) 103 104test_eth_mac_stats() 105{ 106 local pkt_size=100 107 local pkt_size_fcs=$((pkt_size + 4)) 108 local bcast_pkt_format="-a own -b bcast -p $pkt_size" 109 local mcast_pkt_format="-a own -b 01:00:5E:00:00:01 -p $pkt_size" 110 local num_pkts=2000 111 local octets=$((pkt_size_fcs * num_pkts)) 112 local -a counters error_cnt collision_cnt 113 114 # Error counters should be exactly zero 115 counters=("$h1 eth-mac FrameCheckSequenceErrors 0 1" 116 "$h1 eth-mac AlignmentErrors 0 1" 117 "$h1 eth-mac FramesLostDueToIntMACXmitError 0 1" 118 "$h1 eth-mac CarrierSenseErrors 0 1" 119 "$h1 eth-mac FramesLostDueToIntMACRcvError 0 1" 120 "$h1 eth-mac InRangeLengthErrors 0 1" 121 "$h1 eth-mac OutOfRangeLengthField 0 1" 122 "$h1 eth-mac FrameTooLongErrors 0 1" 123 "$h1 eth-mac FramesAbortedDueToXSColls 0 1") 124 traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ 125 "${counters[@]}" 126 127 # Collision related counters should also be zero 128 counters=("$h1 eth-mac SingleCollisionFrames 0 1" 129 "$h1 eth-mac MultipleCollisionFrames 0 1" 130 "$h1 eth-mac FramesWithDeferredXmissions 0 1" 131 "$h1 eth-mac LateCollisions 0 1" 132 "$h1 eth-mac FramesWithExcessiveDeferral 0 1") 133 traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ 134 "${counters[@]}" 135 136 counters=("$h1 eth-mac BroadcastFramesXmittedOK $num_pkts 0" 137 "$h1 eth-mac OctetsTransmittedOK $octets 0") 138 traffic_test "$h1" "$h2" "$num_pkts" "$bcast_pkt_format" \ 139 "${counters[@]}" 140 141 counters=("$h1 eth-mac BroadcastFramesReceivedOK $num_pkts 0" 142 "$h1 eth-mac OctetsReceivedOK $octets 0") 143 traffic_test "$h2" "$h1" "$num_pkts" "$bcast_pkt_format" \ 144 "${counters[@]}" 145 146 counters=("$h1 eth-mac FramesTransmittedOK $num_pkts 0" 147 "$h1 eth-mac MulticastFramesXmittedOK $num_pkts 0") 148 traffic_test "$h1" "$h2" "$num_pkts" "$mcast_pkt_format" \ 149 "${counters[@]}" 150 151 counters=("$h1 eth-mac FramesReceivedOK $num_pkts 0" 152 "$h1 eth-mac MulticastFramesReceivedOK $num_pkts 0") 153 traffic_test "$h2" "$h1" "$num_pkts" "$mcast_pkt_format" \ 154 "${counters[@]}" 155} 156SUBTESTS=$((SUBTESTS + 22)) 157 158test_pause_stats() 159{ 160 local pkt_format="-a own -b 01:80:c2:00:00:01 88:08:00:01:00:01" 161 local xfail_message="software sent pause frames not detected" 162 local num_pkts=2000 163 local -a counters 164 local int 165 local i 166 167 # Check that there is pause frame support 168 for ((i = 1; i <= NUM_NETIFS; ++i)); do 169 int="${NETIFS[p$i]}" 170 if ! run_on "$int" ethtool -I --json -a "$int" > /dev/null 2>&1; then 171 ktap_test_skip "$TEST_NAME.tx_pause_frames" 172 ktap_test_skip "$TEST_NAME.rx_pause_frames" 173 return 174 fi 175 done 176 177 counters=("$h1 pause tx_pause_frames $num_pkts 0 $xfail_message") 178 traffic_test "$h1" "$h2" "$num_pkts" "$pkt_format" \ 179 "${counters[@]}" 180 181 counters=("$h1 pause rx_pause_frames $num_pkts 0") 182 traffic_test "$h2" "$h1" "$num_pkts" "$pkt_format" \ 183 "${counters[@]}" 184} 185SUBTESTS=$((SUBTESTS + 2)) 186 187setup_prepare() 188{ 189 local iface 190 191 h1=${NETIFS[p1]} 192 h2=${NETIFS[p2]} 193 194 h2_mac=$(mac_get "$h2") 195} 196 197ktap_print_header 198ktap_set_plan $SUBTESTS 199 200check_ethtool_counter_group_support 201trap cleanup EXIT 202 203setup_prepare 204setup_wait 205 206tests_run 207 208ktap_finished 209