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 秒实验
- 算一下:MTU 9000 的链路上,一个 1 MB 文件要发多少个包?
- 想一下:为什么以太网选了 1500 而不是 9000?
- 想一下:PPPoE 的 1492 是怎么算出来的?
常见误区
- 以为「MTU 是协议规定的」。 是介质规定的,同一套 IP 跑在不同链路上 MTU 就不同。
- 以为「MTU 和帧长是一回事」。 差 18 字节,帧还有 14 字节头和 4 字节尾。
- 以为「MTU 调小能解决所有连通问题」。 会增加分片,分片多了丢包代价更大。
自测三问(点开对答案)
1. MTU 指的是什么的上限? —— **一个 IP 包的长度**,不含链路层的帧头帧尾。 2. PPPoE 的 MTU 为什么是 1492? —— **因为 PPPoE 在以太网帧里加了 8 字节的头**,1500 减 8 得 1492。 3. 以太网帧最长多少字节? —— **1518 字节**,等于 14 字节帧头加 1500 字节 IP 包加 4 字节帧尾。下一节讲「包太大过不去的时候怎么办」:分片。
- ☐ (本节完,下一节 4.5.2 IP报文的分片与重组)