以太网帧是一段固定格式的字节串,头 14 字节、尾 4 字节,中间夹数据。 所有以太网设备的转发、过滤、统计,都是在这段字节上做文章。
前三节把「以太网是什么」讲完了,这一节开始看「它长什么样」。 这一节是第二章交换机的直接前置:交换机学的 MAC 地址在第 3、4 字节,它判断的广播在第 1 字节, 它不看的 IP 头在数据段里。
一、逐字段看一遍
前导码 7 字节 + SFD 1 字节。全是 1010 交替,最后一个字节以 11 结尾。 作用只有一个:让接收端的时钟与发送端对齐。它不属于帧,不计入帧长。
目的 MAC 6 字节、源 MAC 6 字节。顺序是先目的后源,这是抓包时最容易看错的地方。
类型/长度 2 字节。这里有两个流派:Ethernet II 用它表示上层协议(0x0800 是 IPv4、 0x86DD 是 IPv6、0x8100 是带 VLAN 标签),IEEE 802.3 用它表示数据长度。 今天九成以上是 Ethernet II。
数据 46 到 1500 字节。不够 46 要填充,超过 1500 要分片或被丢。 FCS 4 字节。CRC-32 校验,只查错不纠错,错了整帧丢弃,靠上层重传。
二、两个数字的来历:46 与 1500
46 是算出来的,不是拍的:最小帧 64 减掉头尾 18 字节,剩 46。 所以「不够 46 就填充」这件事,本质是为了让帧够长以便检测冲突。
1500 是历史决定的:早期以太网用 1500 字节的缓存,后来写进标准就再没改。 这个数字被 IP 继承成 MTU 默认值,一路影响到今天所有操作系统。
代价:一个 64 KB 的 IP 包要被切成 44 个 1500 字节的帧,每个帧都有自己的头。 这就是为什么大文件传输时包都顶到 MTU——少一个头就是省 58 字节。
三、带 VLAN 标签的帧:多出 4 个字节
802.1Q 在源 MAC 与类型之间插入 4 字节:2 字节标签协议号(0x8100)、 2 字节标签控制信息(12 位 VLAN ID、3 位优先级)。
插入之后帧长了 4 字节:最大从 1518 变成 1522,最小仍是 64(填充会相应减少)。 这就是规格书里「巨帧」「1522 字节」这些数字的来源。
端口要认得这个标签,否则会当成长度字段乱解析。 交换机端口的三种模式(Access/Trunk/Hybrid)讲的正是「认不认标签、加不加标签」, 这条在 02.08.05 与 04.04.02 会两次回到。
四、抓包时最常看错的四处
① 把前导码算进帧长。Wireshark 显示的帧长不含前导码与 FCS。 ② 把源 MAC 当目的 MAC。前 6 字节是目的,后 6 字节才是源。 ③ 看到 0x0806 不知道是什么。那是 ARP——用 IP 换 MAC 的协议。 ④ 看到小于 64 字节的帧以为正常。那是残帧,正常网卡不会发出来。
这四条都不是理论问题,是现场对不上的时候用来对齐口径的。 比如「为什么交换机统计的字节数比 Wireshark 多 4」——多的就是 FCS。
五、动手 Demo:帧里每一段占多少字节,以及一秒钟到底能发多少帧
这段先把帧拆成七段列表,再把「前导码 + 帧 + 帧间隙」一起算进每帧的开销, 最后算出三种速率下的小包转发率。
TH([u"字段", u"字节", u"作用"], [0, 0, 0])
# ... 七段逐行打印
bits = 64 + 512 + 96 # 前导+最小帧+帧间隙
for r, name in ((10e6, u"10M"), (100e6, u"100M"), (1000e6, u"1G")):
pps = r / bits
print(name, pps, pps * 46 * 8 / 1e6)
实跑输出:
--------------------------------------------------------------------
以太网帧里到底装了什么,每一段占多少字节
--------------------------------------------------------------------
字段 字节 作用
-----------------------------------------------------------
前导码 7 10101010,用来对齐时钟
帧起始定界符 SFD 1 10101011,表示帧开始
目的 MAC 6 收方地址,全 F 是广播
源 MAC 6 发方地址
类型/长度 2 0x0800 是 IPv4
数据 46~1500 不够 46 要填充
FCS 4 CRC-32 校验
**注意前导码不计入帧长。**规格说的 64 字节,是从目的 MAC 算到 FCS:
6+6+2+46+4 = 64。最大 1518 = 6+6+2+1500+4。
**按 64 字节发,一秒钟能发多少个?**这就要把前导码与帧间隙一起算进去:
项 比特 说明
------------------------------------------
前导+SFD 64 8 字节
最小帧 512 64 字节
帧间隙 IFG 96 12 字节
合计 672 每帧占 672 bit
10M:14881 帧/秒(14.9 kpps),折合 5.48 Mbit/s 有效载荷。
100M:148810 帧/秒(148.8 kpps),折合 54.76 Mbit/s 有效载荷。
1G:1488095 帧/秒(1488.1 kpps),折合 547.62 Mbit/s 有效载荷。
这就是规格书里「包转发率」那个数的来历:**线速下按最小帧算,永远是最坏情况。**
最后三行是规格书里「包转发率」的计算式,只是厂家把它写成了结果。 记住 672 这个数:任何速率的线速包转发率都等于速率除以 672。
注意有效载荷那一列:1 G 线速跑最小帧,只有 547 Mbit/s 是数据。 所以「千兆能跑多少」这个问题必须带条件——跑大包接近千兆,跑小包只有一半。
30 秒实验
- 在 Wireshark 里抓一个 ping 包,量它的帧长,跟理论值对一对(差 4 是 FCS)。
- 算一下 10 Gbit/s 跑最小帧的包转发率,跟 14.88 Mpps 这个规格数对一对。
- 找一个带 VLAN 的包,看 0x8100 出现在第几字节。
常见误区
- 把前导码算进 64 字节。64 是从目的 MAC 到 FCS,前导码另算 8 字节。
- 以为 FCS 能纠错。它只检错,错了就丢,靠上层重传。
- 忽略 VLAN 标签的 4 字节。算带宽、算巨帧时经常差这一截。
自测三问(点开对答案)
1. 46 字节的最小载荷是怎么来的? —— 最小帧 64 减头尾 18 字节;这个下限是为了让帧够长,能检出冲突。 2. 0x0800 与 0x8100 分别是什么? —— 0x0800 表示上层是 IPv4;0x8100 表示后面跟着一个 802.1Q VLAN 标签。 3. 为什么千兆跑小包只有一半带宽? —— 每帧都要付 64 字节前导+帧+间隙的固定成本,46 字节载荷只占 672 bit 里的一小半。下一节:从帧回到物理层,看 10BASE-T 是怎么把比特变成电平和跳变的。
- ☐ (本节完,下一节 01.03.02 10BASE-T)
相关笔记
- 10BASE-T
- 第二章 02.01.05 学习MAC地址(后章)
- 🔌 网络是怎样连接的
- 📡 图解网络硬件 · 索引