4. 端口与PHY管理

在 Broadcom 交换芯片的软件栈中,端口(Port)与 PHY 是连接 MAC 层逻辑与物理介质的关键环节。SDK 通过统一的 Port 抽象管理芯片内部 MAC、SerDes、外部 PHY 以及光模块,向上为 NOS 提供端口属性配置、链路状态查询、自协商控制、PHY 寄存器访问和热插拔事件处理能力。理解这一层的对象模型与调用路径,是实现端口 UP/DOWN 控制和状态查询的基础。

端口对象模型与属性

在 SDK 中,每个物理端口由 bcm_port_t 标识,逻辑端口组由 bcm_trunk_t 或 bcm_port_group_t 管理。端口属性通过 bcm_port_control_set() 和 bcm_port_control_get() 读写,常见属性包括:

  • BCM_PORT_CONTROL_ENABLE:端口使能,决定 MAC 是否收发。
  • BCM_PORT_CONTROL_SPEED:端口速率,如 1G、10G、25G、100G。
  • BCM_PORT_CONTROL_AUTONEG:自协商使能,影响链路建立方式。
  • BCM_PORT_CONTROL_DUPLEX:全双工/半双工。
  • BCM_PORT_CONTROL_ENCAP:封装模式,如 IEEE、HG、SGMII。
  • BCM_PORT_CONTROL_PHY_MASTER:主从模式,用于 SGMII/1000BASE-X。

端口状态通过 bcm_port_info_get() 获取,返回 bcm_port_info_t 结构,其中 linkstatus、speed、duplex、autoneg、phy_link 等字段反映当前链路实际情况。NOS 通常周期性轮询或通过中断方式获取这些状态,并同步到内核网络设备状态。

链路状态与自协商

链路状态(Link Status)表示端口是否与对端成功建立物理连接。对于电口,链路建立依赖自协商(Auto-Negotiation)完成速率、双工和流控能力交换;对于光口,通常通过 SerDes 的 CDR 锁定和信号检测判断链路。SDK 提供 bcm_port_link_status_get() 直接查询链路,也可通过 bcm_port_info_get() 读取完整信息。

自协商配置需要区分 MAC 侧和 PHY 侧。以 1000BASE-T 电口为例,典型配置流程如下:

/* 使能自协商 */
bcm_port_control_set(unit, port, bcmPortControlAutoneg, 1);

/* 设置自协商能力:1000M 全双工 + 100M 全双工 */
bcm_port_autoneg_set(unit, port,
    BCM_PORT_ABILITY_1000MB_FD |
    BCM_PORT_ABILITY_100MB_FD  |
    BCM_PORT_ABILITY_10MB_FD);

/* 查询协商结果 */
bcm_port_info_t info;
bcm_port_info_get(unit, port, &info);
printf("link=%d speed=%d duplex=%d\n",
       info.linkstatus, info.speed, info.duplex);

若对端为强制模式,本端自协商可能失败或降速。此时应检查 info.autoneg 与 info.speed 是否与预期一致,必要时改为强制速率并关闭自协商。

PHY 寄存器访问

外部 PHY 通过 MDIO/MDC 总线与 MAC 连接,SDK 提供 bcm_port_phy_reg_get() 和 bcm_port_phy_reg_set() 访问 PHY 寄存器。标准寄存器包括:

寄存器地址作用
BMCR0x00基本控制:复位、自协商、速率、双工
BMSR0x01基本状态:链路、自协商完成、能力
PHYID1/20x02/0x03PHY 厂商与型号标识
ANAR0x04自协商通告能力
ANLPAR0x05对端自协商能力

访问示例:读取 BMSR 判断链路是否建立:

uint16_t bmsr;
bcm_port_phy_reg_get(unit, port, 0x01, &bmsr);
if (bmsr & 0x0004) {
    /* Link up */
}

对于扩展寄存器(如 Broadcom PHY 的 MII 扩展页),需先写寄存器 0x1E 切换页,再访问目标地址。SDK 的 bcm_port_phy_reg_get() 已封装页切换逻辑,直接传入扩展地址即可。

热插拔处理

光模块热插拔通过 SFP/SFP+ 的 MOD_ABS 引脚或 I2C 中断上报。SDK 提供 bcm_port_module_event_register() 注册回调,当模块插入或拔出时触发事件。典型处理流程:

  1. 检测到 MOD_ABS 变化,读取模块 EEPROM 识别类型(SFP/SFP+/QSFP)。
  2. 根据模块类型配置 SerDes 模式与速率。
  3. 使能端口,启动链路训练或自协商。
  4. 轮询链路状态,更新 NOS 端口状态。

热插拔事件处理必须考虑去抖,通常延时 100~200ms 再读取模块状态,避免误判。拔出时应先关闭端口发送,再清理资源。

端口 UP/DOWN 与状态查询

端口 UP/DOWN 控制通过 bcm_port_control_set(unit, port, bcmPortControlEnable, 0/1) 实现。关闭端口时,MAC 停止收发,但 PHY 可能仍保持链路。若需完全断电,可调用 bcm_port_phy_power_set()。

状态查询建议组合使用:

  • bcm_port_info_get():获取链路、速率、双工、自协商状态。
  • bcm_port_link_status_get():快速判断链路 UP/DOWN。
  • bcm_port_phy_reg_get():读取 BMSR 确认 PHY 侧链路。
  • bcm_port_module_event_register():异步获取热插拔事件。
在 NOS 中,端口状态通常由 SDK 轮询线程每 1 秒更新一次,并通过 netlink 通知内核。若链路抖动频繁,应检查自协商配置和线缆质量,必要时启用链路去抖计数。

端口管理状态流转

下图展示端口从初始化到 UP/DOWN 及热插拔事件的状态流转关系,以及 SDK 各接口在其中的作用位置。

端口初始化 bcm_port_init 属性配置 speed / autoneg / encap 端口使能 bcmPortControlEnable=1 链路建立 Link Up 状态查询与监控 bcm_port_info_get / link_status_get / phy_reg_get 自协商配置 bcm_port_autoneg_set PHY 寄存器访问 phy_reg_get / set (MDIO) 热插拔事件 module_event_register 端口 DOWN bcmPortControlEnable=0 / 模块拔出 重新使能 / 模块插入 回到链路建立 配置流 PHY访问 热插拔 恢复路径

实际调试中,建议先通过 bcm_port_info_get() 确认端口基础状态,再结合 PHY 寄存器读取判断物理层问题。若链路无法 UP,依次检查:端口是否使能、自协商能力是否匹配、SerDes 是否锁定、模块是否兼容、线缆或光模块是否正常。通过分层排查,可以快速定位是 MAC 配置问题、PHY 协商问题还是物理介质问题。