feat(pwr): Add blanton_tr518_thermal.sh for the thermal tr 518 load
A copy of blanton_tr518.sh V1.0.1 with the thermal tr 518 arguments (Scenario=6 Profile=2 portstopktszstride=1 Count=260 PktSize=603,218 CheckLinkTime=20 CheckDataTime=200 TestPhase=1, no PortList / rm=ext). The argument string is read from TR_THERMAL_ARGS so an override meant for blanton_tr518.sh does not leak in. Not run on the bench yet; no TTL calls it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0131orciRKrejchsuDk6UpXk
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# blanton_tr518_thermal.sh -- TH6 tr 518 load for thermal tests, via bcmcmd
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.0.0 2026-10-28 First version. Copy of blanton_tr518.sh V1.0.1 with the
|
||||
# thermal tr 518 arguments:
|
||||
# Scenario=6 Profile=2 portstopktszstride=1 Count=260
|
||||
# PktSize=603,218 CheckLinkTime=20 CheckDataTime=200
|
||||
# TestPhase=1
|
||||
# (no PortList / rm=ext, unlike blanton_tr518.sh). The
|
||||
# per-unit sequence is unchanged: port cd lb=mac,
|
||||
# l2 learn off, test mode nr=yes, tr 518. The argument
|
||||
# string is read from TR_THERMAL_ARGS, not TR_TEST_ARGS,
|
||||
# so an override meant for blanton_tr518.sh does not
|
||||
# leak into this one.
|
||||
# =============================================================================
|
||||
#
|
||||
# What this is for: tr 518 loads the switch so the power rails can be measured
|
||||
# under traffic. The usual sequence is
|
||||
#
|
||||
# blanton_tr518_thermal.sh start # loads both units, waits to settle
|
||||
# TH6_SWB0_power_readback.sh # now the numbers mean something
|
||||
# TH6_SWB1_power_readback.sh
|
||||
# blanton_tr518_thermal.sh stop
|
||||
#
|
||||
# ⚠️ tr 518 and blanton_traffic_linespeed CANNOT run at the same time. Both take
|
||||
# over the cd ports and L2 learning; running one while the other is set up
|
||||
# gives numbers from neither test. Stop one before the other starts.
|
||||
#
|
||||
# ⚠️ stop only undoes the loopback -- see TR_RESTORE_* below.
|
||||
#
|
||||
# Usage (run directly):
|
||||
# ./blanton_tr518_thermal.sh start # both units
|
||||
# ./blanton_tr518_thermal.sh start -u 0 # unit 0 only
|
||||
# ./blanton_tr518_thermal.sh start -u 1 # unit 1 only
|
||||
# ./blanton_tr518_thermal.sh stop [-u 0|1]
|
||||
# ./blanton_tr518_thermal.sh help
|
||||
#
|
||||
# Usage (sourced, like the other blanton_*.sh tools):
|
||||
# source blanton_tr518_thermal.sh
|
||||
# blanton_tr518_thermal start -u 0
|
||||
#
|
||||
# Options:
|
||||
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TR_UNITS ("0 1")
|
||||
# -w|--wait <sec> start: settle wait after tr 518 (default $TR_SETTLE_SEC)
|
||||
# --no-wait start: skip the settle wait entirely
|
||||
# -d|--debug print every bcmcmd and its output
|
||||
# -n|--dry-run print commands only, do not touch the DUT
|
||||
# -h|--help help
|
||||
#
|
||||
# Environment overrides:
|
||||
# BCMCMD_CMD=bcmcmd TR_UNITS="0 1" TR_SETTLE_SEC=120 TR_UNIT_GAP_SEC=1
|
||||
# TR_THERMAL_ARGS="..." TR_LB_PORTS=cd TR_RESTORE_LEARN=0 TR_RESTORE_TESTMODE=0
|
||||
# DEBUG_MODE=1
|
||||
# =============================================================================
|
||||
|
||||
# === Config ==================================================================
|
||||
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
|
||||
TR_UNITS="${TR_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
|
||||
|
||||
# Settle wait after tr 518 is issued. The point is NOT the test itself -- it is
|
||||
# to stop someone reading power while traffic is still ramping and reporting a
|
||||
# number that is neither idle nor loaded. Lower it only if you know the rails
|
||||
# have already settled.
|
||||
TR_SETTLE_SEC="${TR_SETTLE_SEC:-120}"
|
||||
|
||||
# Gap between unit 0 and unit 1 (each unit is set up as a complete block, the
|
||||
# way TR518.txt does it -- the cd ports are in MAC loopback, so a unit does not
|
||||
# depend on the other one being ready).
|
||||
TR_UNIT_GAP_SEC="${TR_UNIT_GAP_SEC:-1}"
|
||||
|
||||
# Ports put into MAC loopback. 'cd' = the cd port group, per TR518.txt.
|
||||
TR_LB_PORTS="${TR_LB_PORTS:-cd}"
|
||||
|
||||
# Printed by the BCM shell only after tr 518 has accepted its arguments and
|
||||
# started. Used as the success marker, because bcmcmd's own exit status is not
|
||||
# trustworthy for a command that runs longer than its response poll.
|
||||
TR_TEST_OK_PAT="${TR_TEST_OK_PAT:-TR 518 TEST PARAMETERS}"
|
||||
|
||||
# The thermal tr 518 argument string. One editable line so it can be pasted
|
||||
# straight from / into a manual bcmcmd.
|
||||
TR_THERMAL_ARGS="${TR_THERMAL_ARGS:-Scenario=6 Profile=2 portstopktszstride=1 Count=260 PktSize=603,218 CheckLinkTime=20 CheckDataTime=200 TestPhase=1}"
|
||||
|
||||
# TR518.txt stops with 'port cd lb=none' and nothing else, so that is the
|
||||
# default here too. But note what start changed and stop does NOT put back:
|
||||
# l2 learn off -> the unit keeps learning disabled
|
||||
# test mode nr=yes -> the unit stays in test mode
|
||||
# Both persist until something else changes them or the box reboots. Set these
|
||||
# to 1 if you want stop to be a true inverse; they are off by default because
|
||||
# they are not in the bench-verified list.
|
||||
TR_RESTORE_LEARN="${TR_RESTORE_LEARN:-0}"
|
||||
TR_RESTORE_TESTMODE="${TR_RESTORE_TESTMODE:-0}"
|
||||
|
||||
DEBUG_MODE=${DEBUG_MODE:-0}
|
||||
TR_DRY_RUN=${TR_DRY_RUN:-0}
|
||||
TR_NO_WAIT=${TR_NO_WAIT:-0}
|
||||
|
||||
# === Logging =================================================================
|
||||
_tr_info() { echo -e "[\033[34mINFO\033[0m] $*"; }
|
||||
_tr_ok() { echo -e "[\033[32m OK \033[0m] $*"; }
|
||||
_tr_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; }
|
||||
_tr_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
|
||||
_tr_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; }
|
||||
|
||||
# === bcmcmd wrapper ==========================================================
|
||||
# stdin is closed for the same reason as in blanton_traffic_linespeed.sh:
|
||||
# bcmcmd otherwise inherits the caller's stdin and eats whatever a surrounding
|
||||
# loop was reading.
|
||||
#
|
||||
# bcmcmd exits 0 even when the BCM shell refused the command, so the output is
|
||||
# pattern-matched as well (the V0.3.1 lesson from blanton_traffic_linespeed.sh).
|
||||
TR_ERR_PAT="${TR_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}"
|
||||
|
||||
# ...and the reverse also happens: bcmcmd exits NON-zero on a command that was
|
||||
# accepted and is running. 'tr 518' outlives bcmcmd's response poll, so bcmcmd
|
||||
# gives up with "polling socket timeout: Success" and a non-zero status while
|
||||
# the test carries on inside the BCM shell. Treating that as a failure is what
|
||||
# made V1.0.0 report ERR on a run that was actually fine.
|
||||
TR_BENIGN_PAT="${TR_BENIGN_PAT:-polling socket timeout}"
|
||||
|
||||
# _tr_bcm <unit> <cmd> -> 0 ok, 1 failed
|
||||
# _tr_bcm_ok <unit> <ok_marker> <cmd> -> as above, but if the output contains
|
||||
# <ok_marker> the command is a success
|
||||
# regardless of exit status.
|
||||
#
|
||||
# The marker is a POSITIVE proof of success ("the shell printed the thing it
|
||||
# only prints when it accepted this command"), which is far more reliable than
|
||||
# trying to enumerate every way bcmcmd can look unhappy.
|
||||
_tr_bcm() { _tr_bcm_ok "$1" "" "${@:2}"; }
|
||||
|
||||
_tr_bcm_ok() {
|
||||
local unit="$1" okpat="$2"; shift 2
|
||||
local cmd="$*" out rc why=""
|
||||
_tr_dbg "$BCMCMD_CMD -n $unit -c '$cmd'"
|
||||
if [ "$TR_DRY_RUN" = "1" ]; then
|
||||
echo "[DRY ] $BCMCMD_CMD -n $unit -c '$cmd'"
|
||||
return 0
|
||||
fi
|
||||
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
|
||||
[ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out"
|
||||
|
||||
# 1. positive proof wins over everything else
|
||||
if [ -n "$okpat" ] && echo "$out" | grep -qF "$okpat"; then
|
||||
[ "$rc" -ne 0 ] && _tr_dbg "unit $unit: bcmcmd rc=$rc but '$okpat' seen -> accepted"
|
||||
return 0
|
||||
fi
|
||||
# 2. the BCM shell said no
|
||||
if echo "$out" | grep -qiE "$TR_ERR_PAT"; then
|
||||
why="the BCM shell rejected it"
|
||||
# 3. bcmcmd itself was unhappy -- unless it is the known transport artifact
|
||||
elif [ "$rc" -ne 0 ]; then
|
||||
if echo "$out" | grep -qiE "$TR_BENIGN_PAT"; then
|
||||
_tr_dbg "unit $unit: bcmcmd rc=$rc (${TR_BENIGN_PAT}) -> tolerated"
|
||||
return 0
|
||||
fi
|
||||
why="bcmcmd exited $rc"
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
|
||||
_tr_err "unit $unit: $why -- '$cmd'"
|
||||
[ "$DEBUG_MODE" = "1" ] || { [ -n "$out" ] && echo "$out" >&2; }
|
||||
return 1
|
||||
}
|
||||
|
||||
_tr_units_check() {
|
||||
local u ok=""
|
||||
for u in $TR_UNITS; do
|
||||
case "$u" in
|
||||
0|1) ok="$ok $u" ;;
|
||||
*) _tr_err "invalid unit '$u' (use 0, 1 or all)"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$ok" ] || { _tr_err "no unit selected"; return 1; }
|
||||
TR_UNITS="${ok# }"
|
||||
return 0
|
||||
}
|
||||
|
||||
_tr_is_uint() { case "$1" in ''|*[!0-9]*) return 1 ;; *) return 0 ;; esac; }
|
||||
|
||||
_tr_gap() {
|
||||
[ "$TR_DRY_RUN" = "1" ] && return 0
|
||||
[ "$TR_UNIT_GAP_SEC" = "0" ] && return 0
|
||||
sleep "$TR_UNIT_GAP_SEC"
|
||||
}
|
||||
|
||||
# === start ===================================================================
|
||||
# One complete block per unit, exactly the order in tools/TR518.txt.
|
||||
blanton_tr518_thermal_start() {
|
||||
_tr_units_check || return 1
|
||||
_tr_is_uint "$TR_SETTLE_SEC" || { _tr_err "settle wait '$TR_SETTLE_SEC' is not an integer (-w <sec>)"; return 1; }
|
||||
|
||||
local unit fail=0 first=1
|
||||
_tr_info "TR518 start on unit(s): $TR_UNITS"
|
||||
for unit in $TR_UNITS; do
|
||||
[ "$first" = "0" ] && _tr_gap
|
||||
first=0
|
||||
_tr_info "unit $unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518"
|
||||
_tr_bcm "$unit" "port $TR_LB_PORTS lb=mac" || fail=$((fail+1))
|
||||
_tr_bcm "$unit" "l2 learn off" || fail=$((fail+1))
|
||||
_tr_bcm "$unit" 'dsh -c "test mode nr=yes"' || fail=$((fail+1))
|
||||
# "TR 518 TEST PARAMETERS" is printed only once the shell has parsed the
|
||||
# arguments and started the test -- that is the proof we check for.
|
||||
_tr_bcm_ok "$unit" "$TR_TEST_OK_PAT" "dsh -c \"tr 518 $TR_THERMAL_ARGS\"" || fail=$((fail+1))
|
||||
done
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
_tr_err "$fail command(s) failed -- traffic may not be running, not waiting"
|
||||
_tr_warn "the unit(s) may still be in loopback: blanton_tr518_thermal.sh stop"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$TR_NO_WAIT" = "1" ] || [ "$TR_SETTLE_SEC" = "0" ]; then
|
||||
_tr_ok "TR518 running on unit(s): $TR_UNITS (settle wait skipped)"
|
||||
_tr_warn "rails may still be ramping -- a power reading taken now is not a settled one"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_tr_info "settling ${TR_SETTLE_SEC}s before the rails are worth reading ..."
|
||||
[ "$TR_DRY_RUN" = "1" ] || sleep "$TR_SETTLE_SEC"
|
||||
_tr_ok "TR518 running and settled on unit(s): $TR_UNITS"
|
||||
_tr_info "read power now: TH6_SWB0_power_readback.sh / TH6_SWB1_power_readback.sh"
|
||||
_tr_info "when finished: blanton_tr518_thermal.sh stop"
|
||||
return 0
|
||||
}
|
||||
|
||||
# === stop ====================================================================
|
||||
# TR518.txt stops with 'port cd lb=none' only. l2 learning and test mode are
|
||||
# left as start set them unless TR_RESTORE_* is turned on.
|
||||
blanton_tr518_thermal_stop() {
|
||||
_tr_units_check || return 1
|
||||
local unit fail=0 first=1
|
||||
_tr_info "TR518 stop on unit(s): $TR_UNITS"
|
||||
for unit in $TR_UNITS; do
|
||||
[ "$first" = "0" ] && _tr_gap
|
||||
first=0
|
||||
_tr_bcm "$unit" "port $TR_LB_PORTS lb=none" || fail=$((fail+1))
|
||||
[ "$TR_RESTORE_LEARN" = "1" ] && { _tr_bcm "$unit" "l2 learn on" || fail=$((fail+1)); }
|
||||
[ "$TR_RESTORE_TESTMODE" = "1" ] && { _tr_bcm "$unit" 'dsh -c "test mode nr=no"' || fail=$((fail+1)); }
|
||||
done
|
||||
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
_tr_ok "unit(s) $TR_UNITS: port $TR_LB_PORTS lb=none"
|
||||
[ "$TR_RESTORE_LEARN" = "1" ] || \
|
||||
_tr_info "l2 learning is still off (TR_RESTORE_LEARN=1 to put it back)"
|
||||
[ "$TR_RESTORE_TESTMODE" = "1" ] || \
|
||||
_tr_info "test mode is still nr=yes (TR_RESTORE_TESTMODE=1 to put it back)"
|
||||
else
|
||||
_tr_warn "$fail command(s) failed -- check the unit is not still in loopback:"
|
||||
_tr_warn " bcmcmd -n <u> -c 'port $TR_LB_PORTS' | head"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# === Help ====================================================================
|
||||
blanton_tr518_thermal_help() {
|
||||
echo -e "\033[1mblanton_tr518_thermal.sh - TH6 built-in packet test (tr 518) for thermal loading\033[0m"
|
||||
echo ""
|
||||
echo -e " Units : \033[36m$TR_UNITS\033[0m"
|
||||
echo -e " Settle wait : \033[36m${TR_SETTLE_SEC}s\033[0m after tr 518 (so power is read loaded, not ramping)"
|
||||
echo -e " Loopback : \033[36mport $TR_LB_PORTS lb=mac\033[0m"
|
||||
echo -e " tr 518 args : \033[36m$TR_THERMAL_ARGS\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mSubcommands\033[0m"
|
||||
echo -e " \033[33mstart\033[0m per unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518 -> wait"
|
||||
echo -e " \033[33mstop\033[0m per unit: port $TR_LB_PORTS lb=none"
|
||||
echo -e " \033[33mhelp\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mOptions\033[0m"
|
||||
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TR_UNITS)"
|
||||
echo -e " \033[33m-w|--wait\033[0m <sec> start: settle wait (default $TR_SETTLE_SEC)"
|
||||
echo -e " \033[33m--no-wait\033[0m start: skip the settle wait"
|
||||
echo -e " \033[33m-d|--debug\033[0m print every bcmcmd and its output"
|
||||
echo -e " \033[33m-n|--dry-run\033[0m print commands only, do not touch the DUT"
|
||||
echo ""
|
||||
echo -e "\033[1mExamples\033[0m"
|
||||
echo -e " ./blanton_tr518_thermal.sh start # both units, then wait ${TR_SETTLE_SEC}s"
|
||||
echo -e " ./blanton_tr518_thermal.sh start -u 0 # unit 0 only"
|
||||
echo -e " ./blanton_tr518_thermal.sh stop -u 1 # release unit 1"
|
||||
echo -e " ./blanton_tr518_thermal.sh start -n # show the bcmcmds, touch nothing"
|
||||
echo ""
|
||||
echo -e "\033[33m stop only sends 'port $TR_LB_PORTS lb=none'. l2 learning stays off and test mode\033[0m"
|
||||
echo -e "\033[33m stays nr=yes -- TR_RESTORE_LEARN=1 / TR_RESTORE_TESTMODE=1 to put them back.\033[0m"
|
||||
echo -e "\033[33m tr 518 and blanton_traffic_linespeed cannot run together.\033[0m"
|
||||
}
|
||||
|
||||
# === Argument parsing ========================================================
|
||||
blanton_tr518_thermal() {
|
||||
local sub="${1:-help}"; shift 2>/dev/null
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-u|--unit)
|
||||
case "$2" in
|
||||
all|ALL) TR_UNITS="0 1" ;;
|
||||
*) TR_UNITS="$(echo "$2" | tr ',' ' ')" ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-w|--wait) TR_SETTLE_SEC="$2"; shift 2 ;;
|
||||
--no-wait) TR_NO_WAIT=1; shift ;;
|
||||
-d|--debug) DEBUG_MODE=1; shift ;;
|
||||
-n|--dry-run) TR_DRY_RUN=1; shift ;;
|
||||
-h|--help) blanton_tr518_thermal_help; return 0 ;;
|
||||
*) _tr_err "unknown option '$1'"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$sub" in
|
||||
start) blanton_tr518_thermal_start ;;
|
||||
stop) blanton_tr518_thermal_stop ;;
|
||||
help|-h|--help) blanton_tr518_thermal_help ;;
|
||||
*) _tr_err "unknown subcommand '$sub'"; blanton_tr518_thermal_help; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run when executed, define-only when sourced (same as the other blanton_*.sh).
|
||||
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||
blanton_tr518_thermal "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user