4. 自协商工作流程:从复位到建链的完整握手

自协商(Auto-Negotiation,AN),说白了就是两端设备在连上之后,先互相打个招呼,确认彼此的能力,然后挑一个双方都支持的最佳模式来跑数据。这个过程如果出问题,链路能 up 起来算你运气好,更常见的是链路反复抖动,或者速率、双工模式不匹配,直接导致吞吐惨不忍睹。

我调试过不少自协商失败的案例,发现很多工程师把这步当成“插上线就能用”的黑盒。其实拆开看,每一步都有坑。今天我们就从头到尾捋一遍 AN 的标准握手流程。

4.1 自协商的核心目的

为什么要先做自协商?说白了就两件事:

  • 能力宣告:告诉对端我能跑多快、全双工还是半双工、支不支持流控。
  • 模式匹配:双方选一个共同支持的最高优先级组合。优先级规则通常是:速度优先,同速下全双工优先。

举个例子,一边支持 1000BASE-T 全双工,另一边只支持 100BASE-TX 半双工,AN 的结果就是双方都退到 100M 半双工。嗯,这其实是个灾难场景——我遇到过交换机和摄像头之间因为 AN 协商出半双工,丢包率直接飙到 20%。

4.2 标准流程分解(IEEE 802.3 Clause 28)

IEEE 802.3 把自协商流程定义为几个关键步骤。我一般把它拆成 7 个阶段,方便定位问题:

阶段 动作 时间窗口 常见异常
1. 链路复位 物理层复位,进入自协商状态 ~10ms 复位不完全,死锁
2. 能力检测 发送 FLP 脉冲,侦听对端 FLP ~50~150ms FLP 信号幅度不足,误判为无链接
3. 交换基本能力 Base Page 交互(速率/双工) ~16ms/页 页面校验失败,反复重传
4. 交换下一页 Next Page 交互(EEE、流控等扩展能力) ~16ms/页 EEE 页面超时,不兼容导致协商中断
5. 确认(ACK) 双方确认收到的能力集 ~16ms ACK 丢失,进入 IDLE_DETECT 死循环
6. 协商匹配 根据优先级确定最终工作模式 ~0ms(逻辑运算) 优先级表格冲突,芯片 bug
7. 建立链接 切换 PHY 状态机,进入正常数据模式 ~0~50ms EEE 唤醒时序未完成,链路闪断

这 7 步走完,正常情况应该不到 200ms。但如果在某个阶段卡住,比如第 3 步不断重传 Base Page,或者第 5 步 ACK 收不到,你可能就会看到端口状态一直“Auto-Negotiation in progress”。

调试经验:我在现场最常做的事是检查 MAC 和 PHY 之间的 MDIO 寄存器。很多 PHY 芯片提供了自协商状态寄存器(例如 Marvell 的 0x01 寄存器 bit 5~3),能直接读出“协商完成”、“能力检测中”、“链路 up/down”等状态,配合逻辑分析仪抓 MDC/MDIO 总线,定位效果非常好。

4.3 FLP 脉冲细节

自协商的物理层基础是 FLP(Fast Link Pulse)。它和传统 10BASE-T 的 NLP(Normal Link Pulse)兼容,但改造为脉冲簇来传递数据。

  • 脉冲时序:每 62.5µs ± 4µs 发送一个脉冲,17 个脉冲为一组,其中 16 个数据位加 1 个时钟位。
  • 数据编码:脉冲位置代表 bit 值:按时发表示 0,提前发表示 1。
  • Base Page 结构:16 位;D0-D4 是选择码(速率/双工),D5-D12 是技术能力(如 1000BASE-T 支持),D13-D15 是下一页和 ACK 标志。

你想想看,这么精细的时序,任何一个环节出偏差都可能导致协商失败。我曾经排查过一个案例,一根 50 米长的劣质网线让 FLP 脉冲幅值衰减到 600mV 以下,PHY 接收端无法稳定识别脉冲位置,结果就是两端反复进入“能力检测”阶段,协商永远完不成。

