📚 第四章 IP协议
📄 一句话概括

MTU 是「这条链路一帧最多装多少字节的 IP 包」,由介质决定,不由协议决定。 链路不同 MTU 就不同,所以「一个包能不能原样过去」要看路。

📝 本节和前面几节的关系

第三章讲过各种数据链路,这一节讲它们的「容量上限」。 4.5.2 的分片就是因为 MTU 不一致才出现的,这是它的前置知识。

一、MTU 是什么

全称是 Maximum Transmission Unit,最大传输单元。 它限制的是「一个 IP 包最大能有多长」,单位是字节。 注意它限制的是「IP 包」,不是「帧」:帧里除了 IP 包还有帧头帧尾, 所以以太网帧最长 1518 字节,而 IP 包最长 1500 字节。

层 上限 说明
以太网帧 1518 字节 含 14 字节头和 4 字节尾
IP 包 1500 字节 MTU 说的就是这个
IP 协议上限 65535 字节 首部里的总长度只有 16 位

第三行那个 65535 是「协议允许」,不是「链路允许」:首部的总长度字段 16 位,最大就 65535。 但实际链路上远远到不了——所以「协议上限」和「实际能过」是两回事。

二、各链路的 MTU 差多少

常见值先看一眼:

链路 MTU 为什么是这个数
以太网 1500 历史遗留,成了事实标准
PPPoE 1492 1500 减 8 字节 PPPoE 头
802.11 无线 2304 帧结构不同,能装更多
FDDI 4352 早期骨干网,块大
ATM(AAL5) 9180 信元拼起来能很长

第二行那个 1492 是最有名的「减法」:PPPoE 在以太网帧里又套了一层 8 字节的头, 所以真正能装 IP 包的地方只剩 1492。 ADSL 用户上传大文件慢,一部分原因就在这里——MSS 小 8 字节,每个包少装 8 字节数据。 第四、五行的 4352 和 9180 说明一件事: MTU 不是「越大越好」或「越小越好」,是「跟着介质走」。 以太网选 1500 是一种折中:再大,一个包的传输时间变长,出错重传的代价也变大。

三、差 8 字节为什么影响这么大

因为 MSS 是从 MTU 里扣出来的:MSS 等于 MTU 减 IP 头再减 TCP 头。

链路 MSS(IPv4) 一个 1 MB 文件要多少个包
以太网 1500 1460 719
PPPoE 1492 1452 723

第三列的差是 4 个包——为了传 1 MB,多发了 4 个包。 每个包都有 40 字节的头,所以多花 160 字节的「信封」。 看着不多,但在「每秒几十万包」的链路上就是实打实的开销。 更要紧的是「路径上 MTU 不一致」:源端按 1500 发,中间有一段只有 1492,就得靠分片或者报错。 这就是下一节要讲的分片。

四、各层都有自己的上限

不只是 IP 层有上限,每一层都有:

层 上限的名字 典型值
物理/链路 MTU 1500
网络 总长度字段 65535
传输 MSS 1460
应用 读写缓冲区大小 自己定

这四层是「一层比一层小」的关系:MSS 小于 MTU,MTU 小于协议上限。 任何一层超标,都要在那一层处理掉——传输层切段、网络层分片、链路层拆帧。 「切在越上层越省事」是个通用规律: TCP 切段最省事,因为丢了只重传一段;IP 分片最麻烦,因为丢一片要重传整包。

五、动手 Demo:链路不同,MTU 就不同

先用 psutil 读本机网卡的真实 MTU,再对比各种链路的典型值。 注意最后一张表:4000 字节的包,在 68 字节的链路上要切 83 片。

import psutil
for name, st in psutil.net_if_stats().items():
    if st.isup:
        print(name, st.mtu)

payload = 4000
for mtu in (1500, 1492, 1280, 2304, 4352, 9180):
    step = (mtu - 20) // 8 * 8
    print(mtu, -(-payload // step))

实跑输出:

--------------------------------------------------------------------
链路不同,MTU 就不同
--------------------------------------------------------------------
**MTU 是「这一条链路一帧最多能装多少字节的 IP 包」**:**它不是协议定的,是介质定的。**
**先量一下本机的**:
  网卡(在用)                    MTU
  -------------------------------------
  Loopback Pseudo-Interface 1     1500
  WLAN                            1500

**这是操作系统从网卡驱动读出来的实际值,不是我抄的规格表。**

**再看典型链路的 MTU,以及一个 4000 字节的包要切几片**:
  链路              MTU      4000 字节要切几片
  ---------------------------------------------
  以太网            1500     3
  PPPoE(ADSL)     1492     3
  IPv6 最低要求     1280     4
  IPv4 最低要求     68       83
  802.11 无线       2304     2
  FDDI              4352     1
  ATM(AAL5)       9180     1

**最后两行一片都不用切,第一行要切三片**——**同一个包,走不同的链路,命运不一样。**

**第二行那个 1492 是算出来的**:**1500 减 8 字节的 PPPoE 头,就是 1492。**
**所以 ADSL 拨号上网的用户,MSS 会比光纤用户小 8 字节**——
**这也是「同一条视频,有人卡有人不卡」的一个细节原因。**

**注意「IPv4 最低要求 68」这一行**:
**任何一条链路都必须能传 68 字节的包,否则连最基本的报文都过不去。**
**IPv6 把这个底线抬到了 1280**,**因为 IPv6 取消了「中间路由器分片」,链路必须自己能扛住 1280。**

第一张表里只有两块网卡在用,MTU 都是 1500:这是操作系统从驱动读出来的,不是我抄的规格表。 所以「本机 MTU 是多少」这个问题,答案永远要现场量。 83 片那个数字不是开玩笑: 如果把 MTU 设成 68(协议允许的最小值),一个 4000 字节的包就要切 83 片。 83 片里丢任何一片,整包作废——所以「把 MTU 调小」从来不是解决连通性的好办法。 (mtu - 20) // 8 * 8 这个式子里的两个动作都要看清: 减 20 是去掉 IP 头,除以 8 再乘 8 是「向下取到 8 的倍数」。 为什么必须是 8 的倍数?因为片偏移字段的单位是 8 字节。 这个细节下一节会用上。

30 秒实验

  1. 算一下:MTU 9000 的链路上,一个 1 MB 文件要发多少个包?
  2. 想一下:为什么以太网选了 1500 而不是 9000?
  3. 想一下:PPPoE 的 1492 是怎么算出来的?

常见误区

  1. 以为「MTU 是协议规定的」。 是介质规定的,同一套 IP 跑在不同链路上 MTU 就不同。
  2. 以为「MTU 和帧长是一回事」。 差 18 字节,帧还有 14 字节头和 4 字节尾。
  3. 以为「MTU 调小能解决所有连通问题」。 会增加分片,分片多了丢包代价更大。
自测三问(点开对答案) 1. MTU 指的是什么的上限? —— **一个 IP 包的长度**,不含链路层的帧头帧尾。 2. PPPoE 的 MTU 为什么是 1492? —— **因为 PPPoE 在以太网帧里加了 8 字节的头**,1500 减 8 得 1492。 3. 以太网帧最长多少字节? —— **1518 字节**,等于 14 字节帧头加 1500 字节 IP 包加 4 字节帧尾。

下一节讲「包太大过不去的时候怎么办」:分片。

相关笔记