4. 链路协商基础

链路协商是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)信息。
FLP/NLP 脉冲序列结构对比 NLP (Normal Link Pulse) — 空闲状态心跳 NLP ~16ms NLP ~16ms NLP FLP (Fast Link Pulse) — 自协商能力交换 FLP Burst 包含 17~33 个脉冲,编码 Base 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会回退到并行检测模式:

  1. 检测阶段: 本地PHY在等待FLP超时后(典型100ms),开始检测对端发送的物理信号特征:
    • 检测到NLP脉冲 → 判定为10BASE-T
    • 检测到MLT-3编码的100M信号 → 判定为100BASE-TX
    • 检测到PAM5编码的1000M信号 → 判定为1000BASE-T
  2. 锁定模式: 根据检测到的信号类型,本地PHY强制设定为对应的速率和双工模式(通常为半双工)。
  3. 局限性: 并行检测只能确定速率,无法协商双工模式,因此结果总是半双工(除非对端也支持强制全双工配置)。
调试陷阱: 并行检测是导致“链路能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。
自协商优先级裁决流程 本地PHY能力集 1000M全双工 100M全双工 10M全双工 对端PHY能力集 100M全双工 100M半双工 10M全双工 FLP交换 能力交集 100M全双工, 10M全双工 最终模式:100M 全双工 (优先级最高)

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兼容性上。