// 伪代码:Base Page 解析示意
// 寄存器 0x04(Auto-Negotiation Advertisement Register)
// bit 0-4: Selector Field (00001 = IEEE 802.3)
// bit 5: 10BASE-T
// bit 6: 10BASE-T Full Duplex
// bit 7: 100BASE-TX
// bit 8: 100BASE-TX Full Duplex
// bit 9: 100BASE-T4
// bit 15: Next Page 请求

uint16_t advertise = read_phy_reg(0x04);
if (advertise & (1 << 8)) {
    // 对端宣告支持 100BASE-TX 全双工
    candidate_mode = "100BASE-TX Full Duplex";
}

4.4 下一页(Next Page)扩展与 EEE

Base Page 只有 16 位,很多扩展能力(比如 EEE、多千兆速度)装不下。于是 IEEE 引入了 Next Page 机制。流程是这样:

  1. Base Page 的 D15(NP)位置 1,表示“我还要继续发下一页”。
  2. 后续页面按序发送,每次 16 位,同样携带 ACK 机制。
  3. 双方都收到对方的所有 Next Page,直到 NP=0 结束。

EEE(Energy-Efficient Ethernet)的宣告就在 Next Page 里。具体来说:

  • EEE 的能力位定义在 Clause 45 的寄存器中(例如 10GBASE-T EEE 能力位在寄存器 7.60)。
  • 在自协商的 Next Page 阶段,双方通过特定页面的 code 字段交换 EEE 支持情况。
  • 如果其中一方不支持 EEE,最终协商结果会关掉 EEE 功能。
避坑指南:我遇到过一种半兼容的情况——A 端宣称支持 EEE,B 端也宣称支持,但两端的 EEE 唤醒时序(Tw_phy 参数)不匹配。结果链路建起来后,EEE 进入低功耗模式后无法正常唤醒,导致周期性的超时丢包。如果你怀疑是 EEE 导致的吞吐波动,建议直接关掉 EEE 对比测试。

4.5 协商过程中的状态机

IEEE 802.3 Clause 28 把自协商状态机定义得非常清楚。下面这张状态迁移图总结了我上面讲的所有关键节点:

自协商状态迁移流程图 自协商状态迁移流程图 1. 链路复位 2. 能力检测 3. 交换下一页 4. 确认ACK 5. 协商匹配 6. 建立链接 无法协商 说明: 主流程为实线箭头,异常/重传路径为虚线箭头。确认阶段(节点4)若ACK超时,会回退到交换下一页重发。 无法协商时,链路保持 down 状态,PHY 可能周期性地重新发起能力检测。

4.6 协商完成后——链路完整性的最终验证

当状态机跑到“建立链接”之后,芯片会开启正常的链路完整性检测(Link Integrity Test)。对 1000BASE-T 来说,还得先完成 PMA 的训练(Training),这是个更深度的链路信道校准过程。

一个常见的理解误区是:自协商完成 = 链路 100% 能跑业务。其实不然。AN 只解决了能力匹配,但物理信道的均衡器、回声消除参数还需要 PMA 训练来调整。如果训练失败,即使 AN 显示“协商成功”,链路仍然不会有数据流。

关键点:调试自协商问题时,先确认 Base Page 和 Next Page 交换是否完成(读 PHY 的 AN 状态寄存器),再检查 Link Status(寄存器 0x01 bit 2)。如果 Link Status 是 up 但业务不通,99% 的问题出在 PMA 训练阶段或 EEE 唤醒异常。

回顾一下整体流程:复位 → 发 FLP 探听 → 换 Base Page → 换 Next Page → ACK → 匹配 → 建链。每一步都有对应的寄存器和超时计数器可以查看。我个人的习惯是先把两个端口的 AN 能力寄存器(0x04 和 0x05)dump 出来,确认两边宣告的能力一致,再从上位机看协商结果。如果发现两边宣告不同,比如一边宣告了 EEE 但对端没宣告,那就老老实实关掉 EEE 功能,不要指望它们能“自动兼容”。