#!/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=" rmon_rx_histogram rmon_tx_histogram " : "${DRIVER_TEST_CONFORMANT:=yes}" NUM_NETIFS=2 lib_dir=$(dirname "$0") source "$lib_dir"/../../../net/forwarding/lib.sh source "$lib_dir"/../../../kselftest/ktap_helpers.sh UINT32_MAX=$((2**32 - 1)) ETH_FCS_LEN=4 ETH_HLEN=$((6+6+2)) TEST_NAME=$(basename "$0" .sh) declare -A netif_mtu ensure_mtu() { local iface=$1; shift local len=$1; shift local required=$((len - ETH_HLEN - ETH_FCS_LEN)) local current current=$(run_on "$iface" \ ip -j link show dev "$iface" | jq -r '.[0].mtu') if [ "$current" -lt "$required" ]; then run_on "$iface" ip link set dev "$iface" mtu "$required" \ || return 1 fi } bucket_test() { local iface=$1; shift local neigh=$1; shift local set=$1; shift local bucket=$1; shift local len=$1; shift local num_rx=10000 local num_tx=20000 local expected= local before= local after= local delta= # Mausezahn does not include FCS bytes in its length - but the # histogram counters do len=$((len - ETH_FCS_LEN)) len=$((len > 0 ? len : 0)) before=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val") # Send 10k one way and 20k in the other, to detect counters # mapped to the wrong direction run_on "$neigh" \ "$MZ" "$neigh" -q -c "$num_rx" -p "$len" -a own -b bcast -d 10us run_on "$iface" \ "$MZ" "$iface" -q -c "$num_tx" -p "$len" -a own -b bcast -d 10us hw_stats_settle "$iface" after=$(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ jq -r ".[0].rmon[\"${set}-pktsNtoM\"][$bucket].val") delta=$((after - before)) expected=$([ "$set" = rx ] && echo "$num_rx" || echo "$num_tx") [ "$delta" -ge "$expected" ] && [ "$delta" -le "$UINT32_MAX" ] } rmon_histogram() { local iface=$1; shift local neigh=$1; shift local set=$1; shift local nbuckets=0 local step= while read -r -a bucket; do step="$set-pkts${bucket[0]}to${bucket[1]}" for if in "$iface" "$neigh"; do if ! ensure_mtu "$if" "${bucket[0]}"; then ktap_print_msg "$if does not support the required MTU for $step" ktap_test_xfail "$TEST_NAME.$step" return fi done if ! bucket_test "$iface" "$neigh" "$set" "$nbuckets" "${bucket[0]}"; then ktap_test_fail "$TEST_NAME.$step" return 1 fi ktap_test_pass "$TEST_NAME.$step" nbuckets=$((nbuckets + 1)) done < <(run_on "$iface" ethtool --json -S "$iface" --groups rmon | \ jq -r ".[0].rmon[\"${set}-pktsNtoM\"][]|[.low, .high]|@tsv" 2>/dev/null) if [ "$nbuckets" -eq 0 ]; then ktap_print_msg "$iface does not support $set histogram counters" return fi } rmon_rx_histogram() { rmon_histogram "$h1" "$h2" rx } rmon_tx_histogram() { rmon_histogram "$h1" "$h2" tx } setup_prepare() { h1=${NETIFS[p1]} h2=${NETIFS[p2]} for iface in "$h1" "$h2"; do netif_mtu["$iface"]=$(run_on "$iface" \ ip -j link show dev "$iface" | jq -r '.[0].mtu') done } cleanup() { pre_cleanup # Do not bring down the interfaces, just configure the initial MTU for iface in "$h2" "$h1"; do run_on "$iface" ip link set dev "$iface" \ mtu "${netif_mtu[$iface]}" done } check_ethtool_counter_group_support trap cleanup EXIT bucket_count=$(ethtool --json -S "${NETIFS[p1]}" --groups rmon | \ jq -r '.[0].rmon | "\((."rx-pktsNtoM" | length) + (."tx-pktsNtoM" | length))"') ktap_print_header ktap_set_plan "$bucket_count" setup_prepare setup_wait tests_run ktap_finished