From 071244fde1f90c9ab6532b29b576dc1103545500 Mon Sep 17 00:00:00 2001 From: ETWen Date: Mon, 17 Aug 2026 16:32:43 +0800 Subject: [PATCH] feat(traffic): Add SWB loopback line-speed traffic tool Blanton_Script/blanton_traffic_linespeed.sh V0.3.2 drives the whole loopback traffic run from the DUT shell via bcmcmd, for both switch boards (unit 0 and 1): - init : vlan remove 1 pbm=cd, then create/add the 108 loopback pairs (VLAN 30..137, cdN <-> cdN+32) - clear : clear c - show : show c (raw) - start : tx length= VLantag= per VLAN - stop : remove the pairs, optional --destroy - ps : port status of the cabled ports - report: parse the show c MIB_TPOK/MIB_RPOK counters and lay them out one pair per block with a cross-check verdict (cdA.TX == cdB.RX and cdA.RX == cdB.TX), PASS green / FAIL red / NA yellow, --tolerance for snapshot skew, --tsv, --raw and -f for offline analysis; the raw capture is kept under /tmp - run : ps -> init -> clear -> start -> report Options -u/-c/-l/-p/-T/-d/-n and a sourceable function API, in the style of the other blanton_*.sh tools. Command output matches the former Tera Term macros byte for byte; report output matches tools/bcm_mibpair_report_V1.1.0.py, added here as the off-box equivalent, together with the raw bcmcmd command lists under tools/. ScriptA sources the tool, ScriptB runs ps/init/clear/show/start and drops stress_hhmd and stress_pcie, ScriptC stops the traffic and prints the pair counter report. --- src/Script_ABC_Blanton/1_Blanton_Script_A.ttl | 11 +- src/Script_ABC_Blanton/2_Blanton_Script_B.ttl | 31 +- src/Script_ABC_Blanton/3_Blanton_Script_C.ttl | 14 +- .../blanton_traffic_linespeed.sh | 729 ++++++++++++++++++ tools/bcm_mibpair_report_V1.1.0.py | 325 ++++++++ tools/traffic_loopback_start.txt | 108 +++ tools/traffic_loopback_vlan_remove.txt | 108 +++ tools/traffic_loopback_vlan_setting.txt | 325 ++++++++ 8 files changed, 1624 insertions(+), 27 deletions(-) create mode 100644 src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh create mode 100644 tools/bcm_mibpair_report_V1.1.0.py create mode 100644 tools/traffic_loopback_start.txt create mode 100644 tools/traffic_loopback_vlan_remove.txt create mode 100644 tools/traffic_loopback_vlan_setting.txt diff --git a/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl b/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl index 5d8d97f..ed09795 100644 --- a/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl +++ b/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl @@ -7,7 +7,14 @@ ; Version History: ; V1.0.0 2026-08-13 Initial Version ; V1.0.1 2026-08-14 Add CLEAR PCIE Error -; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status +; V1.0.2 2026-08-17 utils/setup_pmon.ttl Add Leakage Status +; utils/traffic_loopback_vlan_setting.ttl Created +; utils/traffic_loopback_vlan_remove.ttl Created +; utils/traffic_loopback_start.ttl Created +; ScriptB Remove stress_hhmd, stress_pcie +; Blanton_Script Add blanton_traffic_linespeed.sh +; ScriptB/C Add Traffic Test +; ; ============================================================================= include "config.ttl" @@ -52,6 +59,8 @@ sendln "source ~/Blanton_Script/blanton_icb_vi2c.sh" wait prompt_sonic_root sendln "source ~/Blanton_Script/blanton_pwr_data.sh" wait prompt_sonic_root +sendln "source ~/Blanton_Script/blanton_traffic_linespeed.sh" +wait prompt_sonic_root sendln "source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh" ; ========== CLEAR PCIE Error ========== diff --git a/src/Script_ABC_Blanton/2_Blanton_Script_B.ttl b/src/Script_ABC_Blanton/2_Blanton_Script_B.ttl index 43b4360..a60b710 100644 --- a/src/Script_ABC_Blanton/2_Blanton_Script_B.ttl +++ b/src/Script_ABC_Blanton/2_Blanton_Script_B.ttl @@ -1,13 +1,5 @@ ; ============================================================================= ; Script B for Blanton -; Version : V1.0.2 -; Date : 2026-08-17 -; Author : ETWen -; ============================================================================= -; Version History: -; V1.0.0 2026-08-13 Initial Version -; V1.0.1 2026-08-14 Add AMD CPU STRESS TEST -; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status ; ============================================================================= include "config.ttl" @@ -40,18 +32,10 @@ sendln "python ~/hammer/tools/stress_mem.py &" wait prompt_sonic_root sendln "python ~/hammer/tools/stress_mem.py &" -; ========== I2C, LSB and PCIE read with unlimited loop ========== -wait prompt_sonic_root -sendln "python ~/hammer/tools/stress_hhmd.py &" - ; ========== SSD read/write ========== wait prompt_sonic_root sendln "python ~/hammer/tools/stress_ssd.py &" -; ========== PCIe CPU <- PCIe -> ASIC by dumping portStatus ========== -wait prompt_sonic_root -sendln "python ~/hammer/tools/stress_pcie.py &" - ; ========== USB read/write ========== wait prompt_sonic_root sendln "python ~/hammer/tools/stress_usb.py &" @@ -62,6 +46,21 @@ sendln "jobs" ; ========== Take one round of eye measurement on uplink ports ========== +; ========== Traffic START ========== +wait prompt_sonic_root +sendln "blanton_traffic_linespeed ps -u 0" +wait prompt_sonic_root +sendln "blanton_traffic_linespeed init -u 0" +wait prompt_sonic_root +sendln "blanton_traffic_linespeed clear -u 0" +wait prompt_sonic_root +pause 3 +sendln "blanton_traffic_linespeed show -u 0" +wait prompt_sonic_root +sendln "blanton_traffic_linespeed start -u 0" + + + ; ========== Get data every 10mins ========== while 1 include "utils/setup_pmon.ttl" diff --git a/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl b/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl index bcba1df..62f9a75 100644 --- a/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl +++ b/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl @@ -1,13 +1,5 @@ ; ============================================================================= ; Script C for Blanton -; Version : V1.0.2 -; Date : 2026-08-17 -; Author : ETWen -; ============================================================================= -; Version History: -; V1.0.0 2026-08-13 Initial Version -; V1.0.1 2026-08-14 Add Check PCIE error counters,CHECK Stress results -; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status ; ============================================================================= include "config.ttl" @@ -40,8 +32,10 @@ wait prompt_sonic_root sendln "cat ~/hammer/tools/log.stress_ssd" ; ========== CHECK Traffic counters ========== - ;wait prompt_sonic_root - ;sendln "command" +wait prompt_sonic_root +sendln "blanton_traffic_linespeed stop -u 0" +wait prompt_sonic_root +sendln "blanton_traffic_linespeed report -u 0" messagebox 'GOOD JOB! Test Case DONE' 'teraterm' \ No newline at end of file diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh new file mode 100644 index 0000000..23b3617 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh @@ -0,0 +1,729 @@ +#!/usr/bin/env bash +# ============================================================================= +# blanton_traffic_linespeed.sh -- SWB loopback line-speed traffic via bcmcmd +# ============================================================================= +# Version History: +# V0.1.0 2026-08-17 First version. Bash port of the three Tera Term macros +# utils/traffic_loopback_vlan_setting.ttl (VLAN 30..137, +# port pair cdN <-> cdN+32), utils/traffic_loopback_start.ttl +# (tx 100 length=512 VLantag=) and +# utils/traffic_loopback_vlan_remove.ttl. +# One DUT = two switch boards -> bcmcmd unit 0 and 1 +# (bcmcmd -n ), default both. +# V0.2.0 2026-08-17 Add: 'ps' (port status) subcommand -- 'ps ' with +# the cabled-port list as default ($TL_PS_PORTS), -p/--ports +# to override (or a bare port list after 'ps'), 'ps -p all' +# for every port. 'run' now shows port status first. +# V0.3.0 2026-08-17 Add: 'report' subcommand -- runs 'show c', keeps the raw +# log, and renders the MIB_TPOK/MIB_RPOK counters as a +# loopback-pair table with a PASS/FAIL cross-check +# (cdA.TX==cdB.RX and cdA.RX==cdB.TX), i.e. an on-DUT awk +# port of tools/bcm_mibpair_report_V1.1.0.py (same layout, +# same verdict rules, same summary lines, exit 2 on +# FAIL/NA). Options -T/-a/-g/-P/-q/--tsv/--raw and +# -f to re-parse a captured console log offline. +# 'run' now ends with 'report' instead of a raw 'show c'. +# V0.3.1 2026-08-17 Fix: only the FIRST VLAN was configured -- bcmcmd inherited +# the while-loop's stdin (the pair-list here-string) and ate +# the remaining lines, so 'read' hit EOF after one pass. +# bcmcmd now always runs with per-pair +# # TX/RX table + PASS/FAIL +# ./blanton_traffic_linespeed.sh run # ps -> 1 -> 2 -> 4 -> report +# +# Usage (sourced, like the other blanton_*.sh tools): +# source blanton_traffic_linespeed.sh +# blanton_traffic_linespeed init -u 1 -d +# +# Options (any order, after the subcommand): +# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TL_UNITS ("0 1") +# -c|--count tx packet count (default $TL_TX_COUNT) +# -l|--length tx packet length (default $TL_TX_LENGTH) +# -p|--ports ps: port list ('all' = plain 'ps', every port) +# -T|--tolerance report: allowed |delta| in packets (default 0; +# -T 1 absorbs the normal snapshot skew) +# -a|--all report: also list pairs that have no counters +# -g|--grouped report: comma-group the values (1,234,567) +# -P|--with-port report: render cd1(2) instead of cd1 +# -q|--quiet report: drop the trailing summary comments +# --tsv report: tab-separated (paste into Excel) +# --raw report: also print the raw 'show c' output +# --color|--no-color report: force / disable PASS-green FAIL-red colours +# (default: colour only when stdout is a terminal) +# -f|--file report: parse a saved console log, do not touch DUT +# -d|--debug print every bcmcmd before running it +# -n|--dry-run print commands only, do not touch the DUT +# --destroy stop: also 'vlan destroy ' after removing members +# -h|--help help +# +# Environment overrides: +# BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=100 TL_TX_LENGTH=512 +# TL_PS_PORTS="1-24,40-96,..." TL_TOLERANCE=0 TL_LOG_DIR=/tmp +# DEBUG_MODE=1 +# +# Related: tools/bcm_mibpair_report_V1.1.0.py -- same report off-box (python3, +# richer options). 'report' is the awk equivalent so it runs on the SONiC DUT +# itself; both accept the same captured 'show c' log. +# ============================================================================= + +# === Config ================================================================== +BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}" +TL_UNITS="${TL_UNITS:-0 1}" # one DUT = two switch boards (0 and 1) +TL_TX_COUNT="${TL_TX_COUNT:-100}" +TL_TX_LENGTH="${TL_TX_LENGTH:-512}" +TL_DEFAULT_VLAN="${TL_DEFAULT_VLAN:-1}" +TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}" + +# 'ps' port list: the cabled ports of the loopback harness, in bcm logical-port +# numbering (NOT the cdN names used by vlan add). Kept as one string so it can be +# pasted straight from/into a manual "bcmcmd -n 0 -c 'ps '". +TL_PS_PORTS="${TL_PS_PORTS:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}" + +# --- report (pair cross-check) defaults ------------------------------------- +TL_TOLERANCE="${TL_TOLERANCE:-0}" # allowed |delta| in packets before FAIL +TL_LOG_DIR="${TL_LOG_DIR:-/tmp}" # where the raw 'show c' capture is kept +TL_REPORT_ALL=${TL_REPORT_ALL:-0} +TL_REPORT_GROUPED=${TL_REPORT_GROUPED:-0} +TL_REPORT_WITHPORT=${TL_REPORT_WITHPORT:-0} +TL_REPORT_QUIET=${TL_REPORT_QUIET:-0} +TL_REPORT_TSV=${TL_REPORT_TSV:-0} +TL_REPORT_RAW=${TL_REPORT_RAW:-0} +TL_REPORT_FILE="" # -f : parse this instead of the DUT +TL_COLOR="${TL_COLOR:-auto}" # auto|always|never -- PASS green / FAIL red / NA yellow + +# Debug / dry-run (1 = on). DEBUG_MODE is shared with blanton_fpga_pcimem.sh. +DEBUG_MODE=${DEBUG_MODE:-0} +TL_DRY_RUN=${TL_DRY_RUN:-0} +TL_DESTROY=${TL_DESTROY:-0} + +# === VLAN <-> loopback port pair table (from traffic_loopback_vlan_setting.ttl) == +# format: +TL_PAIRS="\ +30 cd0 cd32 +31 cd1 cd33 +32 cd2 cd34 +33 cd3 cd35 +34 cd4 cd36 +35 cd5 cd37 +36 cd6 cd38 +37 cd7 cd39 +38 cd8 cd40 +39 cd9 cd41 +40 cd10 cd42 +41 cd11 cd43 +42 cd12 cd44 +43 cd13 cd45 +44 cd14 cd46 +45 cd20 cd52 +46 cd21 cd53 +47 cd22 cd54 +48 cd23 cd55 +49 cd24 cd56 +50 cd25 cd57 +51 cd26 cd58 +52 cd27 cd59 +53 cd28 cd60 +54 cd29 cd61 +55 cd30 cd62 +56 cd31 cd63 +57 cd64 cd96 +58 cd65 cd97 +59 cd66 cd98 +60 cd67 cd99 +61 cd68 cd100 +62 cd69 cd101 +63 cd70 cd102 +64 cd71 cd103 +65 cd72 cd104 +66 cd73 cd105 +67 cd74 cd106 +68 cd75 cd107 +69 cd76 cd108 +70 cd77 cd109 +71 cd78 cd110 +72 cd84 cd116 +73 cd85 cd117 +74 cd86 cd118 +75 cd87 cd119 +76 cd88 cd120 +77 cd89 cd121 +78 cd90 cd122 +79 cd91 cd123 +80 cd92 cd124 +81 cd93 cd125 +82 cd94 cd126 +83 cd95 cd127 +84 cd128 cd160 +85 cd129 cd161 +86 cd130 cd162 +87 cd131 cd163 +88 cd132 cd164 +89 cd133 cd165 +90 cd134 cd166 +91 cd135 cd167 +92 cd136 cd168 +93 cd137 cd169 +94 cd138 cd170 +95 cd140 cd172 +96 cd141 cd173 +97 cd142 cd174 +98 cd143 cd175 +99 cd144 cd176 +100 cd145 cd177 +101 cd146 cd178 +102 cd147 cd179 +103 cd152 cd184 +104 cd153 cd185 +105 cd154 cd186 +106 cd155 cd187 +107 cd156 cd188 +108 cd157 cd189 +109 cd158 cd190 +110 cd159 cd191 +111 cd192 cd224 +112 cd193 cd225 +113 cd194 cd226 +114 cd195 cd227 +115 cd196 cd228 +116 cd197 cd229 +117 cd198 cd230 +118 cd199 cd231 +119 cd200 cd232 +120 cd201 cd233 +121 cd202 cd234 +122 cd204 cd236 +123 cd205 cd237 +124 cd206 cd238 +125 cd207 cd239 +126 cd208 cd240 +127 cd209 cd241 +128 cd210 cd242 +129 cd211 cd243 +130 cd216 cd248 +131 cd217 cd249 +132 cd218 cd250 +133 cd219 cd251 +134 cd220 cd252 +135 cd221 cd253 +136 cd222 cd254 +137 cd223 cd255" + +# === Logging ================================================================= +_tl_info() { echo -e "[\033[34mINFO\033[0m] $*"; } +_tl_ok() { echo -e "[\033[32m OK \033[0m] $*"; } +_tl_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; } +_tl_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; } +_tl_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; } + +traffic_debug() { + if [ "${1:-}" = "on" ]; then DEBUG_MODE=1 + elif [ "${1:-}" = "off" ]; then DEBUG_MODE=0 + else [ "$DEBUG_MODE" = "0" ] && DEBUG_MODE=1 || DEBUG_MODE=0; fi + _tl_info "DEBUG_MODE=$DEBUG_MODE" +} + +# === bcmcmd wrapper ========================================================== +# IMPORTANT: bcmcmd is always run with stdin closed ( -- streams the DUT output, returns bcmcmd rc +# Debug mode prints the full command line first; dry-run prints and skips it. +_tl_bcm() { + local unit="$1"; shift + local cmd="$*" + _tl_dbg "$BCMCMD_CMD -n $unit -c '$cmd'" + if [ "$TL_DRY_RUN" = "1" ]; then + echo "[DRY ] $BCMCMD_CMD -n $unit -c '$cmd'" + return 0 + fi + "$BCMCMD_CMD" -n "$unit" -c "$cmd" +# 0 = ok, 2 = failed but benign (matches benign_regex), 1 = real failure +# Output is captured (shown in debug mode, or on a real failure) so the ~110 +# vlan create/add lines do not flood the console. +_tl_bcm_run() { + local unit="$1" benign="$2"; shift 2 + local cmd="$*" out rc + if [ "$TL_DRY_RUN" = "1" ]; then _tl_bcm "$unit" "$cmd" >/dev/null; return 0; fi + _tl_dbg "$BCMCMD_CMD -n $unit -c '$cmd'" + out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" &1); rc=$? + [ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out" + if [ "$rc" -ne 0 ] || echo "$out" | grep -qiE "$TL_ERR_PAT"; then + if [ -n "$benign" ] && echo "$out" | grep -qiE "$benign"; then + _tl_dbg "benign: unit $unit '$cmd'" + return 2 + fi + _tl_err "unit $unit: '$cmd' rc=$rc" + [ "$DEBUG_MODE" != "1" ] && [ -n "$out" ] && echo "$out" >&2 + return 1 + fi + return 0 +} + +# _tl_bcm_q -- _tl_bcm_run with no benign pattern +_tl_bcm_q() { local unit="$1"; shift; _tl_bcm_run "$unit" "" "$@"; } + +_tl_units_check() { + local u + for u in $TL_UNITS; do + case "$u" in + 0|1) ;; + *) _tl_err "invalid unit '$u' (expect 0 or 1)"; return 1 ;; + esac + done + if [ "$TL_DRY_RUN" != "1" ] && ! command -v "$BCMCMD_CMD" >/dev/null 2>&1; then + _tl_err "$BCMCMD_CMD not found in PATH (run on the SONiC DUT, or set BCMCMD_CMD)" + return 1 + fi + return 0 +} + +_tl_pair_count() { echo "$TL_PAIRS" | grep -c . ; } + +# === Step 1: VLAN loopback setup (traffic_loopback_vlan_setting.ttl) ========= +traffic_linespeed_init() { + _tl_units_check || return 1 + local unit vid pa pb n fail exist rc + for unit in $TL_UNITS; do + n=0; fail=0; exist=0 + _tl_info "unit $unit: VLAN loopback setup ($(_tl_pair_count) pairs, VLAN 30..137)" + _tl_bcm_q "$unit" "vlan remove $TL_DEFAULT_VLAN pbm=$TL_DEFAULT_VLAN_PBM" \ + || _tl_warn "unit $unit: clearing default VLAN $TL_DEFAULT_VLAN membership failed (continuing)" + # read on fd 3: bcmcmd must not be able to consume the pair list + while read -r vid pa pb <&3; do + [ -z "$vid" ] && continue + _tl_bcm_run "$unit" "$TL_BENIGN_CREATE" "vlan create $vid"; rc=$? + [ "$rc" = "1" ] && fail=$((fail+1)) + [ "$rc" = "2" ] && exist=$((exist+1)) + _tl_bcm_q "$unit" "vlan add $vid pbm=$pa,$pb" || fail=$((fail+1)) + n=$((n+1)) + done 3<<< "$TL_PAIRS" + if [ "$fail" -eq 0 ]; then + _tl_ok "unit $unit: $n VLANs configured$([ "$exist" -gt 0 ] && echo " ($exist already existed)"), port pairs added" + else + _tl_warn "unit $unit: $n VLANs processed, $fail command(s) failed$([ "$exist" -gt 0 ] && echo ", $exist already existed")" + fi + done +} + +# === Step 2: clear counters ================================================== +traffic_linespeed_clear() { + _tl_units_check || return 1 + local unit + for unit in $TL_UNITS; do + _tl_info "unit $unit: clear c" + _tl_bcm "$unit" "clear c" || { _tl_err "unit $unit: clear c failed"; return 1; } + _tl_ok "unit $unit: counters cleared" + done +} + +# === Step 3 / 6: show counters ============================================== +traffic_linespeed_show() { + _tl_units_check || return 1 + local unit + for unit in $TL_UNITS; do + echo "----- unit $unit : show c -----" + _tl_bcm "$unit" "show c" || { _tl_err "unit $unit: show c failed"; return 1; } + done +} + +# === Step 4: start traffic (traffic_loopback_start.ttl) ===================== +traffic_linespeed_start() { + _tl_units_check || return 1 + local unit vid pa pb n fail + for unit in $TL_UNITS; do + n=0; fail=0 + _tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH per VLAN 30..137" + while read -r vid pa pb <&3; do + [ -z "$vid" ] && continue + _tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid" || fail=$((fail+1)) + n=$((n+1)) + done 3<<< "$TL_PAIRS" + if [ "$fail" -eq 0 ]; then + _tl_ok "unit $unit: $n bursts sent ($((n * TL_TX_COUNT)) packets, ${TL_TX_LENGTH}B each)" + else + _tl_warn "unit $unit: $n bursts attempted, $fail failed" + fi + done +} + +# === Step 5: stop traffic (traffic_loopback_vlan_remove.ttl) ================ +traffic_linespeed_stop() { + _tl_units_check || return 1 + local unit vid pa pb n fail + for unit in $TL_UNITS; do + n=0; fail=0 + _tl_info "unit $unit: removing loopback port pairs from VLAN 30..137" + while read -r vid pa pb <&3; do + [ -z "$vid" ] && continue + _tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan remove $vid pbm=$pa,$pb" + [ "$?" = "1" ] && fail=$((fail+1)) + if [ "$TL_DESTROY" = "1" ]; then + _tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan destroy $vid" + [ "$?" = "1" ] && fail=$((fail+1)) + fi + n=$((n+1)) + done 3<<< "$TL_PAIRS" + if [ "$fail" -eq 0 ]; then + _tl_ok "unit $unit: $n VLANs cleaned$([ "$TL_DESTROY" = "1" ] && echo " and destroyed")" + else + _tl_warn "unit $unit: $n VLANs processed, $fail command(s) failed" + fi + done +} + +# === Port status: ps ============================================= +# 'ps' shows link / speed / duplex / flow-control per port. Default list is the +# cabled ports ($TL_PS_PORTS); 'all' (or empty) runs a bare 'ps' = every port. +traffic_linespeed_ps() { + _tl_units_check || return 1 + local unit cmd="ps" + case "${TL_PS_PORTS:-all}" in + all|ALL|"") cmd="ps" ;; + *) cmd="ps $TL_PS_PORTS" ;; + esac + for unit in $TL_UNITS; do + echo "----- unit $unit : $cmd -----" + _tl_bcm "$unit" "$cmd" || { _tl_err "unit $unit: $cmd failed"; return 1; } + done +} + +# === Report: show c -> per-pair TX/RX table + PASS/FAIL ===================== +# Mirrors tools/bcm_mibpair_report_V1.1.0.py, in awk so it runs on the DUT. +# +# Parses MIB_TPOK.cd1(2) : 723,629,081,133 +723,629,081,133 +# MIB_RPOK.cd1(2) : 581,693,309,458 +581,693,309,458 +# Verdict per pair: cdA.TPOK == cdB.RPOK and cdA.RPOK == cdB.TPOK +# PASS within tolerance / FAIL outside / NA when counters are missing +# (a cd port absent from 'show c' means the counter is zero or the +# console scrolled -- cross-check with 'ps' before blaming the port). +# _tl_pair_report -> 0 all PASS, 2 any FAIL/NA, 1 parse error +_tl_pair_report() { + local log="$1" color=0 + # PASS green / FAIL red / NA yellow. auto = only when stdout is a terminal, + # so redirecting to a file or piping into grep/diff stays plain text. + case "$TL_COLOR" in + always|1|yes) color=1 ;; + never|0|no) color=0 ;; + *) [ -t 1 ] && color=1 ;; + esac + [ "$TL_REPORT_TSV" = "1" ] && color=0 + awk -v PAIRS="$TL_PAIRS" \ + -v TOL="$TL_TOLERANCE" \ + -v ALL="$TL_REPORT_ALL" \ + -v GROUPED="$TL_REPORT_GROUPED" \ + -v WITHPORT="$TL_REPORT_WITHPORT" \ + -v QUIET="$TL_REPORT_QUIET" \ + -v TSV="$TL_REPORT_TSV" \ + -v COLOR="$color" ' + function grp(v, s,out,l,i) { + s = sprintf("%d", v) + if (!GROUPED) return s + out = ""; l = length(s) + for (i = 1; i <= l; i++) { + out = out substr(s, i, 1) + if (((l - i) % 3) == 0 && i < l) out = out "," + } + return out + } + function pname(cd) { return (WITHPORT && (cd in LP)) ? cd "(" LP[cd] ")" : cd } + function absd(x) { return (x < 0) ? -x : x } + # colour the verdict token: PASS green, FAIL red, NA yellow + function vc(v) { + if (!COLOR) return v + if (v == "PASS") return "\033[32m" v "\033[0m" + if (v == "FAIL") return "\033[31m" v "\033[0m" + return "\033[33m" v "\033[0m" + } + function redl(s) { return COLOR ? "\033[31m" s "\033[0m" : s } + + BEGIN { + NP = split(PAIRS, L, "\n") + for (i = 1; i <= NP; i++) { split(L[i], f, " "); VID[i] = f[1]; A[i] = f[2]; B[i] = f[3] } + MISSING = "-" + } + { + idx = index($0, "MIB_") + if (idx == 0) next + s = substr($0, idx) + kind = substr(s, 5, 4) + if (kind != "TPOK" && kind != "RPOK") next + p1 = index(s, "."); p2 = index(s, "("); p3 = index(s, ")"); p4 = index(s, ":") + if (p1 == 0 || p2 == 0 || p3 == 0 || p4 == 0 || p2 < p1 || p4 < p3) next + cd = substr(s, p1 + 1, p2 - p1 - 1) + if (cd !~ /^cd[0-9]+$/) next + lp = substr(s, p2 + 1, p3 - p2 - 1) + val = substr(s, p4 + 1) + sub(/^[ \t]+/, "", val) + if (val !~ /^[0-9,]/) next + sub(/[ \t].*$/, "", val) + gsub(/,/, "", val) + LP[cd] = lp + if (kind == "TPOK") { TX[cd] = val + 0; HTX[cd] = 1 } else { RX[cd] = val + 0; HRX[cd] = 1 } + seen++ + } + END { + if (seen == 0) { + print "error: no MIB_TPOK/MIB_RPOK counter found in the log" > "/dev/stderr" + exit 1 + } + npass = nfail = nna = 0; nrow = 0; nrep = 0; miss = ""; nf = 0 + for (i = 1; i <= NP; i++) { + a = A[i]; b = B[i] + oka = (a in HTX) && (a in HRX); okb = (b in HTX) && (b in HRX) + if (!(oka && okb)) { + v = "NA"; nna++ + miss = miss (miss == "" ? "" : " ") a "/" b + if (!ALL) continue + ta = oka ? grp(TX[a]) : MISSING; ra = oka ? grp(RX[a]) : MISSING + tb = okb ? grp(TX[b]) : MISSING; rb = okb ? grp(RX[b]) : MISSING + } else { + dtx = TX[a] - RX[b]; drx = RX[a] - TX[b] + d = absd(dtx); if (absd(drx) > d) d = absd(drx) + if (d <= TOL + 0) { v = "PASS"; npass++ } + else { + v = "FAIL"; nfail++ + FL[++nf] = sprintf("# FAIL %s/%s: %s.TX-%s.RX=%+d %s.RX-%s.TX=%+d", \ + a, b, a, b, dtx, a, b, drx) + } + ta = grp(TX[a]); ra = grp(RX[a]); tb = grp(TX[b]); rb = grp(RX[b]) + } + nrep++ + nrow++; C0[nrow] = pname(a); C1[nrow] = ta; C2[nrow] = ra; C3[nrow] = v + nrow++; C0[nrow] = pname(b); C1[nrow] = tb; C2[nrow] = rb; C3[nrow] = v + } + + H0 = "Port"; H1 = "TX"; H2 = "RX"; H3 = "PASS/FAIL" + if (TSV) { + print H0 "\t" H1 "\t" H2 "\t" H3 + for (r = 1; r <= nrow; r++) print C0[r] "\t" C1[r] "\t" C2[r] "\t" C3[r] + } else { + w0 = length(H0); w1 = length(H1); w2 = length(H2); w3 = length(H3) + for (r = 1; r <= nrow; r++) { + if (length(C0[r]) > w0) w0 = length(C0[r]) + if (length(C1[r]) > w1) w1 = length(C1[r]) + if (length(C2[r]) > w2) w2 = length(C2[r]) + if (length(C3[r]) > w3) w3 = length(C3[r]) + } + w0 += 2; w1 += 2; w2 += 2; w3 += 2 + printf "%-*s%*s%*s%*s\n", w0, H0, w1, H1, w2, H2, w3, H3 + for (r = 1; r <= nrow; r++) { + # pad on the plain text, then colour, so the columns stay aligned + printf "%-*s%*s%*s", w0, C0[r], w1, C1[r], w2, C2[r] + printf "%*s%s\n", w3 - length(C3[r]), "", vc(C3[r]) + } + } + + if (!QUIET) { + print "" + printf "# pairs in table : %d\n", NP + printf "# pairs reported : %d\n", nrep + printf "# %s %d %s %d %s %d (tolerance %d)\n", \ + vc("PASS"), npass, vc("FAIL"), nfail, vc("NA"), nna, TOL + 0 + if (miss != "") printf "# %s (no counters): %s\n", vc("NA"), miss + for (i = 1; i <= nf; i++) print redl(FL[i]) + } + exit (nfail || nna) ? 2 : 0 + }' "$log" +} + +# traffic_linespeed_report -- 'show c' per unit, keep the raw log, render the table +traffic_linespeed_report() { + local unit log rc worst=0 stamp + # -f : offline mode, no DUT access, no unit loop + if [ -n "$TL_REPORT_FILE" ]; then + [ -r "$TL_REPORT_FILE" ] || { _tl_err "cannot read log '$TL_REPORT_FILE'"; return 1; } + _tl_info "report from log: $TL_REPORT_FILE (tolerance $TL_TOLERANCE)" + _tl_pair_report "$TL_REPORT_FILE"; return $? + fi + + _tl_units_check || return 1 + if [ "$TL_DRY_RUN" = "1" ]; then + for unit in $TL_UNITS; do _tl_bcm "$unit" "show c" >/dev/null; done + return 0 + fi + + stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now) + for unit in $TL_UNITS; do + log="$TL_LOG_DIR/showc_unit${unit}_${stamp}.log" + if ! _tl_bcm "$unit" "show c" > "$log" 2>&1; then + _tl_err "unit $unit: show c failed (see $log)"; return 1 + fi + [ "$TL_REPORT_RAW" = "1" ] && { echo "----- unit $unit : raw show c -----"; cat "$log"; } + echo "===== unit $unit : loopback pair counter report (raw: $log) =====" + _tl_pair_report "$log"; rc=$? + [ "$rc" -gt "$worst" ] && worst=$rc + case "$rc" in + 0) _tl_ok "unit $unit: all pairs PASS" ;; + 2) _tl_warn "unit $unit: at least one pair FAIL/NA" ;; + *) _tl_err "unit $unit: report parse error" ;; + esac + done + return "$worst" +} + +# === Convenience: full sequence ps -> 1 -> 2 -> 4 -> report ================== +traffic_linespeed_run() { + traffic_linespeed_ps || return 1 + traffic_linespeed_init || return 1 + traffic_linespeed_clear || return 1 + traffic_linespeed_start || return 1 + traffic_linespeed_report + local rc=$? + _tl_info "traffic done. 'stop' removes the loopback VLAN membership." + return $rc +} + +# === Help ==================================================================== +blanton_traffic_linespeed_help() { + echo -e "\033[1mblanton_traffic_linespeed.sh - SWB loopback line-speed traffic (bcmcmd)\033[0m" + echo "" + echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m" + echo -e " VLANs: 30..137 ($(_tl_pair_count) loopback pairs, cdN <-> cdN+32)" + echo "" + echo -e "\033[1mSubcommands\033[0m" + echo -e " \033[33minit\033[0m step 1 vlan remove 1 pbm=cd, vlan create/add each pair" + echo -e " \033[33mclear\033[0m step 2 clear c" + echo -e " \033[33mshow\033[0m step 3/6 show c (run before and after traffic)" + echo -e " \033[33mstart\033[0m step 4 tx length= VLantag= per VLAN" + echo -e " \033[33mstop\033[0m step 5 vlan remove pbm= [--destroy also destroys]" + echo -e " \033[33mps\033[0m ps port status (link/speed) of the cabled ports" + echo -e " \033[33mreport\033[0m show c -> per-pair TX/RX table + PASS/FAIL cross-check" + echo -e " \033[33mrun\033[0m ps -> init -> clear -> start -> report" + 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: $TL_UNITS)" + echo -e " \033[33m-c|--count\033[0m tx packet count (default $TL_TX_COUNT)" + echo -e " \033[33m-l|--length\033[0m tx packet length (default $TL_TX_LENGTH)" + echo -e " \033[33m-p|--ports\033[0m ps port list, or 'all' for every port" + echo -e " \033[33m-T|--tolerance\033[0m report: allowed |delta| pkts (default $TL_TOLERANCE; -T 1 = snapshot skew)" + echo -e " \033[33m-a|--all\033[0m report: also list pairs with no counters" + echo -e " \033[33m-g|--grouped\033[0m report: comma-group values" + echo -e " \033[33m-P|--with-port\033[0m report: render cd1(2) instead of cd1" + echo -e " \033[33m-q|--quiet\033[0m report: no trailing summary" + echo -e " \033[33m--tsv\033[0m report: tab-separated (Excel)" + echo -e " \033[33m--raw\033[0m report: also dump the raw 'show c'" + echo -e " \033[33m--color|--no-color\033[0m report: force/disable \033[32mPASS\033[0m / \033[31mFAIL\033[0m / \033[33mNA\033[0m colouring" + echo -e " (default: colour only when stdout is a terminal)" + echo -e " \033[33m-f|--file\033[0m report: parse a saved log, no DUT access" + echo -e " \033[33m-d|--debug\033[0m print every bcmcmd command line (stderr) and run it" + echo -e " \033[33m-n|--dry-run\033[0m print commands only, do not touch the DUT" + echo -e " \033[33m--destroy\033[0m stop: also 'vlan destroy' each VLAN" + echo "" + echo -e "\033[1mExamples\033[0m" + echo -e " blanton_traffic_linespeed ps -u 0" + echo -e " blanton_traffic_linespeed init -u 1" + echo -e " blanton_traffic_linespeed clear && blanton_traffic_linespeed start" + echo -e " blanton_traffic_linespeed report -u 1 -T 1" + echo -e " blanton_traffic_linespeed report -u 1 -q | grep -v PASS" + echo -e " blanton_traffic_linespeed report -f /tmp/showc_unit1_*.log -a" + echo -e " blanton_traffic_linespeed show -u 1 | grep -iE 'error|discard|drop'" + echo -e " blanton_traffic_linespeed start -c 1000 -l 9216 -d" + echo -e " blanton_traffic_linespeed stop --destroy" + echo "" + echo -e " report exit code: 0 = all pairs PASS, 2 = any FAIL/NA, 1 = parse error" + echo -e " Off-box equivalent: tools/bcm_mibpair_report_V1.1.0.py (python3)" + echo -e " ps ports: \033[36m$TL_PS_PORTS\033[0m" + echo -e " Table mirrors utils/traffic_loopback_vlan_{setting,remove}.ttl and" + echo -e " utils/traffic_loopback_start.ttl - keep them in sync." +} + +# === Dispatcher ============================================================== +blanton_traffic_linespeed() { + local sub="${1:-help}"; shift 2>/dev/null || true + while [ $# -gt 0 ]; do + case "$1" in + -u|--unit) + case "$2" in + all|both|*,*) TL_UNITS=$(echo "$2" | sed 's/all\|both/0 1/; s/,/ /g') ;; + *) TL_UNITS="$2" ;; + esac + shift 2 ;; + -c|--count) TL_TX_COUNT="$2"; shift 2 ;; + -l|--length) TL_TX_LENGTH="$2"; shift 2 ;; + -p|--ports) TL_PS_PORTS="$2"; shift 2 ;; + -T|--tolerance) TL_TOLERANCE="$2"; shift 2 ;; + -f|--file) TL_REPORT_FILE="$2"; shift 2 ;; + -a|--all) TL_REPORT_ALL=1; shift ;; + -g|--grouped) TL_REPORT_GROUPED=1; shift ;; + -P|--with-port) TL_REPORT_WITHPORT=1; shift ;; + -q|--quiet) TL_REPORT_QUIET=1; shift ;; + --tsv) TL_REPORT_TSV=1; shift ;; + --raw) TL_REPORT_RAW=1; shift ;; + --color) TL_COLOR=always; shift ;; + --no-color) TL_COLOR=never; shift ;; + -d|--debug) DEBUG_MODE=1; shift ;; + -n|--dry-run) TL_DRY_RUN=1; shift ;; + --destroy) TL_DESTROY=1; shift ;; + -h|--help) blanton_traffic_linespeed_help; return 0 ;; + -*) _tl_err "unknown option '$1'"; return 1 ;; + *) # bare argument: only meaningful as the 'ps' port list + if [ "$sub" = "ps" ] || [ "$sub" = "status" ]; then + TL_PS_PORTS="$1"; shift + else + _tl_err "unexpected argument '$1'"; return 1 + fi ;; + esac + done + + case "$sub" in + init) traffic_linespeed_init ;; + clear) traffic_linespeed_clear ;; + show) traffic_linespeed_show ;; + start) traffic_linespeed_start ;; + stop) traffic_linespeed_stop ;; + ps|status) traffic_linespeed_ps ;; + report|rpt) traffic_linespeed_report ;; + run|all) traffic_linespeed_run ;; + debug) traffic_debug on ;; + help|-h|--help) blanton_traffic_linespeed_help ;; + *) _tl_err "unknown subcommand '$sub'"; blanton_traffic_linespeed_help; return 1 ;; + esac +} + +# Executed directly -> dispatch. Sourced -> just expose the functions + help. +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + blanton_traffic_linespeed "$@" +else + blanton_traffic_linespeed_help +fi diff --git a/tools/bcm_mibpair_report_V1.1.0.py b/tools/bcm_mibpair_report_V1.1.0.py new file mode 100644 index 0000000..85595d6 --- /dev/null +++ b/tools/bcm_mibpair_report_V1.1.0.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +bcm_mibpair_report_V1.1.0.py + +Author : ETWen +Date : 20260730 + +Purpose : Extract MIB_TPOK / MIB_RPOK counters from a Broadcom drivshell log + and lay them out horizontally, one loopback pair per block: + + Port TX RX PASS/FAIL + cd1 723629081133 581693309458 PASS + cd33 581693309458 723629081133 PASS + + Pair membership and pair order come from the + "vlan remove pbm=cdA,cdB" lines in the same log, so the report + always follows the order the test actually ran in. + + Verdict per pair comes from the loopback cross-check: for a pair, + cdA.TPOK must equal cdB.RPOK and cdA.RPOK must equal cdB.TPOK. + PASS - both directions match (within --tolerance) + FAIL - at least one direction is off; delta is listed in the + trailing summary + NA - the pair has no counters in the log + +Usage : ./bcm_mibpair_report_V1.1.0.py [options] + + -a, --all also emit pairs that have no counters in the log + (values shown as "-") + -b, --block repeat the header and blank-separate each pair + -g, --grouped keep the SDK's comma grouping (1,234,567) + -p, --with-port render "cd1(2)" instead of "cd1" + -t, --tsv tab-separated output (for Excel / pandas) + -s, --no-status drop the PASS/FAIL column + -T, --tolerance N allowed |delta| in packets before a pair is FAIL + (default 0). A +/-1 skew is normal: the SDK reads + counters port-by-port while traffic still runs, so + -T 1 is a reasonable production setting. + -q, --quiet suppress the trailing summary comments + -o, --output write to a file instead of stdout + +Notes : - The trailing "+delta" column printed by the SDK is stripped. + - A cd port missing from the dump usually means the console + scrolled or auto-logged out mid-"show c", NOT that the port was + down. Cross-check against "ps" before drawing conclusions. + - A +/-1 packet delta between a pair is normal snapshot skew: the + SDK reads counters port-by-port while traffic is still running. + +Exit : 0 = every pair had counters and cross-checked clean + 1 = usage / input error + 2 = at least one pair is FAIL or NA (see summary) + +Version History +V1.0.0 20260730 Initial Version (parity with bcm_mibpair_report_V1.2.0.sh) +V1.0.1 20260730 Handle BrokenPipeError quietly when piped into head +V1.1.0 20260730 Add PASS/FAIL/NA verdict column and --tolerance +""" + +from __future__ import annotations + +import argparse +import re +import sys +from dataclasses import dataclass, field +from pathlib import Path +from typing import Iterable, TextIO + +EXIT_OK = 0 +EXIT_USAGE = 1 +EXIT_WARN = 2 + +# "vlan remove 31 pbm=cd1,cd33" +RE_PBM = re.compile(r"pbm=(cd\d+),(cd\d+)") + +# "MIB_TPOK.cd1(2) : 723,629,081,133 +723,629,081,133" +RE_MIB = re.compile( + r"^MIB_(?PTPOK|RPOK)\.(?Pcd\d+)\((?P\d+)\)\s*:\s*(?P[\d,]+)" +) + +MISSING = "-" + + +@dataclass +class PortCounters: + """TPOK / RPOK for a single cd port.""" + + lport: int | None = None + tx: int | None = None + rx: int | None = None + + @property + def complete(self) -> bool: + return self.tx is not None and self.rx is not None + + +@dataclass +class LogData: + """Everything the report needs, extracted from one drivshell log.""" + + pairs: list[tuple[str, str]] = field(default_factory=list) + ports: dict[str, PortCounters] = field(default_factory=dict) + + def counters(self, cd: str) -> PortCounters: + return self.ports.setdefault(cd, PortCounters()) + + +def parse_log(lines: Iterable[str]) -> LogData: + """Pull pbm pair definitions and TPOK/RPOK counters out of a drivshell log.""" + data = LogData() + seen_pairs: set[tuple[str, str]] = set() + + for raw in lines: + line = raw.rstrip("\r\n") + + for a, b in RE_PBM.findall(line): + if (a, b) not in seen_pairs: + seen_pairs.add((a, b)) + data.pairs.append((a, b)) + + # drivshell echoes commands, so a MIB line may be prefixed with + # "drivshell>" noise; anchor on the MIB_ token instead of the line start. + idx = line.find("MIB_") + if idx < 0: + continue + m = RE_MIB.match(line[idx:]) + if not m: + continue + + pc = data.counters(m.group("cd")) + pc.lport = int(m.group("lport")) + value = int(m.group("val").replace(",", "")) + if m.group("kind") == "TPOK": + pc.tx = value + else: + pc.rx = value + + return data + + +def fmt_value(value: int | None, grouped: bool) -> str: + if value is None: + return MISSING + return f"{value:,}" if grouped else str(value) + + +def fmt_port(cd: str, pc: PortCounters, with_port: bool) -> str: + if with_port and pc.lport is not None: + return f"{cd}({pc.lport})" + return cd + + +PASS, FAIL, NA = "PASS", "FAIL", "NA" + + +def pair_deltas(data: LogData, a: str, b: str) -> tuple[int, int] | None: + """(cdA.TX - cdB.RX, cdA.RX - cdB.TX), or None if counters are missing.""" + pa, pb = data.counters(a), data.counters(b) + if not (pa.complete and pb.complete): + return None + return pa.tx - pb.rx, pa.rx - pb.tx + + +def verdict(data: LogData, a: str, b: str, tolerance: int) -> str: + d = pair_deltas(data, a, b) + if d is None: + return NA + return PASS if max(abs(d[0]), abs(d[1])) <= tolerance else FAIL + + +def render(data: LogData, args: argparse.Namespace, out: TextIO) -> int: + status = not args.no_status + rows: list[tuple[str, ...]] = [] + blocks: list[list[tuple[str, ...]]] = [] + missing: list[tuple[str, str]] = [] + failed: list[tuple[str, str, int, int]] = [] + tally = {PASS: 0, FAIL: 0, NA: 0} + + for a, b in data.pairs: + pa, pb = data.counters(a), data.counters(b) + v = verdict(data, a, b, args.tolerance) + tally[v] += 1 + if v == NA: + missing.append((a, b)) + if not args.all: + continue + elif v == FAIL: + d_tx, d_rx = pair_deltas(data, a, b) + failed.append((a, b, d_tx, d_rx)) + + block = [] + for cd, pc in ((a, pa), (b, pb)): + row = ( + fmt_port(cd, pc, args.with_port), + fmt_value(pc.tx, args.grouped), + fmt_value(pc.rx, args.grouped), + ) + block.append(row + (v,) if status else row) + blocks.append(block) + rows.extend(block) + + header = ("Port", "TX", "RX", "PASS/FAIL") if status else ("Port", "TX", "RX") + + if args.tsv: + if not args.block: + print("\t".join(header), file=out) + for block in blocks: + if args.block: + print("\t".join(header), file=out) + for row in block: + print("\t".join(row), file=out) + if args.block: + print(file=out) + else: + # size columns to the widest cell actually emitted + ncol = len(header) + width = [ + max([len(r[i]) for r in rows] + [len(header[i])]) + 2 + for i in range(ncol) + ] + + def line(row: tuple[str, ...]) -> str: + cells = [f"{row[0]:<{width[0]}}"] + cells += [f"{row[i]:>{width[i]}}" for i in range(1, ncol)] + return "".join(cells).rstrip() + + if not args.block: + print(line(header), file=out) + for block in blocks: + if args.block: + print(line(header), file=out) + for row in block: + print(line(row), file=out) + if args.block: + print(file=out) + + if not args.quiet: + if not args.block: + print(file=out) + print(f"# pairs in pbm list : {len(data.pairs)}", file=out) + print(f"# pairs reported : {len(blocks)}", file=out) + print( + f"# PASS {tally[PASS]} FAIL {tally[FAIL]} NA {tally[NA]}" + f" (tolerance {args.tolerance})", + file=out, + ) + if missing: + joined = " ".join(f"{a}/{b}" for a, b in missing) + print(f"# NA (no counters): {joined}", file=out) + for a, b, d_tx, d_rx in failed: + print( + f"# FAIL {a}/{b}: {a}.TX-{b}.RX={d_tx:+d} {a}.RX-{b}.TX={d_rx:+d}", + file=out, + ) + + return EXIT_WARN if (tally[FAIL] or tally[NA]) else EXIT_OK + + +def build_parser() -> argparse.ArgumentParser: + p = argparse.ArgumentParser( + description="Render Broadcom drivshell MIB_TPOK/RPOK counters as a " + "loopback-pair table.", + epilog="Exit 2 means missing counters and/or a cross-check mismatch.", + ) + p.add_argument("log", type=Path, help="drivshell log file ('-' for stdin)") + p.add_argument("-a", "--all", action="store_true", + help="also emit pairs with no counters") + p.add_argument("-b", "--block", action="store_true", + help="repeat header and blank-separate each pair") + p.add_argument("-g", "--grouped", action="store_true", + help="keep comma grouping in values") + p.add_argument("-p", "--with-port", action="store_true", + help="render cd1(2) instead of cd1") + p.add_argument("-t", "--tsv", action="store_true", + help="tab-separated output") + p.add_argument("-s", "--no-status", action="store_true", + help="drop the PASS/FAIL column") + p.add_argument("-T", "--tolerance", type=int, default=0, metavar="N", + help="allowed |delta| in packets before a pair is FAIL " + "(default 0; -T 1 absorbs normal snapshot skew)") + p.add_argument("-q", "--quiet", action="store_true", + help="suppress trailing summary comments") + p.add_argument("-o", "--output", type=Path, default=None, + help="write to a file instead of stdout") + return p + + +def main(argv: list[str] | None = None) -> int: + args = build_parser().parse_args(argv) + + try: + if str(args.log) == "-": + data = parse_log(sys.stdin) + else: + # console captures are frequently not clean UTF-8 + with args.log.open("r", encoding="utf-8", errors="replace") as fh: + data = parse_log(fh) + except OSError as exc: + print(f"error: cannot read log: {exc}", file=sys.stderr) + return EXIT_USAGE + + if not data.pairs: + print("error: no 'pbm=cdA,cdB' pair definition found in log", + file=sys.stderr) + return EXIT_USAGE + + try: + if args.output: + with args.output.open("w", encoding="utf-8", newline="\n") as fh: + return render(data, args, fh) + return render(data, args, sys.stdout) + except BrokenPipeError: + # downstream closed the pipe (e.g. "| head") - not an error + try: + sys.stdout.close() + except BrokenPipeError: + pass + return EXIT_OK + except OSError as exc: + print(f"error: cannot write output: {exc}", file=sys.stderr) + return EXIT_USAGE + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/traffic_loopback_start.txt b/tools/traffic_loopback_start.txt new file mode 100644 index 0000000..35724f2 --- /dev/null +++ b/tools/traffic_loopback_start.txt @@ -0,0 +1,108 @@ +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=30' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=31' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=32' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=33' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=34' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=35' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=36' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=37' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=38' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=39' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=40' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=41' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=42' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=43' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=44' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=45' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=46' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=47' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=48' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=49' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=50' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=51' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=52' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=53' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=54' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=55' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=56' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=57' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=58' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=59' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=60' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=61' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=62' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=63' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=64' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=65' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=66' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=67' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=68' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=69' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=70' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=71' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=72' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=73' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=74' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=75' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=76' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=77' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=78' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=79' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=80' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=81' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=82' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=83' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=84' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=85' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=86' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=87' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=88' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=89' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=90' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=91' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=92' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=93' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=94' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=95' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=96' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=97' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=98' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=99' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=100' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=101' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=102' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=103' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=104' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=105' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=106' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=107' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=108' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=109' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=110' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=111' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=112' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=113' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=114' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=115' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=116' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=117' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=118' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=119' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=120' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=121' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=122' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=123' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=124' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=125' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=126' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=127' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=128' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=129' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=130' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=131' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=132' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=133' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=134' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=135' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=136' +bcmcmd -n 1 -c 'tx 100 length=512 VLantag=137' diff --git a/tools/traffic_loopback_vlan_remove.txt b/tools/traffic_loopback_vlan_remove.txt new file mode 100644 index 0000000..ec8230f --- /dev/null +++ b/tools/traffic_loopback_vlan_remove.txt @@ -0,0 +1,108 @@ +bcmcmd -n 1 -c 'vlan remove 30 pbm=cd0,cd32' +bcmcmd -n 1 -c 'vlan remove 31 pbm=cd1,cd33' +bcmcmd -n 1 -c 'vlan remove 32 pbm=cd2,cd34' +bcmcmd -n 1 -c 'vlan remove 33 pbm=cd3,cd35' +bcmcmd -n 1 -c 'vlan remove 34 pbm=cd4,cd36' +bcmcmd -n 1 -c 'vlan remove 35 pbm=cd5,cd37' +bcmcmd -n 1 -c 'vlan remove 36 pbm=cd6,cd38' +bcmcmd -n 1 -c 'vlan remove 37 pbm=cd7,cd39' +bcmcmd -n 1 -c 'vlan remove 38 pbm=cd8,cd40' +bcmcmd -n 1 -c 'vlan remove 39 pbm=cd9,cd41' +bcmcmd -n 1 -c 'vlan remove 40 pbm=cd10,cd42' +bcmcmd -n 1 -c 'vlan remove 41 pbm=cd11,cd43' +bcmcmd -n 1 -c 'vlan remove 42 pbm=cd12,cd44' +bcmcmd -n 1 -c 'vlan remove 43 pbm=cd13,cd45' +bcmcmd -n 1 -c 'vlan remove 44 pbm=cd14,cd46' +bcmcmd -n 1 -c 'vlan remove 45 pbm=cd20,cd52' +bcmcmd -n 1 -c 'vlan remove 46 pbm=cd21,cd53' +bcmcmd -n 1 -c 'vlan remove 47 pbm=cd22,cd54' +bcmcmd -n 1 -c 'vlan remove 48 pbm=cd23,cd55' +bcmcmd -n 1 -c 'vlan remove 49 pbm=cd24,cd56' +bcmcmd -n 1 -c 'vlan remove 50 pbm=cd25,cd57' +bcmcmd -n 1 -c 'vlan remove 51 pbm=cd26,cd58' +bcmcmd -n 1 -c 'vlan remove 52 pbm=cd27,cd59' +bcmcmd -n 1 -c 'vlan remove 53 pbm=cd28,cd60' +bcmcmd -n 1 -c 'vlan remove 54 pbm=cd29,cd61' +bcmcmd -n 1 -c 'vlan remove 55 pbm=cd30,cd62' +bcmcmd -n 1 -c 'vlan remove 56 pbm=cd31,cd63' +bcmcmd -n 1 -c 'vlan remove 57 pbm=cd64,cd96' +bcmcmd -n 1 -c 'vlan remove 58 pbm=cd65,cd97' +bcmcmd -n 1 -c 'vlan remove 59 pbm=cd66,cd98' +bcmcmd -n 1 -c 'vlan remove 60 pbm=cd67,cd99' +bcmcmd -n 1 -c 'vlan remove 61 pbm=cd68,cd100' +bcmcmd -n 1 -c 'vlan remove 62 pbm=cd69,cd101' +bcmcmd -n 1 -c 'vlan remove 63 pbm=cd70,cd102' +bcmcmd -n 1 -c 'vlan remove 64 pbm=cd71,cd103' +bcmcmd -n 1 -c 'vlan remove 65 pbm=cd72,cd104' +bcmcmd -n 1 -c 'vlan remove 66 pbm=cd73,cd105' +bcmcmd -n 1 -c 'vlan remove 67 pbm=cd74,cd106' +bcmcmd -n 1 -c 'vlan remove 68 pbm=cd75,cd107' +bcmcmd -n 1 -c 'vlan remove 69 pbm=cd76,cd108' +bcmcmd -n 1 -c 'vlan remove 70 pbm=cd77,cd109' +bcmcmd -n 1 -c 'vlan remove 71 pbm=cd78,cd110' +bcmcmd -n 1 -c 'vlan remove 72 pbm=cd84,cd116' +bcmcmd -n 1 -c 'vlan remove 73 pbm=cd85,cd117' +bcmcmd -n 1 -c 'vlan remove 74 pbm=cd86,cd118' +bcmcmd -n 1 -c 'vlan remove 75 pbm=cd87,cd119' +bcmcmd -n 1 -c 'vlan remove 76 pbm=cd88,cd120' +bcmcmd -n 1 -c 'vlan remove 77 pbm=cd89,cd121' +bcmcmd -n 1 -c 'vlan remove 78 pbm=cd90,cd122' +bcmcmd -n 1 -c 'vlan remove 79 pbm=cd91,cd123' +bcmcmd -n 1 -c 'vlan remove 80 pbm=cd92,cd124' +bcmcmd -n 1 -c 'vlan remove 81 pbm=cd93,cd125' +bcmcmd -n 1 -c 'vlan remove 82 pbm=cd94,cd126' +bcmcmd -n 1 -c 'vlan remove 83 pbm=cd95,cd127' +bcmcmd -n 1 -c 'vlan remove 84 pbm=cd128,cd160' +bcmcmd -n 1 -c 'vlan remove 85 pbm=cd129,cd161' +bcmcmd -n 1 -c 'vlan remove 86 pbm=cd130,cd162' +bcmcmd -n 1 -c 'vlan remove 87 pbm=cd131,cd163' +bcmcmd -n 1 -c 'vlan remove 88 pbm=cd132,cd164' +bcmcmd -n 1 -c 'vlan remove 89 pbm=cd133,cd165' +bcmcmd -n 1 -c 'vlan remove 90 pbm=cd134,cd166' +bcmcmd -n 1 -c 'vlan remove 91 pbm=cd135,cd167' +bcmcmd -n 1 -c 'vlan remove 92 pbm=cd136,cd168' +bcmcmd -n 1 -c 'vlan remove 93 pbm=cd137,cd169' +bcmcmd -n 1 -c 'vlan remove 94 pbm=cd138,cd170' +bcmcmd -n 1 -c 'vlan remove 95 pbm=cd140,cd172' +bcmcmd -n 1 -c 'vlan remove 96 pbm=cd141,cd173' +bcmcmd -n 1 -c 'vlan remove 97 pbm=cd142,cd174' +bcmcmd -n 1 -c 'vlan remove 98 pbm=cd143,cd175' +bcmcmd -n 1 -c 'vlan remove 99 pbm=cd144,cd176' +bcmcmd -n 1 -c 'vlan remove 100 pbm=cd145,cd177' +bcmcmd -n 1 -c 'vlan remove 101 pbm=cd146,cd178' +bcmcmd -n 1 -c 'vlan remove 102 pbm=cd147,cd179' +bcmcmd -n 1 -c 'vlan remove 103 pbm=cd152,cd184' +bcmcmd -n 1 -c 'vlan remove 104 pbm=cd153,cd185' +bcmcmd -n 1 -c 'vlan remove 105 pbm=cd154,cd186' +bcmcmd -n 1 -c 'vlan remove 106 pbm=cd155,cd187' +bcmcmd -n 1 -c 'vlan remove 107 pbm=cd156,cd188' +bcmcmd -n 1 -c 'vlan remove 108 pbm=cd157,cd189' +bcmcmd -n 1 -c 'vlan remove 109 pbm=cd158,cd190' +bcmcmd -n 1 -c 'vlan remove 110 pbm=cd159,cd191' +bcmcmd -n 1 -c 'vlan remove 111 pbm=cd192,cd224' +bcmcmd -n 1 -c 'vlan remove 112 pbm=cd193,cd225' +bcmcmd -n 1 -c 'vlan remove 113 pbm=cd194,cd226' +bcmcmd -n 1 -c 'vlan remove 114 pbm=cd195,cd227' +bcmcmd -n 1 -c 'vlan remove 115 pbm=cd196,cd228' +bcmcmd -n 1 -c 'vlan remove 116 pbm=cd197,cd229' +bcmcmd -n 1 -c 'vlan remove 117 pbm=cd198,cd230' +bcmcmd -n 1 -c 'vlan remove 118 pbm=cd199,cd231' +bcmcmd -n 1 -c 'vlan remove 119 pbm=cd200,cd232' +bcmcmd -n 1 -c 'vlan remove 120 pbm=cd201,cd233' +bcmcmd -n 1 -c 'vlan remove 121 pbm=cd202,cd234' +bcmcmd -n 1 -c 'vlan remove 122 pbm=cd204,cd236' +bcmcmd -n 1 -c 'vlan remove 123 pbm=cd205,cd237' +bcmcmd -n 1 -c 'vlan remove 124 pbm=cd206,cd238' +bcmcmd -n 1 -c 'vlan remove 125 pbm=cd207,cd239' +bcmcmd -n 1 -c 'vlan remove 126 pbm=cd208,cd240' +bcmcmd -n 1 -c 'vlan remove 127 pbm=cd209,cd241' +bcmcmd -n 1 -c 'vlan remove 128 pbm=cd210,cd242' +bcmcmd -n 1 -c 'vlan remove 129 pbm=cd211,cd243' +bcmcmd -n 1 -c 'vlan remove 130 pbm=cd216,cd248' +bcmcmd -n 1 -c 'vlan remove 131 pbm=cd217,cd249' +bcmcmd -n 1 -c 'vlan remove 132 pbm=cd218,cd250' +bcmcmd -n 1 -c 'vlan remove 133 pbm=cd219,cd251' +bcmcmd -n 1 -c 'vlan remove 134 pbm=cd220,cd252' +bcmcmd -n 1 -c 'vlan remove 135 pbm=cd221,cd253' +bcmcmd -n 1 -c 'vlan remove 136 pbm=cd222,cd254' +bcmcmd -n 1 -c 'vlan remove 137 pbm=cd223,cd255' diff --git a/tools/traffic_loopback_vlan_setting.txt b/tools/traffic_loopback_vlan_setting.txt new file mode 100644 index 0000000..f8ffad9 --- /dev/null +++ b/tools/traffic_loopback_vlan_setting.txt @@ -0,0 +1,325 @@ +bcmcmd -n 1 -c 'vlan remove 1 pbm=cd' + +bcmcmd -n 1 -c 'vlan create 30' +bcmcmd -n 1 -c 'vlan add 30 pbm=cd0,cd32' + +bcmcmd -n 1 -c 'vlan create 31' +bcmcmd -n 1 -c 'vlan add 31 pbm=cd1,cd33' + +bcmcmd -n 1 -c 'vlan create 32' +bcmcmd -n 1 -c 'vlan add 32 pbm=cd2,cd34' + +bcmcmd -n 1 -c 'vlan create 33' +bcmcmd -n 1 -c 'vlan add 33 pbm=cd3,cd35' + +bcmcmd -n 1 -c 'vlan create 34' +bcmcmd -n 1 -c 'vlan add 34 pbm=cd4,cd36' + +bcmcmd -n 1 -c 'vlan create 35' +bcmcmd -n 1 -c 'vlan add 35 pbm=cd5,cd37' + +bcmcmd -n 1 -c 'vlan create 36' +bcmcmd -n 1 -c 'vlan add 36 pbm=cd6,cd38' + +bcmcmd -n 1 -c 'vlan create 37' +bcmcmd -n 1 -c 'vlan add 37 pbm=cd7,cd39' + +bcmcmd -n 1 -c 'vlan create 38' +bcmcmd -n 1 -c 'vlan add 38 pbm=cd8,cd40' + +bcmcmd -n 1 -c 'vlan create 39' +bcmcmd -n 1 -c 'vlan add 39 pbm=cd9,cd41' + +bcmcmd -n 1 -c 'vlan create 40' +bcmcmd -n 1 -c 'vlan add 40 pbm=cd10,cd42' + +bcmcmd -n 1 -c 'vlan create 41' +bcmcmd -n 1 -c 'vlan add 41 pbm=cd11,cd43' + +bcmcmd -n 1 -c 'vlan create 42' +bcmcmd -n 1 -c 'vlan add 42 pbm=cd12,cd44' + +bcmcmd -n 1 -c 'vlan create 43' +bcmcmd -n 1 -c 'vlan add 43 pbm=cd13,cd45' + +bcmcmd -n 1 -c 'vlan create 44' +bcmcmd -n 1 -c 'vlan add 44 pbm=cd14,cd46' + +bcmcmd -n 1 -c 'vlan create 45' +bcmcmd -n 1 -c 'vlan add 45 pbm=cd20,cd52' + +bcmcmd -n 1 -c 'vlan create 46' +bcmcmd -n 1 -c 'vlan add 46 pbm=cd21,cd53' + +bcmcmd -n 1 -c 'vlan create 47' +bcmcmd -n 1 -c 'vlan add 47 pbm=cd22,cd54' + +bcmcmd -n 1 -c 'vlan create 48' +bcmcmd -n 1 -c 'vlan add 48 pbm=cd23,cd55' + +bcmcmd -n 1 -c 'vlan create 49' +bcmcmd -n 1 -c 'vlan add 49 pbm=cd24,cd56' + +bcmcmd -n 1 -c 'vlan create 50' +bcmcmd -n 1 -c 'vlan add 50 pbm=cd25,cd57' + +bcmcmd -n 1 -c 'vlan create 51' +bcmcmd -n 1 -c 'vlan add 51 pbm=cd26,cd58' + +bcmcmd -n 1 -c 'vlan create 52' +bcmcmd -n 1 -c 'vlan add 52 pbm=cd27,cd59' + +bcmcmd -n 1 -c 'vlan create 53' +bcmcmd -n 1 -c 'vlan add 53 pbm=cd28,cd60' + +bcmcmd -n 1 -c 'vlan create 54' +bcmcmd -n 1 -c 'vlan add 54 pbm=cd29,cd61' + +bcmcmd -n 1 -c 'vlan create 55' +bcmcmd -n 1 -c 'vlan add 55 pbm=cd30,cd62' + +bcmcmd -n 1 -c 'vlan create 56' +bcmcmd -n 1 -c 'vlan add 56 pbm=cd31,cd63' + +bcmcmd -n 1 -c 'vlan create 57' +bcmcmd -n 1 -c 'vlan add 57 pbm=cd64,cd96' + +bcmcmd -n 1 -c 'vlan create 58' +bcmcmd -n 1 -c 'vlan add 58 pbm=cd65,cd97' + +bcmcmd -n 1 -c 'vlan create 59' +bcmcmd -n 1 -c 'vlan add 59 pbm=cd66,cd98' + +bcmcmd -n 1 -c 'vlan create 60' +bcmcmd -n 1 -c 'vlan add 60 pbm=cd67,cd99' + +bcmcmd -n 1 -c 'vlan create 61' +bcmcmd -n 1 -c 'vlan add 61 pbm=cd68,cd100' + +bcmcmd -n 1 -c 'vlan create 62' +bcmcmd -n 1 -c 'vlan add 62 pbm=cd69,cd101' + +bcmcmd -n 1 -c 'vlan create 63' +bcmcmd -n 1 -c 'vlan add 63 pbm=cd70,cd102' + +bcmcmd -n 1 -c 'vlan create 64' +bcmcmd -n 1 -c 'vlan add 64 pbm=cd71,cd103' + +bcmcmd -n 1 -c 'vlan create 65' +bcmcmd -n 1 -c 'vlan add 65 pbm=cd72,cd104' + +bcmcmd -n 1 -c 'vlan create 66' +bcmcmd -n 1 -c 'vlan add 66 pbm=cd73,cd105' + +bcmcmd -n 1 -c 'vlan create 67' +bcmcmd -n 1 -c 'vlan add 67 pbm=cd74,cd106' + +bcmcmd -n 1 -c 'vlan create 68' +bcmcmd -n 1 -c 'vlan add 68 pbm=cd75,cd107' + +bcmcmd -n 1 -c 'vlan create 69' +bcmcmd -n 1 -c 'vlan add 69 pbm=cd76,cd108' + +bcmcmd -n 1 -c 'vlan create 70' +bcmcmd -n 1 -c 'vlan add 70 pbm=cd77,cd109' + +bcmcmd -n 1 -c 'vlan create 71' +bcmcmd -n 1 -c 'vlan add 71 pbm=cd78,cd110' + +bcmcmd -n 1 -c 'vlan create 72' +bcmcmd -n 1 -c 'vlan add 72 pbm=cd84,cd116' + +bcmcmd -n 1 -c 'vlan create 73' +bcmcmd -n 1 -c 'vlan add 73 pbm=cd85,cd117' + +bcmcmd -n 1 -c 'vlan create 74' +bcmcmd -n 1 -c 'vlan add 74 pbm=cd86,cd118' + +bcmcmd -n 1 -c 'vlan create 75' +bcmcmd -n 1 -c 'vlan add 75 pbm=cd87,cd119' + +bcmcmd -n 1 -c 'vlan create 76' +bcmcmd -n 1 -c 'vlan add 76 pbm=cd88,cd120' + +bcmcmd -n 1 -c 'vlan create 77' +bcmcmd -n 1 -c 'vlan add 77 pbm=cd89,cd121' + +bcmcmd -n 1 -c 'vlan create 78' +bcmcmd -n 1 -c 'vlan add 78 pbm=cd90,cd122' + +bcmcmd -n 1 -c 'vlan create 79' +bcmcmd -n 1 -c 'vlan add 79 pbm=cd91,cd123' + +bcmcmd -n 1 -c 'vlan create 80' +bcmcmd -n 1 -c 'vlan add 80 pbm=cd92,cd124' + +bcmcmd -n 1 -c 'vlan create 81' +bcmcmd -n 1 -c 'vlan add 81 pbm=cd93,cd125' + +bcmcmd -n 1 -c 'vlan create 82' +bcmcmd -n 1 -c 'vlan add 82 pbm=cd94,cd126' + +bcmcmd -n 1 -c 'vlan create 83' +bcmcmd -n 1 -c 'vlan add 83 pbm=cd95,cd127' + +bcmcmd -n 1 -c 'vlan create 84' +bcmcmd -n 1 -c 'vlan add 84 pbm=cd128,cd160' + +bcmcmd -n 1 -c 'vlan create 85' +bcmcmd -n 1 -c 'vlan add 85 pbm=cd129,cd161' + +bcmcmd -n 1 -c 'vlan create 86' +bcmcmd -n 1 -c 'vlan add 86 pbm=cd130,cd162' + +bcmcmd -n 1 -c 'vlan create 87' +bcmcmd -n 1 -c 'vlan add 87 pbm=cd131,cd163' + +bcmcmd -n 1 -c 'vlan create 88' +bcmcmd -n 1 -c 'vlan add 88 pbm=cd132,cd164' + +bcmcmd -n 1 -c 'vlan create 89' +bcmcmd -n 1 -c 'vlan add 89 pbm=cd133,cd165' + +bcmcmd -n 1 -c 'vlan create 90' +bcmcmd -n 1 -c 'vlan add 90 pbm=cd134,cd166' + +bcmcmd -n 1 -c 'vlan create 91' +bcmcmd -n 1 -c 'vlan add 91 pbm=cd135,cd167' + +bcmcmd -n 1 -c 'vlan create 92' +bcmcmd -n 1 -c 'vlan add 92 pbm=cd136,cd168' + +bcmcmd -n 1 -c 'vlan create 93' +bcmcmd -n 1 -c 'vlan add 93 pbm=cd137,cd169' + +bcmcmd -n 1 -c 'vlan create 94' +bcmcmd -n 1 -c 'vlan add 94 pbm=cd138,cd170' + +bcmcmd -n 1 -c 'vlan create 95' +bcmcmd -n 1 -c 'vlan add 95 pbm=cd140,cd172' + +bcmcmd -n 1 -c 'vlan create 96' +bcmcmd -n 1 -c 'vlan add 96 pbm=cd141,cd173' + +bcmcmd -n 1 -c 'vlan create 97' +bcmcmd -n 1 -c 'vlan add 97 pbm=cd142,cd174' + +bcmcmd -n 1 -c 'vlan create 98' +bcmcmd -n 1 -c 'vlan add 98 pbm=cd143,cd175' + +bcmcmd -n 1 -c 'vlan create 99' +bcmcmd -n 1 -c 'vlan add 99 pbm=cd144,cd176' + +bcmcmd -n 1 -c 'vlan create 100' +bcmcmd -n 1 -c 'vlan add 100 pbm=cd145,cd177' + +bcmcmd -n 1 -c 'vlan create 101' +bcmcmd -n 1 -c 'vlan add 101 pbm=cd146,cd178' + +bcmcmd -n 1 -c 'vlan create 102' +bcmcmd -n 1 -c 'vlan add 102 pbm=cd147,cd179' + +bcmcmd -n 1 -c 'vlan create 103' +bcmcmd -n 1 -c 'vlan add 103 pbm=cd152,cd184' + +bcmcmd -n 1 -c 'vlan create 104' +bcmcmd -n 1 -c 'vlan add 104 pbm=cd153,cd185' + +bcmcmd -n 1 -c 'vlan create 105' +bcmcmd -n 1 -c 'vlan add 105 pbm=cd154,cd186' + +bcmcmd -n 1 -c 'vlan create 106' +bcmcmd -n 1 -c 'vlan add 106 pbm=cd155,cd187' + +bcmcmd -n 1 -c 'vlan create 107' +bcmcmd -n 1 -c 'vlan add 107 pbm=cd156,cd188' + +bcmcmd -n 1 -c 'vlan create 108' +bcmcmd -n 1 -c 'vlan add 108 pbm=cd157,cd189' + +bcmcmd -n 1 -c 'vlan create 109' +bcmcmd -n 1 -c 'vlan add 109 pbm=cd158,cd190' + +bcmcmd -n 1 -c 'vlan create 110' +bcmcmd -n 1 -c 'vlan add 110 pbm=cd159,cd191' + +bcmcmd -n 1 -c 'vlan create 111' +bcmcmd -n 1 -c 'vlan add 111 pbm=cd192,cd224' + +bcmcmd -n 1 -c 'vlan create 112' +bcmcmd -n 1 -c 'vlan add 112 pbm=cd193,cd225' + +bcmcmd -n 1 -c 'vlan create 113' +bcmcmd -n 1 -c 'vlan add 113 pbm=cd194,cd226' + +bcmcmd -n 1 -c 'vlan create 114' +bcmcmd -n 1 -c 'vlan add 114 pbm=cd195,cd227' + +bcmcmd -n 1 -c 'vlan create 115' +bcmcmd -n 1 -c 'vlan add 115 pbm=cd196,cd228' + +bcmcmd -n 1 -c 'vlan create 116' +bcmcmd -n 1 -c 'vlan add 116 pbm=cd197,cd229' + +bcmcmd -n 1 -c 'vlan create 117' +bcmcmd -n 1 -c 'vlan add 117 pbm=cd198,cd230' + +bcmcmd -n 1 -c 'vlan create 118' +bcmcmd -n 1 -c 'vlan add 118 pbm=cd199,cd231' + +bcmcmd -n 1 -c 'vlan create 119' +bcmcmd -n 1 -c 'vlan add 119 pbm=cd200,cd232' + +bcmcmd -n 1 -c 'vlan create 120' +bcmcmd -n 1 -c 'vlan add 120 pbm=cd201,cd233' + +bcmcmd -n 1 -c 'vlan create 121' +bcmcmd -n 1 -c 'vlan add 121 pbm=cd202,cd234' + +bcmcmd -n 1 -c 'vlan create 122' +bcmcmd -n 1 -c 'vlan add 122 pbm=cd204,cd236' + +bcmcmd -n 1 -c 'vlan create 123' +bcmcmd -n 1 -c 'vlan add 123 pbm=cd205,cd237' + +bcmcmd -n 1 -c 'vlan create 124' +bcmcmd -n 1 -c 'vlan add 124 pbm=cd206,cd238' + +bcmcmd -n 1 -c 'vlan create 125' +bcmcmd -n 1 -c 'vlan add 125 pbm=cd207,cd239' + +bcmcmd -n 1 -c 'vlan create 126' +bcmcmd -n 1 -c 'vlan add 126 pbm=cd208,cd240' + +bcmcmd -n 1 -c 'vlan create 127' +bcmcmd -n 1 -c 'vlan add 127 pbm=cd209,cd241' + +bcmcmd -n 1 -c 'vlan create 128' +bcmcmd -n 1 -c 'vlan add 128 pbm=cd210,cd242' + +bcmcmd -n 1 -c 'vlan create 129' +bcmcmd -n 1 -c 'vlan add 129 pbm=cd211,cd243' + +bcmcmd -n 1 -c 'vlan create 130' +bcmcmd -n 1 -c 'vlan add 130 pbm=cd216,cd248' + +bcmcmd -n 1 -c 'vlan create 131' +bcmcmd -n 1 -c 'vlan add 131 pbm=cd217,cd249' + +bcmcmd -n 1 -c 'vlan create 132' +bcmcmd -n 1 -c 'vlan add 132 pbm=cd218,cd250' + +bcmcmd -n 1 -c 'vlan create 133' +bcmcmd -n 1 -c 'vlan add 133 pbm=cd219,cd251' + +bcmcmd -n 1 -c 'vlan create 134' +bcmcmd -n 1 -c 'vlan add 134 pbm=cd220,cd252' + +bcmcmd -n 1 -c 'vlan create 135' +bcmcmd -n 1 -c 'vlan add 135 pbm=cd221,cd253' + +bcmcmd -n 1 -c 'vlan create 136' +bcmcmd -n 1 -c 'vlan add 136 pbm=cd222,cd254' + +bcmcmd -n 1 -c 'vlan create 137' +bcmcmd -n 1 -c 'vlan add 137 pbm=cd223,cd255'