以太网 MAC 收发数据通路:前导码、CRC、地址过滤与 DMA
更新时间:2026-09-19。前置:以太网 MII/RMII/GMII、DMA 描述符环、PTP 时间戳。PHY 负责比特/模拟,MAC(Media Access Controller)负责把以太网帧在「字节帧」和「内存 buffer」之间转换,并实现 CSMA/CD、CRC、地址过滤等规则。
本文要回答的问题
- 一帧以太网上线前 MAC 自动加了哪些字段?接收时又去掉/检查什么?
- 硬件地址过滤、CRC 校验、padding 各在哪一级?
- 帧怎么经 DMA 描述符环进出内存?
- 哪些坏帧要丢弃,checksum/VLAN 卸载是什么?
一、帧格式与 MAC 的职责
标准以太网帧(不考虑 VLAN tag):
bash
Preamble(7B 0x55) SFD(1B 0xD5) | DA(6) SA(6) [Type/Len(2)] | Payload(46~1500B) | FCS(4B CRC)
|<-------- MAC 收/发自动处理的封装 ------->|
最小帧 64B、最大普通帧 1518B(含 FCS);帧间有 IFG(12B 时间)- Preamble + SFD:接收端时钟恢复/字节对齐用;MAC 在发送时自动前插,接收时检测 SFD 后才开始组帧(不交给软件)。
- DA/SA:目的/源 MAC 地址。
- Type/Length:上层协议(如 0x0800 IPv4)或长度。
- Payload:不足 46B 时要 padding 到最小 64B 帧长。
- FCS:对 DA..Payload 的 CRC-32,由发送 MAC 计算追加,接收 MAC 校验。
二、接收通路(RX datapath)
bash
MII/GMII 字节(PHY→)
→ SFD 检测/字节对齐
→ 去 Preamble/SFD
→ 地址过滤(DA: 单播匹配 promiscuous/广播/组播 hash)
→ 状态机收 DA SA Type Payload,按字节写 RX FIFO
→ CRC 校验(收到 FCS 或硬件重算比对)
→ 长度/格式检查: RUNT(<64)/超长(jumbo 允许否)/对齐错误
→ (可选)打 PTP 硬件时间戳
→ DMA 从 FIFO 搬到内存 buffer,填描述符状态(CRC err/runt/..) → 中断- 地址过滤:第一级硬件丢弃不是给本机、也非广播/允许组播的帧,省带宽和 CPU;支持 promiscuous(嗅探全收)、multicast hash(用 MAC 地址 hash 位图粗筛,可能有 hash mismatch,软件再细查)。
- CRC/FCS 处理:MAC 通常在校验后剥掉 FCS(也可配置保留);CRC 错则在描述符置 error,一般丢弃。
- padding 剥离:短帧的 padding 是否上交可配。
- 错误统计:CRC 错误、alignment(位数非整字节)、runt、超长、溢出(FIFO/无描述符)等计数器(ifInErrors 类),驱动读取诊断。
三、发送通路(TX datapath)
bash
软件在内存准备 buffer(一般不含 FCS),挂到 TX 描述符环
→ DMA 取描述符、把帧搬到 TX FIFO
→ MAC 发送状态机:
等 IFG(帧间隔)、半双工时先侦听/退避(CSMA/CD)
发 Preamble + SFD
发 DA SA Type Payload
payload 不足 46B → 自动 pad
计算并追加 FCS(CRC-32)
(可插 VLAN tag、TCP/IP checksum 卸载、TSO)
→ 发完置描述符 done/可回收;冲突处理/重传- 自动 IFG:保证相邻帧间隔 12 字节时间;发完一帧不能立刻发下一帧。
- 自动 pad + FCS:软件给短 payload,MAC 补零并算 CRC;也可配置「已含 FCS」直通(桥接场景)。
- 半双工 CSMA/CD:发前侦听载波,冲突时发 jam、按二进制指数退避重传,超过 16 次报 excessive collision。现代全双工交换环境无冲突,但控制器仍保留逻辑。
- 发送时同样可在帧出口打 PTP 时间戳(见 1588)。
四、DMA 描述符环与零拷贝
MAC 通常不直接让 CPU 逐字节搬运,而是挂 RX/TX 描述符环(见 描述符环):
- 每个描述符含:buffer 地址、长度、own 位(硬件/软件拥有)、CRC/错误/帧起止等状态。
- RX:软件预先挂一批空 buffer(ownership 给硬件);MAC 收到帧由 DMA 写入,置 own=软件并中断;软件处理后把 buffer 挂回。
- TX:软件填好帧和长度、own 交硬件,DMA 取出发送,完成后回收。
- 描述符饥饿(descriptor starvation):RX 环被挂空且来不及补,新帧只能丢(missed-frame 计数++);这是高负载丢包的常见软件原因。
- buffer 与 cache:DMA buffer 要 non-cacheable 或做 cache invalidate/clean,否则 CPU 读到旧数据(见 DMA 与 cache 一致性)。
- 中断聚合(收 N 帧或超时才中断)降低 CPU 负载,见 中断聚合。
五、硬件卸载
现代 MAC 在数据通路里集成:
- checksum offload:硬件算/验 IP header checksum、TCP/UDP checksum,软件置标志即可。
- VLAN tag insertion/stripping:硬件加/去 4 字节 tag。
- TSO/LSO(TCP segmentation offload):软件给大段,MAC 按 MSS 切包并补各包头/校验。
- 这些卸载依赖描述符里的控制位和正确的协议偏移;配置错会产生校验错误包。
六、常见的坑
- CRC 错误风暴:多为 PHY/时钟/端接问题(见 MII/RGMII),而非 MAC 逻辑。
- RX 描述符环挂空:高负载下软件 replenish 不及时,帧被静默丢弃,要盯 missed/overflow 计数。
- cache 不一致:未 invalidate RX buffer/clean TX buffer,CPU 与 DMA 看到不同数据。
- FCS/padding 配置不一致:软件自己又算一遍 CRC,或桥接时 MAC 强剥 FCS,导致校验错。
- 组播 hash 当精确匹配:hash 是粗筛,需软件二次校验,否则收到无关组播。
- RUNT/短帧处理错:把冲突残帧当有效帧上交。
- 巨帧未两端都开:MTU>1500 要 MAC 与对端/交换都允许 jumbo,否则超长帧被丢。
- IFG/半双工双工不匹配:一端半双工一端全双工,产生晚冲突/CRC,应协商一致。
- checksum 卸载误配:对非 IP/隧道包硬件算错校验,对端丢弃。
- 时间戳打戳点/通道错:见 PTP,未开硬件戳精度差。
- 字节序/地址对齐:描述符/buffer 对齐要求未满足,DMA 报错。
- 发送完成过早回收:own 位还属硬件就复用 buffer,发出的数据被改写。
相关与延伸
PHY 接口见 MII/RMII/GMII/RGMII;搬运机制见 DMA 描述符环、DMA 突发;硬件时间戳见 PTP 1588;校验原理见 CRC/LFSR。
总结
以太网 MAC 把帧在网线字节和内存 buffer 间转换:发送时 DMA 从 TX 描述符环取帧,经 FIFO 在满足 IFG(半双工还要 CSMA/CD 侦听退避)后自动加前导码/SFD、给不足 46B 的 payload 补 padding、计算并追加 CRC-32 FCS;接收时检测 SFD 对齐、剥掉前导码、先做硬件单播/广播/组播 hash 地址过滤,再校验 CRC、识别 RUNT/超长/对齐错误,最后 DMA 写入预先挂好的 RX buffer 并在描述符记录错误状态后中断;配合 cache 一致性维护、描述符及时 replenish 和 checksum/VLAN/TSO 卸载运行——CRC 风暴多在 PHY 物理层,RX 描述符饥饿和 cache 不刷新才是高负载丢包的常见数据通路根因。