From 59861cf9531df26025a6ffc30aedc5b8ab066217 Mon Sep 17 00:00:00 2001 From: ETWen Date: Fri, 28 Aug 2026 16:33:40 +0800 Subject: [PATCH] feat(ber,power): Add the BER sweep and TR518 load; keep ce0 actually sending Three new tools and one fix to an old one. blanton_ber.sh - PRBS BER across every cabled port, init/start/report/ stop/clear, -u 0|1|all. A lane passes only below 1e-6 (equal to the threshold fails). report ends with a per-unit summary carrying the worst lane, so an all-PASS run still shows how much margin there was. init checks every lane locked, because an unlocked lane still reports a BER and it is a meaningless one. Script C runs it after the traffic report, following SWB_UNIT0/SWB_UNIT1 like the traffic block does. blanton_tr518.sh - the built-in packet test, used to load the rails before measuring power. start settles 120s so the reading afterwards is loaded rather than mid-ramp. stop sends port cd lb=none and nothing else, exactly what the bench procedure does - l2 learning and test mode are left as start set them, and stop says so instead of quietly leaving the box in a state nobody asked about. TH6_SWB{0,1}_power_readback.sh - 19 rails, V x I and total. These read the two sensor tables ONCE. The previous version read them per rail: 38 invocations of a slow CLI at 38 different instants, so the "total" was a sum of readings seconds apart - and under load the currents move (TH6_CORE 186 A -> 636 A). A rail missing from the table now warns on stderr instead of silently contributing 0 W. blanton_traffic_linespeed.sh - ce0 (VLAN 138) joins the test. It has no loopback partner and a switch never sends a frame back out its ingress port, so a tx burst was one round trip and then silence. init now sets an ingress mirror of ce0 back to itself; the mirrored copy is not egress-filtered, so packets keep lapping until stop turns the mirror off. stop is what ends it - removing the VLAN membership does not, because the copy never consulted the VLAN. TL_CE_MODE also drops to 'self': ps ce shows one ce port per unit and a unit-0-only burst returned on unit 0. Read as cross-unit, both links dying would still report PASS (0 == 0). Fixes a parser bug worth remembering: bcmcmd returns CRLF, and the BER is the last token on its line, so the CR stayed glued to the number. Every lane read as NA, and printing the CR sent the cursor to column 1 so the RESULT column overwrote the start of the row. One stray \r, two symptoms. Not yet verified on hardware, all called out in the release notes: the ce0 mirror (destport == srcport may be refused), the 120s settle (tr 518 may be time-limited), and 'test mode nr=no' on stop. Script A -> V1.1.0. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014RetWKFZFG1ZHcitQAyhwM --- ARCHITECTURE.md | 33 +- CLAUDE.md | 35 +- docs/release-notes/v1.1.0.md | 81 ++ src/Script_ABC_Blanton/1_Blanton_Script_A.ttl | 39 +- src/Script_ABC_Blanton/3_Blanton_Script_C.ttl | 48 + .../Blanton_Script/TH6_SWB0_power_readback.sh | 95 ++ .../Blanton_Script/TH6_SWB1_power_readback.sh | 95 ++ .../Blanton_Script/blanton_ber.sh | 495 ++++++++++ .../Blanton_Script/blanton_tr518.sh | 326 +++++++ .../blanton_traffic_linespeed.sh | 295 +++++- tools/100G_Traffic.txt | 12 + tools/BER_Test.txt | 900 ++++++++++++++++++ tools/TR518.txt | 43 +- 13 files changed, 2450 insertions(+), 47 deletions(-) create mode 100644 docs/release-notes/v1.1.0.md create mode 100644 src/Script_ABC_Blanton/Blanton_Script/TH6_SWB0_power_readback.sh create mode 100644 src/Script_ABC_Blanton/Blanton_Script/TH6_SWB1_power_readback.sh create mode 100644 src/Script_ABC_Blanton/Blanton_Script/blanton_ber.sh create mode 100644 src/Script_ABC_Blanton/Blanton_Script/blanton_tr518.sh create mode 100644 tools/100G_Traffic.txt create mode 100644 tools/BER_Test.txt diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index af5d9b5..f2ef3c3 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -132,7 +132,9 @@ Blanton_TTL_Script/ │ │ # ↑ 三份為手動貼上用的原始指令表, │ │ # blanton_traffic_linespeed.sh 是其 bash 版 │ ├── 100G_PRBS.txt # 100G PRBS 原始指令(port_prbs_monitor.sh 的來源) -│ ├── TR518.txt # 內建封包測試 tr 518(Scenario=6 Profile=2)— 尚未腳本化 +│ ├── TR518.txt # 內建封包測試 tr 518 → blanton_tr518.sh +│ ├── BER_Test.txt # 全機 PRBS BER 指令 → blanton_ber.sh +│ ├── 100G_Traffic.txt # ce0 VLAN 138 打流 → blanton_traffic_linespeed.sh │ ├── fan_ctrl.txt # MAX31790 unbind/bind + fan-speed-control.sh 30 │ └── gen_channel_map.sh # settings/*.conf → docs/LTC2980_channel_map.csv(需 gawk) │ @@ -185,6 +187,10 @@ Blanton_TTL_Script/ ├── mgmt_ping_monitor.sh # 10G/1G 管理網路 ping 監控(iproute2) │ # eth0→TARGET_10G、eth1→TARGET_1G,兩張卡同時持續 ping ├── port_prbs_monitor.sh # 100G uplink PRBS 測試(bcmcmd phy diag) + ├── blanton_ber.sh # 全機 SerDes BER 掃描(phydiag prbs / prbsstat) + ├── blanton_tr518.sh # TR518 封包測試,量功耗前的負載來源 + ├── TH6_SWB0_power_readback.sh # SWB0 19 條軌 V×I + 總功耗 + ├── TH6_SWB1_power_readback.sh # SWB1 同上 │ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中) ├── usb_target.sh # 偵測 USB 裝置節點/掛載點(排除系統碟) ├── bmc_monitor.sh # BMC 監控:free -m + I2C 寫入/讀回圖樣測試 @@ -338,8 +344,8 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc |------|--------|------| | **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.0.7 | root 登入 → `date -s` 對時 → 清 job log → `hw-test-session start` → **設定風扇轉速** → **等資料面就緒**(`wait_init.ttl`)→ DUT 清單(boot/version/fwutil/syseeprom/ssdhealth/TPM/NVMe)→ BMC enroll + version/status → source bash 工具 → 清/讀 7 組 PCIe AER + `ras-mc-ctl --summary` → `lspci` → margin → PMON → dmesg → **10G/1G 管理網路 ping** → 100G uplink 設定與狀態 → **一輪流量基線** → `show uptime` | | **Script B(Stress)** | `2_Blanton_Script_B.ttl` | `mlucas-avx2 -cpu 0:15` + `bgctl run` 的 `memtester` / SSD / USB 壓力 + BMC DDR(`bmc-manager run memtester`)→ BMC USB net test(探測 cdc_ncm 介面,`systemd-run` 掛 4 小時 ping)→ 啟動 mgmt ping 監控 → `jobs` / `bgctl list` → traffic(依 `SWB_UNIT`)→ `while 1` 每輪完整 PMON + margin | -| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` + `bgctl stop --all` / `reset` + 停 BMC USB unit 與 mgmt ping → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` → `ip -s link show eth0/eth1` → `cat` mlucas log → traffic `stop` + `report` → NVMe 健康 → `show reboot-cause` / `uptime` → **job log 複製到 USB(帶時戳)** → `hw-test-session finish` | -| **SWB loopback 流量** | `blanton_traffic_linespeed [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 100 length=512`)→ `stop` → `report`(per-pair TX/RX 交叉比對 PASS/FAIL);另有 `ps`(link/speed)與 `run`(一條龍) | +| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` + `bgctl stop --all` / `reset` + 停 BMC USB unit 與 mgmt ping → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` → `ip -s link show eth0/eth1` → `cat` mlucas log → traffic `stop` + `report` → **BER 掃描**(依 `SWB_UNIT`)→ NVMe 健康 → `show reboot-cause` / `uptime` → **job log 複製到 USB(帶時戳)** → `hw-test-session finish` | +| **SWB loopback 流量** | `blanton_traffic_linespeed [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 100 length=512`)→ `stop` → `report`(per-pair TX/RX 交叉比對 PASS/FAIL);另有 `ps`(link/speed)與 `run`(一條龍)。**V0.6.0 起含 100G uplink `ce0`**(VLAN 138):它沒有 loopback 對象,靠 **ingress mirror 打回自己**維持循環,`report` 最後一列就是它,底下再接一份跨 unit summary | | **FPGA 暫存器存取** | `cb_fpga [data]`、`fpga_rescan` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;BDF 於 source 時自動偵測;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 | | **CB I2C / PMBus** | `cb_i2c_init/scan/read/write`、`cb_pmbus_read/write/linear16` | FPGA F3 OpenCores master,**讀用 Repeated START**(SMBus/PMBus 裝置必需) | | **ICB / PDB 存取** | `vi2c_init/scan/read/write`、`vi2c_scan_all` | CB F3 VI2C proxy,~3.3 ms/reg,取代 VSPI 的 ~18 ms/reg(後者會踩 SMBus 25–35 ms timeout) | @@ -351,6 +357,9 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc | **BMC 監控** | `bmc_monitor.sh {start\|stop\|status\|fg\|tail\|clear}` | 由 host 端 `bmc-manager run` 週期取樣 `free -m`,另加一組 **I2C 寫入/讀回圖樣測試**(bus 1、addr 0x41、offset 0x00C0,寫 `55AA55AA` 讀回、再寫 `AA55AA55` 讀回)。B 啟動、C 停止並 `cat log/bmc_poll.log` | | **BMC DDR 壓力** | `bmc_monitor_ddr.sh` | ⚠️ **已停用** —— B/C 內呼叫處已註解,改由 `bgctl run bmc-manager run memtester` 取代。檔案保留未刪 | | **100G PRBS** | `port_prbs_monitor.sh {start [both\|a\|b]\|stop\|status\|report\|clear}` | 兩個 uplink 各一個 worker,可同時或單獨跑。setup(`lpmode off` → `prbs set` → `prbsstat STArt`)→ 週期 `prbs get`(判定)+ `prbsstat Ber`(只記錄)→ teardown(`STOp` + `prbs clear`)。輸出含 `PRBS OK!` 才算 PASS。**⚠️ A/B/C 的呼叫目前註解掉** | +| **SerDes BER 掃描** | `blanton_ber.sh {init\|clear\|start\|stop\|report} [-u 0\|1\|all]` | 全機每個對接 port 的 PRBS BER:`prbs set p=3` + `prbs get`(確認每條 lane 都鎖上)→ `prbsstat STArt Interval=30` →(等一個 interval)→ `prbsstat Ber` → `STOp` → `prbs clear`。`report` 一列一條 lane,**BER < 1e-6 才 PASS**,最後跨 unit 的 summary 帶最差 lane。⚠️ PRBS 期間 link 顯示 DOWN、不過流量 | +| **TR518 負載** | `blanton_tr518.sh {start\|stop} [-u 0\|1\|all]` | `port cd lb=mac` → `l2 learn off` → `test mode nr=yes` → `tr 518 ... testphase=1`,然後 settle `TR_SETTLE_SEC`(120s)再讓人量功耗。`stop` 只送 `port cd lb=none`(照 `TR518.txt`),L2 學習與 test mode **不會還原**,`TR_RESTORE_*=1` 才會 | +| **SWB 軌功耗** | `TH6_SWB{0,1}_power_readback.sh` | 讀 `show platform voltage/current` **各一次**,19 條軌 V×I 與總功耗。舊版每軌各讀一次(38 次呼叫、每軌不同時刻),總和是不同瞬間的加總 | | **USB 目標偵測** | `usb_target.sh [-o dev\|mnt\|both\|id] [-n] [-r sec]` | 找出插入的 USB 儲存裝置,排除 `/` 與 `/host` 的底層碟(本平台可能從 USB DOM 開機),多顆時拒絕猜;掛載時會驗證真的可寫 | | **打包交付** | `publish/publish.sh [-v Ver] [-f] [-z] [-n]` | 版號讀 Script A 檔頭,複製成 `publish/Script_ABC_Blanton_/`,排除 `*.log`,可另出 zip | @@ -771,10 +780,20 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值, - **風扇確認提示是無限等待**:`wait "Set all configured fan channels to"` 之後才 `sendln "y"`; 若該版 `fan-speed-control.sh` 不再詢問(或字串改了),這個 `wait` 會永遠等下去,Script A 停在那裡 且不報錯。加個 `timeout` + 分支會比較保險(記得還原 `timeout = 0`)。 -- **TR518 內建封包測試尚未腳本化**:`tools/TR518.txt` 記下了 `tr 518 Scenario=6 Profile=2 Count=260 - PktSize=324 PortList=1-259,270-565` 這組指令(含 `port all lb=mac` + `l2 learn off` 前置), - 目前只能手貼。它與 `blanton_traffic_linespeed` 是兩條互斥的打流路線(都會動 loopback 與 L2 學習), - 要腳本化的話得先決定兩者怎麼共存,不能同時跑。 +- ✅ **TR518 已腳本化** —— `blanton_tr518.sh` V1.0.1(2026-08-28)。仍與 `blanton_traffic_linespeed` + 互斥(兩者都會動 `port cd` loopback 與 L2 學習),檔頭與 help 都標了。剩下三件事: + `stop` 沒把 `l2 learn` / `test mode` 放回去(照 `TR518.txt` 的定義,旗標可開); + **`sleep 120` 的方向還沒驗證** —— 若 `tr 518` 的流量是有時限的(參數含 `runtime=1`、 + `CheckDataTime=200`),等 120 秒可能量到已經降下來的值,要上機比對 0s / 30s / 120s 三次; + TTL 尚未呼叫它。 +- **`blanton_ber.sh` 的 `sleep 30` 與 `BER_INTERVAL` 是兩處要同步改的數字**:Script C 寫死 + `sendln "sleep 30"`,腳本預設 `BER_INTERVAL=30`。改一邊沒改另一邊,report 會讀到還沒累積完 + 一個 interval 的數字,而且不會有任何警告。 +- **`ce0` 的 ingress mirror 尚未上機驗證**:`mirror port ce0 Mode=Ingress DestPort=ce0` 這條路是 + 推論出來的(鏡像複本不受 egress filter 的 source-port knockout 限制),語法取自 DUT 的 + `help mirror`,但**還沒證明硬體真的接受 destport == srcport**。驗證方式是隔 10 秒看兩次 + `show c | grep POK.ce0`,數字有沒有繼續長 —— 光看 report 的 PASS 分不出來,因為一次性 burst + 也是 TX==RX。不通的話備案是 `tr 518 PortList=268`。 - **SWB 的 LTC2977 有兩條路可以到,目前工具兩條都在用**:`cb_pmbus_*`(CB FPGA F3 → pcimem) 是 `margin_init` / `margin_status` / `margin_set` 走的路;原生 i2c bus(Ch+7 = bus 13/14/15/16) 是 `margin_save blanton` 走的路。後者短很多 —— 不需要通道初始化、不需要 pcimem, diff --git a/CLAUDE.md b/CLAUDE.md index 1e5015e..72c0485 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` → 完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。 -**目前狀態(2026-08-27)**:Script A 為 **V1.0.10**(A 集中記錄 A/B/C 三支的變更)。涵蓋 +**目前狀態(2026-08-28)**:Script A 為 **V1.1.0**(A 集中記錄 A/B/C 三支的變更)。涵蓋 PCIe AER / DDR EDAC / PMON+TPM / 電壓 margin(9 顆 LTC2980)/ SWB loopback 線速流量 / 10G+1G 管理網路 ping / BMC DDR 與 USB / NVMe 健康,壓力層走平台的 `bgctl`。 switch unit 數量由 `config.ttl` 的 `SWB_UNIT0` / `SWB_UNIT1` 宣告,風扇轉速由 `FAN_SPEED` 指定 @@ -17,7 +17,10 @@ switch unit 數量由 `config.ttl` 的 `SWB_UNIT0` / `SWB_UNIT1` 宣告,風扇 測試 job log 收在 DUT 的 `/host/hw-eval/jobs/`,Script C 結束時掛好 USB 再帶時戳複製到 `/mnt/usb/`。 100G PRBS(`port_prbs_monitor.sh`)已隨包交付,但 **A/B/C 的呼叫仍註解掉**,還在 bring-up。 Script B 的 soak 迴圈每輪印 `bgctl list` + `jobs`,並 `pause 60`(V1.0.10 之前完全沒有 pause)。 -最後一次發布是 **V1.0.9**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。 +V1.1.0 新增全機 SerDes BER 掃描(`blanton_ber.sh`,**Script C 已接**,依 `SWB_UNIT` 分支)、 +TR518 負載(`blanton_tr518.sh`,**TTL 尚未接**)、SWB 軌功耗(`TH6_SWB{0,1}_power_readback.sh`), +線速流量也納入 100G `ce0`(VLAN 138,靠 ingress mirror 維持循環)。 +最後一次發布是 **V1.0.11**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。 交付用 `./publish/publish.sh` 打包。 ## 技術棧 @@ -107,6 +110,23 @@ bash ~/Blanton_Script/port_prbs_monitor.sh report # PASS/FAIL 統計(沒 bash ~/Blanton_Script/port_prbs_monitor.sh stop # 收尾會跑 prbsstat STOp + prbs clear # ⚠️ PRBS 打起來時 link 會顯示 down,這是正常的 —— 所以 start 刻意不印 port status +# ── 全機 SerDes BER(PRBS,期間 link 會顯示 DOWN)──── +./Blanton_Script/blanton_ber.sh init # prbs set p=3 + prbs get(檢查每條 lane 鎖定) +./Blanton_Script/blanton_ber.sh start # prbsstat STArt Interval=30 +sleep 30 # 至少等一個 interval 再 report +./Blanton_Script/blanton_ber.sh report # 每 lane 一列,BER < 1e-6 才 PASS,最後 summary +./Blanton_Script/blanton_ber.sh stop # prbsstat STOp +./Blanton_Script/blanton_ber.sh clear # prbs clear(會解除 PRBS,要重測得再 init) +# -u 0 / -u 1 單邊;-c 1e-9 換門檻;-F 只列失敗;-f 離線重解 +# ⚠️ 不能跟 blanton_traffic_linespeed / blanton_tr518 同時跑(都會接管同一批 port) + +# ── TR518 負載 + 量功耗(TTL 尚未接)───────────────── +./Blanton_Script/blanton_tr518.sh start # 兩 unit,跑完 settle 120s +./Blanton_Script/TH6_SWB0_power_readback.sh # 19 條軌 V×I + TOTAL POWER +./Blanton_Script/TH6_SWB1_power_readback.sh +./Blanton_Script/blanton_tr518.sh stop # 只送 port cd lb=none +# ⚠️ stop 不還原 l2 learn / test mode(TR_RESTORE_LEARN=1 / _TESTMODE=1 才會) + # ── USB 目標偵測 ──────────────────────────────────── bash ~/Blanton_Script/usb_target.sh -o dev # /dev/sdX1 bash ~/Blanton_Script/usb_target.sh -o mnt # 掛好並回傳掛載點 @@ -235,6 +255,17 @@ Tera Term 連 COM port (115200-8-N-1) (版本改了、字串換了)就會永遠卡住且不報錯 —— 現場看起來像 Script A 當掉 - ⚠️ **`show_dmesg.ttl` 結尾會 `dmesg -C` 清空 kernel ring buffer**。這是刻意的(讓 Script C 只看到 soak 期間新產生的訊息),但代表事後在 DUT 上 `dmesg` 撈不到舊訊息 —— 內容只存在 master log 裡 +- ⚠️ **`bcmcmd` 的輸出是 CRLF**。`show c` 的計數器後面還跟著 delta,所以「砍掉第一個空白之後」 + 順便把 CR 砍掉了;但 `prbsstat Ber` 的 BER 是**整行最後一個 token**,CR 直接黏在數字上 —— + 數字驗證會失敗(全變 NA),而且印出來時 CR 把游標拉回行首,後面的欄位會**覆蓋掉前面的欄位**。 + 寫新的 awk 解析器時,第一件事就是 `{ gsub(/\r/, "") }`(`blanton_ber.sh` V1.0.1 的教訓) +- ⚠️ **`bcmcmd` 的 exit code 兩邊都不能信**:BCM shell 拒絕指令時它回 **0** + (`blanton_traffic_linespeed.sh` V0.3.1),而 `tr 518` 這種跑很久的指令會讓它 poll 逾時而回 + **非 0**,但指令其實已經在跑(`polling socket timeout: Success`)。可靠的作法是**找成功的證據** + ——例如 `tr 518` 印出 `TR 518 TEST PARAMETERS` 才算收下(`blanton_tr518.sh` V1.0.1) +- ⚠️ **交換晶片不會把封包從進來的那個 port 送回去**(source-port knockout)。所以單一 port 的 + VLAN 打不出持續流量:`tx 100` 就是一趟來回然後結束。`ce0` 靠 **ingress mirror 打回自己**繞過 + 這個限制(鏡像複本不經過 egress filter),**且不 stop 就不會自己停** - ⚠️ **DUT 的 awk 對 `%d` 會夾到 INT32**(2147483647)。線速流量的計數器是 ~10¹² 量級, 所以 awk 裡輸出大數一律用 `%.0f`(double 域,精確到 2⁵³)。`blanton_traffic_linespeed.sh` V0.4.1 已修;寫新的 awk 報表時要記得同一件事 diff --git a/docs/release-notes/v1.1.0.md b/docs/release-notes/v1.1.0.md new file mode 100644 index 0000000..81548ed --- /dev/null +++ b/docs/release-notes/v1.1.0.md @@ -0,0 +1,81 @@ +# v1.1.0 — BER, power under load, and a 100G port that actually keeps sending + +## ✨ New features + +**Whole-switch SerDes BER sweep** +* New `blanton_ber.sh` runs PRBS across every cabled port and reports the bit error rate lane by lane. `init` → `start` → wait → `report` → `stop` → `clear`, with `-u 0` / `-u 1` for a single switch unit. +* **A lane passes only when its BER is below 1e-6.** Equal to the threshold is a FAIL, not a pass. `-c ` sets a different bar. +* `report` ends with a summary across both units, and each unit's row carries its **worst lane** — so a run where everything passes still tells you how much margin there was: + + ``` + Unit LANES PASS FAIL NA WORST BER WORST LANE RESULT + unit 0 432 432 0 0 1.98e-08 203[0] PASS + unit 1 432 432 0 0 6.34e-10 366[1] PASS + ``` +* `init` also checks that every lane locked. This matters: an unlocked lane still reports a BER later, and it is a meaningless one. Without the check, a dead lane can report a beautiful number and pass. +* A lane whose reading is not a number is `NA` — counted separately from `FAIL`, because "not measured" and "measured and bad" are different problems. +* Script C runs the sweep after the traffic report, following `SWB_UNIT0` / `SWB_UNIT1` the same way the traffic block does. + +**TR518 load test, for measuring power under traffic** +* New `blanton_tr518.sh` puts the cd ports in loopback and runs the built-in `tr 518` packet test, then waits `TR_SETTLE_SEC` (120s by default) before handing back — so the power figures you take afterwards are loaded and settled, not caught mid-ramp. +* `-u 0` / `-u 1` for one unit; no flag runs both. +* `stop` sends `port cd lb=none` and nothing else, which is exactly what the bench procedure does. **L2 learning and test mode are left as `start` set them** — the tool says so on every `stop` rather than quietly leaving the box in a state you did not ask about. `TR_RESTORE_LEARN=1` / `TR_RESTORE_TESTMODE=1` if you want a true inverse. + +**Per-rail power readback for both switch boards** +* `TH6_SWB0_power_readback.sh` / `TH6_SWB1_power_readback.sh` report V × I and total power for the 19 rails on each board. + +## 🐛 Bug fixes + +**The power readback measured every rail at a different moment** +* It ran `show platform voltage` and `show platform current` once *per rail* — 38 invocations of a slow CLI, and 38 different instants. Under load the currents move a lot (`TH6_CORE` was seen going from 186 A to 636 A), so the "total" was a sum of readings taken seconds apart. Both tables are now read once, up front. Same output, one moment. +* A rail missing from the sensor table used to contribute a silent `0.000 V / 0.00 W` to the total. It now says so on stderr; the printed report format is unchanged. + +**The 100G port stopped sending after one round trip** +* `ce0` has no loopback partner, and a switch never forwards a frame back out the port it arrived on — so a `tx` burst went out, came back, and was dropped. TX 100, RX 100, silence. That measures the link; it does not exercise it. +* `init` now sets an ingress mirror of `ce0` back to itself. The mirrored copy is not egress-filtered, so each packet keeps lapping and the load is set by how much you inject (`-tx`). **`stop` is what ends it** — removing the VLAN membership does not, because the mirrored copy never consulted the VLAN. + +**The 100G verdict was being decided the wrong way** +* `ce0` was treated as a cross-unit check. The bench says otherwise: there is one `ce0` per unit and a burst sent on unit 0 alone came back on unit 0. It is now judged within its own unit. The distinction is invisible while everything works and decisive when it does not — read as cross-unit, *both* links dying still leaves `unit0.TX == unit1.RX` (0 == 0) and reports PASS. + +**Every BER lane reported `NA`, and the Port column printed `NA` too** +* `bcmcmd` returns CRLF, and the BER is the last token on its line, so the carriage return stayed glued to the number: it failed the numeric check, and printing it sent the cursor back to column 1 so the RESULT column overwrote the start of the row. Both symptoms, one stray `\r`. + +## 📦 Downloads + +| File | Contents | +|---|---| +| `Script_ABC_Blanton_V1.1.0.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT | + +**After copying to the DUT:** + +```bash +chmod +x ~/Blanton_Script/*.sh # see below +grep -rlU $'\r' ~/Blanton_Script # expect no output +``` + +`blanton_ber.sh` is invoked by Script C as `./Blanton_Script/blanton_ber.sh`, so it joins `bmc_monitor.sh` and `usb_target.sh` in needing the execute bit — and neither git nor a Windows/USB copy carries it reliably. Without the `chmod` the BER section fails with `Permission denied` and the log simply has no BER in it. + +## ⚠️ Before you run + +* **These three tests cannot share the switch.** `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed` all take over port loopback and L2 learning. Run one at a time; Script C already orders BER after the traffic report. +* **PRBS takes the links down.** While `blanton_ber.sh` is armed the ports report DOWN and no traffic passes. That is the test working, not a fault. `clear` releases them. +* **`ce0` keeps running until you stop it.** If a run is interrupted between `start` and `stop`, the 100G port stays saturated with nothing in `show interfaces status` to hint at it. `blanton_traffic_linespeed stop` (or `bcmcmd -n -c 'mirror port ce0 Mode=Off'`) ends it. +* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`. Change one without the other and `report` reads an interval that has not finished accumulating — with no warning. +* **`FAN_SPEED` is 100.** This build runs the fans flat out unless you change `config.ttl`. +* **Declare the switch population** with `SWB_UNIT0` / `SWB_UNIT1`; traffic, the readiness gate and now the BER sweep all follow it. +* **PRBS on the two 100G uplinks (`port_prbs_monitor.sh`) is still not wired into the macros.** Unchanged from v1.0.9. + +## 🔬 Not yet verified on hardware + +Three things in this build were reasoned out rather than measured, and each has a one-command check: + +* **The `ce0` ingress mirror.** `mirror port ce0 Mode=Ingress DestPort=ce0` should make the port circulate, but the hardware may refuse a mirror destination equal to its source. Check `show c | grep POK.ce0` twice ten seconds apart — the number must climb. The report cannot tell you: a one-shot burst is also `TX == RX` and also says PASS. Fallback is `tr 518 PortList=268`. +* **The 120s settle in `blanton_tr518.sh`.** If `tr 518`'s traffic is time-limited (its parameters include `runtime=1`, `CheckDataTime=200`), waiting 120s could mean measuring after the load has already dropped. Compare a power readback at 0s, 30s and 120s. +* **`test mode nr=no`** in `blanton_tr518.sh` is the derived inverse of the `nr=yes` that `start` sends; it is not part of the bench-verified sequence, and is off by default. + +## 🔗 Links + +* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints +* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas + +**Full changelog:** [V1.0.11...V1.1.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.11...V1.1.0) diff --git a/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl b/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl index 53222cf..f1f4b81 100644 --- a/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl +++ b/src/Script_ABC_Blanton/1_Blanton_Script_A.ttl @@ -1,6 +1,6 @@ ; ============================================================================= ; Script A for Blanton -; Version : V1.0.11 +; Version : V1.1.0 ; Date : 2026-08-28 ; Author : ETWen ; ============================================================================= @@ -95,6 +95,43 @@ ; LTC2980_Margin_Script/Ref/*.md 0x15 trace note corrected to send-byte ; LTC2980_Margin_Script/script/margin_save_all.sh Point at margin_save all; keep it for subsets ; config.ttl FAN_SPEED 30 -> 100 (full speed by default) +; V1.1.0 2026-08-28 Blanton_Script/blanton_ber.sh Add whole-switch SerDes BER test (PRBS via phydiag) +; init / start / report / stop / clear, -u 0|1|all +; report: one row per lane, PASS when BER < 1e-6, then +; a summary across units carrying the worst lane +; init also checks every lane locked - an unlocked lane +; still reports a BER, and it is a meaningless one +; !! PRBS takes the SerDes out of normal operation: +; links show DOWN, no traffic passes while it runs +; Blanton_Script/blanton_tr518.sh Add TR518 packet test - loads the switch so the rails +; can be measured under traffic +; start [-u 0|1] then settles 120s (TR_SETTLE_SEC), so +; the power read afterwards is loaded, not ramping +; stop = port cd lb=none, exactly what TR518.txt does; +; l2 learn / test mode are NOT put back - stop says so +; Blanton_Script/TH6_SWB{0,1}_power_readback.sh Read the sensor tables ONCE, not once per rail +; 38 'show platform' calls -> 2. The old loop sampled +; each rail at a different instant, so the total was a +; sum of readings seconds apart. Output format unchanged +; A rail missing from the table now warns on stderr +; instead of silently counting as 0 W +; Blanton_Script/blanton_traffic_linespeed.sh Add the 100G uplink (ce0, VLAN 138) to the test +; ce0 has no loopback partner and a switch will not send +; a frame back out its ingress port, so a tx burst was +; one round trip. An INGRESS MIRROR of ce0 back to ce0 +; keeps it circulating until stop turns the mirror off +; !! stop MUST run - the loop does not end on its own +; report: ce0 is the last row; a summary at the bottom +; carries every unit's PASS / FAIL / NA totals +; ScriptC Run the BER sweep, after the traffic report so the +; two do not fight over the same ports +; Follows SWB_UNIT0/SWB_UNIT1 like the traffic block: +; -u 0 / -u 1 / skip, so a single-unit DUT is not asked +; for counters from a board it does not have +; tools/BER_Test.txt Bench command references for the two new scripts +; tools/100G_Traffic.txt +; tools/TR518.txt Corrected on the bench: port cd (not *:port all), +; testphase=1, and an explicit stop ; ============================================================================= include "config.ttl" diff --git a/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl b/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl index 234bdfe..02d5838 100644 --- a/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl +++ b/src/Script_ABC_Blanton/3_Blanton_Script_C.ttl @@ -120,6 +120,54 @@ else endif +; ========== BER ========== +; PRBS takes the SerDes out of normal operation, so this runs AFTER the +; traffic report. sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting +; earlier reads an interval that has not finished accumulating. +if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh init" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh start" + wait prompt_sonic_root + sendln "sleep 30" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh report" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh stop" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh clear" +elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh init -u 0" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh start -u 0" + wait prompt_sonic_root + sendln "sleep 30" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh report -u 0" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh stop -u 0" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh clear -u 0" +elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh init -u 1" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh start -u 1" + wait prompt_sonic_root + sendln "sleep 30" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh report -u 1" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh stop -u 1" + wait prompt_sonic_root + sendln "./Blanton_Script/blanton_ber.sh clear -u 1" +else + +endif + + ; ========== NVME Err Info ========== wait prompt_sonic_root sendln "/usr/sbin/nvme smart-log -H /dev/nvme0" diff --git a/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB0_power_readback.sh b/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB0_power_readback.sh new file mode 100644 index 0000000..237c833 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB0_power_readback.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# ============================================================================= +# TH6_SWB0_power_readback.sh -- SWB0 rail power from the platform sensors +# ============================================================================= +# Version History: +# V1.1.0 2026-08-28 'show platform voltage' and 'show platform current' are +# now read ONCE each instead of once per rail. The old +# loop ran them 19 times apiece (38 invocations of a slow +# Python CLI) and every sample came from a different +# instant, so the rails were never actually measured +# together. Output format is unchanged. +# Rails missing from the tables are reported on stderr +# instead of silently contributing 0.000 V / 0.00 W. +# V1.0.0 2026-08-28 First version. +# ============================================================================= +# +# Reads the two platform sensor tables: +# 'show platform voltage' -> in mV +# 'show platform current' -> _CURRENT in mA +# and reports V x I per rail plus the total. +# +# For a loaded reading, start traffic first: blanton_tr518.sh start +# ============================================================================= + +# --- Rails to report, in output order (edit this list) --- +rails=( + "SWB0_0V9_ANLG0" + "SWB0_0V9_ANLG1" + "SWB0_0V75_ANLG0" + "SWB0_0V75_ANLG1" + "SWB0_PHYTILE_P0" + "SWB0_PHYTILE_P1" + "SWB0_PHYTILE_P2" + "SWB0_PHYTILE_P3" + "SWB0_PHYTILE_P4" + "SWB0_PHYTILE_P5" + "SWB0_PHYTILE_P6" + "SWB0_PHYTILE_P7" + "SWB0_PVDD1V5_CNDR0" + "SWB0_PVDD1V5_CNDR1" + "SWB0_PVDDA_PHYT0" + "SWB0_PVDDA_PHYT1" + "SWB0_PVDDA_PHYT2" + "SWB0_PVDDA_PHYT3" + "SWB0_TH6_CORE" +) + +# --- One snapshot of each table --------------------------------------------- +# Both are taken up front, back to back, so every rail below comes from the same +# moment. Under tr 518 the currents move a lot; re-reading per rail meant the +# total was a sum of readings taken seconds apart. +V_TABLE="$(show platform voltage 2>/dev/null)" +C_TABLE="$(show platform current 2>/dev/null)" + +if [ -z "$V_TABLE" ] || [ -z "$C_TABLE" ]; then + echo "ERROR: 'show platform voltage/current' returned nothing" >&2 + exit 1 +fi + +# --- Join and report --------------------------------------------------------- +# Sensor name is field 1 and the value field 2 in both tables; header and rule +# lines drop out because their field 2 is not numeric. +{ + printf '%s\n' "$V_TABLE" + echo "@@@SPLIT@@@" + printf '%s\n' "$C_TABLE" +} | awk -v rails="${rails[*]}" ' + BEGIN { n = split(rails, R, " "); sec = 1 } + /^@@@SPLIT@@@$/ { sec = 2; next } + { + if (NF < 2) next + name = $1; val = $2 + if (val !~ /^[0-9]+(\.[0-9]+)?$/) next # header / ---- / blank + if (sec == 2) CUR[name] = val + 0 + else VOLT[name] = val + 0 + } + END { + total = 0 + for (i = 1; i <= n; i++) { + rail = R[i]; cname = rail "_CURRENT" + haveV = (rail in VOLT); haveC = (cname in CUR) + if (!haveV || !haveC) + printf "WARN: %s missing from the sensor table (%s%s%s) -- counted as 0 W\n", \ + rail, (haveV ? "" : "no voltage"), \ + ((!haveV && !haveC) ? ", " : ""), \ + (haveC ? "" : "no current") > "/dev/stderr" + v = haveV ? VOLT[rail] : 0 + c = haveC ? CUR[cname] : 0 + p = sprintf("%.2f", (v/1000)*(c/1000)) + printf "%s: Voltage=%.3f V, Current=%.3f A, Power=%.2f W\n", rail, v/1000, c/1000, p + total = sprintf("%.2f", total + p) + } + print "----------------------------------------" + printf "TOTAL POWER: %.2f W\n", total + }' diff --git a/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB1_power_readback.sh b/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB1_power_readback.sh new file mode 100644 index 0000000..45ec2c2 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/TH6_SWB1_power_readback.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# ============================================================================= +# TH6_SWB1_power_readback.sh -- SWB1 rail power from the platform sensors +# ============================================================================= +# Version History: +# V1.1.0 2026-08-28 'show platform voltage' and 'show platform current' are +# now read ONCE each instead of once per rail. The old +# loop ran them 19 times apiece (38 invocations of a slow +# Python CLI) and every sample came from a different +# instant, so the rails were never actually measured +# together. Output format is unchanged. +# Rails missing from the tables are reported on stderr +# instead of silently contributing 0.000 V / 0.00 W. +# V1.0.0 2026-08-28 First version. +# ============================================================================= +# +# Reads the two platform sensor tables: +# 'show platform voltage' -> in mV +# 'show platform current' -> _CURRENT in mA +# and reports V x I per rail plus the total. +# +# For a loaded reading, start traffic first: blanton_tr518.sh start +# ============================================================================= + +# --- Rails to report, in output order (edit this list) --- +rails=( + "SWB1_0V9_ANLG0" + "SWB1_0V9_ANLG1" + "SWB1_0V75_ANLG0" + "SWB1_0V75_ANLG1" + "SWB1_PHYTILE_P0" + "SWB1_PHYTILE_P1" + "SWB1_PHYTILE_P2" + "SWB1_PHYTILE_P3" + "SWB1_PHYTILE_P4" + "SWB1_PHYTILE_P5" + "SWB1_PHYTILE_P6" + "SWB1_PHYTILE_P7" + "SWB1_PVDD1V5_CNDR0" + "SWB1_PVDD1V5_CNDR1" + "SWB1_PVDDA_PHYT0" + "SWB1_PVDDA_PHYT1" + "SWB1_PVDDA_PHYT2" + "SWB1_PVDDA_PHYT3" + "SWB1_TH6_CORE" +) + +# --- One snapshot of each table --------------------------------------------- +# Both are taken up front, back to back, so every rail below comes from the same +# moment. Under tr 518 the currents move a lot; re-reading per rail meant the +# total was a sum of readings taken seconds apart. +V_TABLE="$(show platform voltage 2>/dev/null)" +C_TABLE="$(show platform current 2>/dev/null)" + +if [ -z "$V_TABLE" ] || [ -z "$C_TABLE" ]; then + echo "ERROR: 'show platform voltage/current' returned nothing" >&2 + exit 1 +fi + +# --- Join and report --------------------------------------------------------- +# Sensor name is field 1 and the value field 2 in both tables; header and rule +# lines drop out because their field 2 is not numeric. +{ + printf '%s\n' "$V_TABLE" + echo "@@@SPLIT@@@" + printf '%s\n' "$C_TABLE" +} | awk -v rails="${rails[*]}" ' + BEGIN { n = split(rails, R, " "); sec = 1 } + /^@@@SPLIT@@@$/ { sec = 2; next } + { + if (NF < 2) next + name = $1; val = $2 + if (val !~ /^[0-9]+(\.[0-9]+)?$/) next # header / ---- / blank + if (sec == 2) CUR[name] = val + 0 + else VOLT[name] = val + 0 + } + END { + total = 0 + for (i = 1; i <= n; i++) { + rail = R[i]; cname = rail "_CURRENT" + haveV = (rail in VOLT); haveC = (cname in CUR) + if (!haveV || !haveC) + printf "WARN: %s missing from the sensor table (%s%s%s) -- counted as 0 W\n", \ + rail, (haveV ? "" : "no voltage"), \ + ((!haveV && !haveC) ? ", " : ""), \ + (haveC ? "" : "no current") > "/dev/stderr" + v = haveV ? VOLT[rail] : 0 + c = haveC ? CUR[cname] : 0 + p = sprintf("%.2f", (v/1000)*(c/1000)) + printf "%s: Voltage=%.3f V, Current=%.3f A, Power=%.2f W\n", rail, v/1000, c/1000, p + total = sprintf("%.2f", total + p) + } + print "----------------------------------------" + printf "TOTAL POWER: %.2f W\n", total + }' diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_ber.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_ber.sh new file mode 100644 index 0000000..eac1d52 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_ber.sh @@ -0,0 +1,495 @@ +#!/usr/bin/env bash +# ============================================================================= +# blanton_ber.sh -- SerDes BER test over every cabled port (PRBS via phydiag) +# ============================================================================= +# Version History: +# V1.0.1 2026-08-28 Fix: every lane reported NA and the Port column showed +# "NA". bcmcmd returns CRLF, and the BER is the last token +# on its line, so the CR stayed glued to the number: it +# failed the numeric test (-> NA) and printing it sent the +# cursor back to column 1, so the RESULT column overwrote +# the start of the row. The parser now strips CR first. +# (The traffic report never hit this -- there the counter +# is followed by a delta, so the CR was trimmed with it.) +# V1.0.0 2026-08-28 First version. Bash port of tools/BER_Test.txt. +# init/clear/start/stop/report, -u 0|1|all (default both). +# report parses 'prbsstat Ber' into a per-lane table with a +# PASS/FAIL against BER_MAX (default 1e-6) and a summary +# across units at the very bottom. +# ============================================================================= +# +# This is the WHOLE-SWITCH BER sweep: every cabled port, both lanes, PRBS-31 +# through the SerDes. Not to be confused with port_prbs_monitor.sh, which drives +# the two 100G uplinks only and polls them continuously. +# +# Order of operations (matches tools/BER_Test.txt): +# init phydiag prbs set p=3 arm PRBS on every lane +# phydiag prbs get confirm every lane locked +# start phydiag prbsstat STArt Interval= +# ...wait at least one Interval... +# report phydiag prbsstat Ber read + judge +# stop phydiag prbsstat STOp +# clear phydiag prbs clear disarm, release the lanes +# +# ⚠️ 'clear' disarms PRBS -- run 'init' again before another measurement. +# ⚠️ PRBS takes the SerDes out of normal operation: the links report DOWN and no +# traffic passes while it is armed. Do not run this alongside +# blanton_traffic_linespeed or blanton_tr518. +# +# Usage (run directly): +# ./blanton_ber.sh init # both units +# ./blanton_ber.sh start -u 0 # unit 0 only +# ./blanton_ber.sh report +# ./blanton_ber.sh stop +# ./blanton_ber.sh clear +# +# Usage (sourced, like the other blanton_*.sh tools): +# source blanton_ber.sh +# blanton_ber report -u 1 +# +# Options: +# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $BER_UNITS ("0 1") +# -c|--criteria report: PASS threshold (default $BER_MAX) +# -i|--interval start: prbsstat Interval (default $BER_INTERVAL) +# -p|--ports override the port list +# -F|--fail-only report: list only the lanes that FAIL +# --tsv report: tab-separated (paste into Excel) +# --raw report: also print the raw 'prbsstat Ber' output +# --color|--no-color report: force / disable colours +# -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 +# -h|--help help +# +# Environment overrides: +# BCMCMD_CMD=bcmcmd BER_UNITS="0 1" BER_MAX=1e-6 BER_INTERVAL=30 +# BER_PORTS="1-24,..." BER_POLY=p=3 BER_LOG_DIR=/tmp DEBUG_MODE=1 +# ============================================================================= + +# === Config ================================================================== +BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}" +BER_UNITS="${BER_UNITS:-0 1}" # one DUT = two switch boards (0 and 1) + +# The cabled ports, in bcm logical-port numbering. Same list as +# blanton_traffic_linespeed.sh's TL_PS_PORTS -- kept as one string so it can be +# pasted straight from/into a manual phydiag command. +BER_PORTS="${BER_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}" + +BER_POLY="${BER_POLY:-p=3}" # passed to 'prbs set' +BER_INTERVAL="${BER_INTERVAL:-30}" # passed to 'prbsstat STArt Interval=' + +# PASS threshold. A lane PASSES when its BER is strictly BELOW this. +# 1e-6 is the acceptance figure for this project; the measured lanes sit around +# 1e-13..1e-8, so anything near the threshold is already a real finding. +BER_MAX="${BER_MAX:-1e-6}" + +BER_LOG_DIR="${BER_LOG_DIR:-/tmp}" # where the raw 'prbsstat Ber' capture goes +BER_FAIL_ONLY=${BER_FAIL_ONLY:-0} +BER_TSV=${BER_TSV:-0} +BER_RAW=${BER_RAW:-0} +BER_REPORT_FILE="" # -f : parse this instead of the DUT +BER_COLOR="${BER_COLOR:-auto}" # auto|always|never + +DEBUG_MODE=${DEBUG_MODE:-0} +BER_DRY_RUN=${BER_DRY_RUN:-0} + +# === Logging ================================================================= +_ber_info() { echo -e "[\033[34mINFO\033[0m] $*"; } +_ber_ok() { echo -e "[\033[32m OK \033[0m] $*"; } +_ber_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; } +_ber_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; } +_ber_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; } + +# === bcmcmd wrapper ========================================================== +# stdin closed for the same reason as blanton_traffic_linespeed.sh: bcmcmd +# otherwise inherits the caller's stdin and eats what a surrounding loop reads. +# +# bcmcmd exits 0 even when the BCM shell refused the command, so the output is +# pattern-matched as well. And it exits NON-zero on long-running commands whose +# response poll times out while the command is in fact fine -- that one is +# tolerated (the blanton_tr518.sh lesson). +BER_ERR_PAT="${BER_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}" +BER_BENIGN_PAT="${BER_BENIGN_PAT:-polling socket timeout}" + +# _ber_bcm -- wraps in dsh -c 'phydiag ...' +# echoes the DUT output on stdout, returns 0 ok / 1 failed +_ber_bcm() { + local unit="$1"; shift + local inner="phydiag ${BER_PORTS} $*" + local cmd="dsh -c '${inner}'" + _ber_dbg "$BCMCMD_CMD -n $unit -c \"${cmd}\"" + if [ "$BER_DRY_RUN" = "1" ]; then + echo "[DRY ] $BCMCMD_CMD -n $unit -c \" ${cmd} \"" >&2 + return 0 + fi + local out rc + out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" &1); rc=$? + printf '%s\n' "$out" + if echo "$out" | grep -qiE "$BER_ERR_PAT"; then + _ber_err "unit $unit: the BCM shell rejected 'phydiag ... $*'" + return 1 + fi + if [ "$rc" -ne 0 ] && ! echo "$out" | grep -qiE "$BER_BENIGN_PAT"; then + _ber_err "unit $unit: bcmcmd exited $rc on 'phydiag ... $*'" + return 1 + fi + return 0 +} + +_ber_units_check() { + local u ok="" + for u in $BER_UNITS; do + case "$u" in + 0|1) ok="$ok $u" ;; + *) _ber_err "invalid unit '$u' (use 0, 1 or all)"; return 1 ;; + esac + done + [ -n "$ok" ] || { _ber_err "no unit selected"; return 1; } + BER_UNITS="${ok# }" + return 0 +} + +_ber_use_color() { + case "$BER_COLOR" in + always|1|yes) return 0 ;; + never|0|no) return 1 ;; + *) [ -t 1 ] && [ "$BER_TSV" != "1" ] ;; + esac +} + +# === init ==================================================================== +# prbs set + prbs get. The 'get' is not decoration: a lane that did not lock +# still reports a BER later, and it is a meaningless one. +blanton_ber_init() { + _ber_units_check || return 1 + local unit out total ok rc=0 + for unit in $BER_UNITS; do + _ber_info "unit $unit: prbs set ${BER_POLY} on ${BER_PORTS}" + _ber_bcm "$unit" "prbs set ${BER_POLY}" >/dev/null || { rc=1; continue; } + + out=$(_ber_bcm "$unit" "prbs get") || { rc=1; continue; } + [ "$BER_DRY_RUN" = "1" ] && continue + # lines look like: " 185 : PRBS OK!has been unlocked since last call" + total=$(printf '%s\n' "$out" | grep -cE '^[ \t]*[0-9]+[ \t]*:') + ok=$(printf '%s\n' "$out" | grep -cE '^[ \t]*[0-9]+[ \t]*:.*PRBS OK') + if [ "$total" -eq 0 ]; then + _ber_err "unit $unit: 'prbs get' reported no lanes at all" + rc=1 + elif [ "$ok" -eq "$total" ]; then + _ber_ok "unit $unit: $ok/$total ports locked" + else + _ber_warn "unit $unit: only $ok/$total ports locked -- the rest will report a meaningless BER:" + printf '%s\n' "$out" | grep -E '^[ \t]*[0-9]+[ \t]*:' | grep -v 'PRBS OK' >&2 + rc=2 + fi + done + return $rc +} + +# === clear =================================================================== +blanton_ber_clear() { + _ber_units_check || return 1 + local unit rc=0 + for unit in $BER_UNITS; do + _ber_info "unit $unit: prbs clear" + _ber_bcm "$unit" "prbs clear" >/dev/null || rc=1 + done + [ "$rc" -eq 0 ] && _ber_ok "PRBS disarmed on unit(s): $BER_UNITS -- run 'init' before measuring again" + return $rc +} + +# === start =================================================================== +blanton_ber_start() { + _ber_units_check || return 1 + local unit rc=0 + for unit in $BER_UNITS; do + _ber_info "unit $unit: prbsstat STArt Interval=${BER_INTERVAL}" + _ber_bcm "$unit" "prbsstat STArt Interval=${BER_INTERVAL}" >/dev/null || rc=1 + done + if [ "$rc" -eq 0 ]; then + _ber_ok "BER accumulation running on unit(s): $BER_UNITS" + _ber_info "wait at least ${BER_INTERVAL}s before 'report' -- a shorter run has not accumulated a full interval" + fi + return $rc +} + +# === stop ==================================================================== +blanton_ber_stop() { + _ber_units_check || return 1 + local unit rc=0 + for unit in $BER_UNITS; do + _ber_info "unit $unit: prbsstat STOp" + _ber_bcm "$unit" "prbsstat STOp" >/dev/null || rc=1 + done + if [ "$rc" -eq 0 ]; then + _ber_ok "BER accumulation stopped on unit(s): $BER_UNITS" + _ber_info "PRBS is still armed -- 'clear' releases the lanes and restores normal operation" + fi + return $rc +} + +# === report ================================================================== +# Parses 'prbsstat Ber' output: +# port BER +# ==== +# 1[0] : 3.53e-11 +# 1[1] : 4.00e-11 +# into , PASS when ber < BER_MAX. +# _ber_render [side_file] -> 0 all PASS, 2 any FAIL/NA, 1 parse error +_ber_render() { + local log="$1" side="${2:-/dev/null}" color=0 + _ber_use_color && color=1 + awk -v MAXBER="$BER_MAX" \ + -v FAILONLY="$BER_FAIL_ONLY" \ + -v TSV="$BER_TSV" \ + -v COLOR="$color" \ + -v SIDE="$side" ' + 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" + } + BEGIN { + LIM = MAXBER + 0 + NC = 4 + HDR[1] = "Port"; AL[1] = 1 + HDR[2] = "Lane"; AL[2] = 1 + HDR[3] = "BER"; AL[3] = 1 + HDR[4] = "RESULT"; AL[4] = 1 + worst = -1; worstlane = "-" + } + # bcmcmd hands back CRLF. On the cd/traffic report the counter is followed by + # a delta, so the CR got trimmed with the rest of the line; here the BER is + # the LAST token, so the CR sticks to the number -- it failed the numeric + # test (every lane NA) and, worse, printing it moved the cursor back to + # column 1 so the RESULT column overwrote the start of the row. + { gsub(/\r/, "") } + + { + # " 203[1] : 5.05e-09" (leading spaces vary, "====" separators ignored) + if ($0 !~ /^[ \t]*[0-9]+\[[0-9]+\][ \t]*:/) next + line = $0 + sub(/^[ \t]+/, "", line) + p = index(line, "[") + q = index(line, "]") + c = index(line, ":") + port = substr(line, 1, p - 1) + lane = substr(line, p + 1, q - p - 1) + ber = substr(line, c + 1) + gsub(/^[ \t\r]+|[ \t\r]+$/, "", ber) + sub(/[ \t\r].*$/, "", ber) + seen++ + n++ + PORT[n] = port; LANE[n] = lane; BERS[n] = ber + # a lane that reported something non-numeric has no usable measurement + if (ber ~ /^[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/) { + v = ber + 0 + if (v < LIM) { V[n] = "PASS"; npass++ } + else { V[n] = "FAIL"; nfail++ } + if (v > worst) { worst = v; worstlane = port "[" lane "]"; worststr = ber } + } else { + V[n] = "NA"; nna++ + } + } + END { + if (seen == 0) { + print "error: no \"[] : \" line found in the log" > "/dev/stderr" + exit 1 + } + # column widths over the rows that will actually be printed + for (c2 = 1; c2 <= NC; c2++) w[c2] = length(HDR[c2]) + for (i = 1; i <= n; i++) { + if (FAILONLY && V[i] == "PASS") continue + if (length(PORT[i]) > w[1]) w[1] = length(PORT[i]) + if (length(LANE[i]) > w[2]) w[2] = length(LANE[i]) + if (length(BERS[i]) > w[3]) w[3] = length(BERS[i]) + if (length(V[i]) > w[4]) w[4] = length(V[i]) + } + for (c2 = 1; c2 <= NC; c2++) w[c2] += 2 + + if (TSV) { + print HDR[1] "\t" HDR[2] "\t" HDR[3] "\t" HDR[4] + for (i = 1; i <= n; i++) { + if (FAILONLY && V[i] == "PASS") continue + print PORT[i] "\t" LANE[i] "\t" BERS[i] "\t" V[i] + } + } else { + printf "%*s%*s%*s%*s\n", w[1], HDR[1], w[2], HDR[2], w[3], HDR[3], w[4], HDR[4] + for (i = 1; i <= n; i++) { + if (FAILONLY && V[i] == "PASS") continue + printf "%*s%*s%*s", w[1], PORT[i], w[2], LANE[i], w[3], BERS[i] + # pad on the plain text, then colour, so the columns stay aligned + printf "%*s%s\n", w[4] - length(V[i]), "", vc(V[i]) + } + if (FAILONLY && nfail == 0 && nna == 0) + print " (no failing lane)" + } + + print "" + printf "# lanes measured : %d\n", n + printf "# %s %d %s %d %s %d (criteria BER < %s)\n", \ + vc("PASS"), npass + 0, vc("FAIL"), nfail + 0, vc("NA"), nna + 0, MAXBER + if (worst >= 0) + printf "# worst lane : %s %s\n", worstlane, worststr + if (SIDE != "" && SIDE != "/dev/null") + printf "SUM %d %d %d %d %s %s\n", n, npass + 0, nfail + 0, nna + 0, \ + (worst >= 0 ? worststr : "-"), worstlane > SIDE + exit (nfail || nna) ? 2 : 0 + }' "$log" +} + +# _ber_summary -- one table for every unit, printed last +_ber_summary() { + local stamp="$1" unit side g r y n worst=0 + g=$'\033[32m'; r=$'\033[31m'; y=$'\033[33m'; n=$'\033[0m' + _ber_use_color || { g=""; r=""; y=""; n=""; } + + echo "" + echo "===== summary : all units =====" + printf '%-8s %8s %8s %8s %8s %-12s %-10s %s\n' \ + "Unit" "LANES" "PASS" "FAIL" "NA" "WORST BER" "WORST LANE" "RESULT" + + local tag lanes pass fail na wber wlane v any=0 + for unit in $BER_UNITS; do + side="$BER_LOG_DIR/berside_unit${unit}_${stamp}" + [ -r "$side" ] || continue + read -r tag lanes pass fail na wber wlane < "$side" 2>/dev/null + [ "$tag" = "SUM" ] || continue + any=1 + if [ "${fail:-0}" -gt 0 ] || [ "${na:-0}" -gt 0 ]; then + v="${r}FAIL${n}"; worst=2 + else + v="${g}PASS${n}" + fi + printf '%-8s %8s %8s %8s %8s %-12s %-10s %b\n' \ + "unit $unit" "$lanes" "$pass" "$fail" "$na" "$wber" "$wlane" "$v" + done + [ "$any" = "1" ] || echo " (no unit produced a result)" + echo "" + printf 'criteria: BER < %s\n' "$BER_MAX" + echo "" + return "$worst" +} + +blanton_ber_report() { + local unit log side rc worst=0 stamp + + # -f : offline, no DUT access, no unit loop -> no cross-unit summary + if [ -n "$BER_REPORT_FILE" ]; then + [ -r "$BER_REPORT_FILE" ] || { _ber_err "cannot read log '$BER_REPORT_FILE'"; return 1; } + _ber_info "report from log: $BER_REPORT_FILE (criteria BER < $BER_MAX)" >&2 + _ber_render "$BER_REPORT_FILE"; return $? + fi + + _ber_units_check || return 1 + if [ "$BER_DRY_RUN" = "1" ]; then + for unit in $BER_UNITS; do _ber_bcm "$unit" "prbsstat Ber" >/dev/null; done + return 0 + fi + + stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now) + for unit in $BER_UNITS; do + log="$BER_LOG_DIR/prbsber_unit${unit}_${stamp}.log" + side="$BER_LOG_DIR/berside_unit${unit}_${stamp}" + : > "$side" + if ! _ber_bcm "$unit" "prbsstat Ber" > "$log" 2>&1; then + _ber_err "unit $unit: 'prbsstat Ber' failed (see $log)"; worst=1; continue + fi + [ "$BER_RAW" = "1" ] && { echo "----- unit $unit : raw prbsstat Ber -----"; cat "$log"; } + echo "===== unit $unit : PRBS BER report (raw: $log) =====" + _ber_render "$log" "$side"; rc=$? + [ "$rc" -gt "$worst" ] && worst=$rc + case "$rc" in + 0) _ber_ok "unit $unit: every lane below $BER_MAX" ;; + 2) _ber_warn "unit $unit: at least one lane FAIL/NA" ;; + *) _ber_err "unit $unit: report parse error" ;; + esac + done + + _ber_summary "$stamp"; rc=$? + [ "$rc" -gt "$worst" ] && worst=$rc + rm -f "$BER_LOG_DIR"/berside_unit*_"${stamp}" + return "$worst" +} + +# === Help ==================================================================== +blanton_ber_help() { + echo -e "\033[1mblanton_ber.sh - SerDes BER test over every cabled port (PRBS via phydiag)\033[0m" + echo "" + echo -e " Units : \033[36m$BER_UNITS\033[0m poly: \033[36m$BER_POLY\033[0m interval: \033[36m${BER_INTERVAL}s\033[0m" + echo -e " Criteria : BER < \033[36m$BER_MAX\033[0m" + echo -e " Ports : \033[36m$BER_PORTS\033[0m" + echo "" + echo -e "\033[1mSubcommands\033[0m" + echo -e " \033[33minit\033[0m prbs set $BER_POLY + prbs get (checks every lane locked)" + echo -e " \033[33mstart\033[0m prbsstat STArt Interval=$BER_INTERVAL" + echo -e " \033[33mreport\033[0m prbsstat Ber -> per-lane table + PASS/FAIL + summary" + echo -e " \033[33mstop\033[0m prbsstat STOp" + echo -e " \033[33mclear\033[0m prbs clear (disarms PRBS -- 'init' again before measuring)" + 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: $BER_UNITS)" + echo -e " \033[33m-c|--criteria\033[0m PASS threshold (default $BER_MAX)" + echo -e " \033[33m-i|--interval\033[0m prbsstat Interval (default $BER_INTERVAL)" + echo -e " \033[33m-p|--ports\033[0m override the port list" + echo -e " \033[33m-F|--fail-only\033[0m report: list only failing lanes" + echo -e " \033[33m--tsv\033[0m report: tab-separated" + echo -e " \033[33m--raw\033[0m report: also print the raw output" + echo -e " \033[33m-f|--file\033[0m report: parse a saved log, do not touch the DUT" + echo -e " \033[33m-d|--debug\033[0m print every bcmcmd" + echo -e " \033[33m-n|--dry-run\033[0m print commands only" + echo "" + echo -e "\033[1mTypical run\033[0m" + echo -e " ./blanton_ber.sh init && ./blanton_ber.sh start" + echo -e " sleep $BER_INTERVAL" + echo -e " ./blanton_ber.sh report" + echo -e " ./blanton_ber.sh stop && ./blanton_ber.sh clear" + echo "" + echo -e "\033[33m PRBS takes the SerDes out of normal operation: links show DOWN and no\033[0m" + echo -e "\033[33m traffic passes. Do not run alongside blanton_traffic_linespeed / blanton_tr518.\033[0m" +} + +# === Argument parsing ======================================================== +blanton_ber() { + local sub="${1:-help}"; shift 2>/dev/null + while [ $# -gt 0 ]; do + case "$1" in + -u|--unit) + case "$2" in + all|ALL) BER_UNITS="0 1" ;; + *) BER_UNITS="$(echo "$2" | tr ',' ' ')" ;; + esac + shift 2 ;; + -c|--criteria) BER_MAX="$2"; shift 2 ;; + -i|--interval) BER_INTERVAL="$2"; shift 2 ;; + -p|--ports) BER_PORTS="$2"; shift 2 ;; + -f|--file) BER_REPORT_FILE="$2"; shift 2 ;; + -F|--fail-only) BER_FAIL_ONLY=1; shift ;; + --tsv) BER_TSV=1; shift ;; + --raw) BER_RAW=1; shift ;; + --color) BER_COLOR=always; shift ;; + --no-color) BER_COLOR=never; shift ;; + -d|--debug) DEBUG_MODE=1; shift ;; + -n|--dry-run) BER_DRY_RUN=1; shift ;; + -h|--help) blanton_ber_help; return 0 ;; + *) _ber_err "unknown option '$1'"; return 1 ;; + esac + done + + case "$sub" in + init) blanton_ber_init ;; + clear) blanton_ber_clear ;; + start) blanton_ber_start ;; + stop) blanton_ber_stop ;; + report) blanton_ber_report ;; + help|-h|--help) blanton_ber_help ;; + *) _ber_err "unknown subcommand '$sub'"; blanton_ber_help; return 1 ;; + esac +} + +# Run when executed, define-only when sourced (same as the other blanton_*.sh). +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + blanton_ber "$@" +fi diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518.sh new file mode 100644 index 0000000..7504ac0 --- /dev/null +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_tr518.sh @@ -0,0 +1,326 @@ +#!/usr/bin/env bash +# ============================================================================= +# blanton_tr518.sh -- TH6 built-in packet test (tr 518) via bcmcmd +# ============================================================================= +# Version History: +# V1.0.1 2026-08-28 Fix: start reported ERR on a run that was actually fine. +# bcmcmd exits NON-zero on 'tr 518' because the test +# outlives its response poll ("polling socket timeout: +# Success") -- the command had been accepted and was +# running. The tr 518 step is now judged on a POSITIVE +# marker in the output ("TR 518 TEST PARAMETERS", which +# the shell prints only after it starts the test) instead +# of on bcmcmd's exit status, and "polling socket timeout" +# is tolerated generally. Failures now also say WHICH +# check tripped (shell rejected it / bcmcmd exited N). +# V1.0.0 2026-08-28 First version. Bash port of tools/TR518.txt, command for +# command. start = port cd lb=mac, l2 learn off, +# test mode nr=yes, tr 518 ... testphase=1, then a settle +# wait so a power reading taken afterwards is a loaded and +# stable one rather than a ramping one. +# stop = port cd lb=none (exactly what TR518.txt does). +# -u 0 | -u 1 | -u all (default both). +# ============================================================================= +# +# What this is for: tr 518 loads the switch so the power rails can be measured +# under traffic. The usual sequence is +# +# blanton_tr518.sh start # loads both units, waits to settle +# TH6_SWB0_power_readback.sh # now the numbers mean something +# TH6_SWB1_power_readback.sh +# blanton_tr518.sh stop +# +# ⚠️ tr 518 and blanton_traffic_linespeed CANNOT run at the same time. Both take +# over the cd ports and L2 learning; running one while the other is set up +# gives numbers from neither test. Stop one before the other starts. +# +# ⚠️ stop only undoes the loopback -- see TR_RESTORE_* below. +# +# Usage (run directly): +# ./blanton_tr518.sh start # both units +# ./blanton_tr518.sh start -u 0 # unit 0 only +# ./blanton_tr518.sh start -u 1 # unit 1 only +# ./blanton_tr518.sh stop [-u 0|1] +# ./blanton_tr518.sh help +# +# Usage (sourced, like the other blanton_*.sh tools): +# source blanton_tr518.sh +# blanton_tr518 start -u 0 +# +# Options: +# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TR_UNITS ("0 1") +# -w|--wait start: settle wait after tr 518 (default $TR_SETTLE_SEC) +# --no-wait start: skip the settle wait entirely +# -d|--debug print every bcmcmd and its output +# -n|--dry-run print commands only, do not touch the DUT +# -h|--help help +# +# Environment overrides: +# BCMCMD_CMD=bcmcmd TR_UNITS="0 1" TR_SETTLE_SEC=120 TR_UNIT_GAP_SEC=1 +# TR_TEST_ARGS="..." TR_LB_PORTS=cd TR_RESTORE_LEARN=0 TR_RESTORE_TESTMODE=0 +# DEBUG_MODE=1 +# ============================================================================= + +# === Config ================================================================== +BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}" +TR_UNITS="${TR_UNITS:-0 1}" # one DUT = two switch boards (0 and 1) + +# Settle wait after tr 518 is issued. The point is NOT the test itself -- it is +# to stop someone reading power while traffic is still ramping and reporting a +# number that is neither idle nor loaded. Lower it only if you know the rails +# have already settled. +TR_SETTLE_SEC="${TR_SETTLE_SEC:-120}" + +# Gap between unit 0 and unit 1 (each unit is set up as a complete block, the +# way TR518.txt does it -- the cd ports are in MAC loopback, so a unit does not +# depend on the other one being ready). +TR_UNIT_GAP_SEC="${TR_UNIT_GAP_SEC:-1}" + +# Ports put into MAC loopback. 'cd' = the cd port group, per TR518.txt. +TR_LB_PORTS="${TR_LB_PORTS:-cd}" + +# The tr 518 argument string, verbatim from tools/TR518.txt. One editable line +# so it can be pasted straight from / into a manual bcmcmd. +# Printed by the BCM shell only after tr 518 has accepted its arguments and +# started. Used as the success marker, because bcmcmd's own exit status is not +# trustworthy for a command that runs longer than its response poll. +TR_TEST_OK_PAT="${TR_TEST_OK_PAT:-TR 518 TEST PARAMETERS}" + +TR_TEST_ARGS="${TR_TEST_ARGS:-Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1}" + +# TR518.txt stops with 'port cd lb=none' and nothing else, so that is the +# default here too. But note what start changed and stop does NOT put back: +# l2 learn off -> the unit keeps learning disabled +# test mode nr=yes -> the unit stays in test mode +# Both persist until something else changes them or the box reboots. Set these +# to 1 if you want stop to be a true inverse; they are off by default because +# they are not in the bench-verified list. +TR_RESTORE_LEARN="${TR_RESTORE_LEARN:-0}" +TR_RESTORE_TESTMODE="${TR_RESTORE_TESTMODE:-0}" + +DEBUG_MODE=${DEBUG_MODE:-0} +TR_DRY_RUN=${TR_DRY_RUN:-0} +TR_NO_WAIT=${TR_NO_WAIT:-0} + +# === Logging ================================================================= +_tr_info() { echo -e "[\033[34mINFO\033[0m] $*"; } +_tr_ok() { echo -e "[\033[32m OK \033[0m] $*"; } +_tr_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; } +_tr_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; } +_tr_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; } + +# === bcmcmd wrapper ========================================================== +# stdin is closed for the same reason as in blanton_traffic_linespeed.sh: +# bcmcmd otherwise inherits the caller's stdin and eats whatever a surrounding +# loop was reading. +# +# bcmcmd exits 0 even when the BCM shell refused the command, so the output is +# pattern-matched as well (the V0.3.1 lesson from blanton_traffic_linespeed.sh). +TR_ERR_PAT="${TR_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}" + +# ...and the reverse also happens: bcmcmd exits NON-zero on a command that was +# accepted and is running. 'tr 518' outlives bcmcmd's response poll, so bcmcmd +# gives up with "polling socket timeout: Success" and a non-zero status while +# the test carries on inside the BCM shell. Treating that as a failure is what +# made V1.0.0 report ERR on a run that was actually fine. +TR_BENIGN_PAT="${TR_BENIGN_PAT:-polling socket timeout}" + +# _tr_bcm -> 0 ok, 1 failed +# _tr_bcm_ok -> as above, but if the output contains +# the command is a success +# regardless of exit status. +# +# The marker is a POSITIVE proof of success ("the shell printed the thing it +# only prints when it accepted this command"), which is far more reliable than +# trying to enumerate every way bcmcmd can look unhappy. +_tr_bcm() { _tr_bcm_ok "$1" "" "${@:2}"; } + +_tr_bcm_ok() { + local unit="$1" okpat="$2"; shift 2 + local cmd="$*" out rc why="" + _tr_dbg "$BCMCMD_CMD -n $unit -c '$cmd'" + if [ "$TR_DRY_RUN" = "1" ]; then + echo "[DRY ] $BCMCMD_CMD -n $unit -c '$cmd'" + return 0 + fi + out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" &1); rc=$? + [ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out" + + # 1. positive proof wins over everything else + if [ -n "$okpat" ] && echo "$out" | grep -qF "$okpat"; then + [ "$rc" -ne 0 ] && _tr_dbg "unit $unit: bcmcmd rc=$rc but '$okpat' seen -> accepted" + return 0 + fi + # 2. the BCM shell said no + if echo "$out" | grep -qiE "$TR_ERR_PAT"; then + why="the BCM shell rejected it" + # 3. bcmcmd itself was unhappy -- unless it is the known transport artifact + elif [ "$rc" -ne 0 ]; then + if echo "$out" | grep -qiE "$TR_BENIGN_PAT"; then + _tr_dbg "unit $unit: bcmcmd rc=$rc (${TR_BENIGN_PAT}) -> tolerated" + return 0 + fi + why="bcmcmd exited $rc" + else + return 0 + fi + + _tr_err "unit $unit: $why -- '$cmd'" + [ "$DEBUG_MODE" = "1" ] || { [ -n "$out" ] && echo "$out" >&2; } + return 1 +} + +_tr_units_check() { + local u ok="" + for u in $TR_UNITS; do + case "$u" in + 0|1) ok="$ok $u" ;; + *) _tr_err "invalid unit '$u' (use 0, 1 or all)"; return 1 ;; + esac + done + [ -n "$ok" ] || { _tr_err "no unit selected"; return 1; } + TR_UNITS="${ok# }" + return 0 +} + +_tr_is_uint() { case "$1" in ''|*[!0-9]*) return 1 ;; *) return 0 ;; esac; } + +_tr_gap() { + [ "$TR_DRY_RUN" = "1" ] && return 0 + [ "$TR_UNIT_GAP_SEC" = "0" ] && return 0 + sleep "$TR_UNIT_GAP_SEC" +} + +# === start =================================================================== +# One complete block per unit, exactly the order in tools/TR518.txt. +blanton_tr518_start() { + _tr_units_check || return 1 + _tr_is_uint "$TR_SETTLE_SEC" || { _tr_err "settle wait '$TR_SETTLE_SEC' is not an integer (-w )"; return 1; } + + local unit fail=0 first=1 + _tr_info "TR518 start on unit(s): $TR_UNITS" + for unit in $TR_UNITS; do + [ "$first" = "0" ] && _tr_gap + first=0 + _tr_info "unit $unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518" + _tr_bcm "$unit" "port $TR_LB_PORTS lb=mac" || fail=$((fail+1)) + _tr_bcm "$unit" "l2 learn off" || fail=$((fail+1)) + _tr_bcm "$unit" 'dsh -c "test mode nr=yes"' || fail=$((fail+1)) + # "TR 518 TEST PARAMETERS" is printed only once the shell has parsed the + # arguments and started the test -- that is the proof we check for. + _tr_bcm_ok "$unit" "$TR_TEST_OK_PAT" "dsh -c \"tr 518 $TR_TEST_ARGS\"" || fail=$((fail+1)) + done + + if [ "$fail" -ne 0 ]; then + _tr_err "$fail command(s) failed -- traffic may not be running, not waiting" + _tr_warn "the unit(s) may still be in loopback: blanton_tr518.sh stop" + return 1 + fi + + if [ "$TR_NO_WAIT" = "1" ] || [ "$TR_SETTLE_SEC" = "0" ]; then + _tr_ok "TR518 running on unit(s): $TR_UNITS (settle wait skipped)" + _tr_warn "rails may still be ramping -- a power reading taken now is not a settled one" + return 0 + fi + + _tr_info "settling ${TR_SETTLE_SEC}s before the rails are worth reading ..." + [ "$TR_DRY_RUN" = "1" ] || sleep "$TR_SETTLE_SEC" + _tr_ok "TR518 running and settled on unit(s): $TR_UNITS" + _tr_info "read power now: TH6_SWB0_power_readback.sh / TH6_SWB1_power_readback.sh" + _tr_info "when finished: blanton_tr518.sh stop" + return 0 +} + +# === stop ==================================================================== +# TR518.txt stops with 'port cd lb=none' only. l2 learning and test mode are +# left as start set them unless TR_RESTORE_* is turned on. +blanton_tr518_stop() { + _tr_units_check || return 1 + local unit fail=0 first=1 + _tr_info "TR518 stop on unit(s): $TR_UNITS" + for unit in $TR_UNITS; do + [ "$first" = "0" ] && _tr_gap + first=0 + _tr_bcm "$unit" "port $TR_LB_PORTS lb=none" || fail=$((fail+1)) + [ "$TR_RESTORE_LEARN" = "1" ] && { _tr_bcm "$unit" "l2 learn on" || fail=$((fail+1)); } + [ "$TR_RESTORE_TESTMODE" = "1" ] && { _tr_bcm "$unit" 'dsh -c "test mode nr=no"' || fail=$((fail+1)); } + done + + if [ "$fail" -eq 0 ]; then + _tr_ok "unit(s) $TR_UNITS: port $TR_LB_PORTS lb=none" + [ "$TR_RESTORE_LEARN" = "1" ] || \ + _tr_info "l2 learning is still off (TR_RESTORE_LEARN=1 to put it back)" + [ "$TR_RESTORE_TESTMODE" = "1" ] || \ + _tr_info "test mode is still nr=yes (TR_RESTORE_TESTMODE=1 to put it back)" + else + _tr_warn "$fail command(s) failed -- check the unit is not still in loopback:" + _tr_warn " bcmcmd -n -c 'port $TR_LB_PORTS' | head" + return 1 + fi + return 0 +} + +# === Help ==================================================================== +blanton_tr518_help() { + echo -e "\033[1mblanton_tr518.sh - TH6 built-in packet test (tr 518) for power loading\033[0m" + echo "" + echo -e " Units : \033[36m$TR_UNITS\033[0m" + echo -e " Settle wait : \033[36m${TR_SETTLE_SEC}s\033[0m after tr 518 (so power is read loaded, not ramping)" + echo -e " Loopback : \033[36mport $TR_LB_PORTS lb=mac\033[0m" + echo -e " tr 518 args : \033[36m$TR_TEST_ARGS\033[0m" + echo "" + echo -e "\033[1mSubcommands\033[0m" + echo -e " \033[33mstart\033[0m per unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518 -> wait" + echo -e " \033[33mstop\033[0m per unit: port $TR_LB_PORTS lb=none" + echo -e " \033[33mhelp\033[0m" + echo "" + echo -e "\033[1mOptions\033[0m" + echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TR_UNITS)" + echo -e " \033[33m-w|--wait\033[0m start: settle wait (default $TR_SETTLE_SEC)" + echo -e " \033[33m--no-wait\033[0m start: skip the settle wait" + echo -e " \033[33m-d|--debug\033[0m print every bcmcmd and its output" + echo -e " \033[33m-n|--dry-run\033[0m print commands only, do not touch the DUT" + echo "" + echo -e "\033[1mExamples\033[0m" + echo -e " ./blanton_tr518.sh start # both units, then wait ${TR_SETTLE_SEC}s" + echo -e " ./blanton_tr518.sh start -u 0 # unit 0 only" + echo -e " ./blanton_tr518.sh stop -u 1 # release unit 1" + echo -e " ./blanton_tr518.sh start -n # show the bcmcmds, touch nothing" + echo "" + echo -e "\033[33m stop only sends 'port $TR_LB_PORTS lb=none'. l2 learning stays off and test mode\033[0m" + echo -e "\033[33m stays nr=yes -- TR_RESTORE_LEARN=1 / TR_RESTORE_TESTMODE=1 to put them back.\033[0m" + echo -e "\033[33m tr 518 and blanton_traffic_linespeed cannot run together.\033[0m" +} + +# === Argument parsing ======================================================== +blanton_tr518() { + local sub="${1:-help}"; shift 2>/dev/null + while [ $# -gt 0 ]; do + case "$1" in + -u|--unit) + case "$2" in + all|ALL) TR_UNITS="0 1" ;; + *) TR_UNITS="$(echo "$2" | tr ',' ' ')" ;; + esac + shift 2 ;; + -w|--wait) TR_SETTLE_SEC="$2"; shift 2 ;; + --no-wait) TR_NO_WAIT=1; shift ;; + -d|--debug) DEBUG_MODE=1; shift ;; + -n|--dry-run) TR_DRY_RUN=1; shift ;; + -h|--help) blanton_tr518_help; return 0 ;; + *) _tr_err "unknown option '$1'"; return 1 ;; + esac + done + + case "$sub" in + start) blanton_tr518_start ;; + stop) blanton_tr518_stop ;; + help|-h|--help) blanton_tr518_help ;; + *) _tr_err "unknown subcommand '$sub'"; blanton_tr518_help; return 1 ;; + esac +} + +# Run when executed, define-only when sourced (same as the other blanton_*.sh). +if [ "${BASH_SOURCE[0]}" = "$0" ]; then + blanton_tr518 "$@" +fi diff --git a/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh b/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh index ed0c4e7..9946e98 100644 --- a/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh +++ b/src/Script_ABC_Blanton/Blanton_Script/blanton_traffic_linespeed.sh @@ -74,6 +74,44 @@ # Same fix applied to the "# FAIL ..." delta line (%+d -> # %+.0f), which would otherwise saturate when a dead port # makes the delta the size of the whole counter. +# V0.5.0 2026-08-28 Add: the 100G uplink (ce0, VLAN 138) joins init / start / +# stop / report, from tools/100G_Traffic.txt. +# ce0 is NOT a loopback pair: there is one per unit and the +# two are cabled to each other, so its verdict is a +# CROSS-UNIT check and cannot be decided from one unit's +# counters. It therefore appears as the LAST row of each +# unit table with the verdict DEFER, and is judged in a new +# summary printed once at the very bottom, after every +# unit -- which also carries the per-unit PASS/FAIL/NA +# totals ("all Results" in one place). +# TL_CE_MODE=cross (default) | self picks the topology; +# it is a plain editable flag, NOT auto-detected, because +# a non-zero RX cannot tell the two cablings apart. +# With only one unit selected the summary reports +# UNDECIDED (exit 3) instead of guessing. +# TL_CE_ENABLE=0 restores the old cd-pairs-only behaviour. +# V0.6.0 2026-08-28 Add: ce0 traffic is now SUSTAINED, not a single burst. +# A cd pair keeps its packets circulating because they +# flood to the partner port; ce0 has no partner and a +# switch will not send a frame back out its ingress port, +# so 'tx 100' was exactly one round trip (TX 100/RX 100) +# and then silence. init now sets an INGRESS MIRROR of ce0 +# back to ce0 -- the mirrored copy is not egress-filtered, +# so each packet keeps lapping until stop turns it off. +# init : mirror init; mirror port ce0 Mode=Ingress +# DestPort=ce0; vlan create/add +# stop : mirror port ce0 Mode=Off (FIRST -- this is what +# breaks the loop), then vlan remove +# Bench-verified command set. TL_CE_MIRROR=0 goes back to +# the one-shot burst. +# Change: TL_CE_MODE now defaults to 'self'. 'ps ce' shows +# one ce port per unit and a unit-0-only burst returned on +# unit 0, so the cross-unit reading was wrong. +# V0.5.1 2026-08-28 Add: TL_CE_COUNTER selects which counter judges the ce +# port -- packets (MIB_TPOK/MIB_RPOK, default, same as the +# cd rows) or bytes (MIB_TBYT/MIB_RBYT). The report prints +# which one it used under the table, so a byte figure is +# never mistaken for a packet count next to the cd rows. # ============================================================================= # # The VLAN/port table below is copied verbatim from @@ -145,6 +183,56 @@ TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}" # 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}" +# --- 100G uplink (ce0) ------------------------------------------------------ +# The cd pairs above are loopback pairs WITHIN one switch unit (cdN <-> cdN+32). +# ce0 is not a pair: 'ps ce' shows exactly one ce port per unit, and it is looped +# back on itself. Bench-confirmed 2026-08-28 -- a tx burst on unit 0 alone came +# back on unit 0 (TPOK +100 AND RPOK +100), which only happens on a self loop. +# +# TL_CE_MODE=self ce0 loops back on itself (default, matches bench) +# verdict: TX == RX within the unit, decided in its own table +# TL_CE_MODE=cross unit0.ce0 <-> unit1.ce0 cabled together +# verdict: unit0.TX == unit1.RX and unit0.RX == unit1.TX, +# decided in the summary; needs BOTH units +# +# If the bench cabling changes, edit TL_CE_MODE -- it is not auto-detected, +# because "RX happens to be non-zero" cannot tell the two topologies apart. +# Note the two modes agree whenever both units send the same amount, so a wrong +# setting looks fine until something actually breaks: with a self loop read as +# cross, BOTH links dying still leaves unit0.TX == unit1.RX (0 == 0) -> PASS. +TL_CE_ENABLE=${TL_CE_ENABLE:-1} # 0 = skip ce0 entirely (cd pairs only) +TL_CE_VLAN="${TL_CE_VLAN:-138}" # one past the cd range (30..137) +TL_CE_PORT="${TL_CE_PORT:-ce0}" # bcm port name, same on both units +TL_CE_MODE="${TL_CE_MODE:-self}" # cross | self -- see above + +# --- Why ce0 needs an ingress mirror ----------------------------------------- +# A cd pair sustains itself: the packet floods to the OTHER member, goes out the +# cable, comes back on the partner, floods to the other member again -- forever. +# ce0 has no partner. A switch never forwards a frame back out the port it +# arrived on (source-port knockout), so with ce0 as the only VLAN member the +# returning packet is dropped and one 'tx' burst is exactly one round trip: +# TX 100, RX 100, done. That measures the link, it does not load it. +# +# An INGRESS MIRROR of ce0 back to ce0 is the way round it: the mirrored copy is +# not subject to the egress filter, so it does leave the port it came in on. +# Each circulating packet makes exactly one copy per lap -- 1:1, not amplifying, +# so the load is set by how many packets 'start' injects, and it runs until +# 'stop' turns the mirror off. +# +# ⚠️ The loop does NOT stop on its own. Unlike the cd pairs, removing the VLAN +# membership is not enough -- 'stop' must set Mode=Off, or the port keeps +# running flat out with nothing in 'show interfaces status' to hint at it. +# ⚠️ 'mirror init' resets the mirror module. Anything else using mirroring on +# this box (ERSPAN, monitoring) is cleared. Set TL_CE_MIRROR=0 to skip it. +TL_CE_MIRROR=${TL_CE_MIRROR:-1} # 0 = no mirror (one-shot burst, as before) + +# Which counter the ce port is judged on. Packets by default, the same counter +# as the cd pairs, so every row of the table is in the same unit. +# packets -> MIB_TPOK / MIB_RPOK (default, same as the cd rows) +# bytes -> MIB_TBYT / MIB_RBYT +# Either way the report prints which one it used under the table. +TL_CE_COUNTER="${TL_CE_COUNTER:-packets}" + # --- 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 @@ -378,6 +466,21 @@ traffic_linespeed_init() { _tl_bcm_q "$unit" "vlan add $vid pbm=$pa,$pb" || fail=$((fail+1)) n=$((n+1)) done 3<<< "$TL_PAIRS" + # 100G uplink: one port, its own VLAN, added last so it is easy to skip. + # The mirror goes up BEFORE the VLAN so the loop is armed the moment the + # first packet is injected. + if [ "$TL_CE_ENABLE" = "1" ]; then + if [ "$TL_CE_MIRROR" = "1" ]; then + _tl_bcm_q "$unit" "mirror init" || fail=$((fail+1)) + _tl_bcm_q "$unit" "mirror port $TL_CE_PORT Mode=Ingress DestPort=$TL_CE_PORT" \ + || fail=$((fail+1)) + fi + _tl_bcm_run "$unit" "$TL_BENIGN_CREATE" "vlan create $TL_CE_VLAN"; rc=$? + [ "$rc" = "1" ] && fail=$((fail+1)) + [ "$rc" = "2" ] && exist=$((exist+1)) + _tl_bcm_q "$unit" "vlan add $TL_CE_VLAN pbm=$TL_CE_PORT" || fail=$((fail+1)) + n=$((n+1)) + fi if [ "$fail" -eq 0 ]; then _tl_ok "unit $unit: $n VLANs configured$([ "$exist" -gt 0 ] && echo " ($exist already existed)"), port pairs added" else @@ -421,8 +524,14 @@ traffic_linespeed_start() { _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 [ "$TL_CE_ENABLE" = "1" ]; then + _tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$TL_CE_VLAN" || fail=$((fail+1)) + n=$((n+1)) + fi if [ "$fail" -eq 0 ]; then _tl_ok "unit $unit: $n bursts sent ($((n * TL_TX_COUNT)) packets, ${TL_TX_LENGTH}B each)" + [ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \ + _tl_info "unit $unit: ${TL_CE_PORT} is now circulating and will keep running until 'stop'" else _tl_warn "unit $unit: $n bursts attempted, $fail failed" fi @@ -446,6 +555,25 @@ traffic_linespeed_stop() { fi n=$((n+1)) done 3<<< "$TL_PAIRS" + if [ "$TL_CE_ENABLE" = "1" ]; then + # Mirror OFF first: that is what actually breaks the loop. Removing + # the VLAN membership does not -- the mirrored copy never consulted + # the VLAN in the first place. + if [ "$TL_CE_MIRROR" = "1" ]; then + _tl_bcm_q "$unit" "mirror port $TL_CE_PORT Mode=Off" || { + fail=$((fail+1)) + _tl_err "unit $unit: ${TL_CE_PORT} mirror still ON -- the loop is STILL RUNNING" + _tl_err " stop it by hand: ${BCMCMD_CMD} -n $unit -c 'mirror port $TL_CE_PORT Mode=Off'" + } + fi + _tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan remove $TL_CE_VLAN pbm=$TL_CE_PORT" + [ "$?" = "1" ] && fail=$((fail+1)) + if [ "$TL_DESTROY" = "1" ]; then + _tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan destroy $TL_CE_VLAN" + [ "$?" = "1" ] && fail=$((fail+1)) + fi + n=$((n+1)) + fi if [ "$fail" -eq 0 ]; then _tl_ok "unit $unit: $n VLANs cleaned$([ "$TL_DESTROY" = "1" ] && echo " and destroyed")" else @@ -480,8 +608,11 @@ traffic_linespeed_ps() { # (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 [side_file] +# side_file (optional) receives machine-readable lines for the cross-unit +# summary: SUM CE (CE omitted if absent) _tl_pair_report() { - local log="$1" color=0 + local log="$1" side="${2:-/dev/null}" 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 @@ -497,7 +628,11 @@ _tl_pair_report() { -v WITHPORT="$TL_REPORT_WITHPORT" \ -v QUIET="$TL_REPORT_QUIET" \ -v TSV="$TL_REPORT_TSV" \ - -v COLOR="$color" ' + -v COLOR="$color" \ + -v CEPORT="$([ "$TL_CE_ENABLE" = "1" ] && echo "$TL_CE_PORT")" \ + -v CEMODE="$TL_CE_MODE" \ + -v CECOUNTER="$TL_CE_COUNTER" \ + -v SIDE="$side" ' function grp(v, s,out,l,i) { s = sprintf("%.0f", v) if (!GROUPED) return s @@ -513,8 +648,9 @@ _tl_pair_report() { # 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" + if (v == "PASS") return "\033[32m" v "\033[0m" + if (v == "FAIL") return "\033[31m" v "\033[0m" + if (v == "DEFER") return "\033[36m" v "\033[0m" # cyan: judged in the summary return "\033[33m" v "\033[0m" } function redl(s) { return COLOR ? "\033[31m" s "\033[0m" : s } @@ -535,11 +671,12 @@ _tl_pair_report() { if (idx == 0) next s = substr($0, idx) kind = substr(s, 5, 4) - if (kind != "TPOK" && kind != "RPOK") next + # POK = packets (the cd pairs), BYT = bytes (used for the ce port) + if (kind != "TPOK" && kind != "RPOK" && kind != "TBYT" && kind != "RBYT") 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 + if (cd !~ /^(cd|ce)[0-9]+$/) next lp = substr(s, p2 + 1, p3 - p2 - 1) val = substr(s, p4 + 1) sub(/^[ \t]+/, "", val) @@ -547,7 +684,10 @@ _tl_pair_report() { 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 } + if (kind == "TPOK") { TX[cd] = val + 0; HTX[cd] = 1 } + else if (kind == "RPOK") { RX[cd] = val + 0; HRX[cd] = 1 } + else if (kind == "TBYT") { TXB[cd] = val + 0; HTXB[cd] = 1 } + else { RXB[cd] = val + 0; HRXB[cd] = 1 } seen++ } END { @@ -580,6 +720,41 @@ _tl_pair_report() { nrow++; CELL[nrow,1] = pname(b); CELL[nrow,2] = tb; CELL[nrow,3] = rb; CELL[nrow,4] = v } + # --- 100G uplink, appended LAST so it sits at the bottom of the table --- + # It is a single port, not a pair, so it gets one row. In cross mode the + # verdict needs the OTHER unit counters and is decided in the summary; + # DEFER says "not judged here", which is not the same as NA ("no data"). + cev = ""; ceunit = "" + if (CEPORT != "") { + if (CECOUNTER == "packets") { + ceunit = "packets" + haveT = (CEPORT in HTX); haveR = (CEPORT in HRX) + cetv = TX[CEPORT]; cerv = RX[CEPORT] + } else { + ceunit = "bytes" + haveT = (CEPORT in HTXB); haveR = (CEPORT in HRXB) + cetv = TXB[CEPORT]; cerv = RXB[CEPORT] + } + cet = haveT ? grp(cetv) : MISSING + cer = haveR ? grp(cerv) : MISSING + if (!(haveT && haveR)) { + cev = "NA"; nna++ + } else if (CEMODE == "self") { + if (absd(cetv - cerv) <= TOL + 0) { cev = "PASS"; npass++ } + else { + cev = "FAIL"; nfail++ + FL[++nf] = sprintf("# FAIL %s: TX-RX=%+.0f %s (self loopback)", \ + CEPORT, cetv - cerv, ceunit) + } + } else { + cev = "DEFER" + } + nrep++ + nrow++; CELL[nrow,1] = pname(CEPORT); CELL[nrow,2] = cet; CELL[nrow,3] = cer; CELL[nrow,4] = cev + if (SIDE != "" && SIDE != "/dev/null" && haveT && haveR) + printf "CE %.0f %.0f\n", cetv, cerv > SIDE + } + if (TSV) { line = HDR[1] for (c = 2; c <= NC; c++) line = line "\t" HDR[c] @@ -616,13 +791,103 @@ _tl_pair_report() { 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 (CEPORT != "" && ceunit != "") + printf "# %s TX/RX are %s (MIB_%s/MIB_%s); the cd rows are packets\n", \ + CEPORT, ceunit, \ + (ceunit == "bytes" ? "TBYT" : "TPOK"), \ + (ceunit == "bytes" ? "RBYT" : "RPOK") + if (cev == "DEFER") + printf "# %s is judged across units -- see the summary at the end\n", CEPORT # every NA pair is a visible row -> no long "no counters" list needed for (i = 1; i <= nf; i++) print redl(FL[i]) } + if (SIDE != "" && SIDE != "/dev/null") + printf "SUM %d %d %d\n", npass, nfail, nna > SIDE exit (nfail || nna) ? 2 : 0 }' "$log" } +# _tl_ce_summary -- the cross-unit ce0 verdict + the per-unit totals. +# Printed once, at the very bottom, after every unit's table. +# Args: (side files are $TL_LOG_DIR/tlside_unit_) +# Returns 0 all PASS, 2 any FAIL/NA, 3 could not be decided. +_tl_ce_summary() { + local stamp="$1" unit side c g y n r + c=$'\033[36m'; g=$'\033[32m'; y=$'\033[33m'; r=$'\033[31m'; n=$'\033[0m' + case "$TL_COLOR" in + never|0|no) c=""; g=""; y=""; r=""; n="" ;; + always|1|yes) ;; + *) [ -t 1 ] || { c=""; g=""; y=""; r=""; n=""; } ;; + esac + + local u tx rx pass fail na have="" + local -A CETX CERX UPASS UFAIL UNA + for unit in $TL_UNITS; do + side="$TL_LOG_DIR/tlside_unit${unit}_${stamp}" + [ -r "$side" ] || continue + while read -r tag a b cc; do + case "$tag" in + CE) CETX[$unit]="$a"; CERX[$unit]="$b" ;; + SUM) UPASS[$unit]="$a"; UFAIL[$unit]="$b"; UNA[$unit]="$cc" ;; + esac + done < "$side" + have="$have $unit" + done + + echo "" + echo "===== summary : all units =====" + printf '%-8s %8s %8s %8s %s\n' "Unit" "PASS" "FAIL" "NA" "RESULT" + local worst=0 v + for unit in $have; do + pass="${UPASS[$unit]:-0}"; fail="${UFAIL[$unit]:-0}"; na="${UNA[$unit]:-0}" + if [ "$fail" -gt 0 ] || [ "$na" -gt 0 ]; then v="${r}FAIL${n}"; worst=2 + else v="${g}PASS${n}"; fi + printf '%-8s %8s %8s %8s %b\n' "unit $unit" "$pass" "$fail" "$na" "$v" + done + + [ "$TL_CE_ENABLE" = "1" ] || { echo ""; return "$worst"; } + + echo "" + echo "----- ${TL_CE_PORT} (100G uplink, VLAN ${TL_CE_VLAN}, mode=${TL_CE_MODE}, counter=${TL_CE_COUNTER}) -----" + if [ "$TL_CE_MODE" != "cross" ]; then + echo "# mode=self: the verdict is in each unit's table above" + echo "" + return "$worst" + fi + + # cross mode needs both units' counters + if [ -z "${CETX[0]}" ] || [ -z "${CETX[1]}" ]; then + printf '%b\n' "${y}UNDECIDED${n} ${TL_CE_PORT} is a cross-unit check and needs unit 0 AND unit 1;" + echo " this run had TL_UNITS=\"$TL_UNITS\" (counters seen for:${have:-none})." + echo " Re-run with -u all, or set TL_CE_MODE=self if the cabling is a self loopback." + echo "" + [ "$worst" -lt 3 ] && worst=3 + return "$worst" + fi + + local cu="bytes"; [ "$TL_CE_COUNTER" = "packets" ] && cu="packets" + printf '%-22s %18s %18s\n' "Direction" "TX ($cu)" "RX ($cu)" + printf '%-22s %18s %18s\n' "unit0.${TL_CE_PORT}" "${CETX[0]}" "${CERX[0]}" + printf '%-22s %18s %18s\n' "unit1.${TL_CE_PORT}" "${CETX[1]}" "${CERX[1]}" + + local d1 d2 v1 v2 + d1=$(awk -v a="${CETX[0]}" -v b="${CERX[1]}" 'BEGIN{printf "%.0f", a-b}') + d2=$(awk -v a="${CETX[1]}" -v b="${CERX[0]}" 'BEGIN{printf "%.0f", a-b}') + v1=$(awk -v d="$d1" -v t="$TL_TOLERANCE" 'BEGIN{print (d<0?-d:d)<=t ? "PASS" : "FAIL"}') + v2=$(awk -v d="$d2" -v t="$TL_TOLERANCE" 'BEGIN{print (d<0?-d:d)<=t ? "PASS" : "FAIL"}') + echo "" + printf 'unit0.TX -> unit1.RX delta %+d %b\n' "$d1" "$([ "$v1" = PASS ] && echo "${g}PASS${n}" || echo "${r}FAIL${n}")" + printf 'unit1.TX -> unit0.RX delta %+d %b\n' "$d2" "$([ "$v2" = PASS ] && echo "${g}PASS${n}" || echo "${r}FAIL${n}")" + if [ "$v1" = PASS ] && [ "$v2" = PASS ]; then + printf '%-22s %b\n' "${TL_CE_PORT} RESULT" "${g}PASS${n}" + else + printf '%-22s %b\n' "${TL_CE_PORT} RESULT" "${r}FAIL${n}" + worst=2 + fi + echo "" + return "$worst" +} + # traffic_linespeed_report -- 'show c' per unit, keep the raw log, render the table traffic_linespeed_report() { local unit log rc worst=0 stamp @@ -641,14 +906,17 @@ traffic_linespeed_report() { fi stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now) + local side for unit in $TL_UNITS; do log="$TL_LOG_DIR/showc_unit${unit}_${stamp}.log" + side="$TL_LOG_DIR/tlside_unit${unit}_${stamp}" + : > "$side" 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=$? + _tl_pair_report "$log" "$side"; rc=$? [ "$rc" -gt "$worst" ] && worst=$rc case "$rc" in 0) _tl_ok "unit $unit: all pairs PASS" ;; @@ -656,6 +924,12 @@ traffic_linespeed_report() { *) _tl_err "unit $unit: report parse error" ;; esac done + + # Summary last, after every unit's table -- this is where the cross-unit + # ce0 verdict can finally be decided. + _tl_ce_summary "$stamp"; rc=$? + [ "$rc" -gt "$worst" ] && worst=$rc + rm -f "$TL_LOG_DIR"/tlside_unit*_"${stamp}" return "$worst" } @@ -677,6 +951,8 @@ blanton_traffic_linespeed_help() { 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)" + [ "$TL_CE_ENABLE" = "1" ] && \ + echo -e " 100G : VLAN \033[36m$TL_CE_VLAN\033[0m port \033[36m$TL_CE_PORT\033[0m mode=\033[36m$TL_CE_MODE\033[0m (cross = unit0.$TL_CE_PORT <-> unit1.$TL_CE_PORT cabled)" 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" @@ -684,8 +960,11 @@ blanton_traffic_linespeed_help() { 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]" + [ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \ + echo -e " \033[33m^ also turns the $TL_CE_PORT mirror off -- without it the 100G loop keeps running\033[0m" echo -e " \033[33mps\033[0m ps port status (link/speed) of the cabled ports" echo -e " \033[33mreport\033[0m show c -> per-port TX/RX per pair + PASS/FAIL/NA cross-check" + echo -e " ${TL_CE_PORT} is the last row (DEFER), judged in the summary at the bottom" echo -e " \033[33mrun\033[0m ps -> init -> clear -> start -> report" echo -e " \033[33mhelp\033[0m" echo "" diff --git a/tools/100G_Traffic.txt b/tools/100G_Traffic.txt new file mode 100644 index 0000000..be5c73d --- /dev/null +++ b/tools/100G_Traffic.txt @@ -0,0 +1,12 @@ +//Init +bcmcmd -n 0 -c 'mirror init' +bcmcmd -n 0 -c 'mirror port ce0 Mode=Ingress DestPort=ce0' +bcmcmd -n 0 -c 'vlan create 138' +bcmcmd -n 0 -c 'vlan add 138 pbm=ce0' + +//Start +bcmcmd -n 0 -c 'tx 100 length=512 VLantag=138' + +//stop +bcmcmd -n 0 -c 'mirror port ce0 Mode=Off' +bcmcmd -n 0 -c 'vlan remove 138 pbm=ce0' \ No newline at end of file diff --git a/tools/BER_Test.txt b/tools/BER_Test.txt new file mode 100644 index 0000000..98d7322 --- /dev/null +++ b/tools/BER_Test.txt @@ -0,0 +1,900 @@ +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs set p=3' " +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs get' " + +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbsstat STArt Interval=30' " +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbsstat Ber' " + +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbsstat STOp' " +bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs clear' " + +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs set p=3' " + dsh -c 'phydiag 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 prbs set p=3' +drivshell> +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs get' " + dsh -c 'phydiag 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 prbs get' +1 : PRBS OK!has been unlocked since last call +2 : PRBS OK!has been unlocked since last call +3 : PRBS OK!has been unlocked since last call +4 : PRBS OK!has been unlocked since last call +5 : PRBS OK!has been unlocked since last call +6 : PRBS OK!has been unlocked since last call +7 : PRBS OK!has been unlocked since last call +8 : PRBS OK!has been unlocked since last call +18 : PRBS OK!has been unlocked since last call +19 : PRBS OK!has been unlocked since last call +20 : PRBS OK!has been unlocked since last call +21 : PRBS OK!has been unlocked since last call +22 : PRBS OK!has been unlocked since last call +23 : PRBS OK!has been unlocked since last call +24 : PRBS OK!has been unlocked since last call +40 : PRBS OK!has been unlocked since last call +41 : PRBS OK!has been unlocked since last call +42 : PRBS OK!has been unlocked since last call +43 : PRBS OK!has been unlocked since last call +54 : PRBS OK!has been unlocked since last call +55 : PRBS OK!has been unlocked since last call +56 : PRBS OK!has been unlocked since last call +57 : PRBS OK!has been unlocked since last call +58 : PRBS OK!has been unlocked since last call +59 : PRBS OK!has been unlocked since last call +60 : PRBS OK!has been unlocked since last call +61 : PRBS OK!has been unlocked since last call +72 : PRBS OK!has been unlocked since last call +73 : PRBS OK!has been unlocked since last call +74 : PRBS OK!has been unlocked since last call +75 : PRBS OK!has been unlocked since last call +76 : PRBS OK!has been unlocked since last call +77 : PRBS OK!has been unlocked since last call +78 : PRBS OK!has been unlocked since last call +79 : PRBS OK!has been unlocked since last call +90 : PRBS OK!has been unlocked since last call +91 : PRBS OK!has been unlocked since last call +92 : PRBS OK!has been unlocked since last call +93 : PRBS OK!has been unlocked since last call +94 : PRBS OK!has been unlocked since last call +95 : PRBS OK!has been unlocked since last call +96 : PRBS OK!has been unlocked since last call +112 : PRBS OK!has been unlocked since last call +113 : PRBS OK!has been unlocked since last call +114 : PRBS OK!has been unlocked since last call +115 : PRBS OK!has been unlocked since last call +126 : PRBS OK!has been unlocked since last call +127 : PRBS OK!has been unlocked since last call +128 : PRBS OK!has been unlocked since last call +129 : PRBS OK!has been unlocked since last call +130 : PRBS OK!has been unlocked since last call +131 : PRBS OK!has been unlocked since last call +132 : PRBS OK!has been unlocked since last call +133 : PRBS OK!has been unlocked since last call +144 : PRBS OK!has been unlocked since last call +145 : PRBS OK!has been unlocked since last call +146 : PRBS OK!has been unlocked since last call +147 : PRBS OK!has been unlocked since last call +148 : PRBS OK!has been unlocked since last call +149 : PRBS OK!has been unlocked since last call +150 : PRBS OK!has been unlocked since last call +151 : PRBS OK!has been unlocked since last call +162 : PRBS OK!has been unlocked since last call +163 : PRBS OK!has been unlocked since last call +164 : PRBS OK!has been unlocked since last call +165 : PRBS OK!has been unlocked since last call +166 : PRBS OK!has been unlocked since last call +167 : PRBS OK!has been unlocked since last call +168 : PRBS OK!has been unlocked since last call +184 : PRBS OK!has been unlocked since last call +185 : PRBS OK!has been unlocked since last call +186 : PRBS OK!has been unlocked since last call +187 : PRBS OK!has been unlocked since last call +198 : PRBS OK!has been unlocked since last call +199 : PRBS OK!has been unlocked since last call +200 : PRBS OK!has been unlocked since last call +201 : PRBS OK!has been unlocked since last call +202 : PRBS OK!has been unlocked since last call +203 : PRBS OK!has been unlocked since last call +204 : PRBS OK!has been unlocked since last call +205 : PRBS OK!has been unlocked since last call +216 : PRBS OK!has been unlocked since last call +217 : PRBS OK!has been unlocked since last call +218 : PRBS OK!has been unlocked since last call +219 : PRBS OK!has been unlocked since last call +220 : PRBS OK!has been unlocked since last call +221 : PRBS OK!has been unlocked since last call +222 : PRBS OK!has been unlocked since last call +223 : PRBS OK!has been unlocked since last call +234 : PRBS OK!has been unlocked since last call +235 : PRBS OK!has been unlocked since last call +236 : PRBS OK!has been unlocked since last call +237 : PRBS OK!has been unlocked since last call +238 : PRBS OK!has been unlocked since last call +239 : PRBS OK!has been unlocked since last call +240 : PRBS OK!has been unlocked since last call +256 : PRBS OK!has been unlocked since last call +257 : PRBS OK!has been unlocked since last call +258 : PRBS OK!has been unlocked since last call +259 : PRBS OK!has been unlocked since last call +270 : PRBS OK!has been unlocked since last call +271 : PRBS OK!has been unlocked since last call +272 : PRBS OK!has been unlocked since last call +273 : PRBS OK!has been unlocked since last call +274 : PRBS OK!has been unlocked since last call +275 : PRBS OK!has been unlocked since last call +276 : PRBS OK!has been unlocked since last call +277 : PRBS OK!has been unlocked since last call +288 : PRBS OK!has been unlocked since last call +289 : PRBS OK!has been unlocked since last call +290 : PRBS OK!has been unlocked since last call +291 : PRBS OK!has been unlocked since last call +292 : PRBS OK!has been unlocked since last call +293 : PRBS OK!has been unlocked since last call +294 : PRBS OK!has been unlocked since last call +295 : PRBS OK!has been unlocked since last call +306 : PRBS OK!has been unlocked since last call +307 : PRBS OK!has been unlocked since last call +308 : PRBS OK!has been unlocked since last call +310 : PRBS OK!has been unlocked since last call +311 : PRBS OK!has been unlocked since last call +312 : PRBS OK!has been unlocked since last call +313 : PRBS OK!has been unlocked since last call +324 : PRBS OK!has been unlocked since last call +325 : PRBS OK!has been unlocked since last call +326 : PRBS OK!has been unlocked since last call +327 : PRBS OK!has been unlocked since last call +342 : PRBS OK!has been unlocked since last call +343 : PRBS OK!has been unlocked since last call +344 : PRBS OK!has been unlocked since last call +345 : PRBS OK!has been unlocked since last call +346 : PRBS OK!has been unlocked since last call +347 : PRBS OK!has been unlocked since last call +348 : PRBS OK!has been unlocked since last call +349 : PRBS OK!has been unlocked since last call +360 : PRBS OK!has been unlocked since last call +361 : PRBS OK!has been unlocked since last call +362 : PRBS OK!has been unlocked since last call +363 : PRBS OK!has been unlocked since last call +364 : PRBS OK!has been unlocked since last call +365 : PRBS OK!has been unlocked since last call +366 : PRBS OK!has been unlocked since last call +367 : PRBS OK!has been unlocked since last call +378 : PRBS OK!has been unlocked since last call +379 : PRBS OK!has been unlocked since last call +380 : PRBS OK!has been unlocked since last call +382 : PRBS OK!has been unlocked since last call +383 : PRBS OK!has been unlocked since last call +384 : PRBS OK!has been unlocked since last call +385 : PRBS OK!has been unlocked since last call +396 : PRBS OK!has been unlocked since last call +397 : PRBS OK!has been unlocked since last call +398 : PRBS OK!has been unlocked since last call +399 : PRBS OK!has been unlocked since last call +414 : PRBS OK!has been unlocked since last call +415 : PRBS OK!has been unlocked since last call +416 : PRBS OK!has been unlocked since last call +417 : PRBS OK!has been unlocked since last call +418 : PRBS OK!has been unlocked since last call +419 : PRBS OK!has been unlocked since last call +420 : PRBS OK!has been unlocked since last call +421 : PRBS OK!has been unlocked since last call +432 : PRBS OK!has been unlocked since last call +433 : PRBS OK!has been unlocked since last call +434 : PRBS OK!has been unlocked since last call +435 : PRBS OK!has been unlocked since last call +436 : PRBS OK!has been unlocked since last call +437 : PRBS OK!has been unlocked since last call +438 : PRBS OK!has been unlocked since last call +439 : PRBS OK!has been unlocked since last call +450 : PRBS OK!has been unlocked since last call +451 : PRBS OK!has been unlocked since last call +452 : PRBS OK!has been unlocked since last call +454 : PRBS OK!has been unlocked since last call +455 : PRBS OK!has been unlocked since last call +456 : PRBS OK!has been unlocked since last call +457 : PRBS OK!has been unlocked since last call +468 : PRBS OK!has been unlocked since last call +469 : PRBS OK!has been unlocked since last call +470 : PRBS OK!has been unlocked since last call +471 : PRBS OK!has been unlocked since last call +486 : PRBS OK!has been unlocked since last call +487 : PRBS OK!has been unlocked since last call +488 : PRBS OK!has been unlocked since last call +489 : PRBS OK!has been unlocked since last call +490 : PRBS OK!has been unlocked since last call +491 : PRBS OK!has been unlocked since last call +492 : PRBS OK!has been unlocked since last call +493 : PRBS OK!has been unlocked since last call +504 : PRBS OK!has been unlocked since last call +505 : PRBS OK!has been unlocked since last call +506 : PRBS OK!has been unlocked since last call +507 : PRBS OK!has been unlocked since last call +508 : PRBS OK!has been unlocked since last call +509 : PRBS OK!has been unlocked since last call +510 : PRBS OK!has been unlocked since last call +511 : PRBS OK!has been unlocked since last call +522 : PRBS OK!has been unlocked since last call +523 : PRBS OK!has been unlocked since last call +524 : PRBS OK!has been unlocked since last call +526 : PRBS OK!has been unlocked since last call +527 : PRBS OK!has been unlocked since last call +528 : PRBS OK!has been unlocked since last call +529 : PRBS OK!has been unlocked since last call +540 : PRBS OK!has been unlocked since last call +541 : PRBS OK!has been unlocked since last call +542 : PRBS OK!has been unlocked since last call +543 : PRBS OK!has been unlocked since last call +558 : PRBS OK!has been unlocked since last call +559 : PRBS OK!has been unlocked since last call +560 : PRBS OK!has been unlocked since last call +561 : PRBS OK!has been unlocked since last call +562 : PRBS OK!has been unlocked since last call +563 : PRBS OK!has been unlocked since last call +564 : PRBS OK!has been unlocked since last call +565 : PRBS OK!has been unlocked since last call +drivshell> +root@sonic:~# +root@sonic:~# +root@sonic:~# +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbssat STArt Interval=30' " + dsh -c 'phydiag 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 prbsstat STArt Interval=30' +PRBSStat thread started ... +drivshell> +root@sonic:~# sleep 30 +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbsstat Ber' " + dsh -c 'phydiag 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 prbsstat Ber' +port BER +==== +1[0] : 3.53e-11 +1[1] : 4.00e-11 +==== +2[0] : 1.64e-10 +2[1] : 8.80e-11 +==== +3[0] : 6.01e-11 +3[1] : 3.45e-12 +==== +4[0] : 7.69e-11 +4[1] : 2.60e-11 +==== +5[0] : 9.41e-13 +5[1] : 6.27e-13 +==== +6[0] : 3.14e-13 +6[1] : 6.27e-13 +==== +7[0] : 2.98e-12 +7[1] : 2.20e-12 +==== +8[0] : 4.24e-12 +8[1] : 9.41e-13 +==== +18[0] : 7.84e-13 +18[1] : 2.04e-12 +==== +19[0] : 1.57e-13 +19[1] : 1.73e-12 +==== +20[0] : 1.19e-11 +20[1] : 1.41e-12 +==== +21[0] : 5.65e-12 +21[1] : 7.69e-12 +==== +22[0] : 1.54e-11 +22[1] : 7.84e-13 +==== +23[0] : 1.10e-12 +23[1] : 2.35e-12 +==== +24[0] : 2.51e-12 +24[1] : 1.41e-12 +==== +40[0] : 2.23e-11 +40[1] : 2.35e-11 +==== +41[0] : 3.76e-12 +41[1] : 4.55e-12 +==== +42[0] : 7.84e-12 +42[1] : 3.76e-12 +==== +43[0] : 5.02e-12 +43[1] : 1.35e-11 +==== +54[0] : 7.84e-13 +54[1] : 6.27e-13 +==== +55[0] : 1.57e-13 +55[1] : 1.57e-13 +==== +56[0] : 3.14e-13 +56[1] : 4.71e-13 +==== +57[0] : 4.71e-12 +57[1] : 6.27e-13 +==== +58[0] : 5.80e-12 +58[1] : 4.24e-11 +==== +59[0] : 6.90e-12 +59[1] : 7.84e-13 +==== +60[0] : 1.13e-11 +60[1] : 1.10e-12 +==== +61[0] : 2.35e-12 +61[1] : 5.49e-12 +==== +72[0] : 4.39e-11 +72[1] : 5.49e-12 +==== +73[0] : 7.22e-12 +73[1] : 8.00e-12 +==== +74[0] : 3.29e-12 +74[1] : 1.25e-12 +==== +75[0] : 5.96e-12 +75[1] : 3.45e-12 +==== +76[0] : 1.57e-13 +76[1] : 1.41e-12 +==== +77[0] : 2.20e-12 +77[1] : 1.57e-13 +==== +78[0] : 2.67e-12 +78[1] : 1.41e-12 +==== +79[0] : 6.27e-13 +79[1] : 3.14e-13 +==== +90[0] : 3.61e-12 +90[1] : 1.91e-11 +==== +91[0] : 1.88e-12 +91[1] : 4.24e-12 +==== +92[0] : 8.47e-12 +92[1] : 4.08e-12 +==== +93[0] : 3.92e-12 +93[1] : 1.82e-11 +==== +94[0] : 1.57e-13 +94[1] : 1.41e-12 +==== +95[0] : 1.57e-13 +95[1] : 1.57e-13 +==== +96[0] : 1.57e-13 +96[1] : 4.71e-13 +==== +112[0] : 4.08e-12 +112[1] : 2.04e-12 +==== +113[0] : 4.08e-12 +113[1] : 3.29e-12 +==== +114[0] : 7.84e-13 +114[1] : 9.41e-13 +==== +115[0] : 6.27e-13 +115[1] : 1.88e-12 +==== +126[0] : 2.82e-12 +126[1] : 1.57e-13 +==== +127[0] : 1.57e-13 +127[1] : 4.71e-13 +==== +128[0] : 3.45e-12 +128[1] : 3.14e-13 +==== +129[0] : 4.71e-13 +129[1] : 6.27e-13 +==== +130[0] : 2.67e-12 +130[1] : 1.57e-12 +==== +131[0] : 2.35e-12 +131[1] : 6.12e-12 +==== +132[0] : 3.33e-11 +132[1] : 5.02e-12 +==== +133[0] : 9.88e-12 +133[1] : 6.90e-12 +==== +144[0] : 7.84e-13 +144[1] : 7.22e-12 +==== +145[0] : 3.29e-12 +145[1] : 6.12e-12 +==== +146[0] : 1.02e-11 +146[1] : 1.57e-12 +==== +147[0] : 1.57e-12 +147[1] : 3.92e-12 +==== +148[0] : 1.57e-13 +148[1] : 1.25e-12 +==== +149[0] : 1.57e-13 +149[1] : 1.57e-13 +==== +150[0] : 6.27e-13 +150[1] : 1.57e-13 +==== +151[0] : 6.27e-13 +151[1] : 3.14e-13 +==== +162[0] : 1.57e-13 +162[1] : 6.27e-13 +==== +163[0] : 3.14e-13 +163[1] : 1.57e-12 +==== +164[0] : 1.25e-12 +164[1] : 2.20e-12 +==== +165[0] : 4.71e-13 +165[1] : 2.67e-12 +==== +166[0] : 1.57e-13 +166[1] : 3.14e-13 +==== +167[0] : 1.57e-13 +167[1] : 1.57e-12 +==== +168[0] : 4.71e-13 +168[1] : 1.57e-13 +==== +184[0] : 4.11e-10 +184[1] : 3.12e-10 +==== +185[0] : 1.71e-08 +185[1] : 3.13e-09 +==== +186[0] : 2.05e-10 +186[1] : 2.27e-09 +==== +187[0] : 3.94e-11 +187[1] : 2.97e-09 +==== +198[0] : 3.44e-11 +198[1] : 3.29e-11 +==== +199[0] : 7.53e-10 +199[1] : 1.66e-10 +==== +200[0] : 4.38e-11 +200[1] : 3.81e-11 +==== +201[0] : 5.43e-11 +201[1] : 1.95e-11 +==== +202[0] : 1.82e-10 +202[1] : 5.74e-09 +==== +203[0] : 1.98e-08 +203[1] : 5.05e-09 +==== +204[0] : 2.09e-10 +204[1] : 5.71e-11 +==== +205[0] : 6.59e-11 +205[1] : 5.21e-11 +==== +216[0] : 4.71e-13 +216[1] : 6.27e-13 +==== +217[0] : 1.57e-12 +217[1] : 6.27e-13 +==== +218[0] : 3.14e-13 +218[1] : 1.57e-13 +==== +219[0] : 1.41e-12 +219[1] : 1.41e-12 +==== +220[0] : 1.57e-13 +220[1] : 1.57e-13 +==== +221[0] : 1.57e-13 +221[1] : 1.57e-13 +==== +222[0] : 1.57e-13 +222[1] : 3.14e-13 +==== +223[0] : 9.41e-13 +223[1] : 1.57e-13 +==== +234[0] : 1.57e-13 +234[1] : 4.71e-13 +==== +235[0] : 3.14e-13 +235[1] : 1.25e-12 +==== +236[0] : 4.71e-13 +236[1] : 1.57e-13 +==== +237[0] : 3.14e-13 +237[1] : 1.57e-13 +==== +238[0] : 1.57e-13 +238[1] : 1.57e-13 +==== +239[0] : 3.14e-13 +239[1] : 3.14e-13 +==== +240[0] : 2.35e-12 +240[1] : 1.57e-13 +==== +256[0] : 4.24e-12 +256[1] : 7.37e-12 +==== +257[0] : 4.71e-13 +257[1] : 7.69e-12 +==== +258[0] : 1.09e-09 +258[1] : 6.25e-09 +==== +259[0] : 1.66e-11 +259[1] : 1.02e-10 +==== +270[0] : 1.10e-12 +270[1] : 9.25e-12 +==== +271[0] : 5.33e-12 +271[1] : 1.62e-11 +==== +272[0] : 1.37e-10 +272[1] : 9.15e-10 +==== +273[0] : 9.41e-12 +273[1] : 1.90e-11 +==== +274[0] : 1.57e-13 +274[1] : 2.04e-12 +==== +275[0] : 1.73e-12 +275[1] : 2.20e-12 +==== +276[0] : 1.30e-10 +276[1] : 1.36e-10 +==== +277[0] : 1.41e-12 +277[1] : 2.04e-12 +==== +288[0] : 4.71e-13 +288[1] : 4.71e-13 +==== +289[0] : 3.14e-13 +289[1] : 2.20e-12 +==== +290[0] : 3.14e-13 +290[1] : 1.57e-13 +==== +291[0] : 3.29e-11 +291[1] : 1.08e-11 +==== +292[0] : 3.14e-13 +292[1] : 6.27e-13 +==== +293[0] : 1.57e-13 +293[1] : 5.80e-12 +==== +294[0] : 5.96e-12 +294[1] : 1.88e-12 +==== +295[0] : 1.27e-11 +295[1] : 1.21e-11 +==== +306[0] : 4.71e-13 +306[1] : 1.10e-12 +==== +307[0] : 7.84e-13 +307[1] : 5.02e-12 +==== +308[0] : 3.92e-12 +308[1] : 2.67e-12 +==== +310[0] : 3.92e-12 +310[1] : 1.25e-12 +==== +311[0] : 2.51e-12 +311[1] : 6.27e-13 +==== +312[0] : 2.20e-12 +312[1] : 6.75e-12 +==== +313[0] : 5.43e-11 +313[1] : 2.18e-10 +==== +324[0] : 1.46e-11 +324[1] : 1.27e-11 +==== +325[0] : 2.67e-12 +325[1] : 7.94e-11 +==== +326[0] : 5.35e-11 +326[1] : 2.35e-12 +==== +327[0] : 7.15e-11 +327[1] : 1.11e-11 +==== +342[0] : 2.04e-12 +342[1] : 1.41e-12 +==== +343[0] : 3.14e-13 +343[1] : 3.61e-12 +==== +344[0] : 1.41e-12 +344[1] : 1.57e-13 +==== +345[0] : 1.25e-12 +345[1] : 1.41e-12 +==== +346[0] : 3.14e-13 +346[1] : 1.57e-13 +==== +347[0] : 1.57e-13 +347[1] : 3.14e-13 +==== +348[0] : 1.57e-13 +348[1] : 3.14e-13 +==== +349[0] : 1.73e-12 +349[1] : 2.21e-11 +==== +360[0] : 8.78e-12 +360[1] : 1.24e-11 +==== +361[0] : 7.22e-12 +361[1] : 1.87e-11 +==== +362[0] : 1.30e-11 +362[1] : 1.74e-11 +==== +363[0] : 1.51e-10 +363[1] : 2.85e-11 +==== +364[0] : 1.38e-11 +364[1] : 1.17e-10 +==== +365[0] : 3.95e-11 +365[1] : 2.67e-12 +==== +366[0] : 4.24e-12 +366[1] : 5.49e-12 +==== +367[0] : 1.71e-10 +367[1] : 1.40e-11 +==== +378[0] : 1.41e-11 +378[1] : 3.50e-11 +==== +379[0] : 7.67e-11 +379[1] : 1.03e-09 +==== +380[0] : 2.16e-11 +380[1] : 1.62e-11 +==== +382[0] : 4.35e-11 +382[1] : 1.81e-10 +==== +383[0] : 2.28e-10 +383[1] : 1.41e-10 +==== +384[0] : 7.22e-12 +384[1] : 5.71e-11 +==== +385[0] : 3.36e-11 +385[1] : 2.16e-11 +==== +396[0] : 2.82e-12 +396[1] : 4.55e-12 +==== +397[0] : 1.27e-11 +397[1] : 1.41e-11 +==== +398[0] : 2.99e-10 +398[1] : 5.80e-11 +==== +399[0] : 2.51e-11 +399[1] : 1.11e-11 +==== +414[0] : 4.55e-12 +414[1] : 8.31e-12 +==== +415[0] : 1.57e-13 +415[1] : 9.41e-13 +==== +416[0] : 6.27e-12 +416[1] : 5.96e-12 +==== +417[0] : 2.20e-12 +417[1] : 1.88e-12 +==== +418[0] : 6.27e-13 +418[1] : 1.25e-12 +==== +419[0] : 1.57e-13 +419[1] : 1.41e-12 +==== +420[0] : 3.14e-13 +420[1] : 2.82e-12 +==== +421[0] : 4.39e-12 +421[1] : 1.16e-11 +==== +432[0] : 4.71e-13 +432[1] : 6.27e-13 +==== +433[0] : 4.71e-13 +433[1] : 1.57e-12 +==== +434[0] : 4.71e-13 +434[1] : 1.57e-13 +==== +435[0] : 1.25e-12 +435[1] : 1.57e-13 +==== +436[0] : 1.57e-13 +436[1] : 1.57e-13 +==== +437[0] : 1.57e-13 +437[1] : 4.71e-13 +==== +438[0] : 7.84e-13 +438[1] : 1.41e-12 +==== +439[0] : 1.41e-12 +439[1] : 1.10e-12 +==== +450[0] : 6.27e-13 +450[1] : 4.71e-13 +==== +451[0] : 1.57e-13 +451[1] : 1.25e-12 +==== +452[0] : 1.10e-12 +452[1] : 7.84e-13 +==== +454[0] : 1.10e-12 +454[1] : 1.88e-12 +==== +455[0] : 6.27e-13 +455[1] : 1.57e-12 +==== +456[0] : 1.88e-12 +456[1] : 9.41e-13 +==== +457[0] : 7.84e-13 +457[1] : 4.71e-13 +==== +468[0] : 6.27e-13 +468[1] : 9.41e-13 +==== +469[0] : 2.67e-12 +469[1] : 4.08e-12 +==== +470[0] : 3.14e-13 +470[1] : 4.71e-13 +==== +471[0] : 3.14e-13 +471[1] : 7.84e-13 +==== +486[0] : 1.73e-12 +486[1] : 1.57e-12 +==== +487[0] : 1.10e-12 +487[1] : 2.82e-12 +==== +488[0] : 4.71e-13 +488[1] : 4.71e-13 +==== +489[0] : 9.41e-13 +489[1] : 3.14e-13 +==== +490[0] : 1.57e-13 +490[1] : 3.14e-13 +==== +491[0] : 3.14e-13 +491[1] : 1.57e-13 +==== +492[0] : 9.41e-13 +492[1] : 1.10e-12 +==== +493[0] : 7.84e-13 +493[1] : 2.98e-12 +==== +504[0] : 4.71e-13 +504[1] : 3.14e-13 +==== +505[0] : 1.57e-13 +505[1] : 7.84e-13 +==== +506[0] : 4.71e-13 +506[1] : 1.57e-13 +==== +507[0] : 3.14e-13 +507[1] : 1.57e-13 +==== +508[0] : 2.04e-12 +508[1] : 1.41e-12 +==== +509[0] : 9.41e-13 +509[1] : 7.84e-13 +==== +510[0] : 1.57e-13 +510[1] : 6.27e-13 +==== +511[0] : 6.27e-13 +511[1] : 4.71e-13 +==== +522[0] : 2.35e-12 +522[1] : 1.57e-13 +==== +523[0] : 3.14e-13 +523[1] : 6.27e-13 +==== +524[0] : 7.84e-13 +524[1] : 1.57e-13 +==== +526[0] : 7.84e-13 +526[1] : 3.14e-13 +==== +527[0] : 1.41e-12 +527[1] : 4.71e-13 +==== +528[0] : 3.14e-13 +528[1] : 9.41e-13 +==== +529[0] : 4.71e-13 +529[1] : 1.57e-13 +==== +540[0] : 6.27e-13 +540[1] : 1.25e-12 +==== +541[0] : 3.14e-13 +541[1] : 1.10e-12 +==== +542[0] : 2.98e-12 +542[1] : 6.27e-13 +==== +543[0] : 2.98e-12 +543[1] : 3.14e-13 +==== +558[0] : 9.41e-13 +558[1] : 1.10e-12 +==== +559[0] : 3.29e-12 +559[1] : 2.04e-12 +==== +560[0] : 1.57e-13 +560[1] : 1.57e-13 +==== +561[0] : 2.35e-12 +561[1] : 4.71e-13 +==== +562[0] : 1.57e-13 +562[1] : 1.57e-13 +==== +563[0] : 1.57e-13 +563[1] : 4.71e-13 +==== +564[0] : 1.41e-12 +564[1] : 7.84e-13 +==== +565[0] : 4.55e-12 +565[1] : 1.57e-13 +==== +drivshell> +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbssat STOp' " + dsh -c 'phydiag 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 prbsstat STOp' +Stopping PRBSStat thread +drivshell> +root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 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 prbs clear' " + dsh -c 'phydiag 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 prbs clear' +drivshell> +root@sonic:~# \ No newline at end of file diff --git a/tools/TR518.txt b/tools/TR518.txt index bc2f2eb..f94824b 100644 --- a/tools/TR518.txt +++ b/tools/TR518.txt @@ -1,32 +1,17 @@ -bcmcmd -n 0 -c '*:port all lb=mac' -bcmcmd -n 0 -c '*:l2 learn off' -bcmcmd -n 0 -c '*:dsh -c "test mode nr=yes"' -bcmcmd -n 0 -c '*:dsh -c "tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=2"' +//Start Unit0 Tr518 +bcmcmd -n 0 -c 'port cd lb=mac' +bcmcmd -n 0 -c 'l2 learn off' +bcmcmd -n 0 -c 'dsh -c "test mode nr=yes"' +bcmcmd -n 0 -c 'dsh -c "tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1"' -bcmcmd -n 1 -c "*:port all lb=mac" -bcmcmd -n 1 -c "*:l2 learn off" -bcmcmd -n 1 -c "*:dsh -c 'test mode nr=yes'" -bcmcmd -n 1 -c "*:dsh -c 'tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=2'" +//Stop Unit0 Tr518 +bcmcmd -n 0 -c 'port cd lb=none' +//Start Unit1 Tr518 +bcmcmd -n 1 -c 'port cd lb=mac' +bcmcmd -n 1 -c 'l2 learn off' +bcmcmd -n 1 -c 'dsh -c "test mode nr=yes"' +bcmcmd -n 1 -c 'dsh -c "tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1"' -bcmcmd -n 0 -c "*:port all lb=mac" -sleep 1 -bcmcmd -n 1 -c "*:port all lb=mac" -sleep 1 -bcmcmd -n 0 -c "*:l2 learn off" -sleep 1 -bcmcmd -n 1 -c "*:l2 learn off" -sleep 1 -bcmcmd -n 0 -c "*:dsh -c 'test mode nr=yes'" -sleep 1 -bcmcmd -n 1 -c "*:dsh -c 'test mode nr=yes'" -sleep 1 -bcmcmd -n 0 -c "*:dsh -c 'tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=2'" -sleep 1 -bcmcmd -n 1 -c "*:dsh -c 'tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=2'" -sleep 1 - - -root@(none):/usr/local/bin# swutil *:l2 learn off -root@(none):/usr/local/bin# swutil *:dsh -c \"test mode nr=yes\" -root@(none):/usr/local/bin# swutil *:dsh -c \"tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=2" \ No newline at end of file +//Stop Unit1 Tr518 +bcmcmd -n 1 -c 'port cd lb=none' \ No newline at end of file