Compare commits
20
Commits
725f51681a
...
V1.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
419b680980 | ||
|
|
4ed283d0ca | ||
|
|
491e807cf8 | ||
|
|
18ce7a1a73 | ||
|
|
d1b5cfea0b | ||
|
|
5e63e3da6b | ||
|
|
855b7a6e30 | ||
|
|
310f897067 | ||
|
|
fedf697977 | ||
|
|
ababb2c3d1 | ||
|
|
a9c3dafc22 | ||
|
|
4088a828c6 | ||
|
|
afb7b1e283 | ||
|
|
fd35857d80 | ||
|
|
cdf38a09ae | ||
|
|
8aa5c90166 | ||
|
|
224ddbd21c | ||
|
|
9d61b1aa43 | ||
|
|
071244fde1 | ||
|
|
9bf4291d17 |
@@ -0,0 +1,29 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# 換行符政策
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# 這個 repo 同時被 Windows(Tera Term 端編輯)與 SONiC/Linux(DUT 端執行)使用,
|
||||||
|
# 所以必須明確指定,不能靠各機器的 core.autocrlf。
|
||||||
|
#
|
||||||
|
# 踩過的坑:margin.sh 帶著 CRLF 進 repo,scp 到 DUT 後 bash 直接掛:
|
||||||
|
# -bash: $'\r': command not found
|
||||||
|
# syntax error near unexpected token `$'{\r''
|
||||||
|
# settings/*.conf 同樣危險 —— margin_init 是用 source 讀它們的,未加引號的
|
||||||
|
# 賦值(例如 CB_I2C_CH=6)會變成 "6\r",SWB transport 會拿著壞掉的通道號去打 I2C。
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# 在 DUT / Linux 上執行或被 source 的,一律 LF
|
||||||
|
*.sh text eol=lf
|
||||||
|
*.conf text eol=lf
|
||||||
|
*.py text eol=lf
|
||||||
|
*.txt text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
|
||||||
|
# Tera Term macro 只在 Windows 上跑,維持 CRLF;標成 -text 讓 git 原樣保存,
|
||||||
|
# 避免對既有檔案產生大量純換行符的假 diff
|
||||||
|
*.ttl -text
|
||||||
|
|
||||||
|
# 二進位,不要做任何轉換
|
||||||
|
*.xlsx binary
|
||||||
|
*.docx binary
|
||||||
|
*.pdf binary
|
||||||
|
*.h5 binary
|
||||||
+2
-1
@@ -12,9 +12,10 @@ For_AI/
|
|||||||
!**/logs/.gitkeep
|
!**/logs/.gitkeep
|
||||||
!**/Logs/.gitkeep
|
!**/Logs/.gitkeep
|
||||||
|
|
||||||
# 打包輸出
|
# 打包輸出:產出不進 git,打包工具本身要進
|
||||||
publish/*
|
publish/*
|
||||||
!publish/.gitkeep
|
!publish/.gitkeep
|
||||||
|
!publish/publish.sh
|
||||||
|
|
||||||
# Office 暫存檔
|
# Office 暫存檔
|
||||||
~$*
|
~$*
|
||||||
|
|||||||
+201
-66
@@ -11,8 +11,8 @@
|
|||||||
| Script | 階段 | 做什麼 |
|
| Script | 階段 | 做什麼 |
|
||||||
|--------|------|--------|
|
|--------|------|--------|
|
||||||
| `1_Blanton_Script_A.ttl` | **Pre-test / Baseline** | 登入、對時、載入 shell 工具、清 PCIe AER、抓 PCIe tree / margin / PMON / dmesg 基線 |
|
| `1_Blanton_Script_A.ttl` | **Pre-test / Baseline** | 登入、對時、載入 shell 工具、清 PCIe AER、抓 PCIe tree / margin / PMON / dmesg 基線 |
|
||||||
| `2_Blanton_Script_B.ttl` | **Stress / Soak** | 開 CPU / DDR / SSD / USB / PCIe / I2C 壓力程序,之後進無限迴圈每輪抓 fan / temp / margin |
|
| `2_Blanton_Script_B.ttl` | **Stress / Soak** | 開 CPU / DDR / SSD / USB 壓力程序 + 啟動 SWB loopback 線速流量,之後進無限迴圈每輪抓完整 PMON / margin |
|
||||||
| `3_Blanton_Script_C.ttl` | **Post-test / Verdict** | 殺掉壓力程序、再抓一次 PMON / dmesg / PCIe AER,比對 stress log 判定 |
|
| `3_Blanton_Script_C.ttl` | **Post-test / Verdict** | 殺掉壓力程序、停流量並出 per-pair TX/RX 報表、再抓一次 PMON / dmesg / PCIe AER,比對 stress log 判定 |
|
||||||
|
|
||||||
DUT 端的實際取數能力則來自一組 **bash 工具庫**(`Blanton_Script/`),這一層才是真正碰硬體的地方:
|
DUT 端的實際取數能力則來自一組 **bash 工具庫**(`Blanton_Script/`),這一層才是真正碰硬體的地方:
|
||||||
CB FPGA 的 PCIe BAR(`pcimem`)→ FPGA 內建 I2C / VI2C master → 板上 VRM、溫度感測器、
|
CB FPGA 的 PCIe BAR(`pcimem`)→ FPGA 內建 I2C / VI2C master → 板上 VRM、溫度感測器、
|
||||||
@@ -36,8 +36,11 @@ LTC2980 margin 控制器。TTL 只負責「按順序 `sendln` 並把畫面收進
|
|||||||
| I2C / PMBus 路徑 | CB FPGA F3 OpenCores I2C master、CB FPGA F3 VI2C proxy、CPU 原生 bus(`i2cset`/`i2cget`) |
|
| I2C / PMBus 路徑 | CB FPGA F3 OpenCores I2C master、CB FPGA F3 VI2C proxy、CPU 原生 bus(`i2cset`/`i2cget`) |
|
||||||
| 電源 margin | LTC2980(= 2 × LTC2977)over PMBus,LINEAR16 編碼 |
|
| 電源 margin | LTC2980(= 2 × LTC2977)over PMBus,LINEAR16 編碼 |
|
||||||
| 錯誤計數來源 | Linux PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_ce/ue_count`) |
|
| 錯誤計數來源 | Linux PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_ce/ue_count`) |
|
||||||
| 平台監控 | SONiC `show platform *`(pmon container) |
|
| 平台監控 | SONiC `show platform *`(pmon container,含 `leak status` / `leak channels`) |
|
||||||
| 壓力測試 | `mlucas-avx2`(AMD CPU)、`~/hammer/tools/stress_*.py`(DDR / SSD / USB / PCIe / I2C) |
|
| BMC 存取 | host 端 `bmc-manager run "<cmd>"`(不需對 BMC 開 SSH,繞開其 busybox 工具鏈) |
|
||||||
|
| 壓力測試 | `mlucas-avx2`(AMD CPU)、`~/hammer/tools/stress_{mem,ssd,usb}.py` |
|
||||||
|
| 資料面流量 | `bcmcmd`(Broadcom drivshell)VLAN loopback + `tx` burst,switch unit 0 / 1 |
|
||||||
|
| 流量報表 | DUT 上 awk(`blanton_traffic_linespeed report`);離線 `python3 tools/bcm_mibpair_report_V1.1.0.py` |
|
||||||
| 版本控制 | Git(NAS + Gitea 私有 remote;**不推 GitHub,含客戶 NDA 資料**) |
|
| 版本控制 | Git(NAS + Gitea 私有 remote;**不推 GitHub,含客戶 NDA 資料**) |
|
||||||
|
|
||||||
> ⚠️ **無編譯步驟。** TTL 與 bash 都是直譯執行,「build」等同「把 `src/Script_ABC_Blanton/` 複製到
|
> ⚠️ **無編譯步驟。** TTL 與 bash 都是直譯執行,「build」等同「把 `src/Script_ABC_Blanton/` 複製到
|
||||||
@@ -70,16 +73,19 @@ LTC2980 margin 控制器。TTL 只負責「按順序 `sendln` 並把畫面收進
|
|||||||
│ ├ blanton_icb_vi2c.sh vi2c_* (ICB/PDB proxy) │
|
│ ├ blanton_icb_vi2c.sh vi2c_* (ICB/PDB proxy) │
|
||||||
│ ├ blanton_temp_sensor.sh temp_cb / temp_icb / temp_all │
|
│ ├ blanton_temp_sensor.sh temp_cb / temp_icb / temp_all │
|
||||||
│ ├ blanton_pwr_data.sh pwr_data / pwr_data_pdb │
|
│ ├ blanton_pwr_data.sh pwr_data / pwr_data_pdb │
|
||||||
|
│ ├ blanton_traffic_linespeed.sh │
|
||||||
|
│ │ init/clear/show/start/stop/ps/report (bcmcmd) │
|
||||||
│ └ LTC2980_Margin_Script/ margin_init / margin_status ... │
|
│ └ LTC2980_Margin_Script/ margin_init / margin_status ... │
|
||||||
│ │
|
│ │
|
||||||
│ ~/hammer/tools/ 壓力程序(mlucas-avx2, stress_*.py) │
|
│ ~/hammer/tools/ 壓力程序(mlucas-avx2, stress_*.py) │
|
||||||
│ SONiC CLI show platform fan/temperature/... │
|
│ bcmcmd -n 0|1 Broadcom drivshell(VLAN loopback / tx) │
|
||||||
|
│ SONiC CLI show platform fan/temperature/leak/... │
|
||||||
│ Linux sysfs aer_dev_* / edac mc0/rank* │
|
│ Linux sysfs aer_dev_* / edac mc0/rank* │
|
||||||
└───────────────────────┬──────────────────────────────────────┘
|
└───────────────────────┬──────────────────────────────────────┘
|
||||||
│ pcimem /sys/bus/pci/devices/0000:03:00.<fn>/resource0
|
│ pcimem /sys/bus/pci/devices/0000:03:00.<fn>/resource0
|
||||||
▼
|
▼
|
||||||
┌──────────────────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
│ CB FPGA (PCIe EP,4 個 Function) │
|
│ CB FPGA (PCIe EP,4 個 Function;BDF 於 source 時自動偵測) │
|
||||||
│ F0 local regs:RST_CAUSE_REG 0xD90 / SWB 0xD94,0xD98 │
|
│ F0 local regs:RST_CAUSE_REG 0xD90 / SWB 0xD94,0xD98 │
|
||||||
│ F3 I2C master Ch0..Ch17 (base 0x300, stride 0x20) │
|
│ F3 I2C master Ch0..Ch17 (base 0x300, stride 0x20) │
|
||||||
│ F3 VI2C→ICB Ch0..Ch4 (base 0x780, stride 0x20) │
|
│ F3 VI2C→ICB Ch0..Ch4 (base 0x780, stride 0x20) │
|
||||||
@@ -101,16 +107,24 @@ Blanton_TTL_Script/
|
|||||||
│
|
│
|
||||||
├── CLAUDE.md # 專案記憶 & 給 Claude 的指令
|
├── CLAUDE.md # 專案記憶 & 給 Claude 的指令
|
||||||
├── ARCHITECTURE.md # 本架構文件
|
├── ARCHITECTURE.md # 本架構文件
|
||||||
├── .gitignore # secret/ + For_AI/ + logs 規則
|
├── .gitignore # secret/ + For_AI/ + logs + publish 產出
|
||||||
|
├── .gitattributes # 換行符政策:.sh/.conf 釘 LF、.ttl 保持 CRLF
|
||||||
│
|
│
|
||||||
├── docs/ # 規格與狀態文件(客戶提供 / 專案產出)
|
├── docs/ # 規格與狀態文件(客戶提供 / 專案產出)
|
||||||
│ ├── Blantons_FPGA_Registers.md # FPGA 暫存器規格(markdown 正本,查 offset 用)
|
│ ├── Blantons_FPGA_Registers.md # FPGA 暫存器規格(markdown 正本,查 offset 用)
|
||||||
│ ├── Blantons_FPGA_Registers_draft.docx # 同上,客戶原始 docx
|
│ ├── Blantons_FPGA_Registers_draft.docx # 同上,客戶原始 docx
|
||||||
│ ├── Blantons_FPGA_Registers_Map_draft.xlsx
|
│ ├── Blantons_FPGA_Registers_Map_draft.xlsx
|
||||||
│ ├── Blantons_PCIe_AER_and_DDR_EDAC_checks.pdf # AER / EDAC 檢查點依據
|
│ ├── Blantons_PCIe_AER_and_DDR_EDAC_checks.pdf # AER / EDAC 檢查點依據
|
||||||
│ └── TTL_Script_Blanton_Status_20260814.xlsx # ⭐ 三支腳本逐項 Status(OK / On-Going + Owner)
|
│ ├── TTL_Script_Blanton_Status_20260814.xlsx
|
||||||
|
│ └── TTL_Script_Blanton_Status_20260817.xlsx # ⭐ 最新:三支腳本逐項 Status(OK / On-Going + Owner)
|
||||||
│
|
│
|
||||||
├── tools/ # Host 端輔助腳本(log 解析、報表產生)
|
├── tools/ # Host / 離線端輔助腳本
|
||||||
|
│ ├── bcm_mibpair_report_V1.1.0.py # 離線解析 drivshell log → per-pair TX/RX + PASS/FAIL
|
||||||
|
│ ├── traffic_loopback_vlan_setting.txt # bcmcmd VLAN 30..137 建立 + 成對 pbm(cdN <-> cdN+32)
|
||||||
|
│ ├── traffic_loopback_start.txt # bcmcmd tx 100 length=512 VLantag=<vid>
|
||||||
|
│ └── traffic_loopback_vlan_remove.txt # bcmcmd vlan remove <vid> pbm=...
|
||||||
|
│ # ↑ 三份為手動貼上用的原始指令表,
|
||||||
|
│ # blanton_traffic_linespeed.sh 是其 bash 版
|
||||||
│
|
│
|
||||||
├── secret/ # 🚫 gitignored — DUT 密碼、per-unit BDF、COM 設定
|
├── secret/ # 🚫 gitignored — DUT 密碼、per-unit BDF、COM 設定
|
||||||
│ ├── README.md # ✅ committed — 用途索引
|
│ ├── README.md # ✅ committed — 用途索引
|
||||||
@@ -119,7 +133,9 @@ Blanton_TTL_Script/
|
|||||||
│
|
│
|
||||||
├── For_AI/ # 🚫 gitignored — AI 協作素材(波形截圖、草稿)
|
├── For_AI/ # 🚫 gitignored — AI 協作素材(波形截圖、草稿)
|
||||||
│
|
│
|
||||||
├── publish/ # 可交付的打包輸出(Blanton_Script_ABC_v<ver>_<date>/ + zip)
|
├── publish/
|
||||||
|
│ ├── publish.sh # ✅ committed — 打包工具(版號讀 Script A 檔頭)
|
||||||
|
│ └── Script_ABC_Blanton_<Ver>/ # 🚫 產出,gitignored(-z 另出同名 .zip)
|
||||||
│
|
│
|
||||||
└── src/
|
└── src/
|
||||||
└── Script_ABC_Blanton/ # ← Tera Term 的工作目錄(整包給測試員)
|
└── Script_ABC_Blanton/ # ← Tera Term 的工作目錄(整包給測試員)
|
||||||
@@ -131,10 +147,12 @@ Blanton_TTL_Script/
|
|||||||
│
|
│
|
||||||
├── utils/ # 可 include 的取數片段(TTL,無狀態、只 wait+sendln)
|
├── utils/ # 可 include 的取數片段(TTL,無狀態、只 wait+sendln)
|
||||||
│ ├── pcie_bus.ttl # lspci -tvvv / -vv
|
│ ├── pcie_bus.ttl # lspci -tvvv / -vv
|
||||||
│ ├── setup_pmon.ttl # show platform summary/fan/temperature/psu/voltage/current/ssd
|
│ ├── setup_pmon.ttl # show platform summary/fan/temperature/psustatus/voltage/
|
||||||
|
│ │ # current/ssdhealth/leak status/leak channels(9 項)
|
||||||
│ ├── show_dmesg.ttl # date + dmesg grep error/fail/warning
|
│ ├── show_dmesg.ttl # date + dmesg grep error/fail/warning
|
||||||
│ ├── show_margin_status.ttl # source margin_status_all.sh(掃 9 顆 LTC2980)
|
│ ├── show_margin_status.ttl # source margin_status_all.sh(掃 9 顆 LTC2980)
|
||||||
│ ├── kill_all_process.ttl # kill $(jobs -p)
|
│ ├── kill_all_process.ttl # kill $(jobs -p)
|
||||||
|
│ ├── wait_init.ttl # 輪詢 show platform temperature 直到 pmon 起來
|
||||||
│ ├── show_pcie_error_reg.ttl # 舊的合併版(已被下列 per-device 版取代)
|
│ ├── show_pcie_error_reg.ttl # 舊的合併版(已被下列 per-device 版取代)
|
||||||
│ ├── show_pcie_error_reg_TH6_SWB0.ttl # EP 01:00.0 + RP 00:01.1
|
│ ├── show_pcie_error_reg_TH6_SWB0.ttl # EP 01:00.0 + RP 00:01.1
|
||||||
│ ├── show_pcie_error_reg_TH6_SWB1.ttl # EP 02:00.0 + RP 00:01.2
|
│ ├── show_pcie_error_reg_TH6_SWB1.ttl # EP 02:00.0 + RP 00:01.2
|
||||||
@@ -152,12 +170,20 @@ Blanton_TTL_Script/
|
|||||||
├── blanton_icb_vi2c.sh # CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4)
|
├── blanton_icb_vi2c.sh # CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4)
|
||||||
├── blanton_temp_sensor.sh # TMP75 / TMP432 讀溫(CB Ch10 mux + ICB VI2C Ch2)
|
├── blanton_temp_sensor.sh # TMP75 / TMP432 讀溫(CB Ch10 mux + ICB VI2C Ch2)
|
||||||
├── blanton_pwr_data.sh # SWB VRM + PDB brick 的 Vin/Vout/Iout/Temp 表
|
├── blanton_pwr_data.sh # SWB VRM + PDB brick 的 Vin/Vout/Iout/Temp 表
|
||||||
|
├── blanton_traffic_linespeed.sh # SWB loopback 線速流量(bcmcmd unit 0/1)
|
||||||
|
│ # init/clear/show/start/stop/ps/report/run
|
||||||
|
├── bmc_monitor.sh # BMC 監控:週期跑 free -m,寫輪替 log
|
||||||
|
├── bmc_monitor_ddr.sh # BMC DDR 壓力:memtester,逾時 3600s
|
||||||
|
│ # ↑ 兩支都要 chmod +x 才能跑(見 Key Constraints)
|
||||||
└── LTC2980_Margin_Script/ # 電壓 margin 子專案(另有獨立 repo)
|
└── LTC2980_Margin_Script/ # 電壓 margin 子專案(另有獨立 repo)
|
||||||
├── margin.sh # margin_init/status/set/apply_profile/save
|
├── margin.sh # margin_init/status/set/apply_profile/save
|
||||||
├── settings/*.conf # 一個 .conf = 一顆 LTC2980(CB + SWB0/1 × CONN13~16)
|
├── settings/*.conf # 一個 .conf = 一顆 LTC2980(CB + SWB0/1 × CONN13~16)
|
||||||
├── profiles/*.conf # 16-ch 批次組合(comboA/B、high3/5、low3/5、normal、off)
|
├── profiles/*.conf # 16-ch 批次組合(comboA/B、high3/5、low3/5、normal、off)
|
||||||
├── script/*_all.sh # 跨 9 顆 LTC2980 的批次 status / apply / save
|
├── script/*_all.sh # 跨 9 顆 LTC2980 的批次 status / apply / save
|
||||||
|
├── Ref/margin_command_trace.md # 指令追蹤參考(SWB 章節已標過期,見文件內警告)
|
||||||
└── logs/ # margin 操作 log
|
└── logs/ # margin 操作 log
|
||||||
|
# 註:v2.6.0 起不再內含 blanton_cb_i2c.sh / blanton_fpga_pcimem.sh 的複本,
|
||||||
|
# 改由 _swb_find_backend 往上層 Blanton_Script/ 找共用版
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -193,6 +219,18 @@ Log 檔名規則:`<mdir>\Logs\<project_name>_<strTestcase>_<YYYYmmdd-HHMMSS>.l
|
|||||||
|
|
||||||
Channel 定址:`ch / 8` → `CHIPS[]` index,`ch % 8` → LTC2977 PMBus PAGE(0x00~0x07)。
|
Channel 定址:`ch / 8` → `CHIPS[]` index,`ch % 8` → LTC2977 PMBus PAGE(0x00~0x07)。
|
||||||
|
|
||||||
|
**SWB 通道與位址對應(2026-08-19 上機驗證,`ababb2c`):**
|
||||||
|
|
||||||
|
| FPGA I2C 通道 | 板 / 接頭 | LTC2977 位址(lo / hi) |
|
||||||
|
|---|---|---|
|
||||||
|
| Ch6 | SWB0 CONN14 / CONN16 | CONN14 `0x5C`,`0x5E` ; CONN16 `0x62`,`0x64` |
|
||||||
|
| Ch8 | SWB0 CONN13 / CONN15 | CONN13 `0x5C`,`0x5E` ; CONN15 `0x62`,`0x64` |
|
||||||
|
| Ch7 | SWB1 CONN14 / CONN16 | CONN14 `0x5C`,`0x5E` ; CONN16 `0x62`,`0x64` |
|
||||||
|
| Ch9 | SWB1 CONN13 / CONN15 | CONN13 `0x5C`,`0x5E` ; CONN15 `0x62`,`0x64` |
|
||||||
|
|
||||||
|
> 同一顆 LTC2980 的兩個位址**相差 2**(7-bit,由規格書 8-bit 配對除以 2 而來),不是 1。
|
||||||
|
> 兩張板共用一條通道,所以同通道上的位址必須互斥 —— 上表兩組(`0x5C/0x5E` 與 `0x62/0x64`)不重疊。
|
||||||
|
|
||||||
### 3. `profiles/*.conf` — 16-ch 批次 margin 組合
|
### 3. `profiles/*.conf` — 16-ch 批次 margin 組合
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -235,9 +273,16 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
|
|||||||
| I210 1G NIC | `0000:07:00.0` | `0000:00:02.4` |
|
| I210 1G NIC | `0000:07:00.0` | `0000:00:02.4` |
|
||||||
| NVMe SSD | `0000:06:00.0` | `0000:00:02.1` |
|
| NVMe SSD | `0000:06:00.0` | `0000:00:02.1` |
|
||||||
|
|
||||||
> ⚠️ **BDF 是 per-unit 的**。`blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES` 已經改過三次
|
> ⚠️ **BDF 是 per-unit 的,而且只解決了一半。**
|
||||||
> (04:00.x → 03:00.x → 05:00.x → 03:00.x)。換 DUT 一定要先 `lspci -Dnn | grep -i fpga` 重新確認,
|
> `blanton_fpga_pcimem.sh`(V1.5.0 起)**已改為 source 時自動偵測**,不再需要每台改檔:
|
||||||
> 同理 `show_pcie_error_reg_*.ttl` 裡的 BDF 也要跟著校。
|
> 掃 sysfs 找 `vendor == 0x1590`(HPE)且 `.0`~`.3` 四個 function 都有 `resource0` 的裝置 →
|
||||||
|
> 退回 `lspci -Dnn` 名稱比對 → 再退回 `FPGA_BDF_FALLBACK`(`0000:03:00`)。
|
||||||
|
> 偵測結果會印一行 `[INFO] CB FPGA BDF = ...`,並存在 `FPGA_BDF_ACTIVE`。
|
||||||
|
> 換 DUT 後可用 `fpga_rescan` 重測,或 `FPGA_BDF=0000:05:00 fpga_rescan` 手動釘住。
|
||||||
|
>
|
||||||
|
> **但 `utils/show_pcie_error_reg_*.ttl` 裡的 BDF 仍然是寫死的**(上表那 7 組),
|
||||||
|
> 自動偵測完全沒有涵蓋到它們。換 DUT 時這些 TTL 還是要人工校對,否則 AER 會讀到錯誤的裝置
|
||||||
|
> ——甚至讀到不存在的路徑而整段 `No such file or directory`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -245,15 +290,18 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
|
|||||||
|
|
||||||
| 模組 | 進入點 | 功能 |
|
| 模組 | 進入點 | 功能 |
|
||||||
|------|--------|------|
|
|------|--------|------|
|
||||||
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` | root 登入 → `mkdir ./logs` → `date -s` 對時 → source 五個 bash 工具 → 清/讀 7 組 PCIe AER → `lspci -tvvv/-vv` → margin 全掃 → PMON 七項 → dmesg 三 grep → `messagebox` 提示接 Script B |
|
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.0.3 | root 登入 → `date -s` 對時 → `show boot` → **等 pmon 起來**(`wait_init.ttl`)→ BMC 版本 → source 六個 bash 工具 → 清/讀 7 組 PCIe AER → `lspci` → margin 全掃 → PMON 九項 → dmesg → 100G port 狀態 → **一輪流量基線** → `show uptime` |
|
||||||
| **Script B(Stress)** | `2_Blanton_Script_B.ttl` | `mlucas-avx2 -cpu 0:15` + 5 份 `stress_mem.py` + `stress_hhmd/ssd/pcie/usb.py` 全部背景執行 → `jobs` 確認 → `while 1` 每輪 `show platform fan` / `temperature` / margin |
|
| **Script B(Stress)** | `2_Blanton_Script_B.ttl` | `mlucas-avx2 -cpu 0:15` + 5 份 `stress_mem.py` + `stress_ssd.py` + `stress_usb.py`(**共 8 個 job**)→ 啟動兩支 BMC monitor → `jobs` → 100G port 狀態 → traffic `ps/init/clear/show/start`(**兩個 unit**)→ `while 1` 每輪完整 PMON + margin |
|
||||||
| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` → PMON + dmesg 再抓一次 → 7 組 AER 再抓一次 → `cat` mlucas / stress_ssd log → 完成 messagebox |
|
| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` → PMON + dmesg → 7 組 AER → 停兩支 BMC monitor 並 `cat` 其 log → `cat` mlucas / stress_ssd log → traffic `stop` + `report`(兩個 unit)→ `show reboot-cause` / `show uptime` → 完成 messagebox |
|
||||||
| **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [data]` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 |
|
| **SWB loopback 流量** | `blanton_traffic_linespeed <sub> [-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`(一條龍) |
|
||||||
|
| **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [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 裝置必需) |
|
| **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) |
|
| **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) |
|
||||||
| **溫度** | `temp_cb` / `temp_icb` / `temp_all` | TMP75(12-bit 左靠齊 ×0.0625)、TMP432(含 RANGE bit 的 −64 偏移、remote1/2) |
|
| **溫度** | `temp_cb` / `temp_icb` / `temp_all` | TMP75(12-bit 左靠齊 ×0.0625)、TMP432(含 RANGE bit 的 −64 偏移、remote1/2) |
|
||||||
| **電源資料** | `pwr_data` / `pwr_data_pdb` / `pwr_pdb_id` | SWB VRM 全軌 Vin/Vout/Iout/Temp 對齊表;MP29816 解析度**執行期從 `MFR_VOUT_SCALE_LOOP` 讀**,不寫死 |
|
| **電源資料** | `pwr_data` / `pwr_data_pdb` / `pwr_pdb_id` | SWB VRM 全軌 Vin/Vout/Iout/Temp 對齊表;MP29816 解析度**執行期從 `MFR_VOUT_SCALE_LOOP` 讀**,不寫死 |
|
||||||
| **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描 |
|
| **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描。v2.6.0 起 SWB 路徑真正接上共用 cb_i2c 後端,並有 `margin_swb_info/probe/scan/reset/sem` 除錯包裝 |
|
||||||
|
| **BMC 監控 / 壓力** | `bmc_monitor.sh` / `bmc_monitor_ddr.sh` `{start\|stop\|status\|fg\|tail\|clear}` | 由 host 端 `bmc-manager run` 週期性打 BMC,背景 detached、log 輪替。前者跑 `free -m`(逾時 30s),後者跑 `memtester`(逾時 3600s),各自獨立 log 與 pid |
|
||||||
|
| **打包交付** | `publish/publish.sh [-v Ver] [-f] [-z] [-n]` | 版號讀 Script A 檔頭,複製成 `publish/Script_ABC_Blanton_<Ver>/`,排除 `*.log`,可另出 zip |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -269,30 +317,41 @@ Script A ── logopen Logs/Blanton_Margin_<ts>.log ──┐ (之後所有畫
|
|||||||
│ │
|
│ │
|
||||||
├─ 登入 admin → sudo -i → root@sonic:~# │
|
├─ 登入 admin → sudo -i → root@sonic:~# │
|
||||||
├─ date -s "<host 時間>" ← 讓 DUT 時戳可對照 │
|
├─ date -s "<host 時間>" ← 讓 DUT 時戳可對照 │
|
||||||
├─ source 5 個 bash 工具(函數進 shell) │
|
├─ source 6 個 bash 工具(函數進 shell) │
|
||||||
|
│ └ 此時 blanton_fpga_pcimem.sh 印出 [INFO] CB FPGA BDF = ...(自動偵測結果)
|
||||||
├─ AER 基線:7 組 EP+RP 的 correctable/nonfatal/fatal
|
├─ AER 基線:7 組 EP+RP 的 correctable/nonfatal/fatal
|
||||||
├─ lspci -tvvv / -vv ← 拓樸 + link speed/width
|
├─ lspci -tvvv / -vv ← 拓樸 + link speed/width
|
||||||
├─ margin_status_all ← 9 顆 LTC2980 × 16ch 的 Vout 與偏差%
|
├─ margin_status_all ← 9 顆 LTC2980 × 16ch 的 Vout 與偏差%
|
||||||
├─ show platform × 7 ← fan/temp/psu/voltage/current/ssdhealth
|
├─ show platform × 9 ← fan/temp/psu/voltage/current/ssdhealth/leak status/leak channels
|
||||||
└─ dmesg | grep error/fail/warning
|
├─ dmesg | grep error/fail/warning
|
||||||
|
├─ show interfaces status Ethernet513,Ethernet514 ← 100G uplink 狀態
|
||||||
|
├─ 一輪流量基線:ps → init → clear → show → start → stop → report
|
||||||
|
└─ show uptime
|
||||||
|
(最前面還有 wait_init.ttl:輪詢 show platform temperature 直到不再回報
|
||||||
|
"Thermal Not detected",避免 pmon 還沒起來就抓基線)
|
||||||
▼
|
▼
|
||||||
[messagebox "Start Script B"] ← 人工確認後手動跑 B
|
[messagebox "Start Script B"] ← 人工確認後手動跑 B
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
Script B ── 同一個 log 檔續寫(logwrite 分隔線)
|
Script B ── 同一個 log 檔續寫(logwrite 分隔線)
|
||||||
├─ 背景程序:mlucas-avx2(CPU) ×1, stress_mem ×5,
|
├─ 背景程序:mlucas-avx2(CPU) ×1, stress_mem ×5, stress_ssd, stress_usb → 共 8 個 job
|
||||||
│ stress_hhmd(I2C/LSB/PCIe), stress_ssd, stress_pcie, stress_usb
|
│ (stress_hhmd / stress_pcie 已於 2026-08-17 移除,見 Status 表 ScriptB #5/#7 "KC Remove")
|
||||||
|
├─ BMC: bmc_monitor.sh start + bmc_monitor_ddr.sh start
|
||||||
├─ jobs ← 確認全部起來了
|
├─ jobs ← 確認全部起來了
|
||||||
└─ while 1: fan → temperature → margin_status_all (soak 期間持續取樣)
|
├─ traffic: ps → init → clear → (pause 15) → show → start (unit 0 與 1,VLAN 30..137 loopback)
|
||||||
|
└─ while 1: setup_pmon(9 項)→ margin_status_all (soak 期間持續取樣)
|
||||||
▼
|
▼
|
||||||
[測試員 Ctrl-C / 停止 macro,接著跑 C]
|
[測試員 Ctrl-C / 停止 macro,接著跑 C]
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
Script C
|
Script C
|
||||||
├─ kill $(jobs -p) ← 收掉所有背景壓力
|
├─ kill $(jobs -p) ← 收掉所有背景壓力
|
||||||
├─ show platform × 7 + dmesg ← 收工快照
|
├─ show platform × 9 + dmesg ← 收工快照
|
||||||
├─ AER 再抓一次 ← 與 Script A 基線相減 = 本輪新增錯誤
|
├─ AER 再抓一次 ← 與 Script A 基線相減 = 本輪新增錯誤
|
||||||
└─ cat mlucas_amm_log / log.stress_ssd ← 壓力程式自身的 pass/fail
|
├─ BMC: 兩支 monitor stop → cat log/bmc_poll.log + log/bmc_ddr.log
|
||||||
|
├─ cat mlucas_amm_log / log.stress_ssd ← 壓力程式自身的 pass/fail
|
||||||
|
├─ traffic: stop → report ← per-pair TX/RX 交叉比對,PASS/FAIL/NA(exit 2 = 有 FAIL/NA)
|
||||||
|
└─ show reboot-cause / show uptime ← soak 期間有沒有意外重開,一眼看得到
|
||||||
▼
|
▼
|
||||||
[messagebox "GOOD JOB! Test Case DONE"] → 人工檢查 log
|
[messagebox "GOOD JOB! Test Case DONE"] → 人工檢查 log
|
||||||
```
|
```
|
||||||
@@ -321,8 +380,9 @@ pwr_data
|
|||||||
跑 B/C 前若關掉了 Tera Term,log 就斷了。
|
跑 B/C 前若關掉了 Tera Term,log 就斷了。
|
||||||
3. **PCIe AER 的判定是「差值」不是「絕對值」**:Script A 抓基線、Script C 抓結果,
|
3. **PCIe AER 的判定是「差值」不是「絕對值」**:Script A 抓基線、Script C 抓結果,
|
||||||
兩者相減才是本輪產生的錯誤。EP 與上游 Root Port **兩邊都要看**(錯誤可能只記在 RP)。
|
兩者相減才是本輪產生的錯誤。EP 與上游 Root Port **兩邊都要看**(錯誤可能只記在 RP)。
|
||||||
4. **BDF 是 per-unit 的**,換 DUT 必須重新確認並改 `blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES`
|
4. **BDF 是 per-unit 的,bash 端已自動偵測、TTL 端仍寫死**:`blanton_fpga_pcimem.sh` V1.5.0 起
|
||||||
與 `utils/show_pcie_error_reg_*.ttl`(見 Data Models §5 註)。
|
於 source 時自掃(vendor `0x1590` → `lspci` → fallback),但 `utils/show_pcie_error_reg_*.ttl`
|
||||||
|
的 7 組 BDF 還是硬編碼,換 DUT 仍需人工校對(見 Data Models §5 註)。
|
||||||
5. **ICB / PDB 一律走 VI2C,不走 VSPI**:VSPI ~18 ms/reg 會讓 I2C byte 相之間拉到 ~50 ms,
|
5. **ICB / PDB 一律走 VI2C,不走 VSPI**:VSPI ~18 ms/reg 會讓 I2C byte 相之間拉到 ~50 ms,
|
||||||
踩中 SMBus 25–35 ms timeout,裝置會 NACK register pointer。實測全 5 通道掃描 9.4 s vs 34.0 s。
|
踩中 SMBus 25–35 ms timeout,裝置會 NACK register pointer。實測全 5 通道掃描 9.4 s vs 34.0 s。
|
||||||
6. **I2C 讀一律用 Repeated START**(不是 STOP + START):PMBus / SMBus 裝置(VRM、EFUSE)
|
6. **I2C 讀一律用 Repeated START**(不是 STOP + START):PMBus / SMBus 裝置(VRM、EFUSE)
|
||||||
@@ -334,9 +394,27 @@ pwr_data
|
|||||||
9. **`ARB_LOST` 不等於裝置存在**:`vi2c_scan` 只看 `RX_ACK`,仲裁失敗會被誤報成「有裝置」。
|
9. **`ARB_LOST` 不等於裝置存在**:`vi2c_scan` 只看 `RX_ACK`,仲裁失敗會被誤報成「有裝置」。
|
||||||
`blanton_pwr_data.sh` 因此加了 ARB_LOST-aware retry 與 plausibility window
|
`blanton_pwr_data.sh` 因此加了 ARB_LOST-aware retry 與 plausibility window
|
||||||
(`0xFFFF` 或超出範圍一律回 `NA`)——**寧可 NA 也不要印出一個看起來像數據的錯值**。
|
(`0xFFFF` 或超出範圍一律回 `NA`)——**寧可 NA 也不要印出一個看起來像數據的錯值**。
|
||||||
10. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
10. **`bcmcmd` 成功退出不代表指令成功**:BCM shell 拒絕指令(`VLAN: ERROR: Entry exists` /
|
||||||
|
`Failed to execute the diagnostic command`)時 `bcmcmd` 仍 exit 0。
|
||||||
|
`blanton_traffic_linespeed.sh` 因此改用輸出比對(`$TL_ERR_PAT`),並把
|
||||||
|
`vlan create` 的 `Entry exists`(重跑 init)與 `vlan remove` 的 `not found`(init 前先 stop)
|
||||||
|
當良性情況分開計數。另外 `bcmcmd` 一律以 `</dev/null` 執行 ——
|
||||||
|
否則它會吃掉 while 迴圈的 stdin,導致**只有第一個 VLAN 被設定**(V0.3.1 修的 bug)。
|
||||||
|
11. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
||||||
實際帳密必須放 `secret/config_secret.ttl`(gitignored)並由 `config.ttl` include。
|
實際帳密必須放 `secret/config_secret.ttl`(gitignored)並由 `config.ttl` include。
|
||||||
11. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea,
|
12. **`.sh` / `.conf` 必須是 LF**:CRLF 的 shell script 在 SONiC 上直接掛
|
||||||
|
(`-bash: $'\r': command not found` + `syntax error near unexpected token`),
|
||||||
|
`settings/*.conf` 則因為是被 `source` 的,未加引號的賦值會變成 `"6\r"`(安靜地壞掉)。
|
||||||
|
`.gitattributes` 已把 `*.sh` `*.conf` `*.py` `*.txt` `*.md` 釘成 LF、`*.ttl` 維持 CRLF。
|
||||||
|
⚠️ 但 `.gitattributes` **不會回頭重寫既有工作區檔案** —— 早於它 clone 出來的目錄,
|
||||||
|
需 `git rm --cached -r . && git reset --hard` 或刪掉目錄重新 checkout 才會生效,
|
||||||
|
而且 `git status` 乾淨**不代表**磁碟上是 LF(`--renormalize` 只在進 index 的路上轉換)。
|
||||||
|
13. **`bmc_monitor*.sh` 需要執行權**:它們是本專案第一組「被執行」而非被 `source` 的腳本,
|
||||||
|
而 `do_start` 內部是 `setsid "$SCRIPT_PATH" __daemon`,**即使用 `bash x.sh start` 呼叫
|
||||||
|
也仍需 exec bit**。git 記錄為 `100644`,且 Windows → 隨身碟 → DUT 的路徑無法攜帶權限位元,
|
||||||
|
所以佈署後要先 `chmod +x ~/Blanton_Script/bmc_monitor*.sh`,否則 Script B 的 start 會
|
||||||
|
`Permission denied`、Script C 的 `cat` 撲空(BMC 段全空但不會報錯)。
|
||||||
|
14. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea,
|
||||||
絕不推 GitHub**。
|
絕不推 GitHub**。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -371,22 +449,29 @@ cp secret/config_secret.ttl.example secret/config_secret.ttl
|
|||||||
|
|
||||||
# ── 2. DUT 端:部署 bash 工具庫 ─────────────────────────────
|
# ── 2. DUT 端:部署 bash 工具庫 ─────────────────────────────
|
||||||
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
||||||
|
# 佈署後務必補執行權(Windows/隨身碟路徑帶不動 exec bit):
|
||||||
|
ssh admin@<DUT_IP> 'chmod +x ~/Blanton_Script/bmc_monitor*.sh'
|
||||||
|
# 若曾在舊工作區編輯過,先確認沒有 CRLF:grep -rlU $'\r' ~/Blanton_Script
|
||||||
ssh admin@<DUT_IP> 'sudo -i'
|
ssh admin@<DUT_IP> 'sudo -i'
|
||||||
# (現場無網路時改用 USB 隨身碟複製到 ~/Blanton_Script)
|
# (現場無網路時改用 USB 隨身碟複製到 ~/Blanton_Script)
|
||||||
|
|
||||||
# ── 3. DUT 端:確認 FPGA BDF(每台不同!)────────────────────
|
# ── 3. DUT 端:煙霧測試(跑 Script A 之前先手動確認)──────────
|
||||||
lspci -Dnn | grep -i fpga # 例:0000:03:00.0
|
|
||||||
ls -d /sys/bus/pci/devices/0000:*:00.3
|
|
||||||
# 若不是 0000:03:00.x,改 ~/Blanton_Script/blanton_fpga_pcimem.sh 的 FUNCT0..3_RES
|
|
||||||
# 以及 src/Script_ABC_Blanton/utils/show_pcie_error_reg_*.ttl 內的 BDF
|
|
||||||
|
|
||||||
# ── 4. DUT 端:煙霧測試(跑 Script A 之前先手動確認)──────────
|
|
||||||
source ~/Blanton_Script/blanton_fpga_pcimem.sh
|
source ~/Blanton_Script/blanton_fpga_pcimem.sh
|
||||||
|
# → 會印 [INFO] CB FPGA BDF = 0000:0X:00.0-.3 (resource0) ← BDF 自動偵測,不用改檔
|
||||||
|
# 偵測錯或多顆候選時:FPGA_BDF=0000:05:00 fpga_rescan
|
||||||
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到值 = BAR 通了
|
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到值 = BAR 通了
|
||||||
source ~/Blanton_Script/blanton_cb_i2c.sh
|
source ~/Blanton_Script/blanton_cb_i2c.sh
|
||||||
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
||||||
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
||||||
margin_init Blanton_CB_CONN13 && margin_status
|
margin_init Blanton_CB_CONN13 && margin_status
|
||||||
|
source ~/Blanton_Script/blanton_traffic_linespeed.sh
|
||||||
|
blanton_traffic_linespeed ps -u 0 # 對照線的 link/speed
|
||||||
|
blanton_traffic_linespeed init -u 0 -n # -n = dry-run,先看要下哪些 bcmcmd
|
||||||
|
|
||||||
|
# ── 4. DUT 端:校對 AER 的 BDF(自動偵測沒涵蓋這裡!)─────────
|
||||||
|
lspci -Dnn # 對照 ARCHITECTURE.md 的 PCIe 拓樸表
|
||||||
|
# 與 src/Script_ABC_Blanton/utils/show_pcie_error_reg_*.ttl 內寫死的 7 組 BDF 比對,
|
||||||
|
# 不符就改 TTL——否則 AER 會讀到別的裝置或不存在的路徑
|
||||||
```
|
```
|
||||||
|
|
||||||
**Host(Windows)端:**
|
**Host(Windows)端:**
|
||||||
@@ -402,6 +487,19 @@ margin_init Blanton_CB_CONN13 && margin_status
|
|||||||
8. 檢查 Logs\Blanton_Margin_<ts>.log
|
8. 檢查 Logs\Blanton_Margin_<ts>.log
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**打包交付:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./publish/publish.sh # 版號讀 Script A 檔頭 → publish/Script_ABC_Blanton_V1.0.3/
|
||||||
|
./publish/publish.sh -z # 另外產出同名 .zip
|
||||||
|
./publish/publish.sh -n # dry run,只印會做什麼
|
||||||
|
./publish/publish.sh -f # 覆蓋既有輸出資料夾
|
||||||
|
```
|
||||||
|
|
||||||
|
版號**不是參數而是從 Script A 的 `; Version : Vx.y.z` 讀出來的**,所以資料夾名不可能跟
|
||||||
|
測試員打開 macro 看到的版本不一致。要出新版就先改 Script A 檔頭再跑。
|
||||||
|
輸出會排除 `*.log`(測試 log 含 DUT 序號,不隨交付外流),但保留空的 `logs/` 供 `logopen` 寫入。
|
||||||
|
|
||||||
> 註:本專案非 .NET / Blazor / EC2 架構,`aws-ec2-deploy` 與 `vbox-run-deploy` 兩份部署指南不適用,已跳過。
|
> 註:本專案非 .NET / Blazor / EC2 架構,`aws-ec2-deploy` 與 `vbox-run-deploy` 兩份部署指南不適用,已跳過。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -416,12 +514,13 @@ margin_init Blanton_CB_CONN13 && margin_status
|
|||||||
**目標:** 專案進 git(NAS + Gitea),帳密不再躺在腳本裡,任何人 clone 下來照文件就能跑。
|
**目標:** 專案進 git(NAS + Gitea),帳密不再躺在腳本裡,任何人 clone 下來照文件就能跑。
|
||||||
|
|
||||||
**包含:**
|
**包含:**
|
||||||
- [ ] `git init` + `.gitignore`(`secret/*`、`For_AI/`、`logs/*.log`、`~$*`、`*.DSN`)
|
- [x] `git init` + `.gitignore`(`secret/*`、`For_AI/`、`logs/*.log`、`~$*`、`*.DSN`)
|
||||||
- [ ] 建 `secret/README.md` + `secret/config_secret.ttl.example`(`__CHANGE_ME__` placeholder)
|
- [x] 建 `secret/README.md` + `secret/config_secret.ttl.example`(`__CHANGE_ME__` placeholder)
|
||||||
- [ ] `config.ttl` 改為 `include "..\..\secret\config_secret.ttl"`(或現場放同層),
|
- [ ] `config.ttl` 改為 `include "..\..\secret\config_secret.ttl"`(或現場放同層),
|
||||||
把 `1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 換成 `sendln dut_password`
|
把 `1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 換成 `sendln dut_password`
|
||||||
- [ ] `src/Script_ABC_Blanton/logs/.gitkeep`,既有 `Blanton_Margin_20260814-164122.log` 移出 repo
|
**← 唯一未完成項;密碼目前仍寫在腳本裡**
|
||||||
- [ ] `CLAUDE.md` + `ARCHITECTURE.md` 進 repo,push `nas` + `gitea`(**不推 GitHub**)
|
- [x] `src/Script_ABC_Blanton/logs/.gitkeep`,既有 `Blanton_Margin_20260814-164122.log` 移出 repo
|
||||||
|
- [x] `CLAUDE.md` + `ARCHITECTURE.md` 進 repo,push `nas` + `gitea`(**不推 GitHub**)
|
||||||
|
|
||||||
**驗收條件:** 在另一台機器 `git clone` → 填 `secret/config_secret.ttl` → Script A 能完整登入並產生 log;
|
**驗收條件:** 在另一台機器 `git clone` → 填 `secret/config_secret.ttl` → Script A 能完整登入並產生 log;
|
||||||
`git log -p` 中搜不到任何實際密碼。
|
`git log -p` 中搜不到任何實際密碼。
|
||||||
@@ -442,7 +541,8 @@ margin_init Blanton_CB_CONN13 && margin_status
|
|||||||
- [ ] 新增 `utils/show_pwr_data.ttl`(`pwr_data` + `pwr_data_pdb`)與
|
- [ ] 新增 `utils/show_pwr_data.ttl`(`pwr_data` + `pwr_data_pdb`)與
|
||||||
`utils/show_temp_sensor.ttl`(`temp_all`),把 `blanton_pwr_data.sh` /
|
`utils/show_temp_sensor.ttl`(`temp_all`),把 `blanton_pwr_data.sh` /
|
||||||
`blanton_temp_sensor.sh` 真正接進流程(目前 Script A 只 source 沒用)
|
`blanton_temp_sensor.sh` 真正接進流程(目前 Script A 只 source 沒用)
|
||||||
- [ ] Script A 開頭加 BDF 自檢:`lspci -Dnn | grep -i fpga`,log 裡看得到本台的實際 BDF
|
- [x] Script A 開頭加 BDF 自檢 —— 由 `blanton_fpga_pcimem.sh` V1.5.0 的 source 時自動偵測達成,
|
||||||
|
log 內會出現 `[INFO] CB FPGA BDF = ...`(比原本規劃的 `lspci` 一行更完整)
|
||||||
|
|
||||||
**驗收條件:** 跑一次 Script A,log 內同時含 reset cause 三個暫存器值、9 顆 LTC2980 × 16ch 的
|
**驗收條件:** 跑一次 Script A,log 內同時含 reset cause 三個暫存器值、9 顆 LTC2980 × 16ch 的
|
||||||
margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,且無 `ERR` / `NA` 以外的異常。
|
margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,且無 `ERR` / `NA` 以外的異常。
|
||||||
@@ -458,14 +558,21 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
|
|||||||
(`ls -l ~/hammer/tools/` + `ls ~/hammer/tools/amd/mlucas-avx2`),缺檔就別往下跑
|
(`ls -l ~/hammer/tools/` + `ls ~/hammer/tools/amd/mlucas-avx2`),缺檔就別往下跑
|
||||||
- [ ] 壓力程序 log 加時戳,避免多輪覆蓋:
|
- [ ] 壓力程序 log 加時戳,避免多輪覆蓋:
|
||||||
`mlucas_amm_log` → `~/logs/mlucas_amm_log_$(date +%Y%m%d-%H%M%S).log`(Status 表 ScriptB #2 的既定寫法)
|
`mlucas_amm_log` → `~/logs/mlucas_amm_log_$(date +%Y%m%d-%H%M%S).log`(Status 表 ScriptB #2 的既定寫法)
|
||||||
- [ ] `jobs` 之後加驗證:期望 10 個背景 job(1 mlucas + 5 mem + hhmd/ssd/pcie/usb),
|
- [ ] `jobs` 之後加驗證:期望 **8** 個背景 job(1 mlucas + 5 mem + ssd + usb),
|
||||||
數量不符時 `messagebox` 提示
|
數量不符時 `messagebox` 提示
|
||||||
|
(`stress_hhmd` / `stress_pcie` 已於 2026-08-17 由 KC 移除,原本的 10 改為 8)
|
||||||
- [ ] soak 迴圈改為「每輪先 `date`、跑完 `pause <間隔>`」,
|
- [ ] soak 迴圈改為「每輪先 `date`、跑完 `pause <間隔>`」,
|
||||||
把 `EN_LoopInterval`(預設 600 秒 = 10 min)放進 `config.ttl`,兌現 Status 表的「Get data every 10mins」
|
把 `EN_LoopInterval`(預設 600 秒 = 10 min)放進 `config.ttl`,兌現 Status 表的「Get data every 10mins」
|
||||||
- [ ] soak 每輪補 `show platform psustatus` / `voltage` / `current`(目前只有 fan + temperature)
|
**← 目前 `while 1` 仍無 `pause`,實際間隔取決於指令執行時間,不是 10 分鐘**
|
||||||
|
- [x] soak 每輪補 `show platform psustatus` / `voltage` / `current`
|
||||||
|
—— 迴圈已改為 `include "utils/setup_pmon.ttl"`,九項全收
|
||||||
- [ ] 補 `; ========== CLEAR EVENT ==========`(Status 表 ScriptB #1,Owner: Alan)
|
- [ ] 補 `; ========== CLEAR EVENT ==========`(Status 表 ScriptB #1,Owner: Alan)
|
||||||
|
- [x] BMC 納入 soak:`bmc_monitor.sh`(`free -m` 取樣)與 `bmc_monitor_ddr.sh`(`memtester`)
|
||||||
|
由 Script B 啟動、Script C 停止並把 log 併進 master log
|
||||||
|
- [x] Script A 加開機資訊與就緒等待:`show boot`、BMC `/etc/issue`、`wait_init.ttl`
|
||||||
|
- [x] Script C 加 `show reboot-cause` / `show uptime`,soak 期間意外重開看得見
|
||||||
|
|
||||||
**驗收條件:** Script B 啟動後 `jobs` 顯示 10 個 job;連續跑 3 輪,log 內三段各自帶正確時戳且間隔 ≈10 min;
|
**驗收條件:** Script B 啟動後 `jobs` 顯示 8 個 job;連續跑 3 輪,log 內三段各自帶正確時戳且間隔 ≈10 min;
|
||||||
故意把 `~/hammer` 改名,Script B 會在前置檢查就停下並提示。
|
故意把 `~/hammer` 改名,Script B 會在前置檢查就停下並提示。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -474,19 +581,32 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
|
|||||||
|
|
||||||
**目標:** 補齊 Status 表中 Owner=Alan 的三個 traffic 項目,讓測試涵蓋交換晶片的資料面。
|
**目標:** 補齊 Status 表中 Owner=Alan 的三個 traffic 項目,讓測試涵蓋交換晶片的資料面。
|
||||||
|
|
||||||
**包含:**
|
> 📌 **實作路線與原規劃不同**:原本設想用 SONiC CLI(`sonic-clear counters` / `show interface counters`),
|
||||||
- [ ] `utils/traffic_setup.ttl`:Blanton/SONiC 版的 port 起始設定與 counter 清零
|
> 實際落地的是**更底層的 `bcmcmd` drivshell 路線** —— SWB 實體 loopback 線 + VLAN 成對配置 + `tx` burst,
|
||||||
(對照 Carlsbad 的 `clear int stat global`,改用 SONiC `sonic-clear counters`)
|
> 直接讀 ASIC 的 `MIB_TPOK`/`MIB_RPOK`。好處是能做 per-pair 雙向交叉比對(`cdA.TX == cdB.RX`),
|
||||||
- [ ] `utils/show_traffic_counters.ttl`:`show interface counters`、
|
> 比 SONiC CLI 的單向 counter 強得多;代價是綁定 Broadcom SDK 與那條 loopback 線。
|
||||||
`show interface counters errors`、`show interface status`
|
|
||||||
- [ ] `utils/show_interface_detail.ttl`:`show interface transceiver eeprom/dom`、
|
|
||||||
`show interface link-training`(對照 Carlsbad `sho int transceiver detail`)
|
|
||||||
- [ ] `utils/show_tech.ttl`:`show techsupport`(Script C 收工快照,Status 表 ScriptC #4)
|
|
||||||
- [ ] Script A 的 TRAFFIC-SETUP-STAGE 與 Script C 的 CHECK Traffic counters 接上這些片段
|
|
||||||
- [ ] `config.ttl` 加 `EN_Traffic` 旗標,未接線的站點可整段跳過
|
|
||||||
|
|
||||||
**驗收條件:** `EN_Traffic=1` 時,Script A log 有清零後的 counter 基線、Script C log 有結束時的
|
**包含:**
|
||||||
counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不執行且不報錯。
|
- [x] `blanton_traffic_linespeed.sh`(V0.4.0):`init` / `clear` / `show` / `start` / `stop` /
|
||||||
|
`ps` / `report` / `run`,unit 0 與 1,VLAN 30..137 對應 `cdN` ↔ `cdN+32`
|
||||||
|
(取代原規劃的 `utils/traffic_setup.ttl`)
|
||||||
|
- [x] per-pair TX/RX 報表與 PASS/FAIL 判定:DUT 上 awk(`report`)+ 離線
|
||||||
|
`tools/bcm_mibpair_report_V1.1.0.py`,同版面同判定規則
|
||||||
|
(取代原規劃的 `utils/show_traffic_counters.ttl`)
|
||||||
|
- [x] Script B 接上 `ps → init → clear → show → start`、Script C 接上 `stop → report`
|
||||||
|
- [x] 原始 bcmcmd 指令表留檔:`tools/traffic_loopback_{vlan_setting,start,vlan_remove}.txt`
|
||||||
|
- [x] **Script A 的流量基線** —— 原本的空區塊已改成完整一輪
|
||||||
|
(`ps → init → clear → show → start → stop → report`,含 15 秒沉澱)
|
||||||
|
- [ ] `utils/show_interface_detail.ttl`:`show interface transceiver eeprom/dom`、
|
||||||
|
`show interface link-training`(Status 表 ScriptC #4,仍 On-Going)
|
||||||
|
- [ ] `utils/show_tech.ttl`:`show techsupport`(Script C 收工快照,Status 表 ScriptC #4)
|
||||||
|
- [ ] `config.ttl` 加 `EN_Traffic` 旗標,未接 loopback 線的站點可整段跳過
|
||||||
|
(現在 B/C 是無條件執行,沒接線會整批 bcmcmd 失敗)
|
||||||
|
- [x] `-u 0` 已從三支腳本移除,全部沿用工具預設 `TL_UNITS="0 1"`,兩塊 switch board 都測到
|
||||||
|
- [x] 100G uplink 狀態:`show interfaces status Ethernet513,Ethernet514`(A 與 B 各一次)
|
||||||
|
|
||||||
|
**驗收條件:** `EN_Traffic=1` 時,Script C 的 `report` 印出 108 對的 TX/RX 表且全 PASS;
|
||||||
|
拔掉一條 loopback 線重跑,該對顯示 FAIL 或 NA 且 exit code 為 2;`EN_Traffic=0` 時整段不執行且不報錯。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -502,6 +622,8 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
|||||||
- [ ] Margin 表解析:把 9 顆 × 16ch 的 Vout / 偏差% 收成 CSV,標出超出 ±(profile 設定值 + 容差) 的軌
|
- [ ] Margin 表解析:把 9 顆 × 16ch 的 Vout / 偏差% 收成 CSV,標出超出 ±(profile 設定值 + 容差) 的軌
|
||||||
- [ ] 溫度 / 風扇 / 電源趨勢:soak 期間逐輪取樣 → CSV(可直接畫圖)
|
- [ ] 溫度 / 風扇 / 電源趨勢:soak 期間逐輪取樣 → CSV(可直接畫圖)
|
||||||
- [ ] Stress 判定:`mlucas_amm_log` 與 `log.stress_ssd` 的錯誤關鍵字掃描
|
- [ ] Stress 判定:`mlucas_amm_log` 與 `log.stress_ssd` 的錯誤關鍵字掃描
|
||||||
|
- [ ] Traffic 判定:**直接複用 `tools/bcm_mibpair_report_V1.1.0.py`**(它已能吃 console log 的
|
||||||
|
`show c` 段落並輸出 PASS/FAIL),不要重寫一套解析
|
||||||
- [ ] 產出 `Logs/<run>_summary.md`:一頁 PASS/FAIL + 每個子系統一行結論
|
- [ ] 產出 `Logs/<run>_summary.md`:一頁 PASS/FAIL + 每個子系統一行結論
|
||||||
|
|
||||||
**驗收條件:** 拿一份既有 log(如 `Blanton_Margin_20260814-164122.log`)跑解析器,
|
**驗收條件:** 拿一份既有 log(如 `Blanton_Margin_20260814-164122.log`)跑解析器,
|
||||||
@@ -514,9 +636,9 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
|||||||
**目標:** 產出可直接交給現場測試員(或客戶)的一包,含操作手冊,不需要看原始碼。
|
**目標:** 產出可直接交給現場測試員(或客戶)的一包,含操作手冊,不需要看原始碼。
|
||||||
|
|
||||||
**包含:**
|
**包含:**
|
||||||
- [ ] `tools/publish.sh`:把 `src/Script_ABC_Blanton/` + 空 `Logs/` + `secret/*.example`
|
- [x] `publish/publish.sh`:把 `src/Script_ABC_Blanton/` 打包成
|
||||||
打包成 `publish/Blanton_Script_ABC_v<ver>_<YYYYMMDD>/` 與同名 zip(比照
|
`publish/Script_ABC_Blanton_<Ver>/`(`-z` 另出 zip)。版號讀 Script A 檔頭,
|
||||||
既有的 `Blanton_Script_ABC_v1.0_20251229` 命名)
|
排除 `*.log` 但保留空的 `logs/`。工具本身進 git,產出被 gitignore
|
||||||
- [ ] `README.md`(現場用):Tera Term 設定、A→B→C 操作順序、常見錯誤(BDF 不符、
|
- [ ] `README.md`(現場用):Tera Term 設定、A→B→C 操作順序、常見錯誤(BDF 不符、
|
||||||
margin 掃不到、hammer 工具缺檔)與對應處理
|
margin 掃不到、hammer 工具缺檔)與對應處理
|
||||||
- [ ] `CHANGELOG.md`:延續三支腳本頂端的 Version History,集中成一份
|
- [ ] `CHANGELOG.md`:延續三支腳本頂端的 Version History,集中成一份
|
||||||
@@ -537,12 +659,25 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
|||||||
COM36 才拿到部分結果;`READ_VIN` 已知不是真的輸入電壓(跟隨 `READ_VOUT`)。待拿到 brick 的
|
COM36 才拿到部分結果;`READ_VIN` 已知不是真的輸入電壓(跟隨 `READ_VOUT`)。待拿到 brick 的
|
||||||
`MFR_ID`/`MFR_MODEL` 後對照 datasheet 定案。
|
`MFR_ID`/`MFR_MODEL` 後對照 datasheet 定案。
|
||||||
- **`show_pcie_error_reg.ttl` 淘汰**:舊的合併版已被 7 支 per-device 版取代,確認無人引用後刪除。
|
- **`show_pcie_error_reg.ttl` 淘汰**:舊的合併版已被 7 支 per-device 版取代,確認無人引用後刪除。
|
||||||
- **BDF 自動偵測**:把 `blanton_fpga_pcimem.sh` 註解中的 auto-detect 片段轉正,
|
- ✅ **BDF 自動偵測** —— 已於 `blanton_fpga_pcimem.sh` V1.5.0(2026-08-17)完成。
|
||||||
用 `lspci -Dnn | grep -i fpga` 動態填 `FUNCT0..3_RES`,讓換 DUT 不用改檔。
|
下一步是把同樣的偵測結果餵給 `utils/show_pcie_error_reg_*.ttl`,
|
||||||
|
讓 AER 那 7 組 BDF 也不用手改(目前仍是硬編碼)。
|
||||||
|
- **`stress_hhmd` / `stress_pcie` 的替代**:兩者已於 2026-08-17 移除,I2C/PCIe 的持續讀取壓力
|
||||||
|
目前沒有替代品。若仍需覆蓋這塊,可考慮用 `blanton_cb_i2c.sh` / `cb_fpga` 寫一支輕量 loop。
|
||||||
- **SSH / 網路模式**:目前全走 COM console。若 DUT 管理網路可用,可改用 `plink`/`ssh` 執行同一組
|
- **SSH / 網路模式**:目前全走 COM console。若 DUT 管理網路可用,可改用 `plink`/`ssh` 執行同一組
|
||||||
bash 工具,速度與可靠度都比 serial 好,TTL 只保留開機階段。
|
bash 工具,速度與可靠度都比 serial 好,TTL 只保留開機階段。
|
||||||
- **多 DUT 併行**:多台 DUT 同時 soak 時,Tera Term 每台開一個 macro window;
|
- **多 DUT 併行**:多台 DUT 同時 soak 時,Tera Term 每台開一個 macro window;
|
||||||
可考慮改成 Python(`pyserial`)統一排程與集中收 log。
|
可考慮改成 Python(`pyserial`)統一排程與集中收 log。
|
||||||
- **與 `LTC2980_Margin_Script` 獨立 repo 的同步機制**:目前 `Blanton_Script/LTC2980_Margin_Script/`
|
- ✅ **margin 子專案的重複檔** —— v2.6.0 已移除內含的 `blanton_cb_i2c.sh` /
|
||||||
是該 repo 的複本(少了 `ARCHITECTURE.md`/`CLAUDE.md`/`Reference/`,多了兩支 `blanton_*` 後端)。
|
`blanton_fpga_pcimem.sh` 複本,改由 `_swb_find_backend` 往上層找共用版,漂移風險解除。
|
||||||
待評估改用 git submodule 或明確的 vendored 同步腳本。
|
與獨立 repo `LTC2980_Margin_Script` 的同步機制(submodule 或 vendored 腳本)仍待評估。
|
||||||
|
- **`Ref/margin_command_trace.md` 需重新產生**:SWB 章節的 1223 條 `cb_pmbus_*` 指令是依
|
||||||
|
修正前的通道/位址展開的(其中 487 條用到已不存在的 `0x5D`/`0x5F`/`0x63`/`0x65`),
|
||||||
|
文件已加過期警告但內文未動。第 1~4 章不受影響。
|
||||||
|
- **`wait_init.ttl` 沒有逾時出口**:若 pmon 一直起不來,`result` 既非 1 也非 2,迴圈會無限重試,
|
||||||
|
Script A 既不往下走也不報錯。可加最大重試次數 + `messagebox` 提示。
|
||||||
|
- **`bmc_monitor*.sh` 的執行權**:目前需人工 `chmod +x`。可在 Script B 起它們之前補一行
|
||||||
|
`chmod +x`(比照既有的 `chmod +x ~/hammer/tools/amd/mlucas-avx2`),或在 publish 時處理。
|
||||||
|
- **`bmc_monitor_ddr.sh` 的壓力強度**:`memtester 500M 1` 配 `INTERVAL_SEC=5` 等於整個 soak
|
||||||
|
近乎不間斷壓 BMC 記憶體,而 BMC 同時還要服務 host 的 `show platform` 查詢。
|
||||||
|
若 PMON 取數變慢,先調大 `INTERVAL_SEC` 或縮小 memtester 的量。
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
|||||||
|
|
||||||
完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。
|
完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。
|
||||||
|
|
||||||
|
**目前狀態(2026-08-21)**:Script A/B/C 為 **V1.0.3**,涵蓋 PCIe AER / DDR EDAC / PMON /
|
||||||
|
電壓 margin(9 顆 LTC2980)/ SWB loopback 線速流量(兩個 switch unit)/ BMC 監控與 DDR 壓力。
|
||||||
|
SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。交付用 `./publish/publish.sh` 打包。
|
||||||
|
|
||||||
## 技術棧
|
## 技術棧
|
||||||
|
|
||||||
- **Host**:Tera Term 5.x TTL macro(`.ttl`),Windows
|
- **Host**:Tera Term 5.x TTL macro(`.ttl`),Windows
|
||||||
@@ -17,6 +21,9 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
|||||||
- **I2C/PMBus**:CB FPGA F3 I2C master(Ch0~Ch17,base 0x300 stride 0x20)、
|
- **I2C/PMBus**:CB FPGA F3 I2C master(Ch0~Ch17,base 0x300 stride 0x20)、
|
||||||
CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4,base 0x780)、CPU 原生 bus(`i2cset`/`i2cget`)
|
CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4,base 0x780)、CPU 原生 bus(`i2cset`/`i2cget`)
|
||||||
- **Margin**:LTC2980(= 2 × LTC2977)over PMBus,LINEAR16
|
- **Margin**:LTC2980(= 2 × LTC2977)over PMBus,LINEAR16
|
||||||
|
- **資料面流量**:`bcmcmd`(Broadcom drivshell)SWB loopback,VLAN 30..137 成對 `cdN`/`cdN+32`,
|
||||||
|
`tx 100 length=512`;判定讀 ASIC `MIB_TPOK`/`MIB_RPOK` 做 per-pair 雙向交叉比對
|
||||||
|
- **BMC**:host 端 `bmc-manager run "<cmd>"`,不需對 BMC 開 SSH(繞開其 busybox 工具鏈)
|
||||||
- **判定資料源**:PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_{ce,ue}_count`)、SONiC `show platform *`
|
- **判定資料源**:PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_{ce,ue}_count`)、SONiC `show platform *`
|
||||||
- **無編譯步驟**:TTL 與 bash 都直譯執行
|
- **無編譯步驟**:TTL 與 bash 都直譯執行
|
||||||
|
|
||||||
@@ -26,17 +33,19 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
|||||||
# ── 部署 bash 工具庫到 DUT ──────────────────────────
|
# ── 部署 bash 工具庫到 DUT ──────────────────────────
|
||||||
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
||||||
|
|
||||||
# ── DUT 上先確認 FPGA BDF(每台不同!)───────────────
|
# ── DUT 上載入工具(Script A 也是做這六件事)─────────
|
||||||
lspci -Dnn | grep -i fpga
|
source ~/Blanton_Script/blanton_fpga_pcimem.sh # ← 會自己印出偵測到的 CB FPGA BDF
|
||||||
ls -d /sys/bus/pci/devices/0000:*:00.3
|
|
||||||
|
|
||||||
# ── DUT 上載入工具(Script A 也是做這五件事)─────────
|
|
||||||
source ~/Blanton_Script/blanton_fpga_pcimem.sh
|
|
||||||
source ~/Blanton_Script/blanton_cb_i2c.sh
|
source ~/Blanton_Script/blanton_cb_i2c.sh
|
||||||
source ~/Blanton_Script/blanton_icb_vi2c.sh
|
source ~/Blanton_Script/blanton_icb_vi2c.sh
|
||||||
source ~/Blanton_Script/blanton_pwr_data.sh
|
source ~/Blanton_Script/blanton_pwr_data.sh
|
||||||
|
source ~/Blanton_Script/blanton_traffic_linespeed.sh
|
||||||
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
||||||
|
|
||||||
|
# ── FPGA BDF:自動偵測,不用改檔;必要時手動釘 ───────
|
||||||
|
fpga_rescan # 換 DUT / 重新列舉後重測
|
||||||
|
FPGA_BDF=0000:05:00 fpga_rescan # 偵測到多顆或選錯時,指定 domain:bus:dev(不含 .fn)
|
||||||
|
echo $FPGA_BDF_ACTIVE # 目前生效的 BDF
|
||||||
|
|
||||||
# ── 煙霧測試 ────────────────────────────────────────
|
# ── 煙霧測試 ────────────────────────────────────────
|
||||||
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到 = BAR 通了
|
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到 = BAR 通了
|
||||||
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
||||||
@@ -45,11 +54,45 @@ temp_all # CB + ICB 溫感
|
|||||||
pwr_data # SWB VRM 全軌
|
pwr_data # SWB VRM 全軌
|
||||||
margin_init Blanton_CB_CONN13 && margin_status
|
margin_init Blanton_CB_CONN13 && margin_status
|
||||||
|
|
||||||
|
# ── SWB loopback 流量(bcmcmd,unit 0/1)─────────────
|
||||||
|
# 不帶 -u 就是預設 TL_UNITS="0 1",兩塊 switch board 都做(TTL 三支腳本即如此)
|
||||||
|
blanton_traffic_linespeed ps # 對照線的 link/speed
|
||||||
|
blanton_traffic_linespeed init # VLAN 30..137,cdN <-> cdN+32
|
||||||
|
blanton_traffic_linespeed clear # clear c
|
||||||
|
blanton_traffic_linespeed start -tx 100 -length 512
|
||||||
|
blanton_traffic_linespeed stop # 移除 VLAN 成員(--destroy 連 VLAN 一起砍)
|
||||||
|
blanton_traffic_linespeed report # per-pair TX/RX + PASS/FAIL(exit 2 = 有 FAIL/NA)
|
||||||
|
blanton_traffic_linespeed run # ps → init → clear → start → report 一條龍
|
||||||
|
blanton_traffic_linespeed init -u 0 # 只做單一 unit 時才需要 -u
|
||||||
|
blanton_traffic_linespeed init -n # -n dry-run:只印要下的 bcmcmd,不碰 DUT
|
||||||
|
blanton_traffic_linespeed report -f <log> # 離線重解一份存下來的 console log
|
||||||
|
|
||||||
|
# 離線版報表(開發機上跑,選項更多)
|
||||||
|
python3 tools/bcm_mibpair_report_V1.1.0.py <drivshell.log> -a
|
||||||
|
|
||||||
|
# ── BMC 監控 / 壓力(需先 chmod +x!)────────────────
|
||||||
|
chmod +x ~/Blanton_Script/bmc_monitor*.sh # 佈署後必做一次
|
||||||
|
~/Blanton_Script/bmc_monitor.sh start # free -m 取樣,log/bmc_poll.log
|
||||||
|
~/Blanton_Script/bmc_monitor_ddr.sh start # memtester,log/bmc_ddr.log
|
||||||
|
~/Blanton_Script/bmc_monitor.sh status # pid / log 路徑 / log 大小
|
||||||
|
~/Blanton_Script/bmc_monitor.sh stop
|
||||||
|
# ⚠️ tail 子命令是 tail -f,會卡住不返回;要倒 log 請直接 cat log/*.log
|
||||||
|
|
||||||
# ── 各工具的 help ───────────────────────────────────
|
# ── 各工具的 help ───────────────────────────────────
|
||||||
blanton_fpga_help ; blanton_cb_i2c_help ; vi2c_help
|
blanton_fpga_help ; blanton_cb_i2c_help ; vi2c_help
|
||||||
temp_sensor_help ; pwr_data_help
|
temp_sensor_help ; pwr_data_help ; blanton_traffic_linespeed_help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**打包交付(在開發機上):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./publish/publish.sh # 版號讀 Script A 檔頭 → publish/Script_ABC_Blanton_V1.0.3/
|
||||||
|
./publish/publish.sh -z # 另出 zip
|
||||||
|
./publish/publish.sh -n # dry run
|
||||||
|
```
|
||||||
|
|
||||||
|
要出新版**先改 Script A 檔頭的 `; Version :`**,publish 才會用新版號建資料夾。
|
||||||
|
|
||||||
**Host 端跑一輪測試:**
|
**Host 端跑一輪測試:**
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -69,10 +112,17 @@ Tera Term 連 COM port (115200-8-N-1)
|
|||||||
- **新增取數項目** = 新增一支 `utils/show_xxx.ttl`,再在主腳本 `include`,不要往主腳本塞指令
|
- **新增取數項目** = 新增一支 `utils/show_xxx.ttl`,再在主腳本 `include`,不要往主腳本塞指令
|
||||||
- **bash 命名**:公開函數 `cb_i2c_* / vi2c_* / temp_* / pwr_* / margin_*`,內部 helper 一律底線開頭
|
- **bash 命名**:公開函數 `cb_i2c_* / vi2c_* / temp_* / pwr_* / margin_*`,內部 helper 一律底線開頭
|
||||||
(`_cbi2c_* / _vr / _ts_* / _pwr_*`)
|
(`_cbi2c_* / _vr / _ts_* / _pwr_*`)
|
||||||
- **版本紀錄**:每支 `.ttl` 與 `.sh` 檔頭都有 `Version History` 區塊,改動時**在檔頭補一行**
|
- **版本紀錄**:`.sh` 每支檔頭都有 `Version History` 區塊,改動時**在檔頭補一行**
|
||||||
(`V1.0.2 YYYY-MM-DD <做了什麼>`),不要只改版號
|
(`V1.0.2 YYYY-MM-DD <做了什麼>`),不要只改版號。
|
||||||
|
TTL 這邊 **2026-08-17 起改為集中制**:`1_Blanton_Script_A.ttl` 的 History 記錄 A/B/C 三支的
|
||||||
|
所有變更,B 與 C 的檔頭版本區塊已移除。⚠️ 這是待確認的慣例變更 ——
|
||||||
|
若要回到「每支各自記錄」,B/C 的 History 需要補回去
|
||||||
- **Commit**:Conventional Commits,**英文**。scope 用 `ttl` / `fpga` / `i2c` / `vi2c` /
|
- **Commit**:Conventional Commits,**英文**。scope 用 `ttl` / `fpga` / `i2c` / `vi2c` /
|
||||||
`margin` / `pwr` / `temp` / `docs`
|
`margin` / `pwr` / `temp` / `docs`
|
||||||
|
- **換行符**:由 `.gitattributes` 管理 —— `*.sh` `*.conf` `*.py` `*.txt` `*.md` 釘 **LF**
|
||||||
|
(要在 SONiC 上跑/被 source),`*.ttl` 維持 **CRLF**(Tera Term 只在 Windows 跑)。
|
||||||
|
編輯 `.ttl` 時要保留 CRLF,別讓整檔變成 LF 產生假 diff
|
||||||
|
- **打包**:`./publish/publish.sh`,版號**讀 Script A 檔頭**不是參數 —— 先改檔頭再打包
|
||||||
- **Status 表**:`docs/TTL_Script_Blanton_Status_*.xlsx` 是逐項進度的正本(OK / On-Going + Owner),
|
- **Status 表**:`docs/TTL_Script_Blanton_Status_*.xlsx` 是逐項進度的正本(OK / On-Going + Owner),
|
||||||
完成一項就同步更新,別讓文件跟腳本脫節
|
完成一項就同步更新,別讓文件跟腳本脫節
|
||||||
|
|
||||||
@@ -81,9 +131,12 @@ Tera Term 連 COM port (115200-8-N-1)
|
|||||||
- 🔒 **NDA:本 repo 只推 `nas` + `gitea`,絕不推 GitHub。** `docs/` 內含客戶 FPGA 規格。
|
- 🔒 **NDA:本 repo 只推 `nas` + `gitea`,絕不推 GitHub。** `docs/` 內含客戶 FPGA 規格。
|
||||||
- 🔒 **DUT 帳密不進 git**。`1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
- 🔒 **DUT 帳密不進 git**。`1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
||||||
實際值放 `secret/config_secret.ttl`(gitignored)。**任何 commit 前先 grep 一次確認沒帶到真密碼。**
|
實際值放 `secret/config_secret.ttl`(gitignored)。**任何 commit 前先 grep 一次確認沒帶到真密碼。**
|
||||||
- ⚠️ **PCIe BDF 是 per-unit 的**。`blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES` 已經改過三次
|
- ⚠️ **PCIe BDF 是 per-unit 的 —— bash 端已自動化,TTL 端還沒**。
|
||||||
(04:00.x → 03:00.x → 05:00.x → 03:00.x)。換 DUT 一定先 `lspci -Dnn | grep -i fpga`,
|
`blanton_fpga_pcimem.sh` V1.5.0(2026-08-17)起 source 時自動偵測(sysfs vendor `0x1590` →
|
||||||
`utils/show_pcie_error_reg_*.ttl` 內的 BDF 也要一起校。
|
`lspci` → `FPGA_BDF_FALLBACK`),**不用再每台改檔**;印一行 `[INFO] CB FPGA BDF = ...`,
|
||||||
|
可用 `fpga_rescan` 重測、`FPGA_BDF=... fpga_rescan` 手動釘住。
|
||||||
|
**但 `utils/show_pcie_error_reg_*.ttl` 裡的 7 組 BDF 仍是寫死的**,換 DUT 還是要人工校對 ——
|
||||||
|
不校就會讀到別的裝置,或整段 `No such file or directory`。
|
||||||
- ⚠️ **AER 判定看差值不看絕對值**:Script A 抓基線、Script C 抓結果,相減才是本輪錯誤。
|
- ⚠️ **AER 判定看差值不看絕對值**:Script A 抓基線、Script C 抓結果,相減才是本輪錯誤。
|
||||||
**Endpoint 與上游 Root Port 兩邊都要讀**,錯誤可能只記在 RP。
|
**Endpoint 與上游 Root Port 兩邊都要讀**,錯誤可能只記在 RP。
|
||||||
- ⚠️ **ICB/PDB 一律走 VI2C(`blanton_icb_vi2c.sh`),不要走 VSPI**:VSPI ~18 ms/reg 會讓 I2C
|
- ⚠️ **ICB/PDB 一律走 VI2C(`blanton_icb_vi2c.sh`),不要走 VSPI**:VSPI ~18 ms/reg 會讓 I2C
|
||||||
@@ -99,12 +152,38 @@ Tera Term 連 COM port (115200-8-N-1)
|
|||||||
shell;log 也只有 A 會 `logopen`,B/C 是續寫。中途關掉 window 就得手動收程序、log 也斷了。
|
shell;log 也只有 A 會 `logopen`,B/C 是續寫。中途關掉 window 就得手動收程序、log 也斷了。
|
||||||
- ⚠️ **MP29816 的 Vout 解析度不是固定值**,由 `MFR_VOUT_SCALE_LOOP(0x29)` bit[12:10] 決定,
|
- ⚠️ **MP29816 的 Vout 解析度不是固定值**,由 `MFR_VOUT_SCALE_LOOP(0x29)` bit[12:10] 決定,
|
||||||
`blanton_pwr_data.sh` 執行期從晶片讀;xlsx 上寫的 `/5mV` 與 MP2985B 的 `+49` offset **都是錯的**。
|
`blanton_pwr_data.sh` 執行期從晶片讀;xlsx 上寫的 `/5mV` 與 MP2985B 的 `+49` offset **都是錯的**。
|
||||||
|
- ⚠️ **`bcmcmd` 就算失敗也 exit 0**(`VLAN: ERROR: Entry exists` /
|
||||||
|
`Failed to execute the diagnostic command` 都照樣回 0),所以 `blanton_traffic_linespeed.sh`
|
||||||
|
是**比對輸出**而非看 exit code。另外 `bcmcmd` 一律要 `</dev/null` ——
|
||||||
|
否則它會吃掉 while 迴圈的 stdin,**只有第一個 VLAN 被設定**(V0.3.1 修過的 bug,很難看出來)。
|
||||||
|
- ⚠️ **`stress_hhmd.py` / `stress_pcie.py` 已於 2026-08-17 由 KC 移除**(Status 表 ScriptB #5/#7)。
|
||||||
|
Script B 現在是 **8 個背景 job**(1 mlucas + 5 mem + ssd + usb),不是 10 個。
|
||||||
|
I2C/PCIe 的持續讀取壓力目前沒有替代品。
|
||||||
|
- ⚠️ **soak 迴圈沒有 `pause`**:取樣間隔不是 Status 表寫的 10 分鐘,而是取決於指令執行時間。
|
||||||
|
(`-u 0` 已於 `491e807` 移除,A/B/C 現在都跑兩個 switch unit。)
|
||||||
|
- 🔒 **`.sh` / `.conf` 一定要 LF**。CRLF 的 shell script 在 SONiC 上直接掛(`$'\r': command not found`);
|
||||||
|
`settings/*.conf` 更陰險 —— 它們是被 `source` 的,`CB_I2C_CH=6` 會變成 `"6\r"`,安靜地壞掉。
|
||||||
|
`.gitattributes` 已擋住 git 這條路徑,但**不會回頭重寫既有工作區檔案**:早於它 clone 的目錄要
|
||||||
|
`git rm --cached -r . && git reset --hard` 才會生效,而且 **`git status` 乾淨不代表磁碟上是 LF**
|
||||||
|
(`--renormalize` 只在進 index 的路上轉換)。驗證要看 byte:`grep -rlU $'\r' <dir>`
|
||||||
|
- ⚠️ **`bmc_monitor*.sh` 需要 exec bit**,且**不是改用 `bash x.sh start` 就能繞過** ——
|
||||||
|
`do_start` 內部是 `setsid "$SCRIPT_PATH" __daemon`,直接執行該路徑。git 記錄是 `100644`,
|
||||||
|
Windows → 隨身碟 → DUT 也帶不動權限位元,所以佈署後要 `chmod +x ~/Blanton_Script/bmc_monitor*.sh`。
|
||||||
|
沒做的話 Script B 的 start 會 Permission denied、Script C 的 `cat` 撲空,而且**不會報錯**,
|
||||||
|
只會得到一份 BMC 段全空的 log
|
||||||
|
- ⚠️ **`bmc_monitor*.sh` 的 `tail` 子命令是 `tail -n 50 -f`,永遠不返回**。TTL 裡絕對不要呼叫它
|
||||||
|
(Script C 曾因此卡死,`18ce7a1` 改成直接 `cat log/*.log`)
|
||||||
|
- ⚠️ **DUT 的 awk 對 `%d` 會夾到 INT32**(2147483647)。線速流量的計數器是 ~10¹² 量級,
|
||||||
|
所以 awk 裡輸出大數一律用 `%.0f`(double 域,精確到 2⁵³)。`blanton_traffic_linespeed.sh`
|
||||||
|
V0.4.1 已修;寫新的 awk 報表時要記得同一件事
|
||||||
|
|
||||||
## 資料夾說明
|
## 資料夾說明
|
||||||
|
|
||||||
- `src/Script_ABC_Blanton/` — 可執行內容(Tera Term 工作目錄;內含要 scp 到 DUT 的 `Blanton_Script/`)
|
- `src/Script_ABC_Blanton/` — 可執行內容(Tera Term 工作目錄;內含要 scp 到 DUT 的 `Blanton_Script/`)
|
||||||
- `docs/` — 客戶 FPGA 規格、AER/EDAC 檢查依據、逐項 Status 表
|
- `docs/` — 客戶 FPGA 規格、AER/EDAC 檢查依據、逐項 Status 表(最新為 `*_20260817.xlsx`)
|
||||||
- `tools/` — Host 端輔助腳本(log 解析、報表產生、打包)
|
- `tools/` — Host / 離線端:`bcm_mibpair_report_V1.1.0.py`(drivshell log → per-pair 報表)、
|
||||||
- `publish/` — 交付用打包輸出(`Blanton_Script_ABC_v<ver>_<date>/` + zip)
|
`traffic_loopback_*.txt`(bcmcmd 原始指令表,`blanton_traffic_linespeed.sh` 是其 bash 版,
|
||||||
|
**改 loopback 線路時兩邊要同步**)
|
||||||
|
- `publish/` — `publish.sh`(打包工具,**進 git**)+ `Script_ABC_Blanton_<Ver>/` 產出(**gitignored**)
|
||||||
- `secret/` — 🚫 gitignored(除 `README.md` 與 `*.example`):DUT 帳密、per-unit BDF 覆寫、COM 設定
|
- `secret/` — 🚫 gitignored(除 `README.md` 與 `*.example`):DUT 帳密、per-unit BDF 覆寫、COM 設定
|
||||||
- `For_AI/` — 🚫 gitignored:AI 協作素材(波形截圖、草稿筆記)
|
- `For_AI/` — 🚫 gitignored:AI 協作素材(波形截圖、草稿筆記)
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# publish.sh -- package src/Script_ABC_Blanton for delivery
|
||||||
|
# =============================================================================
|
||||||
|
# Version History:
|
||||||
|
# V1.0.0 2026-08-21 Initial. Copies src/Script_ABC_Blanton to
|
||||||
|
# publish/Script_ABC_Blanton_<Version>, taking <Version>
|
||||||
|
# from the "; Version : Vx.y.z" header of
|
||||||
|
# 1_Blanton_Script_A.ttl.
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# The version is READ FROM Script A rather than passed in, so the folder name
|
||||||
|
# can never disagree with the header the tester sees when they open the macro.
|
||||||
|
# Bump Script A's header first, then run this.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./publish/publish.sh # publish at Script A's version
|
||||||
|
# ./publish/publish.sh -v V1.0.4 # override the version
|
||||||
|
# ./publish/publish.sh -f # overwrite an existing output folder
|
||||||
|
# ./publish/publish.sh -z # also produce a .zip next to it
|
||||||
|
# ./publish/publish.sh -n # dry run: print what would happen
|
||||||
|
# =============================================================================
|
||||||
|
set -u
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
SRC_DIR="${REPO_ROOT}/src/Script_ABC_Blanton"
|
||||||
|
OUT_ROOT="${SCRIPT_DIR}"
|
||||||
|
NAME="Script_ABC_Blanton"
|
||||||
|
VER=""; FORCE=0; ZIP=0; DRY=0
|
||||||
|
|
||||||
|
info() { printf '[\033[34mINFO\033[0m] %s\n' "$*"; }
|
||||||
|
ok() { printf '[\033[32m OK \033[0m] %s\n' "$*"; }
|
||||||
|
die() { printf '[\033[31mERR \033[0m] %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
usage() { sed -n '2,26p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0; }
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-v|--version) VER="${2:-}"; shift 2 ;;
|
||||||
|
-f|--force) FORCE=1; shift ;;
|
||||||
|
-z|--zip) ZIP=1; shift ;;
|
||||||
|
-n|--dry-run) DRY=1; shift ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) die "unknown option '$1' (try -h)" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[ -d "${SRC_DIR}" ] || die "source not found: ${SRC_DIR}"
|
||||||
|
|
||||||
|
# --- version from Script A's header ------------------------------------------
|
||||||
|
# The .ttl files are CRLF, so strip the carriage return or it lands in the
|
||||||
|
# folder name and produces a directory no one can cd into.
|
||||||
|
if [ -z "${VER}" ]; then
|
||||||
|
A_TTL="${SRC_DIR}/1_Blanton_Script_A.ttl"
|
||||||
|
[ -f "${A_TTL}" ] || die "cannot read version: ${A_TTL} missing"
|
||||||
|
VER=$(grep -m1 -E '^;[[:space:]]*Version[[:space:]]*:' "${A_TTL}" \
|
||||||
|
| tr -d '\r' | sed -E 's/.*:[[:space:]]*//; s/[[:space:]]+$//')
|
||||||
|
[ -n "${VER}" ] || die "no '; Version : Vx.y.z' header in $(basename "${A_TTL}")"
|
||||||
|
info "version from $(basename "${A_TTL}") : ${VER}"
|
||||||
|
else
|
||||||
|
info "version (overridden) : ${VER}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${VER}" in
|
||||||
|
V[0-9]*) ;;
|
||||||
|
*) die "version '${VER}' does not look like Vx.y.z" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
DEST="${OUT_ROOT}/${NAME}_${VER}"
|
||||||
|
info "source : ${SRC_DIR#${REPO_ROOT}/}"
|
||||||
|
info "destination : ${DEST#${REPO_ROOT}/}"
|
||||||
|
|
||||||
|
if [ -e "${DEST}" ]; then
|
||||||
|
[ "${FORCE}" = "1" ] || die "${DEST##*/} already exists (use -f to overwrite)"
|
||||||
|
[ "${DRY}" = "1" ] || rm -rf -- "${DEST}"
|
||||||
|
info "existing folder removed (-f)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${DRY}" = "1" ]; then
|
||||||
|
info "dry run: nothing copied"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- copy ---------------------------------------------------------------------
|
||||||
|
# Captured console logs are per-run and often carry DUT serials, so they are
|
||||||
|
# never shipped; the empty logs/ directory itself is kept because Script A's
|
||||||
|
# logopen writes into it.
|
||||||
|
mkdir -p -- "${DEST}" || die "cannot create ${DEST}"
|
||||||
|
if command -v rsync >/dev/null 2>&1; then
|
||||||
|
rsync -a --exclude='*.log' "${SRC_DIR}/" "${DEST}/" || die "rsync failed"
|
||||||
|
else
|
||||||
|
cp -a -- "${SRC_DIR}/." "${DEST}/" || die "cp failed"
|
||||||
|
find "${DEST}" -type f -name '*.log' -delete
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tera Term's logopen target, in case the source tree never had one
|
||||||
|
mkdir -p -- "${DEST}/logs"
|
||||||
|
|
||||||
|
n_files=$(find "${DEST}" -type f | wc -l)
|
||||||
|
ok "${n_files} files -> ${DEST##*/}"
|
||||||
|
|
||||||
|
if [ "${ZIP}" = "1" ]; then
|
||||||
|
command -v zip >/dev/null 2>&1 || die "zip not installed"
|
||||||
|
( cd -- "${OUT_ROOT}" && rm -f -- "${NAME}_${VER}.zip" \
|
||||||
|
&& zip -qr "${NAME}_${VER}.zip" "${NAME}_${VER}" ) || die "zip failed"
|
||||||
|
ok "$(du -h "${OUT_ROOT}/${NAME}_${VER}.zip" | cut -f1) -> ${NAME}_${VER}.zip"
|
||||||
|
fi
|
||||||
@@ -1,13 +1,21 @@
|
|||||||
; =============================================================================
|
; =============================================================================
|
||||||
; Script A for Blanton
|
; Script A for Blanton
|
||||||
; Version : V1.0.2
|
; Version : V1.0.3
|
||||||
; Date : 2026-08-17
|
; Date : 2026-08-21
|
||||||
; Author : ETWen
|
; Author : ETWen
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
; Version History:
|
; Version History:
|
||||||
; V1.0.0 2026-08-13 Initial Version
|
; V1.0.0 2026-08-13 Initial Version
|
||||||
; V1.0.1 2026-08-14 Add CLEAR PCIE Error
|
; V1.0.1 2026-08-14 Add CLEAR PCIE Error
|
||||||
; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status
|
; V1.0.2 2026-08-17 utils/setup_pmon.ttl Add Leakage Status
|
||||||
|
; utils/traffic_loopback_vlan_setting.ttl Created
|
||||||
|
; utils/traffic_loopback_vlan_remove.ttl Created
|
||||||
|
; utils/traffic_loopback_start.ttl Created
|
||||||
|
; ScriptB Remove stress_hhmd, stress_pcie
|
||||||
|
; Blanton_Script Add blanton_traffic_linespeed.sh
|
||||||
|
; ScriptB/C Add Traffic Test
|
||||||
|
; V1.0.3 2026-08-21 utils/wait_init.ttl Created
|
||||||
|
; ScriptA Add Wait DUT Ready
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
include "config.ttl"
|
include "config.ttl"
|
||||||
|
|
||||||
@@ -42,6 +50,18 @@ gettime timestr
|
|||||||
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
|
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
|
||||||
sendln cmd
|
sendln cmd
|
||||||
|
|
||||||
|
; ========== Show Build Name ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "show boot"
|
||||||
|
|
||||||
|
; ========== Wait DUT Init ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
include "utils/wait_init.ttl"
|
||||||
|
|
||||||
|
; ========== BMC version ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "bmc-manager run 'cat /etc/issue'"
|
||||||
|
|
||||||
; ========== Load Shell Script ==========
|
; ========== Load Shell Script ==========
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "source ~/Blanton_Script/blanton_fpga_pcimem.sh"
|
sendln "source ~/Blanton_Script/blanton_fpga_pcimem.sh"
|
||||||
@@ -52,6 +72,8 @@ sendln "source ~/Blanton_Script/blanton_icb_vi2c.sh"
|
|||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "source ~/Blanton_Script/blanton_pwr_data.sh"
|
sendln "source ~/Blanton_Script/blanton_pwr_data.sh"
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
|
sendln "source ~/Blanton_Script/blanton_traffic_linespeed.sh"
|
||||||
|
wait prompt_sonic_root
|
||||||
sendln "source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh"
|
sendln "source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh"
|
||||||
|
|
||||||
; ========== CLEAR PCIE Error ==========
|
; ========== CLEAR PCIE Error ==========
|
||||||
@@ -85,10 +107,32 @@ wait prompt_sonic_root
|
|||||||
;wait prompt_sonic_root
|
;wait prompt_sonic_root
|
||||||
;flushrecv
|
;flushrecv
|
||||||
|
|
||||||
; ========== TRAFFIC-SETUP-STAGE ==========
|
; ========== 100G Port Status ==========
|
||||||
;sendln "command"
|
wait prompt_sonic_root
|
||||||
|
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||||
|
|
||||||
|
; ========== First Traffic Test ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed ps"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed init"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed clear"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
pause 15
|
||||||
|
sendln "blanton_traffic_linespeed show"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed start"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
pause 15
|
||||||
|
sendln "blanton_traffic_linespeed stop"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed report"
|
||||||
|
|
||||||
|
; ========== Show Power on uptime ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "show uptime"
|
||||||
|
|
||||||
|
|
||||||
sendln ""
|
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
messagebox 'Start Script B' 'Script A DONE'
|
messagebox 'Start Script B' 'Script A DONE'
|
||||||
@@ -1,13 +1,5 @@
|
|||||||
; =============================================================================
|
; =============================================================================
|
||||||
; Script B for Blanton
|
; Script B for Blanton
|
||||||
; Version : V1.0.2
|
|
||||||
; Date : 2026-08-17
|
|
||||||
; Author : ETWen
|
|
||||||
; =============================================================================
|
|
||||||
; Version History:
|
|
||||||
; V1.0.0 2026-08-13 Initial Version
|
|
||||||
; V1.0.1 2026-08-14 Add AMD CPU STRESS TEST
|
|
||||||
; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
include "config.ttl"
|
include "config.ttl"
|
||||||
|
|
||||||
@@ -28,6 +20,13 @@ sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2'
|
|||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
|
sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
|
||||||
|
|
||||||
|
; ========== BMC Stress Test ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "./Blanton_Script/bmc_monitor_ddr.sh start"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "./Blanton_Script/bmc_monitor.sh start"
|
||||||
|
|
||||||
|
|
||||||
; ========== DDR MEMORY STRESS TEST ==========
|
; ========== DDR MEMORY STRESS TEST ==========
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||||
@@ -40,18 +39,10 @@ sendln "python ~/hammer/tools/stress_mem.py &"
|
|||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||||
|
|
||||||
; ========== I2C, LSB and PCIE read with unlimited loop ==========
|
|
||||||
wait prompt_sonic_root
|
|
||||||
sendln "python ~/hammer/tools/stress_hhmd.py &"
|
|
||||||
|
|
||||||
; ========== SSD read/write ==========
|
; ========== SSD read/write ==========
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "python ~/hammer/tools/stress_ssd.py &"
|
sendln "python ~/hammer/tools/stress_ssd.py &"
|
||||||
|
|
||||||
; ========== PCIe CPU <- PCIe -> ASIC by dumping portStatus ==========
|
|
||||||
wait prompt_sonic_root
|
|
||||||
sendln "python ~/hammer/tools/stress_pcie.py &"
|
|
||||||
|
|
||||||
; ========== USB read/write ==========
|
; ========== USB read/write ==========
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "python ~/hammer/tools/stress_usb.py &"
|
sendln "python ~/hammer/tools/stress_usb.py &"
|
||||||
@@ -60,7 +51,26 @@ sendln "python ~/hammer/tools/stress_usb.py &"
|
|||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "jobs"
|
sendln "jobs"
|
||||||
|
|
||||||
; ========== Take one round of eye measurement on uplink ports ==========
|
|
||||||
|
; ========== 100G Port Status ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||||
|
|
||||||
|
|
||||||
|
; ========== Traffic START ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed ps"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed init"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed clear"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
pause 15
|
||||||
|
sendln "blanton_traffic_linespeed show"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed start"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ========== Get data every 10mins ==========
|
; ========== Get data every 10mins ==========
|
||||||
while 1
|
while 1
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
; =============================================================================
|
; =============================================================================
|
||||||
; Script C for Blanton
|
; Script C for Blanton
|
||||||
; Version : V1.0.2
|
|
||||||
; Date : 2026-08-17
|
|
||||||
; Author : ETWen
|
|
||||||
; =============================================================================
|
|
||||||
; Version History:
|
|
||||||
; V1.0.0 2026-08-13 Initial Version
|
|
||||||
; V1.0.1 2026-08-14 Add Check PCIE error counters,CHECK Stress results
|
|
||||||
; V1.0.2 2026-08-17 utils/setup_pmon.ttl add Leakage Status
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
include "config.ttl"
|
include "config.ttl"
|
||||||
|
|
||||||
@@ -33,6 +25,17 @@ include "utils/show_pcie_error_reg_DDR.ttl"
|
|||||||
include "utils/show_pcie_error_reg_I210.ttl"
|
include "utils/show_pcie_error_reg_I210.ttl"
|
||||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||||
|
|
||||||
|
; ========== BMC TAKE DATA ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "./Blanton_Script/bmc_monitor_ddr.sh stop"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "./Blanton_Script/bmc_monitor.sh stop"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "cat ./Blanton_Script/log/bmc_poll.log"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "cat ./Blanton_Script/log/bmc_ddr.log"
|
||||||
|
|
||||||
|
|
||||||
; ========== CHECK Stress results ==========
|
; ========== CHECK Stress results ==========
|
||||||
wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
sendln "cat ~/hammer/tools/amd/mlucas_amm_log"
|
sendln "cat ~/hammer/tools/amd/mlucas_amm_log"
|
||||||
@@ -40,8 +43,16 @@ wait prompt_sonic_root
|
|||||||
sendln "cat ~/hammer/tools/log.stress_ssd"
|
sendln "cat ~/hammer/tools/log.stress_ssd"
|
||||||
|
|
||||||
; ========== CHECK Traffic counters ==========
|
; ========== CHECK Traffic counters ==========
|
||||||
;wait prompt_sonic_root
|
wait prompt_sonic_root
|
||||||
;sendln "command"
|
sendln "blanton_traffic_linespeed stop"
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "blanton_traffic_linespeed report"
|
||||||
|
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "show reboot-cause"
|
||||||
|
|
||||||
|
; ========== Show Power on uptime ==========
|
||||||
|
wait prompt_sonic_root
|
||||||
|
sendln "show uptime"
|
||||||
|
|
||||||
messagebox 'GOOD JOB! Test Case DONE' 'teraterm'
|
messagebox 'GOOD JOB! Test Case DONE' 'teraterm'
|
||||||
+2455
File diff suppressed because it is too large
Load Diff
@@ -1,444 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# =============================================================================
|
|
||||||
# blanton_cb_i2c.sh -- CB FPGA (F3) I2C / PMBus over the OpenCores I2C master
|
|
||||||
# =============================================================================
|
|
||||||
# Version History:
|
|
||||||
# V0.1.0 2026-06-16 CB sibling of blanton_icb_i2c.sh. Same OpenCores I2C
|
|
||||||
# handshake, but the I2C block lives in CB FPGA *Function 3*
|
|
||||||
# register space (base 0x300, stride 0x20, Ch0..Ch17), and
|
|
||||||
# is reached via cb_fpga 3 <off> (direct PCIe BAR -> .3/resource0).
|
|
||||||
# =============================================================================
|
|
||||||
#
|
|
||||||
# IMPORTANT (vs the hand-written cb_fpga.md pcimem commands):
|
|
||||||
# * The CB I2C channels are on PCI **Function 3**, so the sysfs file is
|
|
||||||
# .../0000:02:00.3/resource0 (NOT .0). cb_fpga 3 uses FUNCT3_RES for this.
|
|
||||||
# * This tool uses **Repeated START** for reads (write reg pointer with WR only,
|
|
||||||
# no STOP, then Sr + slave|R) so it works for the SMBus/PMBus parts (VRM,
|
|
||||||
# EFUSE) as well as plain register parts. STOP+START only works for the latter.
|
|
||||||
# * Slave addresses are 7-bit here. The spec lists 8-bit pairs (e.g. MAX31790
|
|
||||||
# "0x40/0x41" -> 7-bit 0x20; TCA9546 "0xE8/0xE9" -> 7-bit 0x74). Divide by 2.
|
|
||||||
#
|
|
||||||
# CB FPGA F3 I2C channels (base 0x300, stride 0x20) -- 7-bit addrs in (...):
|
|
||||||
# Ch0 0x300 SWB_0: TCA9546 mux (0x74), M0.C0 temp sensor, ...
|
|
||||||
# Ch1 0x320 SWB_1: TCA9546 mux (0x74), ...
|
|
||||||
# Ch2 0x340 SWB_0: SWB_FPGA (0x40), IO Exp PCA9555 (0x24), ...
|
|
||||||
# Ch3 0x360 SWB_1: SWB_FPGA (0x40), PCA9555 (0x24), ...
|
|
||||||
# Ch4 0x380 SWB_0: M1 TCA9546 mux (0x74), Clk Gen SI5..., ...
|
|
||||||
# Ch5 0x3A0 SWB_1: M1 TCA9546 mux (0x74), ...
|
|
||||||
# Ch6 0x3C0 SWB_0: VRM M29816 (0x20), VRM M2985B (0x21), ... [PMBus]
|
|
||||||
# Ch7 0x3E0 SWB_1: VRM M29816 (0x20), VRM M2985B (0x21), ... [PMBus]
|
|
||||||
# Ch8 0x400 SWB_0: VRM M2985B (0x25), M2985B (0x26), ... [PMBus]
|
|
||||||
# Ch9 0x420 SWB_1: VRM M2985B (0x25), M2985B (0x26), ... [PMBus]
|
|
||||||
# Ch10 0x440 M0 TCA9543 mux (0x70), M0.C0 Clk Buf 9DBL0452, ...
|
|
||||||
# Ch11 0x460 Fan Ctrl MAX31790 (0x20)
|
|
||||||
# Ch12 0x480 ADC leakage ADC128D818 (0x1F)
|
|
||||||
# Ch13 0x4A0 NFC SM-MFAD4-C02 (0x28)
|
|
||||||
# Ch14 0x4C0 M1 TCA9543 mux (0x70), M1.C0 QSFP28.P1 xcvr, ...
|
|
||||||
# Ch15 0x4E0 Fan1/2 EFUSE STEF48H28 (0x10/0x11), ... [PMBus-ish]
|
|
||||||
# Ch16 0x500 1G PHY I210 Ethernet ctrlr (0x49)
|
|
||||||
# Ch17 0x520 Chassis EEPROM (0x28..0x29), Diag EEPROM (0x2B), ...
|
|
||||||
# (slave 7-bit addrs derived from the 8-bit pairs in the register map; verify
|
|
||||||
# against the device datasheet / your board before driving writes.)
|
|
||||||
#
|
|
||||||
# Per-channel register layout (offset from channel base):
|
|
||||||
# +0x00 I2C_PRSCL_LO +0x04 I2C_PRSCL_HI +0x08 I2C_CTRL (bit7 MOD_EN)
|
|
||||||
# +0x0C I2C_TX(W)/I2C_RX(R) +0x10 I2C_CMD(W)/I2C_STAT(R)
|
|
||||||
# +0x14 I2C_MUX_SEL +0x18 I2C_RST (0xD) +0x1C SEM
|
|
||||||
# CMD : STA=0x80 STO=0x40 RD=0x20 WR=0x10 ACK=0x08(1=NACK) IACK=0x01
|
|
||||||
# STAT: RX_ACK=0x80(1=NACK) BUSY=0x40 ARB_LOST=0x20 TIP=0x02 INT_FLAG=0x01
|
|
||||||
# Prescale = (in_clk/(5*scl))-1 @75MHz: 0x88=100kHz, 0x24=400kHz
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# source blanton_fpga_pcimem.sh # provides cb_fpga / fpga_debug
|
|
||||||
# source blanton_cb_i2c.sh
|
|
||||||
# cb_i2c_init 11 # Ch11 (Fan Ctrl) @100kHz
|
|
||||||
# cb_i2c_scan 11
|
|
||||||
# cb_i2c_read 11 0x20 0x01 1 # MAX31790 (7-bit 0x20) reg 0x01
|
|
||||||
# cb_pmbus_read 6 0x20 0x8B 2 # Ch6 VRM READ_VOUT
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
# --- Pull in the register-access backend (cb_fpga) if not present -----------
|
|
||||||
if ! declare -F cb_fpga >/dev/null 2>&1; then
|
|
||||||
_CBI2C_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
|
|
||||||
if [ -n "$_CBI2C_DIR" ] && [ -f "$_CBI2C_DIR/blanton_fpga_pcimem.sh" ]; then
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
source "$_CBI2C_DIR/blanton_fpga_pcimem.sh"
|
|
||||||
else
|
|
||||||
echo -e "[\033[33mWARN\033[0m] blanton_cb_i2c.sh: cb_fpga() not found." >&2
|
|
||||||
echo " source blanton_fpga_pcimem.sh first (provides cb_fpga)." >&2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# === CB I2C geometry =========================================================
|
|
||||||
CBI2C_FN=3 # CB PCI Function hosting the I2C block
|
|
||||||
CBI2C_BASE=0x300 # channel 0 base offset (relative to F3 resource0)
|
|
||||||
CBI2C_CH_STRIDE=0x20
|
|
||||||
CBI2C_CH_MAX=17
|
|
||||||
|
|
||||||
# Per-channel register offsets
|
|
||||||
_CBI2C_PRSCL_LO=0x00
|
|
||||||
_CBI2C_PRSCL_HI=0x04
|
|
||||||
_CBI2C_CTRL=0x08
|
|
||||||
_CBI2C_TX=0x0C
|
|
||||||
_CBI2C_RX=0x0C
|
|
||||||
_CBI2C_CMD=0x10
|
|
||||||
_CBI2C_STAT=0x10
|
|
||||||
_CBI2C_MUX_SEL=0x14
|
|
||||||
_CBI2C_RST=0x18
|
|
||||||
_CBI2C_SEM=0x1C
|
|
||||||
|
|
||||||
# I2C_CTRL_REG / CMD / STAT bits
|
|
||||||
_CBI2C_EN=0x80
|
|
||||||
_CBI2C_STA=0x80
|
|
||||||
_CBI2C_STO=0x40
|
|
||||||
_CBI2C_RD=0x20
|
|
||||||
_CBI2C_WR=0x10
|
|
||||||
_CBI2C_NACK=0x08
|
|
||||||
_CBI2C_RXACK=0x80
|
|
||||||
_CBI2C_TIP=0x02
|
|
||||||
_CBI2C_RST_VAL=0xD
|
|
||||||
|
|
||||||
# Defaults
|
|
||||||
CB_I2C_PRESCALE_LO="${CB_I2C_PRESCALE_LO:-0x88}" # 100 kHz @ 75 MHz
|
|
||||||
CB_I2C_PRESCALE_HI="${CB_I2C_PRESCALE_HI:-0x00}"
|
|
||||||
CB_I2C_AUTO_INIT="${CB_I2C_AUTO_INIT:-1}"
|
|
||||||
CB_I2C_TIP_POLL_MAX="${CB_I2C_TIP_POLL_MAX:-100}"
|
|
||||||
|
|
||||||
# --- External I2C-mux RESET control (verified on COM34, 2026-06-16) ----------
|
|
||||||
# The TCA9543 muxes on CH10 (M0) and CH14 (M1) have an FPGA-driven, active-low
|
|
||||||
# RESET line. On power-up / FPGA reload the FPGA holds them in reset, so 0x70
|
|
||||||
# does NOT ACK on the root bus and all downstream legs are unreachable.
|
|
||||||
#
|
|
||||||
# The control is a GLOBAL register in CB FPGA *Function 0*, offset 0x7D4
|
|
||||||
# (I2C_MUX_RST_REG) -- NOT the per-channel I2C_MUX_SEL_REG (+0x14) which is a
|
|
||||||
# device-select and does nothing to the RESET pin. Per bit: 1 = release,
|
|
||||||
# 0 = hold-in-reset. Observed default 0xDD (bit1=CH10 mux, bit5=CH14 mux held).
|
|
||||||
# Writing 0xFF releases all external muxes (normal operating state). This value
|
|
||||||
# is volatile and is lost on the next power cycle / FPGA reload.
|
|
||||||
CBI2C_MUX_RST_FN="${CBI2C_MUX_RST_FN:-0}"
|
|
||||||
CBI2C_MUX_RST_OFF="${CBI2C_MUX_RST_OFF:-0x7D4}"
|
|
||||||
|
|
||||||
# Channels whose root bus carries an external mux that hangs off the RESET reg.
|
|
||||||
# CH10/CH14 = TCA9543; CH0/1/4/5 = TCA9546 (SWB/M1) per the channel map above.
|
|
||||||
CBI2C_MUX_CHANNELS="${CBI2C_MUX_CHANNELS:-0 1 4 5 10 14}"
|
|
||||||
|
|
||||||
# Auto-release external mux RESET before scanning / mux-writing a mux channel.
|
|
||||||
CB_I2C_AUTO_MUX_RST="${CB_I2C_AUTO_MUX_RST:-1}"
|
|
||||||
|
|
||||||
# --- Single FPGA register read/write via cb_fpga <fn> <off> [data] ----------
|
|
||||||
# _cbi2c_reg <abs_offset> [data] data present = write, absent = read (echo hex)
|
|
||||||
_cbi2c_reg() {
|
|
||||||
local off="$1" data="${2:-}"
|
|
||||||
if [ -n "$data" ]; then cb_fpga "$CBI2C_FN" "$off" "$data"; else cb_fpga "$CBI2C_FN" "$off"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Channel base absolute offset
|
|
||||||
_cbi2c_chan_base() {
|
|
||||||
local ch="$1"
|
|
||||||
if (( ch < 0 || ch > CBI2C_CH_MAX )); then
|
|
||||||
echo "blanton_cb_i2c: ch must be 0..$CBI2C_CH_MAX" >&2; return 1
|
|
||||||
fi
|
|
||||||
printf '0x%X' $(( CBI2C_BASE + ch * CBI2C_CH_STRIDE ))
|
|
||||||
}
|
|
||||||
|
|
||||||
# Normalize a register read-back to a number string ("0x...." -> 0x....)
|
|
||||||
_cbi2c_num() { local v="$1"; [[ "$v" =~ (0[xX][0-9a-fA-F]+) ]] && echo "${BASH_REMATCH[1]}" || echo "0"; }
|
|
||||||
|
|
||||||
# Write CMD then poll STAT (same offset) until TIP clears; echo final status hex
|
|
||||||
_cbi2c_cmd_wait() {
|
|
||||||
local cmd_off="$1" cmd_val="$2" i status
|
|
||||||
_cbi2c_reg "$cmd_off" "$cmd_val" >/dev/null
|
|
||||||
for (( i=0; i<CB_I2C_TIP_POLL_MAX; i++ )); do
|
|
||||||
status=$(_cbi2c_num "$(_cbi2c_reg "$cmd_off")")
|
|
||||||
if (( (status & _CBI2C_TIP) == 0 )); then
|
|
||||||
printf '0x%X' "$status"; return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo -e "[\033[31mERR\033[0m] CB I2C TIP timeout (status=$status)" >&2
|
|
||||||
printf '0x%X' "${status:-0}"; return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check RX_ACK in status (bit7). 0 = ACK, 1 = NACK -> return 1
|
|
||||||
_cbi2c_check_ack() {
|
|
||||||
local status; status=$(_cbi2c_num "$1")
|
|
||||||
(( (status & _CBI2C_RXACK) != 0 )) && return 1 || return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Public: init / reset / semaphore / mux-sel =============================
|
|
||||||
|
|
||||||
# cb_i2c_init <ch> [prescale_lo] [prescale_hi]
|
|
||||||
cb_i2c_init() {
|
|
||||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_init <ch> [prescale_lo] [prescale_hi]"; return 1; }
|
|
||||||
local ch="$1" lo="${2:-$CB_I2C_PRESCALE_LO}" hi="${3:-$CB_I2C_PRESCALE_HI}" base
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_CTRL)))" 0x00 >/dev/null # disable
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_PRSCL_LO)))" "$lo" >/dev/null
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_PRSCL_HI)))" "$hi" >/dev/null
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_CTRL)))" "$_CBI2C_EN" >/dev/null # enable
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_reset <ch>
|
|
||||||
cb_i2c_reset() {
|
|
||||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_reset <ch>"; return 1; }
|
|
||||||
local ch="$1" base; base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_RST)))" "$_CBI2C_RST_VAL" >/dev/null
|
|
||||||
echo " [RST] ch=$ch local I2C controller reset (0xD)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_sem <ch> [status|acquire [val]|release]
|
|
||||||
cb_i2c_sem() {
|
|
||||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_sem <ch> [status|acquire [val]|release]"; return 1; }
|
|
||||||
local ch="$1" act="${2:-status}" base off cur
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
off=$(printf '0x%X' $((base + _CBI2C_SEM)))
|
|
||||||
case "$act" in
|
|
||||||
status)
|
|
||||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
|
||||||
(( (cur & 0xFF) == 0 )) && echo " [SEM] ch=$ch free (0x00)" \
|
|
||||||
|| printf ' [SEM] ch=%s held (0x%02X)\n' "$ch" $((cur & 0xFF)) ;;
|
|
||||||
acquire)
|
|
||||||
local val="${3:-0x01}"
|
|
||||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
|
||||||
if (( (cur & 0xFF) != 0 )); then
|
|
||||||
printf ' [SEM] ch=%s already held (0x%02X) -- not acquired\n' "$ch" $((cur & 0xFF)); return 1
|
|
||||||
fi
|
|
||||||
_cbi2c_reg "$off" "$val" >/dev/null
|
|
||||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
|
||||||
(( (cur & 0xFF) != 0 )) && printf ' [SEM] ch=%s acquired (0x%02X)\n' "$ch" $((cur & 0xFF)) \
|
|
||||||
|| { echo " [SEM] ch=$ch acquire failed"; return 1; } ;;
|
|
||||||
release)
|
|
||||||
_cbi2c_reg "$off" 0x00 >/dev/null; echo " [SEM] ch=$ch released (0x00)" ;;
|
|
||||||
*) echo "Usage: cb_i2c_sem <ch> [status|acquire [val]|release]"; return 1 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_muxsel <ch> <dev_sel> -- write I2C_MUX_SEL_REG (FPGA drives ext mux pins)
|
|
||||||
cb_i2c_muxsel() {
|
|
||||||
[[ $# -lt 2 ]] && { echo "Usage: cb_i2c_muxsel <ch> <dev_sel>"; return 1; }
|
|
||||||
local ch="$1" sel="$2" base; base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_MUX_SEL)))" "$sel" >/dev/null
|
|
||||||
printf ' [MUXSEL] ch=%s DEV_SEL <= 0x%02X\n' "$ch" $((sel & 0xFF))
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_mux_reset_release -- de-assert ALL external mux RESET lines (F0 0x7D4 <= 0xFF)
|
|
||||||
# Global, not per-channel. Volatile: lost on power cycle / FPGA reload.
|
|
||||||
cb_i2c_mux_reset_release() {
|
|
||||||
cb_fpga "$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF" 0xFF >/dev/null
|
|
||||||
local rb; rb=$(_cbi2c_num "$(cb_fpga "$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF")")
|
|
||||||
printf ' [MUX-RST] I2C_MUX_RST_REG (F%s %s) <= 0xFF (all external muxes released, readback %s)\n' \
|
|
||||||
"$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF" "$rb"
|
|
||||||
}
|
|
||||||
|
|
||||||
# _cbi2c_is_mux_channel <ch> -- 0 (true) if ch is in CBI2C_MUX_CHANNELS
|
|
||||||
_cbi2c_is_mux_channel() {
|
|
||||||
local ch="$1" c
|
|
||||||
for c in $CBI2C_MUX_CHANNELS; do [[ "$c" == "$ch" ]] && return 0; done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# _cbi2c_auto_mux_rst <ch> -- release external mux RESET if ch is a mux channel
|
|
||||||
_cbi2c_auto_mux_rst() {
|
|
||||||
[[ "$CB_I2C_AUTO_MUX_RST" == "1" ]] || return 0
|
|
||||||
_cbi2c_is_mux_channel "$1" || return 0
|
|
||||||
cb_i2c_mux_reset_release
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Core transfers (Repeated START, SMBus/PMBus compatible) =================
|
|
||||||
|
|
||||||
# _cbi2c_xfer_read <ch> <slave7> <reg> <nbytes> echoes space-separated hex bytes
|
|
||||||
_cbi2c_xfer_read() {
|
|
||||||
local ch="$1" slave="$2" reg="$3" n="$4" base tx cmd rx status i last cmdv val out=""
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
|
||||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
|
||||||
rx=$(printf '0x%X' $((base + _CBI2C_RX)))
|
|
||||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
|
||||||
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
|
||||||
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((reg & 0xFF)))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR)))") # WR only, no STOP
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on reg 0x$(printf %02X "$reg")" >&2; return 1; }
|
|
||||||
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( ((slave << 1) | 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))") # Repeated START
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (R) 0x$(printf %02X "$slave")" >&2; return 1; }
|
|
||||||
|
|
||||||
for (( i=0; i<n; i++ )); do
|
|
||||||
last=$(( i == n-1 ))
|
|
||||||
if (( last )); then cmdv=$(( _CBI2C_RD | _CBI2C_NACK | _CBI2C_STO )); else cmdv=$(( _CBI2C_RD )); fi
|
|
||||||
_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' "$cmdv")" >/dev/null
|
|
||||||
val=$(_cbi2c_num "$(_cbi2c_reg "$rx")")
|
|
||||||
out+="$(printf '0x%02X ' $((val & 0xFF)))"
|
|
||||||
done
|
|
||||||
echo "${out% }"
|
|
||||||
}
|
|
||||||
|
|
||||||
# _cbi2c_xfer_write <ch> <slave7> <reg> <byte> [byte...]
|
|
||||||
_cbi2c_xfer_write() {
|
|
||||||
local ch="$1" slave="$2" reg="$3"; shift 3
|
|
||||||
local base tx cmd status b last cmdv n=$# idx=0
|
|
||||||
[[ $n -lt 1 ]] && { echo "ERR: no data bytes" >&2; return 1; }
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
|
||||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
|
||||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
|
||||||
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
|
||||||
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((reg & 0xFF)))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on reg 0x$(printf %02X "$reg")" >&2; return 1; }
|
|
||||||
|
|
||||||
for b in "$@"; do
|
|
||||||
idx=$((idx+1)); last=$(( idx == n ))
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( $((b)) & 0xFF )))" >/dev/null
|
|
||||||
if (( last )); then cmdv=$(( _CBI2C_WR | _CBI2C_STO )); else cmdv=$(( _CBI2C_WR )); fi
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' "$cmdv")")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on data byte #$idx" >&2; return 1; }
|
|
||||||
done
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# _cbi2c_xfer_cmd_only <ch> <slave7> <cmd> -- START+W, cmd byte, STOP (no data)
|
|
||||||
_cbi2c_xfer_cmd_only() {
|
|
||||||
local ch="$1" slave="$2" cc="$3" base tx cmd status
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
|
||||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
|
||||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((cc & 0xFF)))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR | _CBI2C_STO)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on cmd 0x$(printf %02X "$cc")" >&2; return 1; }
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Public: generic I2C =====================================================
|
|
||||||
|
|
||||||
# cb_i2c_read <ch> <slave> <reg> [nbytes]
|
|
||||||
cb_i2c_read() {
|
|
||||||
[[ $# -lt 3 ]] && { echo "Usage: cb_i2c_read <ch> <slave> <reg> [nbytes]"; return 1; }
|
|
||||||
local ch="$1" slave=$(( $2 )) reg=$(( $3 )) n="${4:-1}" bytes
|
|
||||||
bytes=$(_cbi2c_xfer_read "$ch" "$slave" "$reg" "$n") || return 1
|
|
||||||
printf ' [I2C-R] ch=%s slave=0x%02X reg=0x%02X => [%s]\n' "$ch" "$slave" "$reg" "$bytes"
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_write <ch> <slave> <reg> <byte> [byte...]
|
|
||||||
cb_i2c_write() {
|
|
||||||
[[ $# -lt 4 ]] && { echo "Usage: cb_i2c_write <ch> <slave> <reg> <byte> [byte...]"; return 1; }
|
|
||||||
local ch="$1" slave=$(( $2 )) reg=$(( $3 )); shift 3
|
|
||||||
_cbi2c_xfer_write "$ch" "$slave" "$reg" "$@" || return 1
|
|
||||||
printf ' [I2C-W] ch=%s slave=0x%02X reg=0x%02X <= [%s]\n' "$ch" "$slave" "$reg" "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_muxwrite <ch> <mux_slave> <ctrl_byte> -- raw 1-byte write, no reg (TCA954x)
|
|
||||||
cb_i2c_muxwrite() {
|
|
||||||
[[ $# -lt 3 ]] && { echo "Usage: cb_i2c_muxwrite <ch> <mux_slave> <ctrl_byte>"; return 1; }
|
|
||||||
local ch="$1" slave=$(( $2 )) val=$(( $3 )) base tx cmd status
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
|
||||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
|
||||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
|
||||||
_cbi2c_auto_mux_rst "$ch"
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on mux addr 0x$(printf %02X "$slave")" >&2; return 1; }
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((val & 0xFF)))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR | _CBI2C_STO)))")
|
|
||||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on mux ctrl byte" >&2; return 1; }
|
|
||||||
printf ' [MUX-W] ch=%s mux=0x%02X <= 0x%02X\n' "$ch" "$slave" "$val"
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_i2c_scan <ch> -- probe 0x08..0x77, report slaves that ACK
|
|
||||||
cb_i2c_scan() {
|
|
||||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_scan <ch>"; return 1; }
|
|
||||||
local ch="$1" base tx cmd a status found=""
|
|
||||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
|
||||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
|
||||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
|
||||||
cb_i2c_init "$ch" >/dev/null
|
|
||||||
_cbi2c_auto_mux_rst "$ch"
|
|
||||||
for (( a=0x08; a<=0x77; a++ )); do
|
|
||||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (a << 1) & 0xFF )))" >/dev/null
|
|
||||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR | _CBI2C_STO)))")
|
|
||||||
_cbi2c_check_ack "$status" && found+="$(printf '0x%02X ' "$a")"
|
|
||||||
done
|
|
||||||
[[ -n "$found" ]] && echo " [SCAN] ch=$ch found: ${found% }" || echo " [SCAN] ch=$ch no devices"
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Public: PMBus (== SMBus; command code + Repeated START read) ============
|
|
||||||
|
|
||||||
# cb_pmbus_read <ch> <slave> <cmd> [nbytes] (default 2 bytes, LSB first)
|
|
||||||
cb_pmbus_read() {
|
|
||||||
[[ $# -lt 3 ]] && { echo "Usage: cb_pmbus_read <ch> <slave> <cmd> [nbytes]"; return 1; }
|
|
||||||
local ch="$1" slave=$(( $2 )) cc=$(( $3 )) n="${4:-2}" bytes
|
|
||||||
bytes=$(_cbi2c_xfer_read "$ch" "$slave" "$cc" "$n") || return 1
|
|
||||||
if [[ "$n" == "2" ]]; then
|
|
||||||
local b0 b1 word; b0=$(( $(echo "$bytes" | awk '{print $1}') )); b1=$(( $(echo "$bytes" | awk '{print $2}') ))
|
|
||||||
word=$(( b0 | (b1 << 8) ))
|
|
||||||
printf ' [PMB-R] ch=%s slave=0x%02X cmd=0x%02X => 0x%04X raw=[%s] linear16=%s\n' \
|
|
||||||
"$ch" "$slave" "$cc" "$word" "$bytes" "$(cb_pmbus_linear16 "$word")"
|
|
||||||
else
|
|
||||||
printf ' [PMB-R] ch=%s slave=0x%02X cmd=0x%02X => [%s]\n' "$ch" "$slave" "$cc" "$bytes"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_pmbus_write <ch> <slave> <cmd> [data byte...] (no byte = send-byte)
|
|
||||||
cb_pmbus_write() {
|
|
||||||
[[ $# -lt 3 ]] && { echo "Usage: cb_pmbus_write <ch> <slave> <cmd> [data byte...]"; return 1; }
|
|
||||||
local ch="$1" slave=$(( $2 )) cc=$(( $3 )); shift 3
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
_cbi2c_xfer_cmd_only "$ch" "$slave" "$cc" || return 1
|
|
||||||
printf ' [PMB-W] ch=%s slave=0x%02X cmd=0x%02X <= (send-byte)\n' "$ch" "$slave" "$cc"; return 0
|
|
||||||
fi
|
|
||||||
_cbi2c_xfer_write "$ch" "$slave" "$cc" "$@" || return 1
|
|
||||||
printf ' [PMB-W] ch=%s slave=0x%02X cmd=0x%02X <= [%s]\n' "$ch" "$slave" "$cc" "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
# cb_pmbus_linear16 <word>
|
|
||||||
cb_pmbus_linear16() {
|
|
||||||
local word=$(( $1 & 0xFFFF ))
|
|
||||||
awk -v w="$word" 'BEGIN{
|
|
||||||
e=int(w/2048)%32; if(e>15)e-=32;
|
|
||||||
m=w%2048; if(m>1023)m-=2048;
|
|
||||||
printf "%.4f", m * (2.0 ^ e);
|
|
||||||
}'
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Help ====================================================================
|
|
||||||
blanton_cb_i2c_help() {
|
|
||||||
echo -e "\033[1mblanton_cb_i2c.sh - CB FPGA (F3) I2C / PMBus over OpenCores I2C master\033[0m"
|
|
||||||
echo ""
|
|
||||||
echo -e " Backend: \033[36mcb_fpga $CBI2C_FN\033[0m (direct PCIe BAR -> .3/resource0), base 0x300, Ch0..$CBI2C_CH_MAX"
|
|
||||||
echo ""
|
|
||||||
echo -e "\033[1mSetup\033[0m"
|
|
||||||
echo -e " \033[33mcb_i2c_init\033[0m <ch> [pre_lo] [pre_hi] prescale + enable (def 0x88/0x00 = 100kHz)"
|
|
||||||
echo -e " \033[33mcb_i2c_reset\033[0m <ch> LCL_RST=0xD"
|
|
||||||
echo -e " \033[33mcb_i2c_sem\033[0m <ch> [status|acquire [v]|release]"
|
|
||||||
echo -e " \033[33mcb_i2c_muxsel\033[0m <ch> <dev_sel> write I2C_MUX_SEL_REG"
|
|
||||||
echo -e " \033[33mcb_i2c_mux_reset_release\033[0m de-assert ALL ext mux RESET (F0 0x7D4<=0xFF)"
|
|
||||||
echo ""
|
|
||||||
echo -e "\033[1mGeneric I2C\033[0m"
|
|
||||||
echo -e " \033[33mcb_i2c_scan\033[0m <ch>"
|
|
||||||
echo -e " \033[33mcb_i2c_read\033[0m <ch> <slave> <reg> [nbytes]"
|
|
||||||
echo -e " \033[33mcb_i2c_write\033[0m <ch> <slave> <reg> <byte> [byte...]"
|
|
||||||
echo -e " \033[33mcb_i2c_muxwrite\033[0m <ch> <mux_slave> <ctrl_byte> raw 1-byte (TCA954x)"
|
|
||||||
echo ""
|
|
||||||
echo -e "\033[1mPMBus / SMBus\033[0m"
|
|
||||||
echo -e " \033[33mcb_pmbus_read\033[0m <ch> <slave> <cmd> [nbytes] (def 2, LE word + linear16)"
|
|
||||||
echo -e " \033[33mcb_pmbus_write\033[0m <ch> <slave> <cmd> [byte...]"
|
|
||||||
echo -e " \033[33mcb_pmbus_linear16\033[0m <word>"
|
|
||||||
echo ""
|
|
||||||
echo -e " Slave = 7-bit (tool shifts). Spec lists 8-bit pairs -> divide by 2."
|
|
||||||
echo -e " \033[33mfpga_debug on\033[0m to see every underlying pcimem command."
|
|
||||||
}
|
|
||||||
|
|
||||||
blanton_cb_i2c_help
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# =============================================================================
|
|
||||||
# blanton_fpga_pcimem.sh -- pcimem backend, sysfs resource file + relative offset
|
|
||||||
# =============================================================================
|
|
||||||
# Version History:
|
|
||||||
# V1.3.0 2026-06-12 pcimem variant (SONiC hardware). memtool variant: blanton_fpga_memtool.sh
|
|
||||||
# Version number kept in sync with blanton_fpga_memtool.sh
|
|
||||||
# V1.4.0 2026-06-15 Fix: VSPI window bases pointed at the VSPI-Flash block
|
|
||||||
# (0x340/0x380/0x3C0/0x400, config-flash channel) so register
|
|
||||||
# reads returned 0; corrected to the VSPI register block
|
|
||||||
# (PMC 0x640 / ICB 0x680 / SWB0 0x6C0 / SWB1 0x700)
|
|
||||||
# Add: _vspi_fnwarn guard - warns when PMC/ICB/SWB are called with
|
|
||||||
# cb_fpga-style "<fn> <addr>" (a read turning into a write)
|
|
||||||
# Change: suppress pcimem write stdout noise (mmap/Written lines)
|
|
||||||
# Docs: comments/help translated to English (ASCII-only for SONiC console)
|
|
||||||
# V1.4.1 2026-06-23 Fix: BDF in example auto-detect was wrong (02:00 vs 04:00); corrected to match the lspci example.
|
|
||||||
# =============================================================================
|
|
||||||
#
|
|
||||||
# SONiC hardware has no memtool / devmem, but it has pcimem. pcimem mmaps the PCI
|
|
||||||
# sysfs resource file directly and takes "resource file + offset relative to BAR
|
|
||||||
# start", not an absolute physical address.
|
|
||||||
#
|
|
||||||
# pcimem { sysfile } { offset } [ type*count [ data ] ]
|
|
||||||
# sysfile : sysfs file for the pci resource (e.g. .../resource0)
|
|
||||||
# offset : offset into pci memory region
|
|
||||||
# type : [b]yte, [h]alfword, [w]ord, [d]ouble-word
|
|
||||||
# *count : number of items (w*100 dump 100 words)
|
|
||||||
# data : data to be written
|
|
||||||
#
|
|
||||||
# This tool always accesses as word (w, 32-bit).
|
|
||||||
#
|
|
||||||
# After sourcing this file the following functions are available:
|
|
||||||
# cb_fpga <fn:0-3> <addr> [data]
|
|
||||||
# pmc_fpga <addr> [data]
|
|
||||||
# icb_fpga <addr> [data]
|
|
||||||
# swb0_fpga <addr> [data]
|
|
||||||
# swb1_fpga <addr> [data]
|
|
||||||
#
|
|
||||||
# data present = write, absent = read.
|
|
||||||
# Usage: source blanton_fpga_pcimem.sh
|
|
||||||
|
|
||||||
# === CB FPGA PCIe resource file (sysfs) ===
|
|
||||||
# Use lspci -D to find the BDF (domain:bus:dev.fn); resource0 is the sysfs mapping of BAR0.
|
|
||||||
# e.g. lspci -Dnn | grep -i fpga -> 0000:02:00.0 ...
|
|
||||||
# memtool variant fills in the BAR value; pcimem variant fills in the resource file
|
|
||||||
# path instead (offset becomes relative to BAR).
|
|
||||||
FUNCT0_RES=/sys/bus/pci/devices/0000:04:00.0/resource0
|
|
||||||
FUNCT1_RES=/sys/bus/pci/devices/0000:04:00.1/resource0
|
|
||||||
FUNCT2_RES=/sys/bus/pci/devices/0000:04:00.2/resource0
|
|
||||||
FUNCT3_RES=/sys/bus/pci/devices/0000:04:00.3/resource0
|
|
||||||
|
|
||||||
# Auto-detect example (uncomment to use; needs the FPGA's BDF prefix):
|
|
||||||
# _BDF=0000:02:00
|
|
||||||
# FUNCT0_RES=/sys/bus/pci/devices/${_BDF}.0/resource0
|
|
||||||
# FUNCT1_RES=/sys/bus/pci/devices/${_BDF}.1/resource0
|
|
||||||
# FUNCT2_RES=/sys/bus/pci/devices/${_BDF}.2/resource0
|
|
||||||
# FUNCT3_RES=/sys/bus/pci/devices/${_BDF}.3/resource0
|
|
||||||
|
|
||||||
# === VSPI window base offset (relative to CB Function 2 resource0 start) ===
|
|
||||||
# NOTE: CB.F2 has TWO near-identical VSPI register blocks (see spec register map):
|
|
||||||
# - VSPI-Flash-* @ 0x340/0x380/0x3C0/0x400 -> accesses the remote FPGA's CONFIG FLASH
|
|
||||||
# - VSPI-* @ 0x640/0x680/0x6C0/0x700 -> accesses the remote FPGA's REGISTERS
|
|
||||||
# This tool reads/writes remote registers, so it uses the VSPI-* block (0x640+).
|
|
||||||
# The VSPI-Flash bases are kept below (commented) in case flash access is needed later.
|
|
||||||
VSPI_PMC_BASE=0x640
|
|
||||||
VSPI_ICB_BASE=0x680
|
|
||||||
VSPI_SWB0_BASE=0x6C0
|
|
||||||
VSPI_SWB1_BASE=0x700
|
|
||||||
|
|
||||||
# VSPI-Flash window bases (config-flash access, not register access):
|
|
||||||
# VSPI_FLASH_PMC_BASE=0x340
|
|
||||||
# VSPI_FLASH_ICB_BASE=0x380
|
|
||||||
# VSPI_FLASH_SWB0_BASE=0x3C0
|
|
||||||
# VSPI_FLASH_SWB1_BASE=0x400
|
|
||||||
|
|
||||||
# === VSPI protocol constants ===
|
|
||||||
_VSPI_CMD_STAT=0x00
|
|
||||||
_VSPI_ADDR=0x04
|
|
||||||
_VSPI_WR_DATA=0x08
|
|
||||||
_VSPI_RD_DATA=0x0C
|
|
||||||
_VSPI_NEW_CMD=0x01
|
|
||||||
_VSPI_READ_W=0x02
|
|
||||||
_VSPI_WRITE_W=0x04
|
|
||||||
_VSPI_READY_MASK=0x100
|
|
||||||
_VSPI_POLL_MAX=200
|
|
||||||
|
|
||||||
# === pcimem command ===
|
|
||||||
PCIMEM_CMD="${PCIMEM_CMD:-pcimem}"
|
|
||||||
|
|
||||||
# === Debug mode (1=print commands AND execute, 0=execute only) ===
|
|
||||||
DEBUG_MODE=${DEBUG_MODE:-0}
|
|
||||||
|
|
||||||
fpga_debug() {
|
|
||||||
if [ "${1:-}" = "on" ]; then DEBUG_MODE=1
|
|
||||||
elif [ "${1:-}" = "off" ]; then DEBUG_MODE=0
|
|
||||||
else [ "$DEBUG_MODE" = "0" ] && DEBUG_MODE=1 || DEBUG_MODE=0; fi
|
|
||||||
echo -e "[\033[34mINFO\033[0m] DEBUG_MODE=$DEBUG_MODE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Wrapper: debug mode prints command (to stderr) AND executes, normal mode executes only.
|
|
||||||
# On read, returns the parsed hex value (stripping pcimem's mmap noise).
|
|
||||||
# Usage: _pcimem <sysfile> <offset> [data] (data present = write, absent = read)
|
|
||||||
_pcimem() {
|
|
||||||
local sysfile="$1" offset="$2" data="${3:-}"
|
|
||||||
if [[ -n "$data" ]]; then
|
|
||||||
[ "$DEBUG_MODE" = "1" ] && \
|
|
||||||
echo -e "\033[90m[DEBG] $PCIMEM_CMD $sysfile $offset w $data\033[0m" >&2
|
|
||||||
# Write output (opened / Target offset / mmap / Written...readback) is never
|
|
||||||
# parsed -> drop stdout noise; keep stderr so real errors still surface.
|
|
||||||
$PCIMEM_CMD "$sysfile" "$offset" w "$data" >/dev/null
|
|
||||||
else
|
|
||||||
[ "$DEBUG_MODE" = "1" ] && \
|
|
||||||
echo -e "\033[90m[DEBG] $PCIMEM_CMD $sysfile $offset w\033[0m" >&2
|
|
||||||
# pcimem read prints mmap info + "Value at offset ...: 0xXXXX";
|
|
||||||
# take the last 0x... token as the actual read-back value.
|
|
||||||
$PCIMEM_CMD "$sysfile" "$offset" w | grep -oiE '0x[0-9a-f]+' | tail -1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# --- Internal VSPI helpers (all hang off CB Function 2's resource0) ---
|
|
||||||
|
|
||||||
_vspi_read() {
|
|
||||||
local win_off="$1" remote_offset="$2"
|
|
||||||
local cmd_off add_off rd_off addr_val status i
|
|
||||||
|
|
||||||
cmd_off=$(printf '0x%X' $(( win_off + _VSPI_CMD_STAT )))
|
|
||||||
add_off=$(printf '0x%X' $(( win_off + _VSPI_ADDR )))
|
|
||||||
rd_off=$(printf '0x%X' $(( win_off + _VSPI_RD_DATA )))
|
|
||||||
addr_val=$(printf '0x%08X' $(( (0x0 << 20) | (remote_offset & 0xFFFFF) )))
|
|
||||||
|
|
||||||
_pcimem "$FUNCT2_RES" "$add_off" "$addr_val"
|
|
||||||
_pcimem "$FUNCT2_RES" "$cmd_off" $(printf '0x%X' $(( _VSPI_NEW_CMD | _VSPI_READ_W )))
|
|
||||||
|
|
||||||
for (( i=0; i<_VSPI_POLL_MAX; i++ )); do
|
|
||||||
status=$(_pcimem "$FUNCT2_RES" "$cmd_off")
|
|
||||||
if (( ( ${status:-0} & _VSPI_READY_MASK) != 0 )); then
|
|
||||||
_pcimem "$FUNCT2_RES" "$rd_off"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "ERROR: VSPI read timeout @ offset $remote_offset" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_vspi_write() {
|
|
||||||
local win_off="$1" remote_offset="$2" data="$3"
|
|
||||||
local cmd_off add_off wr_off addr_val status i
|
|
||||||
|
|
||||||
cmd_off=$(printf '0x%X' $(( win_off + _VSPI_CMD_STAT )))
|
|
||||||
add_off=$(printf '0x%X' $(( win_off + _VSPI_ADDR )))
|
|
||||||
wr_off=$(printf '0x%X' $(( win_off + _VSPI_WR_DATA )))
|
|
||||||
addr_val=$(printf '0x%08X' $(( (0x0 << 20) | (remote_offset & 0xFFFFF) )))
|
|
||||||
|
|
||||||
_pcimem "$FUNCT2_RES" "$wr_off" "$data"
|
|
||||||
_pcimem "$FUNCT2_RES" "$add_off" "$addr_val"
|
|
||||||
_pcimem "$FUNCT2_RES" "$cmd_off" $(printf '0x%X' $(( _VSPI_NEW_CMD | _VSPI_WRITE_W )))
|
|
||||||
|
|
||||||
for (( i=0; i<_VSPI_POLL_MAX; i++ )); do
|
|
||||||
status=$(_pcimem "$FUNCT2_RES" "$cmd_off")
|
|
||||||
if (( ( ${status:-0} & _VSPI_READY_MASK) != 0 )); then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "ERROR: VSPI write timeout @ offset $remote_offset" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Guard: PMC/ICB/SWB are single-function; signature is <addr> [data], NO fn arg.
|
|
||||||
# Common pitfall: using cb_fpga's "<fn> <addr>" form -> 2nd arg becomes data, a read
|
|
||||||
# turns into a write. If addr is 0~3 (looks like fn) AND data is given, warn and
|
|
||||||
# confirm; on a non-tty (script) just warn, don't block.
|
|
||||||
# Usage: _vspi_fnwarn <name> <addr> <data> non-zero return = cancel
|
|
||||||
_vspi_fnwarn() {
|
|
||||||
local name="$1" addr="$2" data="$3"
|
|
||||||
[[ -z "$data" ]] && return 0 # read, nothing to warn
|
|
||||||
case "$addr" in
|
|
||||||
0|1|2|3|0x0|0x1|0x2|0x3|0x00|0x01|0x02|0x03) ;; # looks like fn, warn below
|
|
||||||
*) return 0 ;; # normal offset, allow
|
|
||||||
esac
|
|
||||||
echo -e "[\033[33mWARN\033[0m] $name has no fn arg; signature is <addr> [data] (NOT cb_fpga's <fn> <addr>)." >&2
|
|
||||||
echo -e " This will WRITE $data to PMC/ICB/SWB offset $addr." >&2
|
|
||||||
echo -e " To READ offset $addr, pass a single arg: $name $addr" >&2
|
|
||||||
if [ -t 0 ]; then
|
|
||||||
local ans
|
|
||||||
read -r -p " Proceed with write anyway? [y/N] " ans
|
|
||||||
case "$ans" in
|
|
||||||
y|Y|yes|YES) return 0 ;;
|
|
||||||
*) echo " Cancelled." >&2; return 1 ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# === Public functions ===
|
|
||||||
|
|
||||||
cb_fpga() {
|
|
||||||
if [[ $# -lt 2 ]]; then
|
|
||||||
echo "Usage: cb_fpga <fn:0-3> <addr> [data]"; return 1
|
|
||||||
fi
|
|
||||||
local fn="$1" addr="$2" data="${3:-}" res
|
|
||||||
case "$fn" in
|
|
||||||
0) res=$FUNCT0_RES ;; 1) res=$FUNCT1_RES ;;
|
|
||||||
2) res=$FUNCT2_RES ;; 3) res=$FUNCT3_RES ;;
|
|
||||||
*) echo "cb_fpga: fn must be 0-3" >&2; return 1 ;;
|
|
||||||
esac
|
|
||||||
# pcimem offset is relative to BAR start; do not add BAR.
|
|
||||||
if [[ -z "$data" ]]; then
|
|
||||||
_pcimem "$res" "$addr"
|
|
||||||
else
|
|
||||||
_pcimem "$res" "$addr" "$data"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
pmc_fpga() {
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo "Usage: pmc_fpga <addr> [data]"; return 1
|
|
||||||
fi
|
|
||||||
local addr="$1" data="${2:-}"
|
|
||||||
_vspi_fnwarn pmc_fpga "$addr" "$data" || return 1
|
|
||||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_PMC_BASE" "$addr"
|
|
||||||
else _vspi_write "$VSPI_PMC_BASE" "$addr" "$data"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
icb_fpga() {
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo "Usage: icb_fpga <addr> [data]"; return 1
|
|
||||||
fi
|
|
||||||
local addr="$1" data="${2:-}"
|
|
||||||
_vspi_fnwarn icb_fpga "$addr" "$data" || return 1
|
|
||||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_ICB_BASE" "$addr"
|
|
||||||
else _vspi_write "$VSPI_ICB_BASE" "$addr" "$data"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
swb0_fpga() {
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo "Usage: swb0_fpga <addr> [data]"; return 1
|
|
||||||
fi
|
|
||||||
local addr="$1" data="${2:-}"
|
|
||||||
_vspi_fnwarn swb0_fpga "$addr" "$data" || return 1
|
|
||||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_SWB0_BASE" "$addr"
|
|
||||||
else _vspi_write "$VSPI_SWB0_BASE" "$addr" "$data"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
swb1_fpga() {
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo "Usage: swb1_fpga <addr> [data]"; return 1
|
|
||||||
fi
|
|
||||||
local addr="$1" data="${2:-}"
|
|
||||||
_vspi_fnwarn swb1_fpga "$addr" "$data" || return 1
|
|
||||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_SWB1_BASE" "$addr"
|
|
||||||
else _vspi_write "$VSPI_SWB1_BASE" "$addr" "$data"; fi
|
|
||||||
}
|
|
||||||
|
|
||||||
blanton_fpga_help() {
|
|
||||||
echo -e "\033[1mblanton_fpga (pcimem) - FPGA Register Access Tool\033[0m"
|
|
||||||
echo ""
|
|
||||||
echo -e "\033[1mUsage:\033[0m"
|
|
||||||
echo -e " \033[33mcb_fpga\033[0m <fn:0-3> <addr> [data] CB FPGA direct (sysfs resource0)"
|
|
||||||
echo -e " \033[33mpmc_fpga\033[0m <addr> [data] PMC FPGA via VSPI"
|
|
||||||
echo -e " \033[33micb_fpga\033[0m <addr> [data] ICB FPGA via VSPI"
|
|
||||||
echo -e " \033[33mswb0_fpga\033[0m <addr> [data] SWB0 FPGA via VSPI"
|
|
||||||
echo -e " \033[33mswb1_fpga\033[0m <addr> [data] SWB1 FPGA via VSPI"
|
|
||||||
echo -e " \033[33mfpga_debug\033[0m on|off Toggle debug mode (print commands and execute)"
|
|
||||||
echo ""
|
|
||||||
echo -e " Omit [data] to \033[32mread\033[0m, provide [data] to \033[31mwrite\033[0m."
|
|
||||||
echo -e " Backend: \033[36mpcimem\033[0m (sysfs resource file + relative offset)."
|
|
||||||
echo -e " Run \033[33mblanton_fpga_help\033[0m to show this message again."
|
|
||||||
}
|
|
||||||
|
|
||||||
blanton_fpga_help
|
|
||||||
File diff suppressed because it is too large
Load Diff
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- Transport (blank = i2c): CB's LTC2980 is on the native I2C bus, driven by
|
# --- Transport (blank = i2c): CB's LTC2980 is on the native I2C bus, driven by
|
||||||
# i2cset/i2cget. Only SWB boards set TRANSPORT="swb" + CB_I2C_CH=<6|7|8|9>. ---
|
# i2cset/i2cget. Only SWB boards set TRANSPORT="swb" + CB_I2C_CH=<6|7|8|9>. ---
|
||||||
TRANSPORT=""
|
TRANSPORT=""
|
||||||
CB_I2C_CH=
|
CB_I2C_CH=
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: CB (CONN13)
|
# chip1: CB (CONN13)
|
||||||
"4:0x5C" # CH0 ~ CH7
|
"4:0x5C" # CH0 ~ CH7
|
||||||
"4:0x5E" # CH8 ~ CH15
|
"4:0x5E" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # CB CONN13 (lo)
|
"" # CB CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # CB CONN13 (lo)
|
"" # CB CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: CB (CONN13)
|
# chip1: CB (CONN13)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="5.0"; CH0_NET="V5P0_ALW"
|
CH0_VNOM="5.0"; CH0_NET="V5P0_ALW"
|
||||||
CH1_VNOM="3.3"; CH1_NET="V3P3_ALW"
|
CH1_VNOM="3.3"; CH1_NET="V3P3_ALW"
|
||||||
CH2_VNOM="0.75"; CH2_NET="PWR_VDD_MISC_ALW"
|
CH2_VNOM="0.75"; CH2_NET="PWR_VDD_MISC_ALW"
|
||||||
CH3_VNOM="1.8"; CH3_NET="V1P8_ALW"
|
CH3_VNOM="1.8"; CH3_NET="V1P8_ALW"
|
||||||
CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS"
|
CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS"
|
||||||
CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN"
|
CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN"
|
||||||
CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN"
|
CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN"
|
||||||
CH7_VNOM="0.8"; CH7_NET="V0P8_PHY2_DVDD"
|
CH7_VNOM="0.8"; CH7_NET="V0P8_PHY2_DVDD"
|
||||||
CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD"
|
CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD"
|
||||||
CH9_VNOM="0.8"; CH9_NET="V0P8_PHY"
|
CH9_VNOM="0.8"; CH9_NET="V0P8_PHY"
|
||||||
CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA"
|
CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA"
|
||||||
CH11_VNOM="2.5"; CH11_NET="V2P5_FPGA"
|
CH11_VNOM="2.5"; CH11_NET="V2P5_FPGA"
|
||||||
CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA"
|
CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA"
|
||||||
CH13_VNOM="5.0"; CH13_NET="P5V_STBY"
|
CH13_VNOM="5.0"; CH13_NET="P5V_STBY"
|
||||||
CH14_VNOM="3.3"; CH14_NET="P3V3_STBY"
|
CH14_VNOM="3.3"; CH14_NET="P3V3_STBY"
|
||||||
CH15_VNOM="0.8"; CH15_NET="V0P8_PHY2_AVDD"
|
CH15_VNOM="0.8"; CH15_NET="V0P8_PHY2_AVDD"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=6
|
CB_I2C_CH=8 # CB F3 Ch8 = SWB0 CONN13/CONN15 (shared with CONN15, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB0 (CONN13)
|
# chip1: SWB0 (CONN13)
|
||||||
"0:0x5C" # CH0 ~ CH7
|
"0:0x5C" # CH0 ~ CH7
|
||||||
"0:0x5E" # CH8 ~ CH15
|
"0:0x5E" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB0 CONN13 (lo)
|
"" # SWB0 CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB0 CONN13 (lo)
|
"" # SWB0 CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB0 (CONN13)
|
# chip1: SWB0 (CONN13)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||||
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
||||||
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
||||||
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
||||||
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||||
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
||||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||||
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
||||||
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
||||||
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
||||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=8
|
CB_I2C_CH=6 # CB F3 Ch6 = SWB0 CONN14/CONN16 (shared with CONN16, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB0 (CONN14)
|
# chip1: SWB0 (CONN14)
|
||||||
"0:0x5E" # CH0 ~ CH7
|
"0:0x5C" # CH0 ~ CH7
|
||||||
"0:0x5F" # CH8 ~ CH15
|
"0:0x5E" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB0 CONN14 (lo)
|
"" # SWB0 CONN14 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB0 CONN14 (lo)
|
"" # SWB0 CONN14 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB0 (CONN14)
|
# chip1: SWB0 (CONN14)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
||||||
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
||||||
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
||||||
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
||||||
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||||
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||||
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
||||||
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
||||||
CH10_VNOM="-"; CH10_NET="NC"
|
CH10_VNOM="-"; CH10_NET="NC"
|
||||||
CH11_VNOM="-"; CH11_NET="NC"
|
CH11_VNOM="-"; CH11_NET="NC"
|
||||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||||
CH13_VNOM="-"; CH13_NET="NC"
|
CH13_VNOM="-"; CH13_NET="NC"
|
||||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=6
|
CB_I2C_CH=8 # CB F3 Ch8 = SWB0 CONN13/CONN15 (shared with CONN13, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB0 (CONN15)
|
# chip1: SWB0 (CONN15)
|
||||||
"0:0x62" # CH0 ~ CH7
|
"0:0x62" # CH0 ~ CH7
|
||||||
"0:0x63" # CH8 ~ CH15
|
"0:0x64" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB0 CONN15 (lo)
|
"" # SWB0 CONN15 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB0 CONN15 (lo)
|
"" # SWB0 CONN15 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB0 (CONN15)
|
# chip1: SWB0 (CONN15)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
||||||
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
||||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||||
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
||||||
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
||||||
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||||
CH10_VNOM="-"; CH10_NET="NC"
|
CH10_VNOM="-"; CH10_NET="NC"
|
||||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
||||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||||
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
||||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=8
|
CB_I2C_CH=6 # CB F3 Ch6 = SWB0 CONN14/CONN16 (shared with CONN14, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB0 (CONN16)
|
# chip1: SWB0 (CONN16)
|
||||||
"0:0x64" # CH0 ~ CH7
|
"0:0x62" # CH0 ~ CH7
|
||||||
"0:0x65" # CH8 ~ CH15
|
"0:0x64" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB0 CONN16 (lo)
|
"" # SWB0 CONN16 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB0 CONN16 (lo)
|
"" # SWB0 CONN16 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB0 (CONN16)
|
# chip1: SWB0 (CONN16)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||||
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
||||||
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||||
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||||
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||||
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
||||||
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
||||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||||
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
||||||
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
||||||
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
||||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
||||||
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
||||||
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
||||||
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=7
|
CB_I2C_CH=9 # CB F3 Ch9 = SWB1 CONN13/CONN15 (shared with CONN15, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB1 (CONN13)
|
# chip1: SWB1 (CONN13)
|
||||||
"1:0x5C" # CH0 ~ CH7
|
"1:0x5C" # CH0 ~ CH7
|
||||||
"1:0x5D" # CH8 ~ CH15
|
"1:0x5E" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB1 CONN13 (lo)
|
"" # SWB1 CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB1 CONN13 (lo)
|
"" # SWB1 CONN13 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB1 (CONN13)
|
# chip1: SWB1 (CONN13)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||||
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
||||||
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
||||||
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
||||||
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||||
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
||||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||||
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
||||||
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
||||||
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
||||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=9
|
CB_I2C_CH=7 # CB F3 Ch7 = SWB1 CONN14/CONN16 (shared with CONN16, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB1 (CONN14)
|
# chip1: SWB1 (CONN14)
|
||||||
"1:0x5E" # CH0 ~ CH7
|
"1:0x5C" # CH0 ~ CH7
|
||||||
"1:0x5F" # CH8 ~ CH15
|
"1:0x5E" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB1 CONN14 (lo)
|
"" # SWB1 CONN14 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB1 CONN14 (lo)
|
"" # SWB1 CONN14 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB1 (CONN14)
|
# chip1: SWB1 (CONN14)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
||||||
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
||||||
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
||||||
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
||||||
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||||
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||||
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
||||||
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
||||||
CH10_VNOM="-"; CH10_NET="NC"
|
CH10_VNOM="-"; CH10_NET="NC"
|
||||||
CH11_VNOM="-"; CH11_NET="NC"
|
CH11_VNOM="-"; CH11_NET="NC"
|
||||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||||
CH13_VNOM="-"; CH13_NET="NC"
|
CH13_VNOM="-"; CH13_NET="NC"
|
||||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=7
|
CB_I2C_CH=9 # CB F3 Ch9 = SWB1 CONN13/CONN15 (shared with CONN13, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB1 (CONN15)
|
# chip1: SWB1 (CONN15)
|
||||||
"1:0x62" # CH0 ~ CH7
|
"1:0x62" # CH0 ~ CH7
|
||||||
"1:0x63" # CH8 ~ CH15
|
"1:0x64" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB1 CONN15 (lo)
|
"" # SWB1 CONN15 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB1 CONN15 (lo)
|
"" # SWB1 CONN15 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB1 (CONN15)
|
# chip1: SWB1 (CONN15)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
||||||
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
||||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||||
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
||||||
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
||||||
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
||||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||||
CH10_VNOM="-"; CH10_NET="NC"
|
CH10_VNOM="-"; CH10_NET="NC"
|
||||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
||||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||||
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
||||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||||
|
|||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
# Blanton Channel Settings
|
# Blanton Channel Settings
|
||||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||||
#
|
#
|
||||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||||
# ch_global / 8 -> CHIPS index (0~17)
|
# ch_global / 8 -> CHIPS index (0~17)
|
||||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||||
|
|
||||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||||
TRANSPORT="swb"
|
TRANSPORT="swb"
|
||||||
CB_I2C_CH=9
|
CB_I2C_CH=7 # CB F3 Ch7 = SWB1 CONN14/CONN16 (shared with CONN14, addr must differ)
|
||||||
|
|
||||||
# --- I2C Configuration ---
|
# --- I2C Configuration ---
|
||||||
|
|
||||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||||
CHIPS=(
|
CHIPS=(
|
||||||
# chip1: SWB1 (CONN16)
|
# chip1: SWB1 (CONN16)
|
||||||
"1:0x64" # CH0 ~ CH7
|
"1:0x62" # CH0 ~ CH7
|
||||||
"1:0x65" # CH8 ~ CH15
|
"1:0x64" # CH8 ~ CH15
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-commands to run before accessing each chip (empty = none)
|
# Pre-commands to run before accessing each chip (empty = none)
|
||||||
# Multiple commands separated by ;
|
# Multiple commands separated by ;
|
||||||
CHIP_PRE_CMD=(
|
CHIP_PRE_CMD=(
|
||||||
"" # SWB1 CONN16 (lo)
|
"" # SWB1 CONN16 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||||
CHIP_POST_CMD=(
|
CHIP_POST_CMD=(
|
||||||
"" # SWB1 CONN16 (lo)
|
"" # SWB1 CONN16 (lo)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# chip1: SWB1 (CONN16)
|
# chip1: SWB1 (CONN16)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||||
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
||||||
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||||
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||||
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||||
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
||||||
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
||||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||||
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
||||||
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
||||||
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
||||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
||||||
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
||||||
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
||||||
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
||||||
|
|||||||
@@ -17,10 +17,21 @@
|
|||||||
# V1.4.2 2026-08-10 Change: FUNCT0..3_RES BDF updated 0000:04:00.x -> 0000:03:00.x (current unit's enumeration).
|
# V1.4.2 2026-08-10 Change: FUNCT0..3_RES BDF updated 0000:04:00.x -> 0000:03:00.x (current unit's enumeration).
|
||||||
# V1.4.3 2026-08-12 Change: FUNCT0..3_RES BDF updated 0000:03:00.x -> 0000:05:00.x (current unit's enumeration).
|
# V1.4.3 2026-08-12 Change: FUNCT0..3_RES BDF updated 0000:03:00.x -> 0000:05:00.x (current unit's enumeration).
|
||||||
# V1.4.4 2026-08-12 Change: FUNCT0..3_RES BDF back to 0000:03:00.x for the DUT on COM36.
|
# V1.4.4 2026-08-12 Change: FUNCT0..3_RES BDF back to 0000:03:00.x for the DUT on COM36.
|
||||||
# NOTE: this BDF is per-unit. Check with
|
# V1.5.0 2026-08-17 Change: BDF is no longer hard-coded. FUNCT0..3_RES are now
|
||||||
# lspci -Dnn | grep -i fpga or
|
# auto-detected at source time by scanning sysfs for the HPE
|
||||||
# ls -d /sys/bus/pci/devices/0000:*:00.3
|
# vendor id (0x1590) with all four functions .0-.3 present,
|
||||||
# and edit the four lines below if it differs.
|
# falling back to `lspci -Dnn` name/id match, then to
|
||||||
|
# FPGA_BDF_FALLBACK. No more editing this file per DUT.
|
||||||
|
# Add: fpga_rescan (re-detect after DUT swap / re-enumeration),
|
||||||
|
# FPGA_BDF / FPGA_VENDOR_ID / FPGA_LSPCI_MATCH overrides,
|
||||||
|
# FPGA_BDF_ACTIVE reporting the BDF in use.
|
||||||
|
# Note: detection runs ONCE at source time (one INFO line on
|
||||||
|
# stdout, WARN/FAIL on stderr). FPGA_QUIET=1 silences the
|
||||||
|
# INFO line. cb_fpga/pmc/icb/swb never re-scan, so there is
|
||||||
|
# no per-command output and no per-command overhead.
|
||||||
|
# NOTE: the old per-unit NOTE ("edit the four lines below")
|
||||||
|
# no longer applies - detection handles it. To pin a BDF
|
||||||
|
# manually: FPGA_BDF=0000:05:00 fpga_rescan
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
#
|
#
|
||||||
# SONiC hardware has no memtool / devmem, but it has pcimem. pcimem mmaps the PCI
|
# SONiC hardware has no memtool / devmem, but it has pcimem. pcimem mmaps the PCI
|
||||||
@@ -42,26 +53,112 @@
|
|||||||
# icb_fpga <addr> [data]
|
# icb_fpga <addr> [data]
|
||||||
# swb0_fpga <addr> [data]
|
# swb0_fpga <addr> [data]
|
||||||
# swb1_fpga <addr> [data]
|
# swb1_fpga <addr> [data]
|
||||||
|
# fpga_rescan re-detect the CB FPGA BDF (after a DUT swap)
|
||||||
#
|
#
|
||||||
# data present = write, absent = read.
|
# data present = write, absent = read.
|
||||||
# Usage: source blanton_fpga_pcimem.sh
|
# Usage: source blanton_fpga_pcimem.sh
|
||||||
|
|
||||||
# === CB FPGA PCIe resource file (sysfs) ===
|
# === CB FPGA PCIe resource file (sysfs) - AUTO-DETECTED ===
|
||||||
# Use lspci -D to find the BDF (domain:bus:dev.fn); resource0 is the sysfs mapping of BAR0.
|
# The CB FPGA's BDF (domain:bus:dev.fn) changes per unit / per enumeration, so it is
|
||||||
# e.g. lspci -Dnn | grep -i fpga -> 0000:02:00.0 ...
|
# detected at source time instead of being hard-coded. resource0 is the sysfs mapping
|
||||||
# memtool variant fills in the BAR value; pcimem variant fills in the resource file
|
# of BAR0. (memtool variant fills in the BAR value; pcimem variant fills in the
|
||||||
# path instead (offset becomes relative to BAR).
|
# resource file path instead, so offsets become relative to BAR.)
|
||||||
FUNCT0_RES=/sys/bus/pci/devices/0000:03:00.0/resource0
|
#
|
||||||
FUNCT1_RES=/sys/bus/pci/devices/0000:03:00.1/resource0
|
# Detection order:
|
||||||
FUNCT2_RES=/sys/bus/pci/devices/0000:03:00.2/resource0
|
# 1. FPGA_BDF override e.g. FPGA_BDF=0000:05:00 (domain:bus:dev, WITHOUT .fn)
|
||||||
FUNCT3_RES=/sys/bus/pci/devices/0000:03:00.3/resource0
|
# 2. sysfs vendor scan /sys/bus/pci/devices/*.0 whose vendor == FPGA_VENDOR_ID
|
||||||
|
# (0x1590 = Hewlett Packard Enterprise) and that has all
|
||||||
|
# four functions .0 .1 .2 .3 exposing resource0
|
||||||
|
# 3. lspci -Dnn fallback lines matching FPGA_LSPCI_MATCH
|
||||||
|
# ("Hewlett Packard Enterprise" or vendor id "[1590:")
|
||||||
|
# 4. FPGA_BDF_FALLBACK last-known BDF, only if 1-3 all fail
|
||||||
|
#
|
||||||
|
# Overrides (export before sourcing, or set and call fpga_rescan afterwards):
|
||||||
|
# FPGA_BDF=0000:05:00 pin a specific device, skip detection
|
||||||
|
# FPGA_VENDOR_ID=0x10ee different vendor (e.g. a Xilinx-branded board)
|
||||||
|
# FPGA_LSPCI_MATCH='...' custom lspci grep -iE pattern
|
||||||
|
FPGA_VENDOR_ID="${FPGA_VENDOR_ID:-0x1590}"
|
||||||
|
FPGA_LSPCI_MATCH="${FPGA_LSPCI_MATCH:-Hewlett Packard Enterprise|\[1590:}"
|
||||||
|
FPGA_BDF_FALLBACK="${FPGA_BDF_FALLBACK:-0000:03:00}"
|
||||||
|
|
||||||
# Auto-detect example (uncomment to use; needs the FPGA's BDF prefix):
|
# True if all four functions of <bdf> exist and expose resource0.
|
||||||
# _BDF=0000:02:00
|
# Usage: _fpga_bdf_ok <domain:bus:dev>
|
||||||
# FUNCT0_RES=/sys/bus/pci/devices/${_BDF}.0/resource0
|
_fpga_bdf_ok() {
|
||||||
# FUNCT1_RES=/sys/bus/pci/devices/${_BDF}.1/resource0
|
local bdf="$1" fn
|
||||||
# FUNCT2_RES=/sys/bus/pci/devices/${_BDF}.2/resource0
|
for fn in 0 1 2 3; do
|
||||||
# FUNCT3_RES=/sys/bus/pci/devices/${_BDF}.3/resource0
|
[ -e "/sys/bus/pci/devices/${bdf}.${fn}/resource0" ] || return 1
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the detected FPGA BDF prefix (domain:bus:dev) on stdout; non-zero if none.
|
||||||
|
_fpga_detect_bdf() {
|
||||||
|
local cands="" bdf dir vend want
|
||||||
|
|
||||||
|
# 1. explicit override wins (tolerate a trailing ".fn" being included)
|
||||||
|
if [ -n "${FPGA_BDF:-}" ]; then
|
||||||
|
bdf="$FPGA_BDF"
|
||||||
|
case "$bdf" in *.[0-7]) bdf="${bdf%.*}" ;; esac
|
||||||
|
echo "$bdf"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
want=$(echo "$FPGA_VENDOR_ID" | tr 'A-Z' 'a-z')
|
||||||
|
|
||||||
|
# 2. sysfs vendor-ID scan (no lspci / pci.ids needed)
|
||||||
|
for dir in /sys/bus/pci/devices/*:*.0; do
|
||||||
|
[ -e "$dir/vendor" ] || continue
|
||||||
|
vend=$(tr 'A-Z' 'a-z' < "$dir/vendor" 2>/dev/null)
|
||||||
|
[ "$vend" = "$want" ] || continue
|
||||||
|
bdf="${dir##*/}"; bdf="${bdf%.0}"
|
||||||
|
_fpga_bdf_ok "$bdf" && cands="$cands $bdf"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 3. lspci fallback (device name match, in case the vendor id differs)
|
||||||
|
if [ -z "$cands" ] && command -v lspci >/dev/null 2>&1; then
|
||||||
|
for bdf in $(lspci -Dnn 2>/dev/null | grep -iE "$FPGA_LSPCI_MATCH" \
|
||||||
|
| awk '{print $1}' | sed 's/\.[0-9a-f]*$//' | sort -u); do
|
||||||
|
_fpga_bdf_ok "$bdf" && cands="$cands $bdf"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -- $cands
|
||||||
|
[ $# -eq 0 ] && return 1
|
||||||
|
if [ $# -gt 1 ]; then
|
||||||
|
echo -e "[\033[33mWARN\033[0m] multiple candidate FPGAs found:$cands -> using $1" >&2
|
||||||
|
echo -e " set FPGA_BDF=<domain:bus:dev> and run fpga_rescan to pick another." >&2
|
||||||
|
fi
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# (Re)detect the FPGA BDF and refresh FUNCT0..3_RES. Called once at source time;
|
||||||
|
# call again by hand after swapping/re-enumerating a DUT.
|
||||||
|
# The one-line INFO goes to STDOUT (so wrappers that already do
|
||||||
|
# `source ... >/dev/null` stay silent); WARN/FAIL go to STDERR.
|
||||||
|
# Set FPGA_QUIET=1 to suppress the INFO line entirely.
|
||||||
|
fpga_rescan() {
|
||||||
|
local bdf
|
||||||
|
bdf=$(_fpga_detect_bdf)
|
||||||
|
if [ -z "$bdf" ]; then
|
||||||
|
bdf="$FPGA_BDF_FALLBACK"
|
||||||
|
echo -e "[\033[33mWARN\033[0m] no FPGA found (vendor $FPGA_VENDOR_ID / '$FPGA_LSPCI_MATCH');" >&2
|
||||||
|
echo -e " falling back to $bdf. Check with: lspci -Dnn | grep -iE 'Hewlett|fpga'" >&2
|
||||||
|
fi
|
||||||
|
FPGA_BDF_ACTIVE="$bdf"
|
||||||
|
FUNCT0_RES=/sys/bus/pci/devices/${bdf}.0/resource0
|
||||||
|
FUNCT1_RES=/sys/bus/pci/devices/${bdf}.1/resource0
|
||||||
|
FUNCT2_RES=/sys/bus/pci/devices/${bdf}.2/resource0
|
||||||
|
FUNCT3_RES=/sys/bus/pci/devices/${bdf}.3/resource0
|
||||||
|
if _fpga_bdf_ok "$bdf"; then
|
||||||
|
[ "${FPGA_QUIET:-0}" = "1" ] || \
|
||||||
|
echo -e "[\033[34mINFO\033[0m] CB FPGA BDF = \033[36m${bdf}.0-.3\033[0m (resource0)"
|
||||||
|
else
|
||||||
|
echo -e "[\033[31mFAIL\033[0m] ${bdf}.0-.3 resource0 not all present - register access will fail." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
fpga_rescan
|
||||||
|
|
||||||
# === VSPI window base offset (relative to CB Function 2 resource0 start) ===
|
# === VSPI window base offset (relative to CB Function 2 resource0 start) ===
|
||||||
# NOTE: CB.F2 has TWO near-identical VSPI register blocks (see spec register map):
|
# NOTE: CB.F2 has TWO near-identical VSPI register blocks (see spec register map):
|
||||||
@@ -268,6 +365,9 @@ blanton_fpga_help() {
|
|||||||
echo -e " \033[33mswb0_fpga\033[0m <addr> [data] SWB0 FPGA via VSPI"
|
echo -e " \033[33mswb0_fpga\033[0m <addr> [data] SWB0 FPGA via VSPI"
|
||||||
echo -e " \033[33mswb1_fpga\033[0m <addr> [data] SWB1 FPGA via VSPI"
|
echo -e " \033[33mswb1_fpga\033[0m <addr> [data] SWB1 FPGA via VSPI"
|
||||||
echo -e " \033[33mfpga_debug\033[0m on|off Toggle debug mode (print commands and execute)"
|
echo -e " \033[33mfpga_debug\033[0m on|off Toggle debug mode (print commands and execute)"
|
||||||
|
echo -e " \033[33mfpga_rescan\033[0m Re-detect CB FPGA BDF (after DUT swap / re-enum)"
|
||||||
|
echo ""
|
||||||
|
echo -e " Active CB FPGA BDF: \033[36m${FPGA_BDF_ACTIVE:-unknown}\033[0m .0-.3 (pin with: FPGA_BDF=0000:05:00 fpga_rescan)"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " Omit [data] to \033[32mread\033[0m, provide [data] to \033[31mwrite\033[0m."
|
echo -e " Omit [data] to \033[32mread\033[0m, provide [data] to \033[31mwrite\033[0m."
|
||||||
echo -e " Backend: \033[36mpcimem\033[0m (sysfs resource file + relative offset)."
|
echo -e " Backend: \033[36mpcimem\033[0m (sysfs resource file + relative offset)."
|
||||||
|
|||||||
@@ -0,0 +1,788 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# blanton_traffic_linespeed.sh -- SWB loopback line-speed traffic via bcmcmd
|
||||||
|
# =============================================================================
|
||||||
|
# Version History:
|
||||||
|
# V0.1.0 2026-08-17 First version. Bash port of the three Tera Term macros
|
||||||
|
# utils/traffic_loopback_vlan_setting.ttl (VLAN 30..137,
|
||||||
|
# port pair cdN <-> cdN+32), utils/traffic_loopback_start.ttl
|
||||||
|
# (tx 100 length=512 VLantag=<vid>) and
|
||||||
|
# utils/traffic_loopback_vlan_remove.ttl.
|
||||||
|
# One DUT = two switch boards -> bcmcmd unit 0 and 1
|
||||||
|
# (bcmcmd -n <unit>), default both.
|
||||||
|
# V0.2.0 2026-08-17 Add: 'ps' (port status) subcommand -- 'ps <portlist>' with
|
||||||
|
# the cabled-port list as default ($TL_PS_PORTS), -p/--ports
|
||||||
|
# to override (or a bare port list after 'ps'), 'ps -p all'
|
||||||
|
# for every port. 'run' now shows port status first.
|
||||||
|
# V0.3.0 2026-08-17 Add: 'report' subcommand -- runs 'show c', keeps the raw
|
||||||
|
# log, and renders the MIB_TPOK/MIB_RPOK counters as a
|
||||||
|
# loopback-pair table with a PASS/FAIL cross-check
|
||||||
|
# (cdA.TX==cdB.RX and cdA.RX==cdB.TX), i.e. an on-DUT awk
|
||||||
|
# port of tools/bcm_mibpair_report_V1.1.0.py (same layout,
|
||||||
|
# same verdict rules, same summary lines, exit 2 on
|
||||||
|
# FAIL/NA). Options -T/-a/-g/-P/-q/--tsv/--raw and
|
||||||
|
# -f <log> to re-parse a captured console log offline.
|
||||||
|
# 'run' now ends with 'report' instead of a raw 'show c'.
|
||||||
|
# V0.3.1 2026-08-17 Fix: only the FIRST VLAN was configured -- bcmcmd inherited
|
||||||
|
# the while-loop's stdin (the pair-list here-string) and ate
|
||||||
|
# the remaining lines, so 'read' hit EOF after one pass.
|
||||||
|
# bcmcmd now always runs with </dev/null and the loops read
|
||||||
|
# on fd 3 (3<<< "$TL_PAIRS").
|
||||||
|
# Fix: bcmcmd exits 0 even when the BCM shell rejects the
|
||||||
|
# command ("VLAN: ERROR: Entry exists" / "Failed to execute
|
||||||
|
# the diagnostic command"), so failures were counted as OK.
|
||||||
|
# Output is now pattern-matched ($TL_ERR_PAT), with benign
|
||||||
|
# cases tolerated and counted separately: 'Entry exists' on
|
||||||
|
# 'vlan create' (re-run of init) and 'not found' on
|
||||||
|
# 'vlan remove/destroy' (stop before init).
|
||||||
|
# V0.3.2 2026-08-17 Add: report colours the verdict -- PASS green, FAIL red,
|
||||||
|
# NA yellow (also in the summary lines). Padding is applied
|
||||||
|
# to the plain text before colouring so the columns stay
|
||||||
|
# aligned. Auto-disabled when stdout is not a terminal or
|
||||||
|
# with --tsv; --color / --no-color / TL_COLOR force it.
|
||||||
|
# V0.3.3 2026-08-17 Add: -tx / -length aliases for -c / -l so the tx burst can
|
||||||
|
# be written the way the bcm command reads
|
||||||
|
# ("start -u 0 -tx 100 -length 512"). Values are validated
|
||||||
|
# as positive integers; omitted = defaults 100 / 512.
|
||||||
|
# Fix: --dry-run printed nothing for init/start/stop/report
|
||||||
|
# since V0.3.1 (the new wrapper discarded the "[DRY ]"
|
||||||
|
# lines); the commands are listed again.
|
||||||
|
# V0.4.0 2026-08-17 Change: report now lists ALL 108 pairs, PASS / FAIL / NA
|
||||||
|
# alike, keeping one line per port (two lines per pair):
|
||||||
|
# Port TX RX PASS/FAIL
|
||||||
|
# cd0 4 4 PASS
|
||||||
|
# cd32 4 4 PASS
|
||||||
|
# cd204 - - NA
|
||||||
|
# cd236 - - NA
|
||||||
|
# Missing counters show '-'. -a is therefore the default
|
||||||
|
# (the flag is still accepted), and the long
|
||||||
|
# "# NA (no counters): ..." summary line is dropped because
|
||||||
|
# every NA pair is now a visible row. This is the only
|
||||||
|
# intentional difference from
|
||||||
|
# tools/bcm_mibpair_report_V1.1.0.py, which hides NA pairs
|
||||||
|
# unless -a is given.
|
||||||
|
# V0.4.1 2026-08-19 Fix: report printed every counter as 2147483647 (INT32_MAX).
|
||||||
|
# grp() rendered values with sprintf("%d", v); the DUT's awk
|
||||||
|
# casts to a 32-bit int for %d, so any counter above 2^31-1
|
||||||
|
# -- i.e. every real line-speed run -- saturated. Values are
|
||||||
|
# now formatted with %.0f, which stays in awk's double domain
|
||||||
|
# (exact to 2^53, far above any MIB counter).
|
||||||
|
# NOTE: the PASS/FAIL verdicts were NEVER affected -- the
|
||||||
|
# cross-check compares TX[]/RX[] doubles directly and only
|
||||||
|
# the display path went through grp(). Past reports that said
|
||||||
|
# PASS were right; only the numbers shown were wrong.
|
||||||
|
# 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.
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# The VLAN/port table below is copied verbatim from
|
||||||
|
# utils/traffic_loopback_vlan_setting.ttl -- it is NOT generated, because the
|
||||||
|
# port map has gaps (cd15..19, cd47..51, cd79..83, cd111..115, cd139,
|
||||||
|
# cd148..151, cd171, cd180..183, cd203, cd212..215, cd235, cd244..247 are not
|
||||||
|
# cabled). Keep this file and the .ttl in sync if the loopback harness changes.
|
||||||
|
#
|
||||||
|
# Usage (run directly):
|
||||||
|
# ./blanton_traffic_linespeed.sh init # step 1: VLAN loopback setup
|
||||||
|
# ./blanton_traffic_linespeed.sh clear # step 2: clear c
|
||||||
|
# ./blanton_traffic_linespeed.sh show # step 3/6: show c
|
||||||
|
# ./blanton_traffic_linespeed.sh start # step 4: tx burst per VLAN
|
||||||
|
# ./blanton_traffic_linespeed.sh stop # step 5: remove VLAN members
|
||||||
|
# ./blanton_traffic_linespeed.sh ps # port status (link/speed) of
|
||||||
|
# # the cabled ports
|
||||||
|
# ./blanton_traffic_linespeed.sh report # step 6+: show c -> per-pair
|
||||||
|
# # TX/RX table + PASS/FAIL
|
||||||
|
# ./blanton_traffic_linespeed.sh run # ps -> 1 -> 2 -> 4 -> report
|
||||||
|
#
|
||||||
|
# Usage (sourced, like the other blanton_*.sh tools):
|
||||||
|
# source blanton_traffic_linespeed.sh
|
||||||
|
# blanton_traffic_linespeed init -u 1 -d
|
||||||
|
#
|
||||||
|
# Options (any order, after the subcommand):
|
||||||
|
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TL_UNITS ("0 1")
|
||||||
|
# -c|--count <n> tx packet count (default $TL_TX_COUNT)
|
||||||
|
# aliases: -tx | --tx
|
||||||
|
# -l|--length <n> tx packet length (default $TL_TX_LENGTH)
|
||||||
|
# aliases: -length | --len
|
||||||
|
# -p|--ports <list|all> ps: port list ('all' = plain 'ps', every port)
|
||||||
|
# -T|--tolerance <n> report: allowed |delta| in packets (default 0;
|
||||||
|
# -T 1 absorbs the normal snapshot skew)
|
||||||
|
# -a|--all report: accepted for compatibility -- every pair is
|
||||||
|
# listed by default, NA included
|
||||||
|
# -g|--grouped report: comma-group the values (1,234,567)
|
||||||
|
# -P|--with-port report: render cd1(2) instead of cd1
|
||||||
|
# -q|--quiet report: drop the trailing summary comments
|
||||||
|
# --tsv report: tab-separated (paste into Excel)
|
||||||
|
# --raw report: also print the raw 'show c' output
|
||||||
|
# --color|--no-color report: force / disable PASS-green FAIL-red colours
|
||||||
|
# (default: colour only when stdout is a terminal)
|
||||||
|
# -f|--file <log> report: parse a saved console log, do not touch DUT
|
||||||
|
# -d|--debug print every bcmcmd before running it
|
||||||
|
# -n|--dry-run print commands only, do not touch the DUT
|
||||||
|
# --destroy stop: also 'vlan destroy <vid>' after removing members
|
||||||
|
# -h|--help help
|
||||||
|
#
|
||||||
|
# Environment overrides:
|
||||||
|
# BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=100 TL_TX_LENGTH=512
|
||||||
|
# TL_PS_PORTS="1-24,40-96,..." TL_TOLERANCE=0 TL_LOG_DIR=/tmp
|
||||||
|
# DEBUG_MODE=1
|
||||||
|
#
|
||||||
|
# Related: tools/bcm_mibpair_report_V1.1.0.py -- same report off-box (python3,
|
||||||
|
# richer options). 'report' is the awk equivalent so it runs on the SONiC DUT
|
||||||
|
# itself; both accept the same captured 'show c' log.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# === Config ==================================================================
|
||||||
|
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
|
||||||
|
TL_UNITS="${TL_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
|
||||||
|
TL_TX_COUNT="${TL_TX_COUNT:-100}"
|
||||||
|
TL_TX_LENGTH="${TL_TX_LENGTH:-512}"
|
||||||
|
TL_DEFAULT_VLAN="${TL_DEFAULT_VLAN:-1}"
|
||||||
|
TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}"
|
||||||
|
|
||||||
|
# 'ps' port list: the cabled ports of the loopback harness, in bcm logical-port
|
||||||
|
# numbering (NOT the cdN names used by vlan add). Kept as one string so it can be
|
||||||
|
# pasted straight from/into a manual "bcmcmd -n 0 -c 'ps <list>'".
|
||||||
|
TL_PS_PORTS="${TL_PS_PORTS:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}"
|
||||||
|
|
||||||
|
# --- report (pair cross-check) defaults -------------------------------------
|
||||||
|
TL_TOLERANCE="${TL_TOLERANCE:-0}" # allowed |delta| in packets before FAIL
|
||||||
|
TL_LOG_DIR="${TL_LOG_DIR:-/tmp}" # where the raw 'show c' capture is kept
|
||||||
|
TL_REPORT_ALL=${TL_REPORT_ALL:-0}
|
||||||
|
TL_REPORT_GROUPED=${TL_REPORT_GROUPED:-0}
|
||||||
|
TL_REPORT_WITHPORT=${TL_REPORT_WITHPORT:-0}
|
||||||
|
TL_REPORT_QUIET=${TL_REPORT_QUIET:-0}
|
||||||
|
TL_REPORT_TSV=${TL_REPORT_TSV:-0}
|
||||||
|
TL_REPORT_RAW=${TL_REPORT_RAW:-0}
|
||||||
|
TL_REPORT_FILE="" # -f <log>: parse this instead of the DUT
|
||||||
|
TL_COLOR="${TL_COLOR:-auto}" # auto|always|never -- PASS green / FAIL red / NA yellow
|
||||||
|
|
||||||
|
# Debug / dry-run (1 = on). DEBUG_MODE is shared with blanton_fpga_pcimem.sh.
|
||||||
|
DEBUG_MODE=${DEBUG_MODE:-0}
|
||||||
|
TL_DRY_RUN=${TL_DRY_RUN:-0}
|
||||||
|
TL_DESTROY=${TL_DESTROY:-0}
|
||||||
|
|
||||||
|
# === VLAN <-> loopback port pair table (from traffic_loopback_vlan_setting.ttl) ==
|
||||||
|
# format: <vid> <port_a> <port_b>
|
||||||
|
TL_PAIRS="\
|
||||||
|
30 cd0 cd32
|
||||||
|
31 cd1 cd33
|
||||||
|
32 cd2 cd34
|
||||||
|
33 cd3 cd35
|
||||||
|
34 cd4 cd36
|
||||||
|
35 cd5 cd37
|
||||||
|
36 cd6 cd38
|
||||||
|
37 cd7 cd39
|
||||||
|
38 cd8 cd40
|
||||||
|
39 cd9 cd41
|
||||||
|
40 cd10 cd42
|
||||||
|
41 cd11 cd43
|
||||||
|
42 cd12 cd44
|
||||||
|
43 cd13 cd45
|
||||||
|
44 cd14 cd46
|
||||||
|
45 cd20 cd52
|
||||||
|
46 cd21 cd53
|
||||||
|
47 cd22 cd54
|
||||||
|
48 cd23 cd55
|
||||||
|
49 cd24 cd56
|
||||||
|
50 cd25 cd57
|
||||||
|
51 cd26 cd58
|
||||||
|
52 cd27 cd59
|
||||||
|
53 cd28 cd60
|
||||||
|
54 cd29 cd61
|
||||||
|
55 cd30 cd62
|
||||||
|
56 cd31 cd63
|
||||||
|
57 cd64 cd96
|
||||||
|
58 cd65 cd97
|
||||||
|
59 cd66 cd98
|
||||||
|
60 cd67 cd99
|
||||||
|
61 cd68 cd100
|
||||||
|
62 cd69 cd101
|
||||||
|
63 cd70 cd102
|
||||||
|
64 cd71 cd103
|
||||||
|
65 cd72 cd104
|
||||||
|
66 cd73 cd105
|
||||||
|
67 cd74 cd106
|
||||||
|
68 cd75 cd107
|
||||||
|
69 cd76 cd108
|
||||||
|
70 cd77 cd109
|
||||||
|
71 cd78 cd110
|
||||||
|
72 cd84 cd116
|
||||||
|
73 cd85 cd117
|
||||||
|
74 cd86 cd118
|
||||||
|
75 cd87 cd119
|
||||||
|
76 cd88 cd120
|
||||||
|
77 cd89 cd121
|
||||||
|
78 cd90 cd122
|
||||||
|
79 cd91 cd123
|
||||||
|
80 cd92 cd124
|
||||||
|
81 cd93 cd125
|
||||||
|
82 cd94 cd126
|
||||||
|
83 cd95 cd127
|
||||||
|
84 cd128 cd160
|
||||||
|
85 cd129 cd161
|
||||||
|
86 cd130 cd162
|
||||||
|
87 cd131 cd163
|
||||||
|
88 cd132 cd164
|
||||||
|
89 cd133 cd165
|
||||||
|
90 cd134 cd166
|
||||||
|
91 cd135 cd167
|
||||||
|
92 cd136 cd168
|
||||||
|
93 cd137 cd169
|
||||||
|
94 cd138 cd170
|
||||||
|
95 cd140 cd172
|
||||||
|
96 cd141 cd173
|
||||||
|
97 cd142 cd174
|
||||||
|
98 cd143 cd175
|
||||||
|
99 cd144 cd176
|
||||||
|
100 cd145 cd177
|
||||||
|
101 cd146 cd178
|
||||||
|
102 cd147 cd179
|
||||||
|
103 cd152 cd184
|
||||||
|
104 cd153 cd185
|
||||||
|
105 cd154 cd186
|
||||||
|
106 cd155 cd187
|
||||||
|
107 cd156 cd188
|
||||||
|
108 cd157 cd189
|
||||||
|
109 cd158 cd190
|
||||||
|
110 cd159 cd191
|
||||||
|
111 cd192 cd224
|
||||||
|
112 cd193 cd225
|
||||||
|
113 cd194 cd226
|
||||||
|
114 cd195 cd227
|
||||||
|
115 cd196 cd228
|
||||||
|
116 cd197 cd229
|
||||||
|
117 cd198 cd230
|
||||||
|
118 cd199 cd231
|
||||||
|
119 cd200 cd232
|
||||||
|
120 cd201 cd233
|
||||||
|
121 cd202 cd234
|
||||||
|
122 cd204 cd236
|
||||||
|
123 cd205 cd237
|
||||||
|
124 cd206 cd238
|
||||||
|
125 cd207 cd239
|
||||||
|
126 cd208 cd240
|
||||||
|
127 cd209 cd241
|
||||||
|
128 cd210 cd242
|
||||||
|
129 cd211 cd243
|
||||||
|
130 cd216 cd248
|
||||||
|
131 cd217 cd249
|
||||||
|
132 cd218 cd250
|
||||||
|
133 cd219 cd251
|
||||||
|
134 cd220 cd252
|
||||||
|
135 cd221 cd253
|
||||||
|
136 cd222 cd254
|
||||||
|
137 cd223 cd255"
|
||||||
|
|
||||||
|
# === Logging =================================================================
|
||||||
|
_tl_info() { echo -e "[\033[34mINFO\033[0m] $*"; }
|
||||||
|
_tl_ok() { echo -e "[\033[32m OK \033[0m] $*"; }
|
||||||
|
_tl_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; }
|
||||||
|
_tl_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
|
||||||
|
_tl_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; }
|
||||||
|
|
||||||
|
traffic_debug() {
|
||||||
|
if [ "${1:-}" = "on" ]; then DEBUG_MODE=1
|
||||||
|
elif [ "${1:-}" = "off" ]; then DEBUG_MODE=0
|
||||||
|
else [ "$DEBUG_MODE" = "0" ] && DEBUG_MODE=1 || DEBUG_MODE=0; fi
|
||||||
|
_tl_info "DEBUG_MODE=$DEBUG_MODE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === bcmcmd wrapper ==========================================================
|
||||||
|
# IMPORTANT: bcmcmd is always run with stdin closed (</dev/null). Without it
|
||||||
|
# bcmcmd inherits the caller's stdin and eats the rest of the pair list that the
|
||||||
|
# while-loops read, so only the first VLAN got configured (fixed in V0.3.1).
|
||||||
|
#
|
||||||
|
# _tl_bcm <unit> <bcm shell command> -- streams the DUT output, returns bcmcmd rc
|
||||||
|
# Debug mode prints the full command line first; dry-run prints and skips it.
|
||||||
|
_tl_bcm() {
|
||||||
|
local unit="$1"; shift
|
||||||
|
local cmd="$*"
|
||||||
|
_tl_dbg "$BCMCMD_CMD -n $unit -c '$cmd'"
|
||||||
|
if [ "$TL_DRY_RUN" = "1" ]; then
|
||||||
|
echo "[DRY ] $BCMCMD_CMD -n $unit -c '$cmd'"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
"$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# bcmcmd exits 0 even when the BCM shell itself refused the command
|
||||||
|
# ("VLAN: ERROR: Entry exists", "Failed to execute the diagnostic command"),
|
||||||
|
# so the captured output has to be pattern-matched as well.
|
||||||
|
TL_ERR_PAT="${TL_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|not found}"
|
||||||
|
TL_BENIGN_CREATE="${TL_BENIGN_CREATE:-Entry exists|already exist}"
|
||||||
|
TL_BENIGN_REMOVE="${TL_BENIGN_REMOVE:-Entry not found|not found|does not exist|no such}"
|
||||||
|
|
||||||
|
# _tl_bcm_run <unit> <benign_regex|""> <cmd...>
|
||||||
|
# 0 = ok, 2 = failed but benign (matches benign_regex), 1 = real failure
|
||||||
|
# Output is captured (shown in debug mode, or on a real failure) so the ~110
|
||||||
|
# vlan create/add lines do not flood the console.
|
||||||
|
_tl_bcm_run() {
|
||||||
|
local unit="$1" benign="$2"; shift 2
|
||||||
|
local cmd="$*" out rc
|
||||||
|
# dry-run: let _tl_bcm print the "[DRY ] bcmcmd ..." line, run nothing
|
||||||
|
if [ "$TL_DRY_RUN" = "1" ]; then _tl_bcm "$unit" "$cmd"; return 0; fi
|
||||||
|
_tl_dbg "$BCMCMD_CMD -n $unit -c '$cmd'"
|
||||||
|
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
|
||||||
|
[ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out"
|
||||||
|
if [ "$rc" -ne 0 ] || echo "$out" | grep -qiE "$TL_ERR_PAT"; then
|
||||||
|
if [ -n "$benign" ] && echo "$out" | grep -qiE "$benign"; then
|
||||||
|
_tl_dbg "benign: unit $unit '$cmd'"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
_tl_err "unit $unit: '$cmd' rc=$rc"
|
||||||
|
[ "$DEBUG_MODE" != "1" ] && [ -n "$out" ] && echo "$out" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# _tl_bcm_q <unit> <cmd> -- _tl_bcm_run with no benign pattern
|
||||||
|
_tl_bcm_q() { local unit="$1"; shift; _tl_bcm_run "$unit" "" "$@"; }
|
||||||
|
|
||||||
|
_tl_units_check() {
|
||||||
|
local u
|
||||||
|
for u in $TL_UNITS; do
|
||||||
|
case "$u" in
|
||||||
|
0|1) ;;
|
||||||
|
*) _tl_err "invalid unit '$u' (expect 0 or 1)"; return 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ "$TL_DRY_RUN" != "1" ] && ! command -v "$BCMCMD_CMD" >/dev/null 2>&1; then
|
||||||
|
_tl_err "$BCMCMD_CMD not found in PATH (run on the SONiC DUT, or set BCMCMD_CMD)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
_tl_pair_count() { echo "$TL_PAIRS" | grep -c . ; }
|
||||||
|
|
||||||
|
# positive integer? (tx count / length come straight from the command line)
|
||||||
|
_tl_is_uint() { case "$1" in ''|*[!0-9]*) return 1 ;; 0) return 1 ;; *) return 0 ;; esac; }
|
||||||
|
|
||||||
|
# === Step 1: VLAN loopback setup (traffic_loopback_vlan_setting.ttl) =========
|
||||||
|
traffic_linespeed_init() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
local unit vid pa pb n fail exist rc
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
n=0; fail=0; exist=0
|
||||||
|
_tl_info "unit $unit: VLAN loopback setup ($(_tl_pair_count) pairs, VLAN 30..137)"
|
||||||
|
_tl_bcm_q "$unit" "vlan remove $TL_DEFAULT_VLAN pbm=$TL_DEFAULT_VLAN_PBM" \
|
||||||
|
|| _tl_warn "unit $unit: clearing default VLAN $TL_DEFAULT_VLAN membership failed (continuing)"
|
||||||
|
# read on fd 3: bcmcmd must not be able to consume the pair list
|
||||||
|
while read -r vid pa pb <&3; do
|
||||||
|
[ -z "$vid" ] && continue
|
||||||
|
_tl_bcm_run "$unit" "$TL_BENIGN_CREATE" "vlan create $vid"; rc=$?
|
||||||
|
[ "$rc" = "1" ] && fail=$((fail+1))
|
||||||
|
[ "$rc" = "2" ] && exist=$((exist+1))
|
||||||
|
_tl_bcm_q "$unit" "vlan add $vid pbm=$pa,$pb" || fail=$((fail+1))
|
||||||
|
n=$((n+1))
|
||||||
|
done 3<<< "$TL_PAIRS"
|
||||||
|
if [ "$fail" -eq 0 ]; then
|
||||||
|
_tl_ok "unit $unit: $n VLANs configured$([ "$exist" -gt 0 ] && echo " ($exist already existed)"), port pairs added"
|
||||||
|
else
|
||||||
|
_tl_warn "unit $unit: $n VLANs processed, $fail command(s) failed$([ "$exist" -gt 0 ] && echo ", $exist already existed")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Step 2: clear counters ==================================================
|
||||||
|
traffic_linespeed_clear() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
local unit
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
_tl_info "unit $unit: clear c"
|
||||||
|
_tl_bcm "$unit" "clear c" || { _tl_err "unit $unit: clear c failed"; return 1; }
|
||||||
|
_tl_ok "unit $unit: counters cleared"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Step 3 / 6: show counters ==============================================
|
||||||
|
traffic_linespeed_show() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
local unit
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
echo "----- unit $unit : show c -----"
|
||||||
|
_tl_bcm "$unit" "show c" || { _tl_err "unit $unit: show c failed"; return 1; }
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Step 4: start traffic (traffic_loopback_start.ttl) =====================
|
||||||
|
traffic_linespeed_start() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
_tl_is_uint "$TL_TX_COUNT" || { _tl_err "tx count '$TL_TX_COUNT' is not a positive integer (-tx|-c <n>)"; return 1; }
|
||||||
|
_tl_is_uint "$TL_TX_LENGTH" || { _tl_err "tx length '$TL_TX_LENGTH' is not a positive integer (-length|-l <n>)"; return 1; }
|
||||||
|
local unit vid pa pb n fail
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
n=0; fail=0
|
||||||
|
_tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH per VLAN 30..137"
|
||||||
|
while read -r vid pa pb <&3; do
|
||||||
|
[ -z "$vid" ] && continue
|
||||||
|
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid" || fail=$((fail+1))
|
||||||
|
n=$((n+1))
|
||||||
|
done 3<<< "$TL_PAIRS"
|
||||||
|
if [ "$fail" -eq 0 ]; then
|
||||||
|
_tl_ok "unit $unit: $n bursts sent ($((n * TL_TX_COUNT)) packets, ${TL_TX_LENGTH}B each)"
|
||||||
|
else
|
||||||
|
_tl_warn "unit $unit: $n bursts attempted, $fail failed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Step 5: stop traffic (traffic_loopback_vlan_remove.ttl) ================
|
||||||
|
traffic_linespeed_stop() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
local unit vid pa pb n fail
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
n=0; fail=0
|
||||||
|
_tl_info "unit $unit: removing loopback port pairs from VLAN 30..137"
|
||||||
|
while read -r vid pa pb <&3; do
|
||||||
|
[ -z "$vid" ] && continue
|
||||||
|
_tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan remove $vid pbm=$pa,$pb"
|
||||||
|
[ "$?" = "1" ] && fail=$((fail+1))
|
||||||
|
if [ "$TL_DESTROY" = "1" ]; then
|
||||||
|
_tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan destroy $vid"
|
||||||
|
[ "$?" = "1" ] && fail=$((fail+1))
|
||||||
|
fi
|
||||||
|
n=$((n+1))
|
||||||
|
done 3<<< "$TL_PAIRS"
|
||||||
|
if [ "$fail" -eq 0 ]; then
|
||||||
|
_tl_ok "unit $unit: $n VLANs cleaned$([ "$TL_DESTROY" = "1" ] && echo " and destroyed")"
|
||||||
|
else
|
||||||
|
_tl_warn "unit $unit: $n VLANs processed, $fail command(s) failed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Port status: ps <portlist> =============================================
|
||||||
|
# 'ps' shows link / speed / duplex / flow-control per port. Default list is the
|
||||||
|
# cabled ports ($TL_PS_PORTS); 'all' (or empty) runs a bare 'ps' = every port.
|
||||||
|
traffic_linespeed_ps() {
|
||||||
|
_tl_units_check || return 1
|
||||||
|
local unit cmd="ps"
|
||||||
|
case "${TL_PS_PORTS:-all}" in
|
||||||
|
all|ALL|"") cmd="ps" ;;
|
||||||
|
*) cmd="ps $TL_PS_PORTS" ;;
|
||||||
|
esac
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
echo "----- unit $unit : $cmd -----"
|
||||||
|
_tl_bcm "$unit" "$cmd" || { _tl_err "unit $unit: $cmd failed"; return 1; }
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Report: show c -> per-pair TX/RX table + PASS/FAIL =====================
|
||||||
|
# Mirrors tools/bcm_mibpair_report_V1.1.0.py, in awk so it runs on the DUT.
|
||||||
|
#
|
||||||
|
# Parses MIB_TPOK.cd1(2) : 723,629,081,133 +723,629,081,133
|
||||||
|
# MIB_RPOK.cd1(2) : 581,693,309,458 +581,693,309,458
|
||||||
|
# Verdict per pair: cdA.TPOK == cdB.RPOK and cdA.RPOK == cdB.TPOK
|
||||||
|
# PASS within tolerance / FAIL outside / NA when counters are missing
|
||||||
|
# (a cd port absent from 'show c' means the counter is zero or the
|
||||||
|
# console scrolled -- cross-check with 'ps' before blaming the port).
|
||||||
|
# _tl_pair_report <logfile> -> 0 all PASS, 2 any FAIL/NA, 1 parse error
|
||||||
|
_tl_pair_report() {
|
||||||
|
local log="$1" color=0
|
||||||
|
# PASS green / FAIL red / NA yellow. auto = only when stdout is a terminal,
|
||||||
|
# so redirecting to a file or piping into grep/diff stays plain text.
|
||||||
|
case "$TL_COLOR" in
|
||||||
|
always|1|yes) color=1 ;;
|
||||||
|
never|0|no) color=0 ;;
|
||||||
|
*) [ -t 1 ] && color=1 ;;
|
||||||
|
esac
|
||||||
|
[ "$TL_REPORT_TSV" = "1" ] && color=0
|
||||||
|
awk -v PAIRS="$TL_PAIRS" \
|
||||||
|
-v TOL="$TL_TOLERANCE" \
|
||||||
|
-v ALL="$TL_REPORT_ALL" \
|
||||||
|
-v GROUPED="$TL_REPORT_GROUPED" \
|
||||||
|
-v WITHPORT="$TL_REPORT_WITHPORT" \
|
||||||
|
-v QUIET="$TL_REPORT_QUIET" \
|
||||||
|
-v TSV="$TL_REPORT_TSV" \
|
||||||
|
-v COLOR="$color" '
|
||||||
|
function grp(v, s,out,l,i) {
|
||||||
|
s = sprintf("%.0f", v)
|
||||||
|
if (!GROUPED) return s
|
||||||
|
out = ""; l = length(s)
|
||||||
|
for (i = 1; i <= l; i++) {
|
||||||
|
out = out substr(s, i, 1)
|
||||||
|
if (((l - i) % 3) == 0 && i < l) out = out ","
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
function pname(cd) { return (WITHPORT && (cd in LP)) ? cd "(" LP[cd] ")" : cd }
|
||||||
|
function absd(x) { return (x < 0) ? -x : x }
|
||||||
|
# colour the verdict token: PASS green, FAIL red, NA yellow
|
||||||
|
function vc(v) {
|
||||||
|
if (!COLOR) return v
|
||||||
|
if (v == "PASS") return "\033[32m" v "\033[0m"
|
||||||
|
if (v == "FAIL") return "\033[31m" v "\033[0m"
|
||||||
|
return "\033[33m" v "\033[0m"
|
||||||
|
}
|
||||||
|
function redl(s) { return COLOR ? "\033[31m" s "\033[0m" : s }
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
NP = split(PAIRS, L, "\n")
|
||||||
|
for (i = 1; i <= NP; i++) { split(L[i], f, " "); VID[i] = f[1]; A[i] = f[2]; B[i] = f[3] }
|
||||||
|
MISSING = "-"
|
||||||
|
NC = 4
|
||||||
|
HDR[1] = "Port"; AL[1] = 0
|
||||||
|
HDR[2] = "TX"; AL[2] = 1
|
||||||
|
HDR[3] = "RX"; AL[3] = 1
|
||||||
|
HDR[4] = "PASS/FAIL"; AL[4] = 1
|
||||||
|
VCOL = NC # the verdict is always the last column
|
||||||
|
}
|
||||||
|
{
|
||||||
|
idx = index($0, "MIB_")
|
||||||
|
if (idx == 0) next
|
||||||
|
s = substr($0, idx)
|
||||||
|
kind = substr(s, 5, 4)
|
||||||
|
if (kind != "TPOK" && kind != "RPOK") next
|
||||||
|
p1 = index(s, "."); p2 = index(s, "("); p3 = index(s, ")"); p4 = index(s, ":")
|
||||||
|
if (p1 == 0 || p2 == 0 || p3 == 0 || p4 == 0 || p2 < p1 || p4 < p3) next
|
||||||
|
cd = substr(s, p1 + 1, p2 - p1 - 1)
|
||||||
|
if (cd !~ /^cd[0-9]+$/) next
|
||||||
|
lp = substr(s, p2 + 1, p3 - p2 - 1)
|
||||||
|
val = substr(s, p4 + 1)
|
||||||
|
sub(/^[ \t]+/, "", val)
|
||||||
|
if (val !~ /^[0-9,]/) next
|
||||||
|
sub(/[ \t].*$/, "", val)
|
||||||
|
gsub(/,/, "", val)
|
||||||
|
LP[cd] = lp
|
||||||
|
if (kind == "TPOK") { TX[cd] = val + 0; HTX[cd] = 1 } else { RX[cd] = val + 0; HRX[cd] = 1 }
|
||||||
|
seen++
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (seen == 0) {
|
||||||
|
print "error: no MIB_TPOK/MIB_RPOK counter found in the log" > "/dev/stderr"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
npass = nfail = nna = 0; nrow = 0; nrep = 0; miss = ""; nf = 0
|
||||||
|
for (i = 1; i <= NP; i++) {
|
||||||
|
a = A[i]; b = B[i]
|
||||||
|
oka = (a in HTX) && (a in HRX); okb = (b in HTX) && (b in HRX)
|
||||||
|
if (!(oka && okb)) {
|
||||||
|
v = "NA"; nna++
|
||||||
|
# every pair is listed, NA included; absent counters show '-'
|
||||||
|
ta = (a in HTX) ? grp(TX[a]) : MISSING; ra = (a in HRX) ? grp(RX[a]) : MISSING
|
||||||
|
tb = (b in HTX) ? grp(TX[b]) : MISSING; rb = (b in HRX) ? grp(RX[b]) : MISSING
|
||||||
|
} else {
|
||||||
|
dtx = TX[a] - RX[b]; drx = RX[a] - TX[b]
|
||||||
|
d = absd(dtx); if (absd(drx) > d) d = absd(drx)
|
||||||
|
if (d <= TOL + 0) { v = "PASS"; npass++ }
|
||||||
|
else {
|
||||||
|
v = "FAIL"; nfail++
|
||||||
|
FL[++nf] = sprintf("# FAIL %s/%s: %s.TX-%s.RX=%+.0f %s.RX-%s.TX=%+.0f", \
|
||||||
|
a, b, a, b, dtx, a, b, drx)
|
||||||
|
}
|
||||||
|
ta = grp(TX[a]); ra = grp(RX[a]); tb = grp(TX[b]); rb = grp(RX[b])
|
||||||
|
}
|
||||||
|
nrep++
|
||||||
|
nrow++; CELL[nrow,1] = pname(a); CELL[nrow,2] = ta; CELL[nrow,3] = ra; CELL[nrow,4] = v
|
||||||
|
nrow++; CELL[nrow,1] = pname(b); CELL[nrow,2] = tb; CELL[nrow,3] = rb; CELL[nrow,4] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSV) {
|
||||||
|
line = HDR[1]
|
||||||
|
for (c = 2; c <= NC; c++) line = line "\t" HDR[c]
|
||||||
|
print line
|
||||||
|
for (r = 1; r <= nrow; r++) {
|
||||||
|
line = CELL[r, 1]
|
||||||
|
for (c = 2; c <= NC; c++) line = line "\t" CELL[r, c]
|
||||||
|
print line
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (c = 1; c <= NC; c++) {
|
||||||
|
w[c] = length(HDR[c])
|
||||||
|
for (r = 1; r <= nrow; r++) if (length(CELL[r, c]) > w[c]) w[c] = length(CELL[r, c])
|
||||||
|
w[c] += 2
|
||||||
|
}
|
||||||
|
for (c = 1; c <= NC; c++) printf(AL[c] ? "%*s" : "%-*s", w[c], HDR[c])
|
||||||
|
printf "\n"
|
||||||
|
for (r = 1; r <= nrow; r++) {
|
||||||
|
for (c = 1; c <= NC; c++) {
|
||||||
|
if (c == VCOL) {
|
||||||
|
# pad on the plain text, then colour, so columns stay aligned
|
||||||
|
printf "%*s%s", w[c] - length(CELL[r, c]), "", vc(CELL[r, c])
|
||||||
|
} else {
|
||||||
|
printf(AL[c] ? "%*s" : "%-*s", w[c], CELL[r, c])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QUIET) {
|
||||||
|
print ""
|
||||||
|
printf "# pairs in table : %d\n", NP
|
||||||
|
printf "# pairs reported : %d\n", nrep
|
||||||
|
printf "# %s %d %s %d %s %d (tolerance %d)\n", \
|
||||||
|
vc("PASS"), npass, vc("FAIL"), nfail, vc("NA"), nna, TOL + 0
|
||||||
|
# every NA pair is a visible row -> no long "no counters" list needed
|
||||||
|
for (i = 1; i <= nf; i++) print redl(FL[i])
|
||||||
|
}
|
||||||
|
exit (nfail || nna) ? 2 : 0
|
||||||
|
}' "$log"
|
||||||
|
}
|
||||||
|
|
||||||
|
# traffic_linespeed_report -- 'show c' per unit, keep the raw log, render the table
|
||||||
|
traffic_linespeed_report() {
|
||||||
|
local unit log rc worst=0 stamp
|
||||||
|
# -f <log>: offline mode, no DUT access, no unit loop
|
||||||
|
if [ -n "$TL_REPORT_FILE" ]; then
|
||||||
|
[ -r "$TL_REPORT_FILE" ] || { _tl_err "cannot read log '$TL_REPORT_FILE'"; return 1; }
|
||||||
|
# note on stderr so the table on stdout stays pipe/diff clean
|
||||||
|
_tl_info "report from log: $TL_REPORT_FILE (tolerance $TL_TOLERANCE)" >&2
|
||||||
|
_tl_pair_report "$TL_REPORT_FILE"; return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
_tl_units_check || return 1
|
||||||
|
if [ "$TL_DRY_RUN" = "1" ]; then
|
||||||
|
for unit in $TL_UNITS; do _tl_bcm "$unit" "show c"; done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now)
|
||||||
|
for unit in $TL_UNITS; do
|
||||||
|
log="$TL_LOG_DIR/showc_unit${unit}_${stamp}.log"
|
||||||
|
if ! _tl_bcm "$unit" "show c" > "$log" 2>&1; then
|
||||||
|
_tl_err "unit $unit: show c failed (see $log)"; return 1
|
||||||
|
fi
|
||||||
|
[ "$TL_REPORT_RAW" = "1" ] && { echo "----- unit $unit : raw show c -----"; cat "$log"; }
|
||||||
|
echo "===== unit $unit : loopback pair counter report (raw: $log) ====="
|
||||||
|
_tl_pair_report "$log"; rc=$?
|
||||||
|
[ "$rc" -gt "$worst" ] && worst=$rc
|
||||||
|
case "$rc" in
|
||||||
|
0) _tl_ok "unit $unit: all pairs PASS" ;;
|
||||||
|
2) _tl_warn "unit $unit: at least one pair FAIL/NA" ;;
|
||||||
|
*) _tl_err "unit $unit: report parse error" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
return "$worst"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Convenience: full sequence ps -> 1 -> 2 -> 4 -> report ==================
|
||||||
|
traffic_linespeed_run() {
|
||||||
|
traffic_linespeed_ps || return 1
|
||||||
|
traffic_linespeed_init || return 1
|
||||||
|
traffic_linespeed_clear || return 1
|
||||||
|
traffic_linespeed_start || return 1
|
||||||
|
traffic_linespeed_report
|
||||||
|
local rc=$?
|
||||||
|
_tl_info "traffic done. 'stop' removes the loopback VLAN membership."
|
||||||
|
return $rc
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Help ====================================================================
|
||||||
|
blanton_traffic_linespeed_help() {
|
||||||
|
echo -e "\033[1mblanton_traffic_linespeed.sh - SWB loopback line-speed traffic (bcmcmd)\033[0m"
|
||||||
|
echo ""
|
||||||
|
echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m"
|
||||||
|
echo -e " VLANs: 30..137 ($(_tl_pair_count) loopback pairs, cdN <-> cdN+32)"
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[1mSubcommands\033[0m"
|
||||||
|
echo -e " \033[33minit\033[0m step 1 vlan remove 1 pbm=cd, vlan create/add each pair"
|
||||||
|
echo -e " \033[33mclear\033[0m step 2 clear c"
|
||||||
|
echo -e " \033[33mshow\033[0m step 3/6 show c (run before and after traffic)"
|
||||||
|
echo -e " \033[33mstart\033[0m step 4 tx <count> length=<len> VLantag=<vid> per VLAN"
|
||||||
|
echo -e " \033[33mstop\033[0m step 5 vlan remove <vid> pbm=<pair> [--destroy also destroys]"
|
||||||
|
echo -e " \033[33mps\033[0m ps <portlist> port status (link/speed) of the cabled ports"
|
||||||
|
echo -e " \033[33mreport\033[0m show c -> per-port TX/RX per pair + PASS/FAIL/NA cross-check"
|
||||||
|
echo -e " \033[33mrun\033[0m ps -> init -> clear -> start -> report"
|
||||||
|
echo -e " \033[33mhelp\033[0m"
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[1mOptions\033[0m"
|
||||||
|
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TL_UNITS)"
|
||||||
|
echo -e " \033[33m-c|--count|-tx\033[0m <n> tx packet count (default $TL_TX_COUNT)"
|
||||||
|
echo -e " \033[33m-l|--length|-length\033[0m <n> tx packet length (default $TL_TX_LENGTH)"
|
||||||
|
echo -e " \033[33m-p|--ports\033[0m <list> ps port list, or 'all' for every port"
|
||||||
|
echo -e " \033[33m-T|--tolerance\033[0m <n> report: allowed |delta| pkts (default $TL_TOLERANCE; -T 1 = snapshot skew)"
|
||||||
|
echo -e " \033[33m-a|--all\033[0m report: kept for compatibility (all pairs are listed)"
|
||||||
|
echo -e " \033[33m-g|--grouped\033[0m report: comma-group values"
|
||||||
|
echo -e " \033[33m-P|--with-port\033[0m report: render cd1(2) instead of cd1"
|
||||||
|
echo -e " \033[33m-q|--quiet\033[0m report: no trailing summary"
|
||||||
|
echo -e " \033[33m--tsv\033[0m report: tab-separated (Excel)"
|
||||||
|
echo -e " \033[33m--raw\033[0m report: also dump the raw 'show c'"
|
||||||
|
echo -e " \033[33m--color|--no-color\033[0m report: force/disable \033[32mPASS\033[0m / \033[31mFAIL\033[0m / \033[33mNA\033[0m colouring"
|
||||||
|
echo -e " (default: colour only when stdout is a terminal)"
|
||||||
|
echo -e " \033[33m-f|--file\033[0m <log> report: parse a saved log, no DUT access"
|
||||||
|
echo -e " \033[33m-d|--debug\033[0m print every bcmcmd command line (stderr) and run it"
|
||||||
|
echo -e " \033[33m-n|--dry-run\033[0m print commands only, do not touch the DUT"
|
||||||
|
echo -e " \033[33m--destroy\033[0m stop: also 'vlan destroy' each VLAN"
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[1mExamples\033[0m"
|
||||||
|
echo -e " blanton_traffic_linespeed ps -u 0"
|
||||||
|
echo -e " blanton_traffic_linespeed init -u 1"
|
||||||
|
echo -e " blanton_traffic_linespeed clear && blanton_traffic_linespeed start"
|
||||||
|
echo -e " blanton_traffic_linespeed report -u 1 -T 1"
|
||||||
|
echo -e " blanton_traffic_linespeed report -u 1 -q | grep -v PASS"
|
||||||
|
echo -e " blanton_traffic_linespeed report -f /tmp/showc_unit1_*.log -a"
|
||||||
|
echo -e " blanton_traffic_linespeed show -u 1 | grep -iE 'error|discard|drop'"
|
||||||
|
echo -e " blanton_traffic_linespeed start -u 0 -tx 100 -length 512"
|
||||||
|
echo -e " blanton_traffic_linespeed start -tx 100000 -length 9216 -d"
|
||||||
|
echo -e " blanton_traffic_linespeed stop --destroy"
|
||||||
|
echo ""
|
||||||
|
echo -e " report exit code: 0 = all pairs PASS, 2 = any FAIL/NA, 1 = parse error"
|
||||||
|
echo -e " Off-box equivalent: tools/bcm_mibpair_report_V1.1.0.py (python3)"
|
||||||
|
echo -e " ps ports: \033[36m$TL_PS_PORTS\033[0m"
|
||||||
|
echo -e " Table mirrors utils/traffic_loopback_vlan_{setting,remove}.ttl and"
|
||||||
|
echo -e " utils/traffic_loopback_start.ttl - keep them in sync."
|
||||||
|
}
|
||||||
|
|
||||||
|
# === Dispatcher ==============================================================
|
||||||
|
blanton_traffic_linespeed() {
|
||||||
|
local sub="${1:-help}"; shift 2>/dev/null || true
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-u|--unit)
|
||||||
|
case "$2" in
|
||||||
|
all|both|*,*) TL_UNITS=$(echo "$2" | sed 's/all\|both/0 1/; s/,/ /g') ;;
|
||||||
|
*) TL_UNITS="$2" ;;
|
||||||
|
esac
|
||||||
|
shift 2 ;;
|
||||||
|
-c|--count|-tx|--tx) TL_TX_COUNT="$2"; shift 2 ;;
|
||||||
|
-l|-length|--length|--len) TL_TX_LENGTH="$2"; shift 2 ;;
|
||||||
|
-p|--ports) TL_PS_PORTS="$2"; shift 2 ;;
|
||||||
|
-T|--tolerance) TL_TOLERANCE="$2"; shift 2 ;;
|
||||||
|
-f|--file) TL_REPORT_FILE="$2"; shift 2 ;;
|
||||||
|
-a|--all) TL_REPORT_ALL=1; shift ;;
|
||||||
|
-g|--grouped) TL_REPORT_GROUPED=1; shift ;;
|
||||||
|
-P|--with-port) TL_REPORT_WITHPORT=1; shift ;;
|
||||||
|
-q|--quiet) TL_REPORT_QUIET=1; shift ;;
|
||||||
|
--tsv) TL_REPORT_TSV=1; shift ;;
|
||||||
|
--raw) TL_REPORT_RAW=1; shift ;;
|
||||||
|
--color) TL_COLOR=always; shift ;;
|
||||||
|
--no-color) TL_COLOR=never; shift ;;
|
||||||
|
-d|--debug) DEBUG_MODE=1; shift ;;
|
||||||
|
-n|--dry-run) TL_DRY_RUN=1; shift ;;
|
||||||
|
--destroy) TL_DESTROY=1; shift ;;
|
||||||
|
-h|--help) blanton_traffic_linespeed_help; return 0 ;;
|
||||||
|
-*) _tl_err "unknown option '$1'"; return 1 ;;
|
||||||
|
*) # bare argument: only meaningful as the 'ps' port list
|
||||||
|
if [ "$sub" = "ps" ] || [ "$sub" = "status" ]; then
|
||||||
|
TL_PS_PORTS="$1"; shift
|
||||||
|
else
|
||||||
|
_tl_err "unexpected argument '$1'"; return 1
|
||||||
|
fi ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
case "$sub" in
|
||||||
|
init) traffic_linespeed_init ;;
|
||||||
|
clear) traffic_linespeed_clear ;;
|
||||||
|
show) traffic_linespeed_show ;;
|
||||||
|
start) traffic_linespeed_start ;;
|
||||||
|
stop) traffic_linespeed_stop ;;
|
||||||
|
ps|status) traffic_linespeed_ps ;;
|
||||||
|
report|rpt) traffic_linespeed_report ;;
|
||||||
|
run|all) traffic_linespeed_run ;;
|
||||||
|
debug) traffic_debug on ;;
|
||||||
|
help|-h|--help) blanton_traffic_linespeed_help ;;
|
||||||
|
*) _tl_err "unknown subcommand '$sub'"; blanton_traffic_linespeed_help; return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Executed directly -> dispatch. Sourced -> just expose the functions + help.
|
||||||
|
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||||
|
blanton_traffic_linespeed "$@"
|
||||||
|
else
|
||||||
|
blanton_traffic_linespeed_help
|
||||||
|
fi
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###############################################################################
|
||||||
|
# bmc_monitor.sh
|
||||||
|
#
|
||||||
|
# Version : V1.1.0
|
||||||
|
# Author : ETWen
|
||||||
|
# Date : 20260820
|
||||||
|
#
|
||||||
|
# Purpose : Periodically execute a list of commands on the BMC through
|
||||||
|
# `bmc-manager run "<cmd>"` from the SONiC host side, and append all
|
||||||
|
# output to a rotating log file. Designed to run detached in the
|
||||||
|
# background so no interactive SSH session to the BMC is required.
|
||||||
|
#
|
||||||
|
# Notes : - Everything runs on the HOST. Nothing is deployed to the BMC, so
|
||||||
|
# the BMC busybox toolchain (no base64 / no setsid ...) is a
|
||||||
|
# non-issue.
|
||||||
|
# - `bmc-manager run` prints the remote command output on stdout and
|
||||||
|
# its own banner on stderr; the two streams are captured separately
|
||||||
|
# so the log stays clean.
|
||||||
|
#
|
||||||
|
# Version History
|
||||||
|
# V1.0.0 20260820 Initial Version
|
||||||
|
# V1.1.0 20260820 `start` clears the previous log by default
|
||||||
|
# (START_LOG_MODE: new / archive / append)
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# User Configurable Section -- normally this is the only part you need to edit
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Commands executed on the BMC, one per line, in this order.
|
||||||
|
# Add a line to add a command; comment it out to disable it.
|
||||||
|
COMMANDS=(
|
||||||
|
"free -m"
|
||||||
|
#"uptime"
|
||||||
|
#"cat /proc/loadavg"
|
||||||
|
#"cat /proc/meminfo"
|
||||||
|
#"df -h /tmp"
|
||||||
|
#"dmesg | tail -n 30"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Seconds to wait after a full round (all COMMANDS executed) before the next one
|
||||||
|
INTERVAL_SEC=10
|
||||||
|
|
||||||
|
# Seconds to wait between two commands inside the same round (0 = no wait)
|
||||||
|
INTER_CMD_DELAY_SEC=0
|
||||||
|
|
||||||
|
# Per-command timeout in seconds; prevents a hung bmc-manager from freezing the
|
||||||
|
# whole loop. Set to 0 to disable.
|
||||||
|
CMD_TIMEOUT_SEC=30
|
||||||
|
|
||||||
|
# Stop after this many rounds. 0 = run until stopped manually.
|
||||||
|
MAX_ROUNDS=0
|
||||||
|
|
||||||
|
# Command runner. Final invocation is:
|
||||||
|
# "$RUNNER_BIN" "${RUNNER_ARGS[@]}" "<command string>"
|
||||||
|
# BMC side : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(run)
|
||||||
|
# BMC by IP : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(--ip 192.168.200.200 run)
|
||||||
|
# Host side : RUNNER_BIN="bash" ; RUNNER_ARGS=(-c)
|
||||||
|
RUNNER_BIN="bmc-manager"
|
||||||
|
RUNNER_ARGS=(run)
|
||||||
|
|
||||||
|
# stderr handling of the runner (bmc-manager banner lives here)
|
||||||
|
# 0 = log stderr only when the command fails (recommended, keeps log clean)
|
||||||
|
# 1 = always log stderr
|
||||||
|
LOG_STDERR=0
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_DIR="" # empty = <script directory>/log
|
||||||
|
LOG_NAME="bmc_poll.log"
|
||||||
|
MAX_LOG_SIZE_MB=100 # rotate above this size; 0 = never rotate
|
||||||
|
MAX_LOG_KEEP=5 # keep .1 .. .N
|
||||||
|
|
||||||
|
# What `start` does with the log left behind by the previous run:
|
||||||
|
# new = begin with an empty log; previous content and rotated copies are
|
||||||
|
# discarded (default -- one run, one log)
|
||||||
|
# archive = rename the previous log to <log>.YYYYmmdd-HHMMSS, then begin empty
|
||||||
|
# append = keep appending to the existing log
|
||||||
|
START_LOG_MODE="new"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Internal
|
||||||
|
###############################################################################
|
||||||
|
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||||
|
SCRIPT_PATH="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/${SCRIPT_NAME}"
|
||||||
|
[ -n "${LOG_DIR}" ] || LOG_DIR="$(dirname -- "${SCRIPT_PATH}")/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||||
|
PID_FILE="${LOG_DIR}/${LOG_NAME%.log}.pid"
|
||||||
|
|
||||||
|
LOG_TO_FILE=0
|
||||||
|
STOP=0
|
||||||
|
SLEEP_PID=""
|
||||||
|
|
||||||
|
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||||
|
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
on_signal() {
|
||||||
|
STOP=1
|
||||||
|
[ -n "${SLEEP_PID}" ] && kill "${SLEEP_PID}" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# sleep that can be aborted immediately by SIGTERM/SIGINT
|
||||||
|
interruptible_sleep() {
|
||||||
|
local sec="$1"
|
||||||
|
[ "${sec}" -gt 0 ] 2>/dev/null || return 0
|
||||||
|
sleep "${sec}" &
|
||||||
|
SLEEP_PID=$!
|
||||||
|
wait "${SLEEP_PID}" 2>/dev/null
|
||||||
|
SLEEP_PID=""
|
||||||
|
}
|
||||||
|
|
||||||
|
# echo the pid and return 0 when a live instance is found
|
||||||
|
is_running() {
|
||||||
|
local pid
|
||||||
|
[ -f "${PID_FILE}" ] || return 1
|
||||||
|
pid="$(cat "${PID_FILE}" 2>/dev/null)"
|
||||||
|
[[ "${pid}" =~ ^[0-9]+$ ]] || return 1
|
||||||
|
kill -0 "${pid}" 2>/dev/null || return 1
|
||||||
|
grep -qa "${SCRIPT_NAME}" "/proc/${pid}/cmdline" 2>/dev/null || return 1
|
||||||
|
printf '%s' "${pid}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate_log_if_needed() {
|
||||||
|
local max_bytes size i
|
||||||
|
[ "${LOG_TO_FILE}" -eq 1 ] || return 0
|
||||||
|
[ "${MAX_LOG_SIZE_MB}" -gt 0 ] || return 0
|
||||||
|
[ -f "${LOG_FILE}" ] || return 0
|
||||||
|
|
||||||
|
max_bytes=$(( MAX_LOG_SIZE_MB * 1024 * 1024 ))
|
||||||
|
size="$(stat -c %s "${LOG_FILE}" 2>/dev/null || echo 0)"
|
||||||
|
[ "${size}" -ge "${max_bytes}" ] || return 0
|
||||||
|
|
||||||
|
for (( i = MAX_LOG_KEEP - 1; i >= 1; i-- )); do
|
||||||
|
[ -f "${LOG_FILE}.${i}" ] && mv -f "${LOG_FILE}.${i}" "${LOG_FILE}.$(( i + 1 ))"
|
||||||
|
done
|
||||||
|
mv -f "${LOG_FILE}" "${LOG_FILE}.1"
|
||||||
|
exec >>"${LOG_FILE}" 2>&1 # re-bind stdout/stderr to the new file
|
||||||
|
printf '[%s] INFO : log rotated at %s MB\n' "$(ts)" "${MAX_LOG_SIZE_MB}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove the rotated copies (.1 .. .N) only. Timestamped archives are kept.
|
||||||
|
remove_rotated_logs() {
|
||||||
|
local i
|
||||||
|
for (( i = 1; i <= MAX_LOG_KEEP + 1; i++ )); do
|
||||||
|
rm -f "${LOG_FILE}.${i}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply START_LOG_MODE just before a background run is launched.
|
||||||
|
prepare_log_on_start() {
|
||||||
|
local stamp
|
||||||
|
case "${START_LOG_MODE}" in
|
||||||
|
append)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
archive)
|
||||||
|
if [ -s "${LOG_FILE}" ]; then
|
||||||
|
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||||
|
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" \
|
||||||
|
|| die "cannot archive ${LOG_FILE}"
|
||||||
|
printf 'previous log archived: %s.%s\n' "${LOG_FILE}" "${stamp}"
|
||||||
|
fi
|
||||||
|
remove_rotated_logs
|
||||||
|
;;
|
||||||
|
new)
|
||||||
|
# Truncate rather than unlink: the inode is preserved, so a `tail -f`
|
||||||
|
# that is already attached keeps following the new run.
|
||||||
|
if [ -f "${LOG_FILE}" ]; then
|
||||||
|
: > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"
|
||||||
|
fi
|
||||||
|
remove_rotated_logs
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "invalid START_LOG_MODE: ${START_LOG_MODE}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
run_one_command() {
|
||||||
|
local cmd="$1"
|
||||||
|
local out err rc t0 elapsed err_file
|
||||||
|
|
||||||
|
err_file="$(mktemp)"
|
||||||
|
t0=${SECONDS}
|
||||||
|
if [ "${CMD_TIMEOUT_SEC}" -gt 0 ]; then
|
||||||
|
out="$(timeout "${CMD_TIMEOUT_SEC}" \
|
||||||
|
"${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||||
|
else
|
||||||
|
out="$("${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||||
|
fi
|
||||||
|
rc=$?
|
||||||
|
elapsed=$(( SECONDS - t0 ))
|
||||||
|
err="$(cat "${err_file}" 2>/dev/null)"
|
||||||
|
rm -f "${err_file}"
|
||||||
|
|
||||||
|
printf '===== [%s] CMD: %s | rc=%d | %ds =====\n' "$(ts)" "${cmd}" "${rc}" "${elapsed}"
|
||||||
|
printf '%s\n' "${out}"
|
||||||
|
if [ "${rc}" -eq 124 ]; then
|
||||||
|
printf '[%s] WARN : timeout after %ds\n' "$(ts)" "${CMD_TIMEOUT_SEC}"
|
||||||
|
fi
|
||||||
|
if [ -n "${err}" ] && { [ "${LOG_STDERR}" -eq 1 ] || [ "${rc}" -ne 0 ]; }; then
|
||||||
|
printf -- '--- stderr ---\n%s\n' "${err}"
|
||||||
|
fi
|
||||||
|
printf '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop() {
|
||||||
|
local round=0 cmd
|
||||||
|
|
||||||
|
[ "${#COMMANDS[@]}" -gt 0 ] || die "COMMANDS is empty"
|
||||||
|
command -v "${RUNNER_BIN}" >/dev/null 2>&1 || die "runner not found: ${RUNNER_BIN}"
|
||||||
|
|
||||||
|
trap on_signal INT TERM
|
||||||
|
|
||||||
|
printf '#############################################################\n'
|
||||||
|
printf '[%s] START: pid=%d interval=%ds timeout=%ds cmds=%d\n' \
|
||||||
|
"$(ts)" "$$" "${INTERVAL_SEC}" "${CMD_TIMEOUT_SEC}" "${#COMMANDS[@]}"
|
||||||
|
printf '#############################################################\n'
|
||||||
|
|
||||||
|
while [ "${STOP}" -eq 0 ]; do
|
||||||
|
round=$(( round + 1 ))
|
||||||
|
printf -- '---------- ROUND %d @ %s ----------\n' "${round}" "$(ts)"
|
||||||
|
|
||||||
|
for cmd in "${COMMANDS[@]}"; do
|
||||||
|
[ "${STOP}" -eq 0 ] || break
|
||||||
|
run_one_command "${cmd}"
|
||||||
|
[ "${INTER_CMD_DELAY_SEC}" -gt 0 ] && interruptible_sleep "${INTER_CMD_DELAY_SEC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
rotate_log_if_needed
|
||||||
|
|
||||||
|
if [ "${MAX_ROUNDS}" -gt 0 ] && [ "${round}" -ge "${MAX_ROUNDS}" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# Fixed gap between rounds. For a fixed cadence instead, replace with:
|
||||||
|
# interruptible_sleep $(( INTERVAL_SEC - round_elapsed ))
|
||||||
|
[ "${STOP}" -eq 0 ] && interruptible_sleep "${INTERVAL_SEC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '[%s] STOP : pid=%d after %d round(s)\n' "$(ts)" "$$" "${round}"
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Sub-commands
|
||||||
|
###############################################################################
|
||||||
|
do_start() {
|
||||||
|
local pid
|
||||||
|
pid="$(is_running)" && die "already running (pid=${pid})"
|
||||||
|
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||||
|
prepare_log_on_start
|
||||||
|
|
||||||
|
if command -v setsid >/dev/null 2>&1; then
|
||||||
|
setsid "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||||
|
else
|
||||||
|
nohup "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||||
|
disown 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
pid="$(is_running)" || die "start failed, check ${LOG_FILE}"
|
||||||
|
printf 'started (pid=%s)\nlog: %s\n' "${pid}" "${LOG_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_daemon() {
|
||||||
|
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||||
|
LOG_TO_FILE=1
|
||||||
|
exec >>"${LOG_FILE}" 2>&1
|
||||||
|
printf '%d\n' "$$" > "${PID_FILE}"
|
||||||
|
trap 'rm -f "${PID_FILE}"' EXIT
|
||||||
|
main_loop
|
||||||
|
}
|
||||||
|
|
||||||
|
do_stop() {
|
||||||
|
local pid i
|
||||||
|
pid="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||||
|
|
||||||
|
kill -TERM -"${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null
|
||||||
|
for (( i = 0; i < 20; i++ )); do
|
||||||
|
kill -0 "${pid}" 2>/dev/null || break
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
if kill -0 "${pid}" 2>/dev/null; then
|
||||||
|
printf 'SIGTERM ignored, sending SIGKILL\n'
|
||||||
|
kill -KILL -"${pid}" 2>/dev/null || kill -KILL "${pid}" 2>/dev/null
|
||||||
|
fi
|
||||||
|
rm -f "${PID_FILE}"
|
||||||
|
printf 'stopped (pid=%s)\n' "${pid}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_status() {
|
||||||
|
local pid
|
||||||
|
if pid="$(is_running)"; then
|
||||||
|
printf 'status : running (pid=%s)\n' "${pid}"
|
||||||
|
else
|
||||||
|
printf 'status : stopped\n'
|
||||||
|
fi
|
||||||
|
printf 'log : %s\n' "${LOG_FILE}"
|
||||||
|
[ -f "${LOG_FILE}" ] && printf 'size : %s\n' "$(du -h "${LOG_FILE}" | cut -f1)"
|
||||||
|
printf 'cmds : %d, interval=%ds\n' "${#COMMANDS[@]}" "${INTERVAL_SEC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: ${SCRIPT_NAME} {start|stop|status|fg|tail|clear}
|
||||||
|
|
||||||
|
start Run detached in the background; the previous log is discarded first
|
||||||
|
(see START_LOG_MODE)
|
||||||
|
stop Stop the background instance
|
||||||
|
status Show pid / log path / log size
|
||||||
|
fg Run in the foreground, output to the terminal (for a quick check)
|
||||||
|
tail tail -f the log file
|
||||||
|
clear Remove the log file and all rotated copies (must be stopped first)
|
||||||
|
|
||||||
|
Log file : ${LOG_FILE}
|
||||||
|
|
||||||
|
To add a command, edit the COMMANDS array at the top of this script.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Entry point
|
||||||
|
###############################################################################
|
||||||
|
case "${1:-}" in
|
||||||
|
start) do_start ;;
|
||||||
|
stop) do_stop ;;
|
||||||
|
status) do_status ;;
|
||||||
|
fg) LOG_TO_FILE=0; main_loop ;;
|
||||||
|
tail) tail -n 50 -f "${LOG_FILE}" ;;
|
||||||
|
clear)
|
||||||
|
is_running >/dev/null && die "still running, stop it first"
|
||||||
|
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]*
|
||||||
|
printf 'log cleared\n'
|
||||||
|
;;
|
||||||
|
__daemon) do_daemon ;;
|
||||||
|
-h|--help|"") usage ;;
|
||||||
|
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###############################################################################
|
||||||
|
# bmc_monitor_ddr.sh
|
||||||
|
#
|
||||||
|
# Version : V1.1.0
|
||||||
|
# Author : ETWen
|
||||||
|
# Date : 20260820
|
||||||
|
#
|
||||||
|
# Purpose : Periodically execute a list of commands on the BMC through
|
||||||
|
# `bmc-manager run "<cmd>"` from the SONiC host side, and append all
|
||||||
|
# output to a rotating log file. Designed to run detached in the
|
||||||
|
# background so no interactive SSH session to the BMC is required.
|
||||||
|
#
|
||||||
|
# Notes : - Everything runs on the HOST. Nothing is deployed to the BMC, so
|
||||||
|
# the BMC busybox toolchain (no base64 / no setsid ...) is a
|
||||||
|
# non-issue.
|
||||||
|
# - `bmc-manager run` prints the remote command output on stdout and
|
||||||
|
# its own banner on stderr; the two streams are captured separately
|
||||||
|
# so the log stays clean.
|
||||||
|
#
|
||||||
|
# Version History
|
||||||
|
# V1.0.0 20260820 Initial Version
|
||||||
|
# V1.1.0 20260820 `start` clears the previous log by default
|
||||||
|
# (START_LOG_MODE: new / archive / append)
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# User Configurable Section -- normally this is the only part you need to edit
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
# Commands executed on the BMC, one per line, in this order.
|
||||||
|
# Add a line to add a command; comment it out to disable it.
|
||||||
|
COMMANDS=(
|
||||||
|
"memtester 500M 1"
|
||||||
|
#"uptime"
|
||||||
|
#"cat /proc/loadavg"
|
||||||
|
#"cat /proc/meminfo"
|
||||||
|
#"df -h /tmp"
|
||||||
|
#"dmesg | tail -n 30"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Seconds to wait after a full round (all COMMANDS executed) before the next one
|
||||||
|
INTERVAL_SEC=5
|
||||||
|
|
||||||
|
# Seconds to wait between two commands inside the same round (0 = no wait)
|
||||||
|
INTER_CMD_DELAY_SEC=0
|
||||||
|
|
||||||
|
# Per-command timeout in seconds; prevents a hung bmc-manager from freezing the
|
||||||
|
# whole loop. Set to 0 to disable.
|
||||||
|
CMD_TIMEOUT_SEC=3600
|
||||||
|
|
||||||
|
# Stop after this many rounds. 0 = run until stopped manually.
|
||||||
|
MAX_ROUNDS=0
|
||||||
|
|
||||||
|
# Command runner. Final invocation is:
|
||||||
|
# "$RUNNER_BIN" "${RUNNER_ARGS[@]}" "<command string>"
|
||||||
|
# BMC side : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(run)
|
||||||
|
# BMC by IP : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(--ip 192.168.200.200 run)
|
||||||
|
# Host side : RUNNER_BIN="bash" ; RUNNER_ARGS=(-c)
|
||||||
|
RUNNER_BIN="bmc-manager"
|
||||||
|
RUNNER_ARGS=(run)
|
||||||
|
|
||||||
|
# stderr handling of the runner (bmc-manager banner lives here)
|
||||||
|
# 0 = log stderr only when the command fails (recommended, keeps log clean)
|
||||||
|
# 1 = always log stderr
|
||||||
|
LOG_STDERR=0
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_DIR="" # empty = <script directory>/log
|
||||||
|
LOG_NAME="bmc_ddr.log"
|
||||||
|
MAX_LOG_SIZE_MB=100 # rotate above this size; 0 = never rotate
|
||||||
|
MAX_LOG_KEEP=5 # keep .1 .. .N
|
||||||
|
|
||||||
|
# What `start` does with the log left behind by the previous run:
|
||||||
|
# new = begin with an empty log; previous content and rotated copies are
|
||||||
|
# discarded (default -- one run, one log)
|
||||||
|
# archive = rename the previous log to <log>.YYYYmmdd-HHMMSS, then begin empty
|
||||||
|
# append = keep appending to the existing log
|
||||||
|
START_LOG_MODE="new"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Internal
|
||||||
|
###############################################################################
|
||||||
|
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||||
|
SCRIPT_PATH="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/${SCRIPT_NAME}"
|
||||||
|
[ -n "${LOG_DIR}" ] || LOG_DIR="$(dirname -- "${SCRIPT_PATH}")/log"
|
||||||
|
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||||
|
PID_FILE="${LOG_DIR}/${LOG_NAME%.log}.pid"
|
||||||
|
|
||||||
|
LOG_TO_FILE=0
|
||||||
|
STOP=0
|
||||||
|
SLEEP_PID=""
|
||||||
|
|
||||||
|
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||||
|
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
on_signal() {
|
||||||
|
STOP=1
|
||||||
|
[ -n "${SLEEP_PID}" ] && kill "${SLEEP_PID}" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# sleep that can be aborted immediately by SIGTERM/SIGINT
|
||||||
|
interruptible_sleep() {
|
||||||
|
local sec="$1"
|
||||||
|
[ "${sec}" -gt 0 ] 2>/dev/null || return 0
|
||||||
|
sleep "${sec}" &
|
||||||
|
SLEEP_PID=$!
|
||||||
|
wait "${SLEEP_PID}" 2>/dev/null
|
||||||
|
SLEEP_PID=""
|
||||||
|
}
|
||||||
|
|
||||||
|
# echo the pid and return 0 when a live instance is found
|
||||||
|
is_running() {
|
||||||
|
local pid
|
||||||
|
[ -f "${PID_FILE}" ] || return 1
|
||||||
|
pid="$(cat "${PID_FILE}" 2>/dev/null)"
|
||||||
|
[[ "${pid}" =~ ^[0-9]+$ ]] || return 1
|
||||||
|
kill -0 "${pid}" 2>/dev/null || return 1
|
||||||
|
grep -qa "${SCRIPT_NAME}" "/proc/${pid}/cmdline" 2>/dev/null || return 1
|
||||||
|
printf '%s' "${pid}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
rotate_log_if_needed() {
|
||||||
|
local max_bytes size i
|
||||||
|
[ "${LOG_TO_FILE}" -eq 1 ] || return 0
|
||||||
|
[ "${MAX_LOG_SIZE_MB}" -gt 0 ] || return 0
|
||||||
|
[ -f "${LOG_FILE}" ] || return 0
|
||||||
|
|
||||||
|
max_bytes=$(( MAX_LOG_SIZE_MB * 1024 * 1024 ))
|
||||||
|
size="$(stat -c %s "${LOG_FILE}" 2>/dev/null || echo 0)"
|
||||||
|
[ "${size}" -ge "${max_bytes}" ] || return 0
|
||||||
|
|
||||||
|
for (( i = MAX_LOG_KEEP - 1; i >= 1; i-- )); do
|
||||||
|
[ -f "${LOG_FILE}.${i}" ] && mv -f "${LOG_FILE}.${i}" "${LOG_FILE}.$(( i + 1 ))"
|
||||||
|
done
|
||||||
|
mv -f "${LOG_FILE}" "${LOG_FILE}.1"
|
||||||
|
exec >>"${LOG_FILE}" 2>&1 # re-bind stdout/stderr to the new file
|
||||||
|
printf '[%s] INFO : log rotated at %s MB\n' "$(ts)" "${MAX_LOG_SIZE_MB}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove the rotated copies (.1 .. .N) only. Timestamped archives are kept.
|
||||||
|
remove_rotated_logs() {
|
||||||
|
local i
|
||||||
|
for (( i = 1; i <= MAX_LOG_KEEP + 1; i++ )); do
|
||||||
|
rm -f "${LOG_FILE}.${i}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply START_LOG_MODE just before a background run is launched.
|
||||||
|
prepare_log_on_start() {
|
||||||
|
local stamp
|
||||||
|
case "${START_LOG_MODE}" in
|
||||||
|
append)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
archive)
|
||||||
|
if [ -s "${LOG_FILE}" ]; then
|
||||||
|
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||||
|
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" \
|
||||||
|
|| die "cannot archive ${LOG_FILE}"
|
||||||
|
printf 'previous log archived: %s.%s\n' "${LOG_FILE}" "${stamp}"
|
||||||
|
fi
|
||||||
|
remove_rotated_logs
|
||||||
|
;;
|
||||||
|
new)
|
||||||
|
# Truncate rather than unlink: the inode is preserved, so a `tail -f`
|
||||||
|
# that is already attached keeps following the new run.
|
||||||
|
if [ -f "${LOG_FILE}" ]; then
|
||||||
|
: > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"
|
||||||
|
fi
|
||||||
|
remove_rotated_logs
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "invalid START_LOG_MODE: ${START_LOG_MODE}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
run_one_command() {
|
||||||
|
local cmd="$1"
|
||||||
|
local out err rc t0 elapsed err_file
|
||||||
|
|
||||||
|
err_file="$(mktemp)"
|
||||||
|
t0=${SECONDS}
|
||||||
|
if [ "${CMD_TIMEOUT_SEC}" -gt 0 ]; then
|
||||||
|
out="$(timeout "${CMD_TIMEOUT_SEC}" \
|
||||||
|
"${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||||
|
else
|
||||||
|
out="$("${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||||
|
fi
|
||||||
|
rc=$?
|
||||||
|
elapsed=$(( SECONDS - t0 ))
|
||||||
|
err="$(cat "${err_file}" 2>/dev/null)"
|
||||||
|
rm -f "${err_file}"
|
||||||
|
|
||||||
|
printf '===== [%s] CMD: %s | rc=%d | %ds =====\n' "$(ts)" "${cmd}" "${rc}" "${elapsed}"
|
||||||
|
printf '%s\n' "${out}"
|
||||||
|
if [ "${rc}" -eq 124 ]; then
|
||||||
|
printf '[%s] WARN : timeout after %ds\n' "$(ts)" "${CMD_TIMEOUT_SEC}"
|
||||||
|
fi
|
||||||
|
if [ -n "${err}" ] && { [ "${LOG_STDERR}" -eq 1 ] || [ "${rc}" -ne 0 ]; }; then
|
||||||
|
printf -- '--- stderr ---\n%s\n' "${err}"
|
||||||
|
fi
|
||||||
|
printf '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop() {
|
||||||
|
local round=0 cmd
|
||||||
|
|
||||||
|
[ "${#COMMANDS[@]}" -gt 0 ] || die "COMMANDS is empty"
|
||||||
|
command -v "${RUNNER_BIN}" >/dev/null 2>&1 || die "runner not found: ${RUNNER_BIN}"
|
||||||
|
|
||||||
|
trap on_signal INT TERM
|
||||||
|
|
||||||
|
printf '#############################################################\n'
|
||||||
|
printf '[%s] START: pid=%d interval=%ds timeout=%ds cmds=%d\n' \
|
||||||
|
"$(ts)" "$$" "${INTERVAL_SEC}" "${CMD_TIMEOUT_SEC}" "${#COMMANDS[@]}"
|
||||||
|
printf '#############################################################\n'
|
||||||
|
|
||||||
|
while [ "${STOP}" -eq 0 ]; do
|
||||||
|
round=$(( round + 1 ))
|
||||||
|
printf -- '---------- ROUND %d @ %s ----------\n' "${round}" "$(ts)"
|
||||||
|
|
||||||
|
for cmd in "${COMMANDS[@]}"; do
|
||||||
|
[ "${STOP}" -eq 0 ] || break
|
||||||
|
run_one_command "${cmd}"
|
||||||
|
[ "${INTER_CMD_DELAY_SEC}" -gt 0 ] && interruptible_sleep "${INTER_CMD_DELAY_SEC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
rotate_log_if_needed
|
||||||
|
|
||||||
|
if [ "${MAX_ROUNDS}" -gt 0 ] && [ "${round}" -ge "${MAX_ROUNDS}" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# Fixed gap between rounds. For a fixed cadence instead, replace with:
|
||||||
|
# interruptible_sleep $(( INTERVAL_SEC - round_elapsed ))
|
||||||
|
[ "${STOP}" -eq 0 ] && interruptible_sleep "${INTERVAL_SEC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '[%s] STOP : pid=%d after %d round(s)\n' "$(ts)" "$$" "${round}"
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Sub-commands
|
||||||
|
###############################################################################
|
||||||
|
do_start() {
|
||||||
|
local pid
|
||||||
|
pid="$(is_running)" && die "already running (pid=${pid})"
|
||||||
|
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||||
|
prepare_log_on_start
|
||||||
|
|
||||||
|
if command -v setsid >/dev/null 2>&1; then
|
||||||
|
setsid "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||||
|
else
|
||||||
|
nohup "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||||
|
disown 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
pid="$(is_running)" || die "start failed, check ${LOG_FILE}"
|
||||||
|
printf 'started (pid=%s)\nlog: %s\n' "${pid}" "${LOG_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_daemon() {
|
||||||
|
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||||
|
LOG_TO_FILE=1
|
||||||
|
exec >>"${LOG_FILE}" 2>&1
|
||||||
|
printf '%d\n' "$$" > "${PID_FILE}"
|
||||||
|
trap 'rm -f "${PID_FILE}"' EXIT
|
||||||
|
main_loop
|
||||||
|
}
|
||||||
|
|
||||||
|
do_stop() {
|
||||||
|
local pid i
|
||||||
|
pid="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||||
|
|
||||||
|
kill -TERM -"${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null
|
||||||
|
for (( i = 0; i < 20; i++ )); do
|
||||||
|
kill -0 "${pid}" 2>/dev/null || break
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
if kill -0 "${pid}" 2>/dev/null; then
|
||||||
|
printf 'SIGTERM ignored, sending SIGKILL\n'
|
||||||
|
kill -KILL -"${pid}" 2>/dev/null || kill -KILL "${pid}" 2>/dev/null
|
||||||
|
fi
|
||||||
|
rm -f "${PID_FILE}"
|
||||||
|
printf 'stopped (pid=%s)\n' "${pid}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_status() {
|
||||||
|
local pid
|
||||||
|
if pid="$(is_running)"; then
|
||||||
|
printf 'status : running (pid=%s)\n' "${pid}"
|
||||||
|
else
|
||||||
|
printf 'status : stopped\n'
|
||||||
|
fi
|
||||||
|
printf 'log : %s\n' "${LOG_FILE}"
|
||||||
|
[ -f "${LOG_FILE}" ] && printf 'size : %s\n' "$(du -h "${LOG_FILE}" | cut -f1)"
|
||||||
|
printf 'cmds : %d, interval=%ds\n' "${#COMMANDS[@]}" "${INTERVAL_SEC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: ${SCRIPT_NAME} {start|stop|status|fg|tail|clear}
|
||||||
|
|
||||||
|
start Run detached in the background; the previous log is discarded first
|
||||||
|
(see START_LOG_MODE)
|
||||||
|
stop Stop the background instance
|
||||||
|
status Show pid / log path / log size
|
||||||
|
fg Run in the foreground, output to the terminal (for a quick check)
|
||||||
|
tail tail -f the log file
|
||||||
|
clear Remove the log file and all rotated copies (must be stopped first)
|
||||||
|
|
||||||
|
Log file : ${LOG_FILE}
|
||||||
|
|
||||||
|
To add a command, edit the COMMANDS array at the top of this script.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Entry point
|
||||||
|
###############################################################################
|
||||||
|
case "${1:-}" in
|
||||||
|
start) do_start ;;
|
||||||
|
stop) do_stop ;;
|
||||||
|
status) do_status ;;
|
||||||
|
fg) LOG_TO_FILE=0; main_loop ;;
|
||||||
|
tail) tail -n 50 -f "${LOG_FILE}" ;;
|
||||||
|
clear)
|
||||||
|
is_running >/dev/null && die "still running, stop it first"
|
||||||
|
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]*
|
||||||
|
printf 'log cleared\n'
|
||||||
|
;;
|
||||||
|
__daemon) do_daemon ;;
|
||||||
|
-h|--help|"") usage ;;
|
||||||
|
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||||
|
esac
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
;================================================================
|
;================================================================
|
||||||
; User Configuration
|
; User Configuration
|
||||||
;================================================================
|
;================================================================
|
||||||
strTestcase="Margin"
|
|
||||||
project_name = "Blanton"
|
project_name = "Blanton"
|
||||||
|
strTestcase="ENV" ;ENV,EMC,Margin...etc
|
||||||
|
|
||||||
EN_Margin = 1 ; 1: Enable Margin Test, 0: Disable Margin Test
|
EN_Margin = 0 ; 1: Enable Margin Test, 0: Disable Margin Test
|
||||||
|
|
||||||
EN_log = 1 ; 1: Enable log, 0: Disable log
|
EN_log = 1 ; 1: Enable log, 0: Disable log
|
||||||
;================================================================
|
;================================================================
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
; =============================================================================
|
||||||
|
; File : utils/wait_init.ttl
|
||||||
|
; Version : V1.0.0
|
||||||
|
; Date : 2026-08-21
|
||||||
|
; Author : ETWen
|
||||||
|
; =============================================================================
|
||||||
|
; Wait until "show platform temperature" is not "Thermal Not detected".
|
||||||
|
; Enter : prompt of the previous command is NOT consumed.
|
||||||
|
; Exit : "show platform temperature" is sent, prompt NOT consumed.
|
||||||
|
;
|
||||||
|
; Version History:
|
||||||
|
; V1.0.0 2026-08-21 Initial Version
|
||||||
|
; =============================================================================
|
||||||
|
wt_interval = 10
|
||||||
|
timeout = 30
|
||||||
|
wait prompt_sonic_root
|
||||||
|
|
||||||
|
:WAIT_THERMAL
|
||||||
|
sendln "show platform temperature"
|
||||||
|
wait "Thermal Not detected" prompt_sonic_root
|
||||||
|
if result = 2 then
|
||||||
|
goto THERMAL_OK
|
||||||
|
endif
|
||||||
|
wait prompt_sonic_root
|
||||||
|
pause wt_interval
|
||||||
|
goto WAIT_THERMAL
|
||||||
|
|
||||||
|
:THERMAL_OK
|
||||||
|
timeout = 0
|
||||||
|
sendln "show platform temperature"
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
bcm_mibpair_report_V1.1.0.py
|
||||||
|
|
||||||
|
Author : ETWen
|
||||||
|
Date : 20260730
|
||||||
|
|
||||||
|
Purpose : Extract MIB_TPOK / MIB_RPOK counters from a Broadcom drivshell log
|
||||||
|
and lay them out horizontally, one loopback pair per block:
|
||||||
|
|
||||||
|
Port TX RX PASS/FAIL
|
||||||
|
cd1 723629081133 581693309458 PASS
|
||||||
|
cd33 581693309458 723629081133 PASS
|
||||||
|
|
||||||
|
Pair membership and pair order come from the
|
||||||
|
"vlan remove <vid> pbm=cdA,cdB" lines in the same log, so the report
|
||||||
|
always follows the order the test actually ran in.
|
||||||
|
|
||||||
|
Verdict per pair comes from the loopback cross-check: for a pair,
|
||||||
|
cdA.TPOK must equal cdB.RPOK and cdA.RPOK must equal cdB.TPOK.
|
||||||
|
PASS - both directions match (within --tolerance)
|
||||||
|
FAIL - at least one direction is off; delta is listed in the
|
||||||
|
trailing summary
|
||||||
|
NA - the pair has no counters in the log
|
||||||
|
|
||||||
|
Usage : ./bcm_mibpair_report_V1.1.0.py <drivshell.log> [options]
|
||||||
|
|
||||||
|
-a, --all also emit pairs that have no counters in the log
|
||||||
|
(values shown as "-")
|
||||||
|
-b, --block repeat the header and blank-separate each pair
|
||||||
|
-g, --grouped keep the SDK's comma grouping (1,234,567)
|
||||||
|
-p, --with-port render "cd1(2)" instead of "cd1"
|
||||||
|
-t, --tsv tab-separated output (for Excel / pandas)
|
||||||
|
-s, --no-status drop the PASS/FAIL column
|
||||||
|
-T, --tolerance N allowed |delta| in packets before a pair is FAIL
|
||||||
|
(default 0). A +/-1 skew is normal: the SDK reads
|
||||||
|
counters port-by-port while traffic still runs, so
|
||||||
|
-T 1 is a reasonable production setting.
|
||||||
|
-q, --quiet suppress the trailing summary comments
|
||||||
|
-o, --output write to a file instead of stdout
|
||||||
|
|
||||||
|
Notes : - The trailing "+delta" column printed by the SDK is stripped.
|
||||||
|
- A cd port missing from the dump usually means the console
|
||||||
|
scrolled or auto-logged out mid-"show c", NOT that the port was
|
||||||
|
down. Cross-check against "ps" before drawing conclusions.
|
||||||
|
- A +/-1 packet delta between a pair is normal snapshot skew: the
|
||||||
|
SDK reads counters port-by-port while traffic is still running.
|
||||||
|
|
||||||
|
Exit : 0 = every pair had counters and cross-checked clean
|
||||||
|
1 = usage / input error
|
||||||
|
2 = at least one pair is FAIL or NA (see summary)
|
||||||
|
|
||||||
|
Version History
|
||||||
|
V1.0.0 20260730 Initial Version (parity with bcm_mibpair_report_V1.2.0.sh)
|
||||||
|
V1.0.1 20260730 Handle BrokenPipeError quietly when piped into head
|
||||||
|
V1.1.0 20260730 Add PASS/FAIL/NA verdict column and --tolerance
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Iterable, TextIO
|
||||||
|
|
||||||
|
EXIT_OK = 0
|
||||||
|
EXIT_USAGE = 1
|
||||||
|
EXIT_WARN = 2
|
||||||
|
|
||||||
|
# "vlan remove 31 pbm=cd1,cd33"
|
||||||
|
RE_PBM = re.compile(r"pbm=(cd\d+),(cd\d+)")
|
||||||
|
|
||||||
|
# "MIB_TPOK.cd1(2) : 723,629,081,133 +723,629,081,133"
|
||||||
|
RE_MIB = re.compile(
|
||||||
|
r"^MIB_(?P<kind>TPOK|RPOK)\.(?P<cd>cd\d+)\((?P<lport>\d+)\)\s*:\s*(?P<val>[\d,]+)"
|
||||||
|
)
|
||||||
|
|
||||||
|
MISSING = "-"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PortCounters:
|
||||||
|
"""TPOK / RPOK for a single cd port."""
|
||||||
|
|
||||||
|
lport: int | None = None
|
||||||
|
tx: int | None = None
|
||||||
|
rx: int | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def complete(self) -> bool:
|
||||||
|
return self.tx is not None and self.rx is not None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LogData:
|
||||||
|
"""Everything the report needs, extracted from one drivshell log."""
|
||||||
|
|
||||||
|
pairs: list[tuple[str, str]] = field(default_factory=list)
|
||||||
|
ports: dict[str, PortCounters] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def counters(self, cd: str) -> PortCounters:
|
||||||
|
return self.ports.setdefault(cd, PortCounters())
|
||||||
|
|
||||||
|
|
||||||
|
def parse_log(lines: Iterable[str]) -> LogData:
|
||||||
|
"""Pull pbm pair definitions and TPOK/RPOK counters out of a drivshell log."""
|
||||||
|
data = LogData()
|
||||||
|
seen_pairs: set[tuple[str, str]] = set()
|
||||||
|
|
||||||
|
for raw in lines:
|
||||||
|
line = raw.rstrip("\r\n")
|
||||||
|
|
||||||
|
for a, b in RE_PBM.findall(line):
|
||||||
|
if (a, b) not in seen_pairs:
|
||||||
|
seen_pairs.add((a, b))
|
||||||
|
data.pairs.append((a, b))
|
||||||
|
|
||||||
|
# drivshell echoes commands, so a MIB line may be prefixed with
|
||||||
|
# "drivshell>" noise; anchor on the MIB_ token instead of the line start.
|
||||||
|
idx = line.find("MIB_")
|
||||||
|
if idx < 0:
|
||||||
|
continue
|
||||||
|
m = RE_MIB.match(line[idx:])
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
|
||||||
|
pc = data.counters(m.group("cd"))
|
||||||
|
pc.lport = int(m.group("lport"))
|
||||||
|
value = int(m.group("val").replace(",", ""))
|
||||||
|
if m.group("kind") == "TPOK":
|
||||||
|
pc.tx = value
|
||||||
|
else:
|
||||||
|
pc.rx = value
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_value(value: int | None, grouped: bool) -> str:
|
||||||
|
if value is None:
|
||||||
|
return MISSING
|
||||||
|
return f"{value:,}" if grouped else str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_port(cd: str, pc: PortCounters, with_port: bool) -> str:
|
||||||
|
if with_port and pc.lport is not None:
|
||||||
|
return f"{cd}({pc.lport})"
|
||||||
|
return cd
|
||||||
|
|
||||||
|
|
||||||
|
PASS, FAIL, NA = "PASS", "FAIL", "NA"
|
||||||
|
|
||||||
|
|
||||||
|
def pair_deltas(data: LogData, a: str, b: str) -> tuple[int, int] | None:
|
||||||
|
"""(cdA.TX - cdB.RX, cdA.RX - cdB.TX), or None if counters are missing."""
|
||||||
|
pa, pb = data.counters(a), data.counters(b)
|
||||||
|
if not (pa.complete and pb.complete):
|
||||||
|
return None
|
||||||
|
return pa.tx - pb.rx, pa.rx - pb.tx
|
||||||
|
|
||||||
|
|
||||||
|
def verdict(data: LogData, a: str, b: str, tolerance: int) -> str:
|
||||||
|
d = pair_deltas(data, a, b)
|
||||||
|
if d is None:
|
||||||
|
return NA
|
||||||
|
return PASS if max(abs(d[0]), abs(d[1])) <= tolerance else FAIL
|
||||||
|
|
||||||
|
|
||||||
|
def render(data: LogData, args: argparse.Namespace, out: TextIO) -> int:
|
||||||
|
status = not args.no_status
|
||||||
|
rows: list[tuple[str, ...]] = []
|
||||||
|
blocks: list[list[tuple[str, ...]]] = []
|
||||||
|
missing: list[tuple[str, str]] = []
|
||||||
|
failed: list[tuple[str, str, int, int]] = []
|
||||||
|
tally = {PASS: 0, FAIL: 0, NA: 0}
|
||||||
|
|
||||||
|
for a, b in data.pairs:
|
||||||
|
pa, pb = data.counters(a), data.counters(b)
|
||||||
|
v = verdict(data, a, b, args.tolerance)
|
||||||
|
tally[v] += 1
|
||||||
|
if v == NA:
|
||||||
|
missing.append((a, b))
|
||||||
|
if not args.all:
|
||||||
|
continue
|
||||||
|
elif v == FAIL:
|
||||||
|
d_tx, d_rx = pair_deltas(data, a, b)
|
||||||
|
failed.append((a, b, d_tx, d_rx))
|
||||||
|
|
||||||
|
block = []
|
||||||
|
for cd, pc in ((a, pa), (b, pb)):
|
||||||
|
row = (
|
||||||
|
fmt_port(cd, pc, args.with_port),
|
||||||
|
fmt_value(pc.tx, args.grouped),
|
||||||
|
fmt_value(pc.rx, args.grouped),
|
||||||
|
)
|
||||||
|
block.append(row + (v,) if status else row)
|
||||||
|
blocks.append(block)
|
||||||
|
rows.extend(block)
|
||||||
|
|
||||||
|
header = ("Port", "TX", "RX", "PASS/FAIL") if status else ("Port", "TX", "RX")
|
||||||
|
|
||||||
|
if args.tsv:
|
||||||
|
if not args.block:
|
||||||
|
print("\t".join(header), file=out)
|
||||||
|
for block in blocks:
|
||||||
|
if args.block:
|
||||||
|
print("\t".join(header), file=out)
|
||||||
|
for row in block:
|
||||||
|
print("\t".join(row), file=out)
|
||||||
|
if args.block:
|
||||||
|
print(file=out)
|
||||||
|
else:
|
||||||
|
# size columns to the widest cell actually emitted
|
||||||
|
ncol = len(header)
|
||||||
|
width = [
|
||||||
|
max([len(r[i]) for r in rows] + [len(header[i])]) + 2
|
||||||
|
for i in range(ncol)
|
||||||
|
]
|
||||||
|
|
||||||
|
def line(row: tuple[str, ...]) -> str:
|
||||||
|
cells = [f"{row[0]:<{width[0]}}"]
|
||||||
|
cells += [f"{row[i]:>{width[i]}}" for i in range(1, ncol)]
|
||||||
|
return "".join(cells).rstrip()
|
||||||
|
|
||||||
|
if not args.block:
|
||||||
|
print(line(header), file=out)
|
||||||
|
for block in blocks:
|
||||||
|
if args.block:
|
||||||
|
print(line(header), file=out)
|
||||||
|
for row in block:
|
||||||
|
print(line(row), file=out)
|
||||||
|
if args.block:
|
||||||
|
print(file=out)
|
||||||
|
|
||||||
|
if not args.quiet:
|
||||||
|
if not args.block:
|
||||||
|
print(file=out)
|
||||||
|
print(f"# pairs in pbm list : {len(data.pairs)}", file=out)
|
||||||
|
print(f"# pairs reported : {len(blocks)}", file=out)
|
||||||
|
print(
|
||||||
|
f"# PASS {tally[PASS]} FAIL {tally[FAIL]} NA {tally[NA]}"
|
||||||
|
f" (tolerance {args.tolerance})",
|
||||||
|
file=out,
|
||||||
|
)
|
||||||
|
if missing:
|
||||||
|
joined = " ".join(f"{a}/{b}" for a, b in missing)
|
||||||
|
print(f"# NA (no counters): {joined}", file=out)
|
||||||
|
for a, b, d_tx, d_rx in failed:
|
||||||
|
print(
|
||||||
|
f"# FAIL {a}/{b}: {a}.TX-{b}.RX={d_tx:+d} {a}.RX-{b}.TX={d_rx:+d}",
|
||||||
|
file=out,
|
||||||
|
)
|
||||||
|
|
||||||
|
return EXIT_WARN if (tally[FAIL] or tally[NA]) else EXIT_OK
|
||||||
|
|
||||||
|
|
||||||
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
|
p = argparse.ArgumentParser(
|
||||||
|
description="Render Broadcom drivshell MIB_TPOK/RPOK counters as a "
|
||||||
|
"loopback-pair table.",
|
||||||
|
epilog="Exit 2 means missing counters and/or a cross-check mismatch.",
|
||||||
|
)
|
||||||
|
p.add_argument("log", type=Path, help="drivshell log file ('-' for stdin)")
|
||||||
|
p.add_argument("-a", "--all", action="store_true",
|
||||||
|
help="also emit pairs with no counters")
|
||||||
|
p.add_argument("-b", "--block", action="store_true",
|
||||||
|
help="repeat header and blank-separate each pair")
|
||||||
|
p.add_argument("-g", "--grouped", action="store_true",
|
||||||
|
help="keep comma grouping in values")
|
||||||
|
p.add_argument("-p", "--with-port", action="store_true",
|
||||||
|
help="render cd1(2) instead of cd1")
|
||||||
|
p.add_argument("-t", "--tsv", action="store_true",
|
||||||
|
help="tab-separated output")
|
||||||
|
p.add_argument("-s", "--no-status", action="store_true",
|
||||||
|
help="drop the PASS/FAIL column")
|
||||||
|
p.add_argument("-T", "--tolerance", type=int, default=0, metavar="N",
|
||||||
|
help="allowed |delta| in packets before a pair is FAIL "
|
||||||
|
"(default 0; -T 1 absorbs normal snapshot skew)")
|
||||||
|
p.add_argument("-q", "--quiet", action="store_true",
|
||||||
|
help="suppress trailing summary comments")
|
||||||
|
p.add_argument("-o", "--output", type=Path, default=None,
|
||||||
|
help="write to a file instead of stdout")
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str] | None = None) -> int:
|
||||||
|
args = build_parser().parse_args(argv)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if str(args.log) == "-":
|
||||||
|
data = parse_log(sys.stdin)
|
||||||
|
else:
|
||||||
|
# console captures are frequently not clean UTF-8
|
||||||
|
with args.log.open("r", encoding="utf-8", errors="replace") as fh:
|
||||||
|
data = parse_log(fh)
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"error: cannot read log: {exc}", file=sys.stderr)
|
||||||
|
return EXIT_USAGE
|
||||||
|
|
||||||
|
if not data.pairs:
|
||||||
|
print("error: no 'pbm=cdA,cdB' pair definition found in log",
|
||||||
|
file=sys.stderr)
|
||||||
|
return EXIT_USAGE
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args.output:
|
||||||
|
with args.output.open("w", encoding="utf-8", newline="\n") as fh:
|
||||||
|
return render(data, args, fh)
|
||||||
|
return render(data, args, sys.stdout)
|
||||||
|
except BrokenPipeError:
|
||||||
|
# downstream closed the pipe (e.g. "| head") - not an error
|
||||||
|
try:
|
||||||
|
sys.stdout.close()
|
||||||
|
except BrokenPipeError:
|
||||||
|
pass
|
||||||
|
return EXIT_OK
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"error: cannot write output: {exc}", file=sys.stderr)
|
||||||
|
return EXIT_USAGE
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=30'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=31'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=32'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=33'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=34'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=35'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=36'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=37'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=38'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=39'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=40'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=41'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=42'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=43'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=44'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=45'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=46'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=47'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=48'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=49'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=50'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=51'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=52'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=53'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=54'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=55'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=56'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=57'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=58'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=59'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=60'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=61'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=62'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=63'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=64'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=65'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=66'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=67'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=68'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=69'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=70'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=71'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=72'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=73'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=74'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=75'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=76'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=77'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=78'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=79'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=80'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=81'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=82'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=83'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=84'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=85'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=86'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=87'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=88'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=89'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=90'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=91'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=92'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=93'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=94'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=95'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=96'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=97'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=98'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=99'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=100'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=101'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=102'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=103'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=104'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=105'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=106'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=107'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=108'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=109'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=110'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=111'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=112'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=113'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=114'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=115'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=116'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=117'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=118'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=119'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=120'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=121'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=122'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=123'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=124'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=125'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=126'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=127'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=128'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=129'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=130'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=131'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=132'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=133'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=134'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=135'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=136'
|
||||||
|
bcmcmd -n 1 -c 'tx 100 length=512 VLantag=137'
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
bcmcmd -n 1 -c 'vlan remove 30 pbm=cd0,cd32'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 31 pbm=cd1,cd33'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 32 pbm=cd2,cd34'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 33 pbm=cd3,cd35'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 34 pbm=cd4,cd36'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 35 pbm=cd5,cd37'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 36 pbm=cd6,cd38'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 37 pbm=cd7,cd39'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 38 pbm=cd8,cd40'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 39 pbm=cd9,cd41'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 40 pbm=cd10,cd42'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 41 pbm=cd11,cd43'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 42 pbm=cd12,cd44'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 43 pbm=cd13,cd45'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 44 pbm=cd14,cd46'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 45 pbm=cd20,cd52'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 46 pbm=cd21,cd53'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 47 pbm=cd22,cd54'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 48 pbm=cd23,cd55'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 49 pbm=cd24,cd56'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 50 pbm=cd25,cd57'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 51 pbm=cd26,cd58'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 52 pbm=cd27,cd59'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 53 pbm=cd28,cd60'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 54 pbm=cd29,cd61'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 55 pbm=cd30,cd62'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 56 pbm=cd31,cd63'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 57 pbm=cd64,cd96'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 58 pbm=cd65,cd97'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 59 pbm=cd66,cd98'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 60 pbm=cd67,cd99'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 61 pbm=cd68,cd100'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 62 pbm=cd69,cd101'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 63 pbm=cd70,cd102'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 64 pbm=cd71,cd103'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 65 pbm=cd72,cd104'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 66 pbm=cd73,cd105'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 67 pbm=cd74,cd106'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 68 pbm=cd75,cd107'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 69 pbm=cd76,cd108'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 70 pbm=cd77,cd109'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 71 pbm=cd78,cd110'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 72 pbm=cd84,cd116'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 73 pbm=cd85,cd117'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 74 pbm=cd86,cd118'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 75 pbm=cd87,cd119'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 76 pbm=cd88,cd120'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 77 pbm=cd89,cd121'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 78 pbm=cd90,cd122'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 79 pbm=cd91,cd123'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 80 pbm=cd92,cd124'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 81 pbm=cd93,cd125'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 82 pbm=cd94,cd126'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 83 pbm=cd95,cd127'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 84 pbm=cd128,cd160'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 85 pbm=cd129,cd161'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 86 pbm=cd130,cd162'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 87 pbm=cd131,cd163'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 88 pbm=cd132,cd164'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 89 pbm=cd133,cd165'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 90 pbm=cd134,cd166'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 91 pbm=cd135,cd167'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 92 pbm=cd136,cd168'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 93 pbm=cd137,cd169'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 94 pbm=cd138,cd170'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 95 pbm=cd140,cd172'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 96 pbm=cd141,cd173'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 97 pbm=cd142,cd174'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 98 pbm=cd143,cd175'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 99 pbm=cd144,cd176'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 100 pbm=cd145,cd177'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 101 pbm=cd146,cd178'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 102 pbm=cd147,cd179'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 103 pbm=cd152,cd184'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 104 pbm=cd153,cd185'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 105 pbm=cd154,cd186'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 106 pbm=cd155,cd187'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 107 pbm=cd156,cd188'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 108 pbm=cd157,cd189'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 109 pbm=cd158,cd190'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 110 pbm=cd159,cd191'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 111 pbm=cd192,cd224'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 112 pbm=cd193,cd225'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 113 pbm=cd194,cd226'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 114 pbm=cd195,cd227'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 115 pbm=cd196,cd228'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 116 pbm=cd197,cd229'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 117 pbm=cd198,cd230'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 118 pbm=cd199,cd231'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 119 pbm=cd200,cd232'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 120 pbm=cd201,cd233'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 121 pbm=cd202,cd234'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 122 pbm=cd204,cd236'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 123 pbm=cd205,cd237'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 124 pbm=cd206,cd238'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 125 pbm=cd207,cd239'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 126 pbm=cd208,cd240'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 127 pbm=cd209,cd241'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 128 pbm=cd210,cd242'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 129 pbm=cd211,cd243'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 130 pbm=cd216,cd248'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 131 pbm=cd217,cd249'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 132 pbm=cd218,cd250'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 133 pbm=cd219,cd251'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 134 pbm=cd220,cd252'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 135 pbm=cd221,cd253'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 136 pbm=cd222,cd254'
|
||||||
|
bcmcmd -n 1 -c 'vlan remove 137 pbm=cd223,cd255'
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
bcmcmd -n 1 -c 'vlan remove 1 pbm=cd'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 30'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 30 pbm=cd0,cd32'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 31'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 31 pbm=cd1,cd33'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 32'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 32 pbm=cd2,cd34'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 33'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 33 pbm=cd3,cd35'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 34'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 34 pbm=cd4,cd36'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 35'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 35 pbm=cd5,cd37'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 36'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 36 pbm=cd6,cd38'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 37'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 37 pbm=cd7,cd39'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 38'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 38 pbm=cd8,cd40'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 39'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 39 pbm=cd9,cd41'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 40'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 40 pbm=cd10,cd42'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 41'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 41 pbm=cd11,cd43'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 42'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 42 pbm=cd12,cd44'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 43'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 43 pbm=cd13,cd45'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 44'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 44 pbm=cd14,cd46'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 45'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 45 pbm=cd20,cd52'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 46'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 46 pbm=cd21,cd53'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 47'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 47 pbm=cd22,cd54'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 48'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 48 pbm=cd23,cd55'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 49'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 49 pbm=cd24,cd56'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 50'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 50 pbm=cd25,cd57'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 51'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 51 pbm=cd26,cd58'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 52'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 52 pbm=cd27,cd59'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 53'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 53 pbm=cd28,cd60'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 54'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 54 pbm=cd29,cd61'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 55'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 55 pbm=cd30,cd62'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 56'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 56 pbm=cd31,cd63'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 57'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 57 pbm=cd64,cd96'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 58'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 58 pbm=cd65,cd97'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 59'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 59 pbm=cd66,cd98'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 60'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 60 pbm=cd67,cd99'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 61'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 61 pbm=cd68,cd100'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 62'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 62 pbm=cd69,cd101'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 63'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 63 pbm=cd70,cd102'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 64'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 64 pbm=cd71,cd103'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 65'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 65 pbm=cd72,cd104'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 66'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 66 pbm=cd73,cd105'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 67'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 67 pbm=cd74,cd106'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 68'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 68 pbm=cd75,cd107'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 69'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 69 pbm=cd76,cd108'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 70'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 70 pbm=cd77,cd109'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 71'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 71 pbm=cd78,cd110'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 72'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 72 pbm=cd84,cd116'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 73'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 73 pbm=cd85,cd117'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 74'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 74 pbm=cd86,cd118'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 75'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 75 pbm=cd87,cd119'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 76'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 76 pbm=cd88,cd120'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 77'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 77 pbm=cd89,cd121'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 78'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 78 pbm=cd90,cd122'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 79'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 79 pbm=cd91,cd123'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 80'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 80 pbm=cd92,cd124'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 81'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 81 pbm=cd93,cd125'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 82'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 82 pbm=cd94,cd126'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 83'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 83 pbm=cd95,cd127'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 84'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 84 pbm=cd128,cd160'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 85'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 85 pbm=cd129,cd161'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 86'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 86 pbm=cd130,cd162'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 87'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 87 pbm=cd131,cd163'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 88'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 88 pbm=cd132,cd164'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 89'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 89 pbm=cd133,cd165'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 90'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 90 pbm=cd134,cd166'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 91'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 91 pbm=cd135,cd167'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 92'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 92 pbm=cd136,cd168'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 93'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 93 pbm=cd137,cd169'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 94'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 94 pbm=cd138,cd170'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 95'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 95 pbm=cd140,cd172'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 96'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 96 pbm=cd141,cd173'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 97'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 97 pbm=cd142,cd174'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 98'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 98 pbm=cd143,cd175'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 99'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 99 pbm=cd144,cd176'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 100'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 100 pbm=cd145,cd177'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 101'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 101 pbm=cd146,cd178'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 102'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 102 pbm=cd147,cd179'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 103'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 103 pbm=cd152,cd184'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 104'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 104 pbm=cd153,cd185'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 105'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 105 pbm=cd154,cd186'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 106'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 106 pbm=cd155,cd187'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 107'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 107 pbm=cd156,cd188'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 108'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 108 pbm=cd157,cd189'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 109'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 109 pbm=cd158,cd190'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 110'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 110 pbm=cd159,cd191'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 111'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 111 pbm=cd192,cd224'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 112'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 112 pbm=cd193,cd225'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 113'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 113 pbm=cd194,cd226'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 114'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 114 pbm=cd195,cd227'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 115'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 115 pbm=cd196,cd228'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 116'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 116 pbm=cd197,cd229'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 117'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 117 pbm=cd198,cd230'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 118'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 118 pbm=cd199,cd231'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 119'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 119 pbm=cd200,cd232'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 120'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 120 pbm=cd201,cd233'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 121'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 121 pbm=cd202,cd234'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 122'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 122 pbm=cd204,cd236'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 123'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 123 pbm=cd205,cd237'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 124'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 124 pbm=cd206,cd238'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 125'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 125 pbm=cd207,cd239'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 126'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 126 pbm=cd208,cd240'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 127'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 127 pbm=cd209,cd241'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 128'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 128 pbm=cd210,cd242'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 129'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 129 pbm=cd211,cd243'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 130'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 130 pbm=cd216,cd248'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 131'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 131 pbm=cd217,cd249'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 132'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 132 pbm=cd218,cd250'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 133'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 133 pbm=cd219,cd251'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 134'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 134 pbm=cd220,cd252'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 135'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 135 pbm=cd221,cd253'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 136'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 136 pbm=cd222,cd254'
|
||||||
|
|
||||||
|
bcmcmd -n 1 -c 'vlan create 137'
|
||||||
|
bcmcmd -n 1 -c 'vlan add 137 pbm=cd223,cd255'
|
||||||
Reference in New Issue
Block a user