4. 链路协商基础:自协商(Auto-Negotiation)原理、FLP/NLP脉冲、并行检测、优先级解析
链路协商是PHY芯片在物理连接建立后、数据通信开始前必须完成的握手过程。其核心目标是让链路两端的PHY自动确定双方都能支持的最高性能工作模式(速率+双工模式),无需人工干预。本章深入剖析自协商的底层机制、脉冲编码、冲突解决策略及Linux内核中的协商流程。
4.1 自协商(Auto-Negotiation)概述
自协商由IEEE 802.3u标准定义,最初用于100BASE-TX,后扩展到1000BASE-T及更高速度。其基本原理是:两端PHY通过交换包含各自能力信息的脉冲序列,在数百毫秒内完成模式匹配。
核心目标: 自动选择两端PHY共同支持的最高优先级工作模式(速率优先,同速率下全双工优先)。
| 特性 | 描述 |
|---|---|
| 标准依据 | IEEE 802.3u Clause 28 (100M) / Clause 40 (1000M) |
| 协商对象 | 速率(10M/100M/1000M)与双工模式(半双工/全双工) |
| 物理载体 | FLP (Fast Link Pulse) 或 NLP (Normal Link Pulse) |
| 协商时间 | 典型 50ms ~ 200ms,取决于链路质量和PHY实现 |
| 失败后果 | 链路无法UP,或降级到最低公共能力(如10M半双工) |
4.2 FLP/NLP脉冲:自协商的物理语言
自协商通过链路上的脉冲信号传递能力信息。根据链路状态不同,PHY发送两种脉冲序列:
- NLP (Normal Link Pulse):用于链路空闲状态下的“心跳”检测。PHY在无数据时每隔16ms±8ms发送一个NLP脉冲,向对端表明自己在线且支持自协商。
- FLP (Fast Link Pulse):自协商的核心载体。当PHY检测到对端存在并准备协商时,发送FLP突发(Burst)。每个FLP突发包含17~33个脉冲,编码为“时钟脉冲+数据脉冲”的交替序列。
关键区别: NLP是单脉冲,仅用于“存在性宣告”;FLP是脉冲串,携带完整的能力寄存器(Base Page + Next Page)信息。
4.3 Base Page 能力编码
FLP Burst 中携带的 Base Page 是一个16位寄存器,定义了PHY支持的能力。以1000BASE-T为例,Base Page格式如下:
| Bit 位置 | 字段名 | 含义 |
|---|---|---|
| 15 | S0 | 选择器字段(Selector Field),标识PHY类型(如以太网=00001) |
| 14 | S1 | 选择器字段高位 |
| 13 | S2 | 选择器字段高位 |
| 12 | S3 | 选择器字段高位 |
| 11 | S4 | 选择器字段高位 |
| 10 | A0 | 10BASE-T 半双工 |
| 9 | A1 | 10BASE-T 全双工 |
| 8 | A2 | 100BASE-TX 半双工 |
| 7 | A3 | 100BASE-TX 全双工 |
| 6 | A4 | 100BASE-T4 (已废弃) |
| 5 | A5 | PAUSE (流控) |
| 4 | A6 | 非对称PAUSE |
| 3 | A7 | 保留 |
| 2 | A8 | 保留 |
| 1 | A9 | 保留 |
| 0 | A10 | 保留 |
注意: 1000BASE-T 使用额外的 Next Page 交换来传递千兆能力(如 1000BASE-T 半双工/全双工)。Base Page 的 A0~A10 仅覆盖 10M/100M 能力。
4.4 并行检测(Parallel Detection)
当链路对端PHY不支持自协商(例如老旧的10BASE-T设备只发送NLP,不发送FLP)时,自协商机制无法完成。此时PHY会回退到并行检测模式:
- 检测阶段: 本地PHY在等待FLP超时后(典型100ms),开始检测对端发送的物理信号特征:
- 检测到NLP脉冲 → 判定为10BASE-T
- 检测到MLT-3编码的100M信号 → 判定为100BASE-TX
- 检测到PAM5编码的1000M信号 → 判定为1000BASE-T
- 锁定模式: 根据检测到的信号类型,本地PHY强制设定为对应的速率和双工模式(通常为半双工)。
- 局限性: 并行检测只能确定速率,无法协商双工模式,因此结果总是半双工(除非对端也支持强制全双工配置)。
调试陷阱: 并行检测是导致“链路能UP但速度只有10M”或“协商为半双工”的常见原因。在Linux内核中,可以通过
ethtool eth0 查看 Auto-negotiation: off 或 Link partner advertised: 10baseT/Half 来识别。
4.5 优先级解析:如何选择最终工作模式
自协商完成后,两端PHY通过交换Base Page(和可选的Next Page)获得对端的能力集。最终工作模式的选择遵循严格的优先级表:
| 优先级 | 工作模式 | 速率 | 双工 |
|---|---|---|---|
| 1 (最高) | 1000BASE-T 全双工 | 1000M | 全双工 |
| 2 | 1000BASE-T 半双工 | 1000M | 半双工 |
| 3 | 100BASE-TX 全双工 | 100M | 全双工 |
| 4 | 100BASE-TX 半双工 | 100M | 半双工 |
| 5 | 10BASE-T 全双工 | 10M | 全双工 |
| 6 (最低) | 10BASE-T 半双工 | 10M | 半双工 |
选择算法:
- 两端PHY各自将本地能力集与对端能力集取交集。
- 在交集中选择优先级最高的模式(即上表中序号最小的)。
- 如果交集为空(例如一端只支持100M全双工,另一端只支持10M半双工),则协商失败,链路无法UP。
4.6 Linux内核中的自协商实现
在Linux内核中,自协商流程由PHY驱动框架(drivers/net/phy/phy.c)和具体PHY芯片驱动共同完成。关键函数调用链如下:
// 用户空间触发自协商
ethtool -s eth0 autoneg on
// 内核调用路径
phy_ethtool_set_settings()
-> phy_start_aneg() // 启动自协商
-> genphy_config_aneg() // 通用自协商配置
-> genphy_setup_forced() // 如果关闭自协商,强制设置
-> genphy_restart_aneg() // 发送FLP重启协商
-> phy_write(phydev, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART)
// 中断或轮询方式检测协商完成
phy_interrupt() / phy_state_machine()
-> phy_aneg_done() // 检查自协商是否完成
-> phy_read(phydev, MII_BMSR) & BMSR_ANEGCOMPLETE
-> genphy_read_status() // 读取协商结果
-> phy_read(phydev, MII_LPA) // 读取对端能力
-> phy_resolve_aneg_linkmode() // 优先级解析
-> linkmode_and() // 取能力交集
-> phy_resolve_aneg_pause() // 流控协商
调试关键点: 在
genphy_read_status() 中,内核通过读取 MII_LPA (Link Partner Ability) 寄存器获取对端能力,然后调用 phy_resolve_aneg_linkmode() 执行优先级解析。如果解析结果为空,链路状态会被设置为 PHY_NOLINK。
4.7 常见自协商失败场景与调试方法
| 现象 | 可能原因 | 调试命令/方法 |
|---|---|---|
| 链路无法UP | 对端不支持自协商且并行检测失败;线缆故障 | ethtool eth0 查看 Link detected: no;检查PHY寄存器 MII_BMSR |
| 协商到10M半双工 | 并行检测生效,对端只发送NLP | ethtool eth0 查看 Auto-negotiation: off;强制设置速率 |
| 协商结果不稳定 | 链路质量差,FLP脉冲丢失;PHY电源噪声 | 抓取PHY中断;cat /proc/net/dev 查看错误计数 |
| 千兆协商失败 | 对端不支持千兆;Next Page交换异常 | ethtool eth0 查看 Advertised link modes 是否包含1000baseT |
实用技巧: 在调试自协商问题时,可以使用
ethtool -s eth0 autoneg off speed 100 duplex full 强制设置工作模式,以排除自协商逻辑本身的故障。如果强制模式能正常工作,则问题大概率出在自协商流程或对端PHY兼容性上。