feat(fdr): Add blanton_fdr.sh for phydiag fdrstat

start / clear / rdcnt / stop send fdrstat STArt bin_group=both
Interval=30 / clear / Counters / STOp through bcmcmd on ports
'1-259,270-565', unit 0 then unit 1, and print the output as is. -u
picks one unit, -i sets the interval, -n is a dry run, FDR_PORTS
overrides the port list.

The STOp keyword is inferred from prbsstat STOp and has not been
checked on the bench.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0131orciRKrejchsuDk6UpXk
This commit is contained in:
2026-10-21 22:50:25 +08:00
co-authored by Claude Opus 5.5
parent 16da1c68f2
commit 319ee07de3
@@ -0,0 +1,98 @@
#!/usr/bin/env bash
# =============================================================================
# blanton_fdr.sh -- SerDes FDR statistics (phydiag fdrstat), raw output
# =============================================================================
# Version History:
# V1.0.0 2026-10-21 First version. start / clear / rdcnt / stop over
# 'phydiag <ports> fdrstat ...' through bcmcmd, the same
# way blanton_ber_debug.sh drives prbsstat. Every bcmcmd
# output is printed as is -- no parsing, no PASS/FAIL.
#
# Sub-commands (each one runs on unit 0, then unit 1):
# start phydiag '<ports>' fdrstat STArt bin_group=both Interval=30
# clear phydiag '<ports>' fdrstat clear
# rdcnt phydiag '<ports>' fdrstat Counters
# stop phydiag '<ports>' fdrstat STOp
#
# ⚠️ 'stop' sends 'fdrstat STOp', by analogy with 'prbsstat STOp'. It has
# not been checked on the bench -- if the BCM shell rejects it, look at
# 'phydiag help' (or 'fdrstat' with no argument) for the right keyword.
# ⚠️ bcmcmd exits 0 even when the BCM shell refuses a command, so this
# script cannot tell success from failure. Read the output.
#
# Usage:
# ./blanton_fdr.sh <start|clear|rdcnt|stop> [-u 0|1] [-i <sec>] [-n]
# -u 0 | -u 1 one switch unit only (default: both, 0 then 1)
# -i <sec> start: fdrstat Interval (default 30)
# -n dry run: print the bcmcmd lines, do not run them
#
# Env overrides:
# BCMCMD_CMD=bcmcmd FDR_PORTS=1-259,270-565 FDR_INTERVAL=30
# FDR_BIN_GROUP=both
# =============================================================================
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
FDR_UNITS="0 1"
FDR_PORTS="${FDR_PORTS:-1-259,270-565}"
FDR_INTERVAL="${FDR_INTERVAL:-30}"
FDR_BIN_GROUP="${FDR_BIN_GROUP:-both}"
FDR_DRY_RUN=0
usage() {
sed -n '/^# Usage:/,/^# =====/p' "$0" | sed '$d; s/^# \{0,1\}//'
}
[ $# -ge 1 ] || { usage >&2; exit 2; }
ACT=$1; shift
case "$ACT" in
start|clear|rdcnt|stop) ;;
-h|--help|help) usage; exit 0 ;;
*) echo "[ERR ] unknown sub-command '$ACT'" >&2; usage >&2; exit 2 ;;
esac
while [ $# -gt 0 ]; do
case "$1" in
-u|--unit)
case "$2" in
0|1) FDR_UNITS="$2" ;;
*) echo "[ERR ] invalid unit '$2' (use 0 or 1)" >&2; exit 2 ;;
esac
shift 2 ;;
-i|--interval)
case "$2" in
''|*[!0-9]*) echo "[ERR ] invalid interval '$2'" >&2; exit 2 ;;
*) FDR_INTERVAL="$2" ;;
esac
shift 2 ;;
-n|--dry-run) FDR_DRY_RUN=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "[ERR ] unknown option '$1'" >&2; usage >&2; exit 2 ;;
esac
done
# bcmcmd reads stdin -- keep it on /dev/null (see blanton_traffic_linespeed.sh V0.3.1)
_bcm() {
local unit="$1"; shift
local cmd="dsh -c \"phydiag '${FDR_PORTS}' fdrstat $*\""
echo
echo "### [$(date '+%F %T')] unit $unit: phydiag '${FDR_PORTS}' fdrstat $*"
if [ "$FDR_DRY_RUN" = "1" ]; then
echo "[DRY ] $BCMCMD_CMD -n $unit -c ' ${cmd} '"
return 0
fi
"$BCMCMD_CMD" -n "$unit" -c " ${cmd} " </dev/null 2>&1
}
case "$ACT" in
start) SUB="STArt bin_group=${FDR_BIN_GROUP} Interval=${FDR_INTERVAL}" ;;
clear) SUB="clear" ;;
rdcnt) SUB="Counters" ;;
stop) SUB="STOp" ;;
esac
for u in $FDR_UNITS; do
_bcm "$u" "$SUB"
done
echo
echo "### [$(date '+%F %T')] FDR_${ACT^^}_DONE units: $FDR_UNITS"