数据链路层(一):帧结构与封装、MAC地址与寻址、以太网帧格式

各位好,欢迎来到数据链路层的第一讲。说实话,很多做嵌入式开发的朋友,对TCP/IP协议栈的熟悉程度远高于数据链路层。但我要说,真正出问题、最难定位的,往往就在这一层。你想想看,物理层把比特流送上去了,数据链路层就得负责把这些比特组织成有意义的“帧”,还得保证它们能准确找到目标设备。今天我们就来把这层的关键概念掰开揉碎了讲清楚。

帧结构与封装:比特流的“集装箱”

物理层传的是原始的比特流,0和1。但光有比特流没用,你得知道从哪里开始读,哪里结束,这包数据是给谁的。数据链路层干的活,就是给这些比特流加上“包装”,这个包装就是帧(Frame)。

我个人习惯把帧想象成一个快递包裹。包裹外面有发件人地址、收件人地址,里面才是真正的货物。帧也一样,它由三大部分组成:

  • 头部(Header):包含控制信息,比如目标MAC地址、源MAC地址、上层协议类型等。
  • 数据载荷(Payload):上层(网络层)传下来的数据包,比如IP包。
  • 尾部(Trailer):通常包含帧校验序列(FCS),用于检测传输过程中是否出错。

核心要点:封装的过程,就是上层数据包“套上”下层的头部和尾部。数据链路层收到网络层的IP包后,在前面加上MAC头部,在后面加上FCS尾部,形成一个完整的帧,然后交给物理层发送。

这里有个容易忽略的点:帧的长度是有上下限的。以太网规定,帧的最小长度是64字节,最大是1518字节(不含前导码)。为什么有最小长度?我在项目中遇到过,如果帧太短,在发送过程中可能还没来得及检测到冲突就发完了,CSMA/CD机制就没法正常工作。嗯,这个后面讲以太网原理时会细说。

MAC地址与寻址:设备的“身份证”

MAC地址,也叫硬件地址或物理地址。它是在设备出厂时烧录在网卡里的,理论上全球唯一。MAC地址长什么样?6个字节,48位,通常用十六进制表示,比如 00:1A:2B:3C:4D:5E。

MAC地址的寻址方式有三种:

  • 单播(Unicast):发往单个目标设备。目标MAC地址的第一个字节最低位为0。
  • 广播(Broadcast):发往同一广播域内的所有设备。目标MAC地址全为 FF:FF:FF:FF:FF:FF。
  • 组播(Multicast):发往一组特定的设备。目标MAC地址的第一个字节最低位为1。
寻址类型 目标MAC地址特征 典型应用场景
单播 第一个字节最低位 = 0 两台设备直接通信
广播 全F(FF:FF:FF:FF:FF:FF) ARP请求、DHCP发现
组播 第一个字节最低位 = 1 视频会议、流媒体

避坑指南:我曾经调试一个网络不通的问题,折腾了半天,最后发现是MAC地址配置错了。设备上电后,网卡会读取MAC地址,如果读出来的是全0或者全F,那通信肯定出问题。所以,在产品量产时,一定要确保MAC地址烧录正确,并且不能重复。

以太网帧格式:Ethernet II vs 802.3

以太网帧格式主要有两种:Ethernet II(也叫DIX以太网)和IEEE 802.3。现在绝大多数网络设备用的都是Ethernet II格式。802.3格式主要用于一些老旧的网络环境或者特定的工业协议中。

我们先看Ethernet II帧格式,这是最常用的:

+----------------+----------------+----------------+----------------+----------------+----------------+
| 前导码 (7B)    | 帧起始定界符   | 目标MAC地址    | 源MAC地址      | 类型/长度      | 数据载荷       | 帧校验序列     |
|                | (1B)           | (6B)           | (6B)           | (2B)           | (46-1500B)     | (4B)           |
+----------------+----------------+----------------+----------------+----------------+----------------+

关键字段说明:

  • 前导码(Preamble):7个字节的10101010...,用于同步时钟。注意,这个字段在物理层处理,数据链路层不关心。
  • 帧起始定界符(SFD):1个字节的10101011,表示帧的开始。
  • 目标MAC地址:6字节,接收方地址。
  • 源MAC地址:6字节,发送方地址。
  • 类型/长度字段:在Ethernet II中,这个字段表示上层协议类型,比如0x0800表示IP协议,0x0806表示ARP协议。在802.3中,这个字段表示数据载荷的长度。
  • 数据载荷:46到1500字节。如果上层数据不足46字节,需要填充(Padding)到46字节。
  • 帧校验序列(FCS):4字节,使用CRC32算法,校验整个帧(从目标MAC地址到数据载荷)的完整性。

IEEE 802.3帧格式与Ethernet II的主要区别在于:

  • 802.3的“类型/长度”字段如果值小于等于1500,表示数据长度;如果大于等于1536,表示协议类型。Ethernet II则始终表示协议类型。
  • 802.3帧中,如果数据载荷是LLC(逻辑链路控制)数据,则后面还有DSAP、SSAP、Control等字段。

注意:在实际开发中,我们通常用Ethernet II格式。但有些工业以太网协议(如PROFINET)会用到802.3格式。我曾经在做一个工业网关项目时,就因为这个格式不匹配,导致数据解析完全错误。所以,在对接不同设备时,一定要先确认对方用的是哪种帧格式。

下面我用一张图来展示Ethernet II帧的封装过程,以及各层之间的关系:

以太网帧封装与数据链路层结构 以太网帧封装与数据链路层结构 应用层数据 TCP/UDP头部 + 应用层数据(段) IP头部 + TCP/UDP头部 + 应用层数据(包) MAC头部(14B) + IP头部 + TCP/UDP头部 + 应用层数据 + FCS尾部(4B) 目标MAC(6B) | 源MAC(6B) | 类型(2B) | 数据载荷(46-1500B) | FCS(4B) 比特流(010101...) 说明: 1. 数据链路层收到网络层的IP包后,添加MAC头部(14字节)和FCS尾部(4字节),形成帧。 2. 帧的最小长度为64字节(不含前导码),最大为1518字节。

从这张图可以看得很清楚:数据从应用层一路向下,每一层都会加上自己的头部。到了数据链路层,加上MAC头部和FCS尾部,就变成了一个完整的帧。然后交给物理层,变成比特流发送出去。

接收端的过程正好相反:物理层收到比特流,数据链路层检查FCS,如果校验通过,就剥掉MAC头部和尾部,把中间的IP包交给网络层。

总结一下今天的内容:

  • 帧是数据链路层的数据单元,由头部、数据载荷和尾部组成。
  • MAC地址是设备的物理地址,用于在局域网内寻址,有单播、广播、组播三种方式。
  • 以太网帧格式主流是Ethernet II,通过类型字段标识上层协议;802.3格式主要用于特定场景。
  • 帧的封装和解封装过程,是理解整个协议栈通信的基础。