4. Broadcom SDK与遥测API
在 Broadcom 交换平台上做遥测与健康诊断,绕不开一个问题:数据从哪里来。芯片内部的计数器、寄存器、事件状态并不会自动变成可用的指标,必须通过一层软件接口把它们“取出来”。Broadcom 生态里这套接口并不是单一的,而是由多个层次、多种风格的 API 和工具共同组成。理解它们各自的位置和适用场景,是后续所有采集与诊断工作的前提。
四类接口的分层关系
从最贴近芯片到最贴近运维,可以分成四层。最底层是 BCM SDK,它是 Broadcom 官方的 C 语言开发库,直接封装了对芯片寄存器、内存表、计数器和中断的访问。所有上层接口最终都落到 SDK 的函数调用上。往上一层是 OpenNSL,它把 BCM SDK 中一部分常用能力抽象成更简洁的开源 API,主要面向白盒交换机场景,屏蔽了部分芯片型号差异。再往上是 SAI(Switch Abstraction Interface),这是 ONIE/SAI 生态定义的统一抽象层,用标准化的对象模型(端口、队列、ACL、计数器)描述交换行为,由各厂商提供 SAI 实现,Broadcom 的 SAI 实现内部再调用 SDK。最上层是运维工具,包括 Diag Shell 和 bcmcmd,它们提供交互式命令行,适合现场排查和一次性读取。
这四层不是替代关系,而是互补关系。做批量遥测采集,通常走 SAI 或 SDK 的编程接口;做现场故障定位,往往直接进 Diag Shell 敲命令。下面这张图展示了从芯片到运维工具的数据通路与调用关系。
寄存器读写与计数器读取
寄存器读写是最底层的访问方式。BCM SDK 提供 bcm_reg_read() 和 bcm_reg_write(),参数是寄存器地址和值。寄存器地址通常来自芯片数据手册或 SDK 头文件中的宏定义。例如读取端口 MAC 层的某个状态寄存器,需要先知道该寄存器的偏移量,再调用读取函数。寄存器读写的价值在于可以访问那些没有被封装成标准计数器的内部状态位,比如链路训练状态、SerDes 均衡器系数、温度传感器原始值。
计数器读取则更常用。SDK 中典型接口是 bcm_port_stat_get(),传入单元号、端口号和统计项枚举,返回 64 位计数值。统计项包括 snmpIfInOctets、snmpIfOutUcastPkts、snmpIfInErrors、snmpIfOutDiscards 等。SAI 层对应的是 sai_get_port_stats(),通过属性 ID 数组一次性取多个计数器,减少调用次数。实际采集时要注意:计数器是累积值,遥测系统需要做差分计算速率;同时要处理计数器回绕,64 位计数器在高速端口上回绕周期可能只有几十分钟。
// BCM SDK 读取端口入方向字节数示例
uint64_t val = 0;
int unit = 0;
bcm_port_t port = 1;
bcm_port_stat_get(unit, port, snmpIfInOctets, &val);
printf("port %d in_octets = %llu\n", port, (unsigned long long)val);
// SAI 批量读取端口统计
sai_stat_id_t ids[] = { SAI_PORT_STAT_IF_IN_OCTETS,
SAI_PORT_STAT_IF_IN_ERRORS,
SAI_PORT_STAT_IF_OUT_DISCARDS };
uint64_t values[3];
sai_get_port_stats(port_id, 3, ids, values);
Diag Shell 与 bcmcmd 的实操差异
Diag Shell 是进入芯片诊断模式的交互式环境,通常通过 diag 命令或串口进入。它支持大量以 diag 开头的命令,例如 diag port stat 查看端口统计,diag reg read 读寄存器,diag counter 查看计数器。Diag Shell 的优势是命令丰富、可以逐层深入,适合现场排查链路不通、计数器异常、寄存器状态不对等问题。缺点是输出格式面向人阅读,不适合程序解析。
bcmcmd 则是“一条命令一次执行”的模式,典型用法是 bcmcmd "port stat 1" 或 bcmcmd "reg read 0x1234"。它可以直接在 Linux shell 里调用,输出可以重定向到文件,适合写进脚本做批量采集或定时巡检。两者的命令语法有重叠但不完全一致,Diag Shell 里能用的命令不一定在 bcmcmd 里可用,反之亦然。工程上常见的做法是:日常遥测走 SAI/SDK 编程接口,现场应急用 Diag Shell,自动化巡检用 bcmcmd 脚本。
事件通知机制
前面讲的都是“主动去读”,而事件通知是“芯片主动告诉你”。BCM SDK 提供 bcm_switch_event_register() 注册事件回调,当芯片检测到链路状态变化、端口 up/down、温度越限、包丢弃异常等事件时,SDK 会触发回调函数。SAI 层对应的是 sai_switch_event_notification 机制,通过 sai_switch_api_t 中的事件通知回调上报。
事件通知的价值在于实时性。如果只靠轮询,链路闪断可能在两次采集之间被漏掉;而事件回调可以在毫秒级捕获状态变化。实际部署时,通常把事件回调与计数器轮询结合:事件负责捕捉“发生了什么”,计数器负责量化“发生了多少”。需要注意的是,事件回调运行在 SDK 的线程上下文里,回调函数里不能做耗时操作,应该只做标记或投递到队列,由后台线程处理。
接口选择与典型场景对照
| 场景 | 推荐接口 | 关键调用/命令 | 注意事项 |
|---|---|---|---|
| 周期性端口计数器采集 | SAI 或 BCM SDK | sai_get_port_stats / bcm_port_stat_get | 做差分算速率,处理 64 位回绕 |
| 读取芯片内部温度原始值 | BCM SDK 寄存器读写 | bcm_reg_read | 需查数据手册确认地址和换算公式 |
| 现场排查链路不通 | Diag Shell | diag port stat / diag reg read | 输出面向人,不适合程序解析 |
| 定时巡检脚本 | bcmcmd | bcmcmd "port stat 1" | 命令语法与 Diag Shell 不完全一致 |
| 链路闪断实时捕获 | 事件通知 | bcm_switch_event_register | 回调中不做耗时操作,投递队列处理 |
把这套接口体系理清楚之后,后续的遥测采集设计就有了明确的落点:数据源在哪一层、用什么方式取、取到的值如何解释,都能对应到具体的 API 或命令上。这也是做健康诊断时判断“指标异常是芯片真实状态还是采集方式问题”的基础。