|
|
|
@@ -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=<vid>) and
|
|
|
|
|
# utils/traffic_loopback_vlan_remove.ttl.
|
|
|
|
|
# One DUT = two switch boards -> bcmcmd unit 0 and 1
|
|
|
|
|
# (bcmcmd -n <unit>), default both.
|
|
|
|
|
# V0.2.0 2026-08-17 Add: 'ps' (port status) subcommand -- 'ps <portlist>' 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 <log> 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 </dev/null and the loops read
|
|
|
|
|
# on fd 3 (3<<< "$TL_PAIRS").
|
|
|
|
|
# Fix: bcmcmd exits 0 even when the BCM shell rejects the
|
|
|
|
|
# command ("VLAN: ERROR: Entry exists" / "Failed to execute
|
|
|
|
|
# the diagnostic command"), so failures were counted as OK.
|
|
|
|
|
# Output is now pattern-matched ($TL_ERR_PAT), with benign
|
|
|
|
|
# cases tolerated and counted separately: 'Entry exists' on
|
|
|
|
|
# 'vlan create' (re-run of init) and 'not found' on
|
|
|
|
|
# 'vlan remove/destroy' (stop before init).
|
|
|
|
|
# V0.3.2 2026-08-17 Add: report colours the verdict -- PASS green, FAIL red,
|
|
|
|
|
# NA yellow (also in the summary lines). Padding is applied
|
|
|
|
|
# to the plain text before colouring so the columns stay
|
|
|
|
|
# aligned. Auto-disabled when stdout is not a terminal or
|
|
|
|
|
# with --tsv; --color / --no-color / TL_COLOR force it.
|
|
|
|
|
# =============================================================================
|
|
|
|
|
#
|
|
|
|
|
# The VLAN/port table below is copied verbatim from
|
|
|
|
|
# utils/traffic_loopback_vlan_setting.ttl -- it is NOT generated, because the
|
|
|
|
|
# port map has gaps (cd15..19, cd47..51, cd79..83, cd111..115, cd139,
|
|
|
|
|
# cd148..151, cd171, cd180..183, cd203, cd212..215, cd235, cd244..247 are not
|
|
|
|
|
# cabled). Keep this file and the .ttl in sync if the loopback harness changes.
|
|
|
|
|
#
|
|
|
|
|
# Usage (run directly):
|
|
|
|
|
# ./blanton_traffic_linespeed.sh init # step 1: VLAN loopback setup
|
|
|
|
|
# ./blanton_traffic_linespeed.sh clear # step 2: clear c
|
|
|
|
|
# ./blanton_traffic_linespeed.sh show # step 3/6: show c
|
|
|
|
|
# ./blanton_traffic_linespeed.sh start # step 4: tx burst per VLAN
|
|
|
|
|
# ./blanton_traffic_linespeed.sh stop # step 5: remove VLAN members
|
|
|
|
|
# ./blanton_traffic_linespeed.sh ps # port status (link/speed) of
|
|
|
|
|
# # the cabled ports
|
|
|
|
|
# ./blanton_traffic_linespeed.sh report # step 6+: show c -> 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 <n> tx packet count (default $TL_TX_COUNT)
|
|
|
|
|
# -l|--length <n> tx packet length (default $TL_TX_LENGTH)
|
|
|
|
|
# -p|--ports <list|all> ps: port list ('all' = plain 'ps', every port)
|
|
|
|
|
# -T|--tolerance <n> 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 <log> 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 <vid>' 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 <list>'".
|
|
|
|
|
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 <log>: 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: <vid> <port_a> <port_b>
|
|
|
|
|
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 (</dev/null). Without it
|
|
|
|
|
# bcmcmd inherits the caller's stdin and eats the rest of the pair list that the
|
|
|
|
|
# while-loops read, so only the first VLAN got configured (fixed in V0.3.1).
|
|
|
|
|
#
|
|
|
|
|
# _tl_bcm <unit> <bcm shell command> -- 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" </dev/null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# bcmcmd exits 0 even when the BCM shell itself refused the command
|
|
|
|
|
# ("VLAN: ERROR: Entry exists", "Failed to execute the diagnostic command"),
|
|
|
|
|
# so the captured output has to be pattern-matched as well.
|
|
|
|
|
TL_ERR_PAT="${TL_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|not found}"
|
|
|
|
|
TL_BENIGN_CREATE="${TL_BENIGN_CREATE:-Entry exists|already exist}"
|
|
|
|
|
TL_BENIGN_REMOVE="${TL_BENIGN_REMOVE:-Entry not found|not found|does not exist|no such}"
|
|
|
|
|
|
|
|
|
|
# _tl_bcm_run <unit> <benign_regex|""> <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" </dev/null 2>&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 <unit> <cmd> -- _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 <portlist> =============================================
|
|
|
|
|
# '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 <logfile> -> 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 <log>: 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 <count> length=<len> VLantag=<vid> per VLAN"
|
|
|
|
|
echo -e " \033[33mstop\033[0m step 5 vlan remove <vid> pbm=<pair> [--destroy also destroys]"
|
|
|
|
|
echo -e " \033[33mps\033[0m ps <portlist> 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 <n> tx packet count (default $TL_TX_COUNT)"
|
|
|
|
|
echo -e " \033[33m-l|--length\033[0m <n> tx packet length (default $TL_TX_LENGTH)"
|
|
|
|
|
echo -e " \033[33m-p|--ports\033[0m <list> ps port list, or 'all' for every port"
|
|
|
|
|
echo -e " \033[33m-T|--tolerance\033[0m <n> 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 <log> 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
|