📡 第一章 网络硬件通用基础知识
📄 一句话概括

以太网帧是一段固定格式的字节串,头 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 秒实验

  1. 在 Wireshark 里抓一个 ping 包,量它的帧长,跟理论值对一对(差 4 是 FCS)。
  2. 算一下 10 Gbit/s 跑最小帧的包转发率,跟 14.88 Mpps 这个规格数对一对。
  3. 找一个带 VLAN 的包,看 0x8100 出现在第几字节。

常见误区

  1. 把前导码算进 64 字节。64 是从目的 MAC 到 FCS,前导码另算 8 字节。
  2. 以为 FCS 能纠错。它只检错,错了就丢,靠上层重传。
  3. 忽略 VLAN 标签的 4 字节。算带宽、算巨帧时经常差这一截。
自测三问(点开对答案) 1. 46 字节的最小载荷是怎么来的? —— 最小帧 64 减头尾 18 字节;这个下限是为了让帧够长,能检出冲突。 2. 0x0800 与 0x8100 分别是什么? —— 0x0800 表示上层是 IPv4;0x8100 表示后面跟着一个 802.1Q VLAN 标签。 3. 为什么千兆跑小包只有一半带宽? —— 每帧都要付 64 字节前导+帧+间隙的固定成本,46 字节载荷只占 672 bit 里的一小半。

下一节:从帧回到物理层,看 10BASE-T 是怎么把比特变成电平和跳变的。

相关笔记