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 rmon_rx_histogram 8 rmon_tx_histogram 9" 10 11: "${DRIVER_TEST_CONFORMANT:=yes}" 12NUM_NETIFS=2 13lib_dir=$(dirname "$0") 14source "$lib_dir"/../../../net/forwarding/lib.sh 15source "$lib_dir"/../../../kselftest/ktap_helpers.sh 16 17UINT32_MAX=$((2**32 - 1)) 18ETH_FCS_LEN=4 19ETH_HLEN=$((6+6+2)) 20TEST_NAME=$(basename "$0" .sh) 21 22declare -A netif_mtu 23 24ensure_mtu() 25{ 26 local iface=$1; shift 27 local len=$1; shift 28 local required=$((len - ETH_HLEN - ETH_FCS_LEN)) 29 local current 30 31 current=$(run_on "$iface" \ 32 ip -j link show dev "$iface" | jq -r '.[0].mtu') 33 if [ "$current" -lt "$required" ]; then 34 run_on "$iface" ip link set dev "$iface" mtu "$required" \ 35 || return 1 36 fi 37} 38 39bucket_test() 40{ 41 local iface=$1; shift 42 local neigh=$1; shift 43 local set=$1; shift 44 local bucket=$1; shift 45 local len=$1; shift 46 local num_rx=10000 47 local num_tx=20000 48 local expected= 49 local before= 50 local after= 51 local delta= 52 53 # Mausezahn does not include FCS bytes in its length - but the 54 # histogram counters do 55 len=$((len - ETH_FCS_LEN)) 56 len=$((len > 0 ? len : 0)) 57 58 before=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ 59 jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val") 60 61 # Send 10k one way and 20k in the other, to detect counters 62 # mapped to the wrong direction 63 run_on "$neigh" \ 64 "$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us 65 run_on "$iface" \ 66 "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us 67 68 hw_stats_settle "$iface" 69 70 after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ 71 jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val") 72 73 delta=$((after - before)) 74 75 expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx") 76 77 [ "$delta" -ge "$expected" ] && [ "$delta" -le "$UINT32_MAX" ] 78} 79 80rmon_histogram() 81{ 82 local iface=$1; shift 83 local neigh=$1; shift 84 local set=$1; shift 85 local nbuckets=0 86 local step= 87 88 while read -r -a bucket; do 89 step="$set-pkts${bucket[0]}to${bucket[1]}" 90 91 for if in "$iface" "$neigh"; do 92 if ! ensure_mtu "$if" "${bucket[0]}"; then 93 ktap_print_msg "$if does not support the required MTU for $step" 94 ktap_test_xfail "$TEST_NAME.$step" 95 return 96 fi 97 done 98 99 if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then 100 ktap_test_fail "$TEST_NAME.$step" 101 return 1 102 fi 103 ktap_test_pass "$TEST_NAME.$step" 104 nbuckets=$((nbuckets + 1)) 105 done < <(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ 106 jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null) 107 108 if [ "$nbuckets" -eq 0 ]; then 109 ktap_print_msg "$iface does not support $set histogram counters" 110 return 111 fi 112} 113 114rmon_rx_histogram() 115{ 116 rmon_histogram "$h1" "$h2" rx 117} 118 119rmon_tx_histogram() 120{ 121 rmon_histogram "$h1" "$h2" tx 122} 123 124setup_prepare() 125{ 126 h1=${NETIFS[p1]} 127 h2=${NETIFS[p2]} 128 129 for iface in "$h1" "$h2"; do 130 netif_mtu["$iface"]=$(run_on "$iface" \ 131 ip -j link show dev "$iface" | jq -r '.[0].mtu') 132 done 133} 134 135cleanup() 136{ 137 pre_cleanup 138 139 # Do not bring down the interfaces, just configure the initial MTU 140 for iface in "$h2" "$h1"; do 141 run_on "$iface" ip link set dev "$iface" \ 142 mtu "${netif_mtu[$iface]}" 143 done 144} 145 146check_ethtool_counter_group_support 147trap cleanup EXIT 148 149bucket_count=$(ethtool --json -S "${NETIFS[p1]}" --groups rmon | \ 150 jq -r '.[0].rmon | 151 "\((."rx-pktsNtoM" | length) + 152 (."tx-pktsNtoM" | length))"') 153ktap_print_header 154ktap_set_plan "$bucket_count" 155 156setup_prepare 157setup_wait 158 159tests_run 160 161ktap_finished 162