前阵子帮一个做物联网网关的团队排查丢包,抓包文件里密密麻麻全是FCS错误。团队里一位同事盯着十六进制看了半天,问我:“这个帧的目的MAC地址是不是从第7个字节开始?”我愣了一下,突然意识到,很多人虽然能背出MAC帧格式的各个字段,但到了真实抓包场景,前导码、FCS、类型/长度这些细节还是会对不上。所以这篇文章我想把MAC Frame从物理线上到Wireshark里的完整形态掰开揉碎讲一遍。内容包括经典的Ethernet II帧格式逐字段拆解、一个真实帧的十六进制读取方法、以及网上经常搜到的改MAC、读MAC、MAC和PHY分工、PCS/PMA/PMD这些内容。适合做网络驱动、嵌入式开发、网络排障,以及刚学完计算机网络还想再深一步的朋友。
1. 为什么一个MAC帧值得重新细读
1.1 我们常说的“以太网头部”只是MAC帧的一部分
先澄清一个概念:多数抓包工具里显示的Ethernet II头部,是“目的MAC 6字节 + 源MAC 6字节 + EtherType 2字节”,一共14字节。这是很多人理解的“MAC帧头”,也确实最常被用到。但一个完整的MAC Frame,在物理线路上还要包含前导码、帧起始定界符、数据负载和FCS帧校验序列。尤其是做网卡驱动、FPGA逻辑、或需要和PHY芯片调试的人,如果脑子里只有那14字节,八成会在现场卡住。
这里有一个长期存在的概念分歧:IEEE 802.3标准里,前导码和SFD属于物理层会聚功能,MAC帧本身并不包括这两个字段;而从目的地址开始到FCS结束,才是标准的MAC frame。Wireshark展示的也是从目的地址开始的帧内容,FCS只显示校验结果。但你在逻辑分析仪上抓MAC层接口时,往往会看到前导码和SFD也被数据链路层/物理层芯片处理。所以网上资料里“MAC帧最小64字节”和“以太网帧最小72字节”两种说法都成立,区别只在于算不算前导码和SFD。理解这个区别,再去看各种文档就不会绕晕。
1.2 MAC帧解决的是“下一跳”的问题
MAC帧的核心任务是让一个报文从链路的一端到达相邻的另一端。IP层关心的是从源主机到目标主机的端到端通路,沿途每个路由器的IP地址不会变。而MAC层每经过一跳,帧里的源MAC和目的MAC都会被重新封装。
举个生活化的例子:你要寄一个国际快递包裹(相当于IP报文)到另一个城市,包裹上的寄件人和收件人始终不变;但包裹需要先坐小区里快递员的三轮车(第一个MAC帧),再到分拣中心换大货车(第二个MAC帧),最后到小区门口换另一辆三轮车(第三个MAC帧)。每个运输段的“上一站/下一站”就是MAC地址,每换一次运输工具,运输标签就要换一次。
在网络里,路由器转发IP包时,会把收到的以太网帧解封装,根据路由表决定出接口,再用新的源/目的MAC重新封装一个帧。这就是为什么抓包时中间路由器前后帧的MAC地址会变,而IP地址不变。理解这个关系,对后面理解帧字段就很关键。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 经典Ethernet II帧逐字段拆解:从同步比特到CRC
2.1 前导码和SFD:接收方靠什么找到帧的开头
当PHY在介质上检测到信号时,首先要做的是比特级同步。前导码是7字节的0x55,二进制是01010101,也就是0和1高频交替。接收方利用这种翻转来锁定接收时钟,恢复出数据位,所以前导码必须是一串交替码型。
第8个字节是SFD(Start Frame Delimiter),值固定为0xAB,二进制10101011,表示从下一个字节开始就是真正的MAC帧内容。SFD不仅仅是“开头标志”,它最后的两个1是给接收方一个明确的“对齐点”,从这之后,字节边界就和发送端一致了。
这部分完全由PHY/MAC硬件处理,CPU和驱动几乎不感知。所以你用Wireshark看不到前导码和SFD,但在芯片内部寄存器或逻辑分析仪上能看到。如果调试FPGA的MAC接口,你会看到8字节的0x55...0xAB序列,然后才是目的MAC。如果在驱动层把这些同步字段也计入帧长,那抓包长度就会整体偏大8字节,对比不同层级的数据时对不上,这是我在现场看过的真实问题。
2.2 目的地址与源地址:48位MAC地址里的隐藏标志
MAC地址为什么是6字节而不是4字节?因为48位地址空间由IEEE统一分配,OUI厂商前缀占24位,后24位由厂商分配,足够覆盖海量设备。
目的MAC地址的第一字节最低位叫I/G位,0表示单播,1表示多播,全1则是广播地址
