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