首页 / 资讯中心 / 文章详情

以太网标准802.3解析:分层编码、FEC与链路排查

以太网标准802.3解析:分层编码、FEC与链路排查 ★ FEATURED ARTICLE
简介IEEE 802.3-2022《以太网标准》正式版面向网络工程师、协议与芯片开发者、PHY及测试认证人员提供从1 Mb/s到400 Gb/s以太网MAC、MII、PHY与管理信息库的权威规范依据可用于接口设计、合规验证和协议排错。相较2018版文档扩充至约7025页重点增补25G至100G相关条款并修订10G内容同时整合此前多项修订。资源包为1个PDF文件大小93.79MB单文件体量较大但章节体系完整便于按速率、子层或关键词检索。当前已有287人学习适合需要查阅正式标准原文、核对寄存器与电气规范或撰写测试方案的读者。需注意2022版之后的802.3df-2024、802.3ck-2022等修订未纳入涉及400/800Gb/s及100/200/400Gb/s新增内容时应另行对照。1. 7025 页不是冗余以太网标准为什么必须这么厚打开 802.3-2022 这份以太网标准第一反应多半是文件坏了7025 页。比 2018 版多出来的一千四百多页绝大部分在讲 25G 到 100G 这一段链路怎么把比特稳稳送出去。反直觉的地方在于以太网标准的膨胀不是因为技术越堆越多而是因为它几乎不删东西——上世纪的 CSMA/CD 还躺在文档里当着半双工的最后一道兼容底线8b/10b 编码也还在只是退到了 1G 和更老速率的角落里。搞懂这份文档的价值就在这儿它把“为什么这么设计”的账全记在条款编号、状态机和参数表里而不是散落在各种二手的“经验帖”里。读懂它你排查链路不通的时候就不再靠玄学。2. 分层不是画着好看MAC 与 MII 之间为什么要插一个 RS以太网的分层图谁都见过MAC、RS、MII、PCS、PMA、PMD、MDI。但多数人对 RSReconciliation Sublayer协调子层的印象就是一个“过渡方块”画在那占位置。实际上这层是整个设计里最省事的一笔投资——它把“帧”这种逻辑概念和“引脚上的电平”这种物理事实彻底隔开了。2.1 RS 到底做了什么从服务原语到引脚电平的翻译MAC 子层是纯逻辑它只认字节流和状态位这帧有效、那帧错、现在可以发。它不知道对面是同轴、双绞线还是光纤也不知道速率是多少。RS 的存在就是把这套内部语言翻译成 MII 上的信号组发送时给出 TX_EN 和 TXD接收时把 RXD、RX_DV、RX_ER 收进来同时把 PHY 报上来的载波监听、冲突检测映射回 MAC 需要的状态。这意味着同一套 MAC 逻辑接 10M 的 PHY 和接 400G 的 PHY上层代码几乎不用改换掉的只是 RS 与 MII 之间的适配。常见的实现思路是把前导码和 SFD 的生成放在 RS 一侧、由 MAC 提供帧内容也有些实现把它们算作 MAC 的一部分。两种划分在标准里都能找到对应描述真正重要的是那条边界前导码参与物理同步但不参与 FCS 校验。PREAMBLE b\x55 * 7 # 7 字节作用是让接收端 CDR 锁定、AGC 收敛 SFD b\xd5 # 帧起始定界符最后一个字节用 0xD5 而不是 0x55 def to_wire(payload: bytes, ifg_bits: int 96): frame payload # 已含 DA / SA / Type # 1. 最小帧长 64 字节不含前导码载荷不足就补零补的是载荷不是前导码 if len(frame) 60: frame b\x00 * (60 - len(frame)) # 2. FCS 覆盖 DA 到载荷末尾不含前导码和 SFD字节内比特是 LSB 先发 fcs crc32(frame) frame fcs.to_bytes(4, little) # 低字节先上线这点最容易写错 # 3. RS 把前导码和 SFD 贴在帧头交给 MIIPHY 全程不改内容 return PREAMBLE SFD frame, ifg_bits这段代码里有三个参数值得记住因为它们在排查现场会反复出现。60是不含 FCS 的最小载荷加头部长度加上 4 字节 FCS 正好 64 字节——短于此的帧会被 PHY 或交换芯片直接丢弃抓包工具里表现为“runt”。crc32的输出必须按小端序写入因为以太网规定每个字节内部低位先发这个比特序问题在自制抓包工具或 FPGA 实现里翻车率极高。ifg_bits 96是帧间隔也就是 12 个字节时间留给接收端做时钟恢复和缓冲半双工下还兼作别的站点的退避窗口。2.2 MII 的每一次重造为什么速率一提接口就得换MII 是 MAC 和 PHY 之间的契约。契约的内容很简单并行数据总线、时钟、几个控制信号。问题是速率一上去这套并行总线就没法用了——要么把时钟拉到几百兆要么把位宽摊到几十位两条路在 PCB 上都走不通。于是标准选择了第三条路逻辑上保持一个 MII物理上换成串行加编码或者拆成多条 lane。接口位宽时钟承载速率典型场景MII4 bit25 MHz100 Mb/s快速以太网GMII8 bit125 MHz1 Gb/s千兆铜缆/光纤RGMII4 bit DDR125 MHz1 Gb/s交换芯片省引脚SGMII1 对差分1.25 Gb/s1 Gb/s光模块、板间XGMII32 bit DDR156.25 MHz10 Gb/s10G 早期实现CGMII64 bit多 lane100 Gb/s100G 背板SGMII 是这张表里最能说明设计动机的一行它把 8 位并行总线换成一对 1.25 Gb/s 差分线用 8b/10b 编码把 1 Gb/s 的有效载荷塞进去。代价是 20% 的编码开销换来的是管脚数量和布线难度大幅下降。这种“拿带宽换工程可行性”的取舍在后面每一代速率上都会重演一次。管理接口同理。早期的 MDIO 用 5 位寄存器地址一共 32 个寄存器够用了。到 10G 之后PCS、PMA、PMD 各自都有几十个寄存器和一堆误码统计计数器32 个地址根本不够分于是有了间接寻址的管理接口先写设备地址再写寄存器地址最后读写数据。你在一台设备上读误码计数背后走的往往是这一串间接访问。2.3 半双工为什么还留着CSMA/CD 与 PLCA 的接力CSMA/CD 的核心不是“监听”而是那个冲突窗口。发送站在发出第一个比特后的一个往返时间内必须能检测到冲突否则它已经把帧发完了重传就没有意义。这个窗口叫时隙时间10 Mb/s 下是 512 比特时间也就是 51.2 微秒换算成同轴电缆的传播速度就倒推出约 2500 米的网络直径上限。整条链路的物理尺寸是被 MAC 层的一个计时器定死的。到了千兆同样的 512 比特时间只剩 0.512 微秒物理上根本铺不开所以千兆半双工基本只存在于纸面。真正有意思的是后来的分支面向车载和工业的多点总线上标准没有沿用 CSMA/CD而是引入了 PLCA——用一个协调节点周期性发 beacon各站按节点 ID 轮流获得发送机会。冲突从“随机发生再退避”变成“结构上不会发生”代价是需要一个协调者、需要维护轮转周期链路里多了一个必须活着的角色。3. 64b/66b 与 PCS编码开销从 25% 降到 3% 的代价物理编码子层是整份标准里条款最密集的地方也是最容易被跳过的地方。跳过它的后果是你能算出线速但算不对有效吞吐你能看到链路 up但不知道为什么误码计数在涨。3.1 8b/10b 的 25% 税和 64b/66b 怎么把它压到 3.125%8b/10b 的逻辑很优雅每 8 位数据映射成 10 位码组保证任意码流里 0 和 1 的数量大致平衡直流平衡并且连续相同比特不超过 5 个游程受限。这两个性质正好喂饱接收端的时钟恢复电路和 AC 耦合电容。代价是每传 8 位要发 10 位25% 的带宽就这么交出去了。10G 开始这笔税交不起了。64b/66b 的思路完全反过来不再靠编码表保证游程而是给每 64 位数据加一个 2 位同步头01表示这 64 位全是数据10表示里面混了控制字符00和11是非法组合用来判错。剩下的比特平衡问题交给扰码器用的生成多项式是 1 x^39 x^58把数据打散成近似随机的序列长连 0 和长连 1 的概率被压到可接受范围。SYNC_DATA, SYNC_CTRL, SYNC_BAD 0b01, 0b10, 0b00 def encode_block(payload64: int, is_control: bool, scrambler_state: int) - int: # 1. 先扰码只有 64 位载荷参与同步头不扰码否则接收端无法识别边界 scrambled scrambler(payload64, scrambler_state) # 2. 同步头是唯一的定界信息接收端靠它做块同步靠它区分数据块与控制块 sync SYNC_CTRL if is_control else SYNC_DATA return (sync 64) | scrambled # 控制块里的类型字段决定语义0x1EIDLE0x78START0xFEERROR CTRL_IDLE, CTRL_START, CTRL_ERROR 0x1E, 0x78, 0xFE代码里最关键的一行是注释“同步头不扰码”。这是块同步能工作的前提接收端先扫描 66 位窗口看这 2 位是不是合法的01或10合法才认为对齐。如果同步头也被扰码边界信息就没了接收端只能靠猜测。开销从 25% 降到 3.125%账面上很划算代价是接收端多了一整套状态机块同步、扰码器同步、控制字符解析。而且因为不再有编码表兜底一旦同步丢失恢复过程比 8b/10b 慢得多。3.2 块同步与对齐标记接收端怎么知道自己对齐了块同步的逻辑在标准里写成状态机核心是两个计数器。接收端连续收到 64 个合法的同步头才认为锁定锁定之后如果连续若干个块同步头非法就判定失锁向下滑动一个比特重新找边界。这个“64 个”不是随便定的太少会被随机数据里的伪同步头骗过去太多则恢复时间过长。多 lane 场景更麻烦。100G 走 4 条 25G lane每条 lane 有自己的延迟接收端必须把它们重新对齐成一个字节流。做法是在每条 lane 上周期性插入对齐标记标记里编了 lane 编号接收端一旦在每条 lane 上都找到对齐标记就知道各自的偏移量做去偏斜。def block_lock(rx_bits): good 0 for i in range(0, len(rx_bits) - 65, 66): sync (rx_bits[i] 1) | rx_bits[i 1] if sync in (0b01, 0b10): good 1 if good 64: return (LOCKED, i) # 连续 64 个合法同步头才认锁 else: good 0 # 一个非法就清零滑动 1 bit 重找 return (HUNT, None)实际实现里不会真的逐比特滑而是几个候选相位并行检测。但状态机的语义就是这个意思锁定的判据是连续命中而不是单次命中。这条设计原则能解释很多现场现象比如链路起来后误码计数先涨一段再稳定那就是同步还在收敛。3.3 PAM4 与通道绑定25G/lane 之后信噪比怎么换带宽NRZ 每个符号周期只传 1 位判决门限一个眼睛张开度大抗噪好。PAM4 每个符号传 2 位四个电平三个眼相同波特率下速率翻倍代价是每个眼的张开度只有 NRZ 的三分之一信噪比要求提高大约 9 到 10 dB。这笔账直接决定了为什么 25G/lane 之后 FEC 从“可选”变成“必须有”。也决定了为什么高速链路的标准里编码、FEC、训练序列总是绑在一起出现——它们是同一个信噪比预算下的三个变量动一个另外两个就得跟着动。你在现场看到“同型号模块A 厂商的能起B 厂商的起不来”多半就是这三个变量的实现细节有差异而不是模块坏了。4. FEC 与自协商链路先“谈”还是先“纠”链路起不来的时候最折磨人的两种情况是两端都不报错就是不 up或者 up 了但误码率在 1e-8 附近晃。前者十有八九是自协商后者十有八九是 FEC。4.1 自协商16 位基础页能谈出什么自协商的本质是交换能力位图。两端各自发一串差分曼彻斯特编码的脉冲里面装的是 16 位基础页速率能力、双工能力、是否支持下一页、远端故障位。双方收到对方的位图后按标准里定义的优先级顺序取交集选出共同支持的最高能力然后各自配置到那个模式。这里有个必须记住的设计前提自协商是双向的、对等的。一端开自协商、另一端强制固定速率协商就不成立。强制端不发脉冲自协商端收不到对端能力只能退化成并行检测——只看线路上有没有信号能量据此猜一个速率。猜出来的结果通常是最保守的组合比如半双工。下一页机制让这个能力位图可以扩展。标准的做法是第一条下一页放一个消息页说明后面跟的是什么类型的数据后面的非格式化页承载实际内容。这让自协商能传厂商自定义信息、能传 FEC 能力、能传 EEE 支持情况。4.2 FEC为什么 25G 之后纠错变成必选项FEC 在标准里的存在感随速率单调上升。1G 时代基本靠编码本身的性质就够了10G 时代 FEC 是背板场景的可选项25G 之后PAM4 带来的信噪比损失让 FEC 成为链路预算里不可省的一环。主流的两套里德-所罗门参数是这样的def rs_profile(n, k, symbol_bits10): return { 码长 n: n, 信息位 k: k, 可纠符号数 t: (n - k) // 2, # 每个符号 10 bit错一个符号可能只错 1 bit 开销 %: round((n - k) / k * 100, 2), } print(rs_profile(528, 514)) # t7, 开销约 2.72%25G/100G 背板与铜缆常用 print(rs_profile(544, 514)) # t15, 开销约 5.84%50G/lane 以上常用参数表背后是两个取舍。第一纠错能力 t 越大能容忍的误码越多开销也越大5.84% 的开销意味着 100G 线路上有近 6G 是校验位不载业务。第二光有纠错不够还要交织。PAM4 接收端的错误往往是突发的一个判决错误会连累相邻几个符号把码字按符号轮转交织到不同位置突发错误就被摊成随机错误落到每个码字里只剩零星几个正好在 t 的能力范围内。排查现场最有用的一个数是“已纠正码字数”。这个计数在缓慢增长说明链路处于临界状态现在能通温度变一点、插损大一点就会掉。它涨得很快但链路没断说明 FEC 正在硬扛属于黑匣子里的预警信号比等到链路 down 再看要早得多。5. 避坑与排查读标准与做链路时最容易翻车的五件事5.1 现象按条款号去查翻到的内容和记忆里不一样原因很常见802.3 是滚动合并的版本每次修订把当年所有修订件并进一本但条款号一旦分配就不再回收废弃的条款号会留空或标注保留。而你手上的其他资料可能是基于某个中间修订件写的编号自然对不上。解决方法是先确认手上的文档集合。802.3-2022 是基准版本2022 年之后发布的那些修订件并不在里面——包括 400G/800G 相关的内容、以及 100/200/400G 的若干补充。判断一个特性在不在你手上的文档里最稳的办法是先查那份修订件清单再回到基准文档里比对条款是否存在而不是直接搜关键词然后抱怨搜不到。5.2 现象一端自协商、一端强制链路起不来或降到半双工原因是对端不发协商脉冲自协商端只能并行检测猜速率猜出来的组合往往不匹配。标准里写得很清楚自协商是可选功能但一旦启用就必须两端都启用。解决办法是统一策略要么两端都自协商要么两端都强制且参数完全一致。工程上更推荐全自协商因为强制模式会屏蔽掉 FEC、EEE 这些后续才加的能力协商等于主动放弃了链路自愈的余地。5.3 现象链路能 up但误码计数持续增长业务偶发丢包原因大概率是 FEC 配置不一致或者一端开了交织另一端没开。FEC 不是“开了就更好”收发两端必须在码型、交织深度、符号映射上完全对齐否则接收端解出来的就是噪声。解决办法是先读两端的 FEC 状态寄存器确认码型一致再看已纠正码字和不可纠正码字的比例。只涨前者是链路余量不足两者都涨就是配置错位。5.4 现象按 8b/10b 的 25% 开销算带宽算出来的吞吐对不上原因是 10G 之后大量链路用的是 64b/66b开销是 3.125% 而不是 25%两者差了一倍多。反过来的坑也存在某些老链路你按 3.125% 算实际却是 8b/10b。解决办法是看这条链路工作在哪个 PCS 类型上别按速率猜编码。同是 10G光纤和背板可能用不同的编码同是 1G铜缆和光纤的编码也不一样。5.5 现象低负载时延迟抖动明显抓包看到周期性停顿原因是 EEE。链路空闲一段时间后 PHY 进入低功耗状态有数据要发时得先唤醒唤醒时间在几十微秒量级对时延敏感的业务就是灾难。解决办法是把 EEE 关掉或者只在确认业务对微秒级抖动不敏感时开启。这个功能的取舍很典型省电和确定性在物理层是互斥的标准把选择权交给了部署方。6. 兼容、解耦、可验证三笔账压出来的设计取舍把这份 7000 多页的文档当成一个整体看会发现它反复在做三笔交易。第一笔是兼容换简洁。CSMA/CD、8b/10b、半双工这些机制在新场景里几乎没有意义但标准不删。删掉它们等于宣布旧设备不合法而以太网的全部价值就建立在“新旧能插在同一个网络里”这件事上。代价是文档越来越厚实现者的状态机越来越多。第二笔是解耦换效率。RS 隔开 MAC 与 PHYMII 隔开逻辑与引脚PCS/PMA/PMD 再逐层切分。每一刀都带来一点开销——多一层映射、多一组寄存器、多一次状态转换——换来的是任何一层单独演进都不影响其他层。第三笔是可验证换灵活。标准里几乎所有关键逻辑都写成显式状态机而不是描述性文字。这让一致性测试有据可依也让不同厂商的实现能互通。代价是状态机一旦写进标准就很难改后来的修订只能加分支、不能重写主干。我的习惯是每次拿到一条新链路先把这三笔账在纸上过一遍——这条链路在兼容什么、在哪一层解耦、哪个状态机可能还没收敛。从那以后我每次定位链路问题都强制先读一遍对应条款的状态图和参数表再动手改配置而不是先怀疑硬件。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站