From 957eda3ab4f8fc79192694b226d4d51c9994a67d Mon Sep 17 00:00:00 2001 From: ETWen Date: Thu, 12 Nov 2026 20:35:58 +0800 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_0131orciRKrejchsuDk6UpXk --- .../Blanton_Script/blanton_tr518_thermal.sh | 320 ++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 src/Script_ABC_Blanton/Blanton_Script/blanton_tr518_thermal.sh diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518_thermal.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518_thermal.sh new file mode 100644 index 0000000..137ded6 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518_thermal.sh @@ -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 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 -> 0 ok, 1 failed +# _tr_bcm_ok -> as above, but if the output contains +# 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" &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 )"; 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 -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 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