Appearance
IP Fragmentation(IP 分片)
背景:当 IP 数据包的大小超过 MTU(Maximum Transmission Unit, 最大传输单元)时,IP 层需要对数据进行分片,否则数据包将被丢弃。分片发生在 出方向 的接口上。
参考:MTU 介绍
1. IP 分片实例(以太网环境)
分片过程
- 以太网的默认 MTU 为 1500 字节,IP 头部占 20 字节,因此 IP 层最大有效载荷(payload)为 1480 字节。
- 若传输的数据超过 1480 字节,则 IP 协议需要进行分片。
- IP 层的分片对 传输层协议(TCP/UDP)是透明的,即 TCP/UDP 本身不关心分片的过程。
示例
假设使用 UDP 传输 2000 字节的数据,加上 8 字节的 UDP 头部,IP 层总共需要传输 2008 字节:
- 第一个 IP 包:
- UDP 头部 (8B) + 数据载荷 (1472B) = 1480B
- 第二个 IP 包:
- 无 UDP 头部,仅有剩余载荷 (528B)
分片示意图
分片标志位(Flags 字段)
IP 头部的 Flags 字段用于控制分片:
More Fragments
(MF)=1
:表示该分片 后面还有更多分片。More Fragments
(MF)=0
:表示该分片是 最后一个分片。
Flags: 0x00
0... .... = Reserved bit: Not set
.0.. .... = Don't fragment: Not set
..0. .... = More fragments: Not set // 被分片的包除最后一个均为1。
2. 禁止 IP 分片(Don't Fragment,DF 标志位)
概述
IP 头部的 DF(Don't Fragment)标志位 控制是否允许分片:
- DF = 1:不允许分片,如果数据包超过 MTU,则直接丢弃。
- DF = 0:允许分片,当数据包超过 MTU 时,会被拆分成多个 IP 片段。
2.1 使用 ping 命令测试 DF 标志位
可以使用 ping
命令手动指定 DF 置位,以测试网络路径上的 MTU 限制。
Linux (Ubuntu, CentOS)
-M do
:设置 DF 标志位,确保数据包不会被分片。-s
:指定 ICMP 报文的大小。
shell
# Ubunut
ping -M do www.baidu.com -s 1472
PING www.a.shifen.com (180.101.49.11) 1472(1500) bytes of data.
1480 bytes from 180.101.49.11: icmp_seq=1 ttl=52 time=4.84 ms
1480 bytes from 180.101.49.11: icmp_seq=2 ttl=52 time=4.82 ms
ping -M do www.baidu.com -s 1473
PING www.a.shifen.com (180.101.49.11) 1473(1501) bytes of data.
ping: local error: Message too long, mtu=1500
ping: local error: Message too long, mtu=1500
Macos
-D
:设置 DF 标志位,防止分片。
shell
# MacOS
~> ping -D www.baidu.com -s 1472
PING www.a.shifen.com (182.61.200.7): 1472 data bytes
1480 bytes from 182.61.200.7: icmp_seq=0 ttl=54 time=5.904 ms
1480 bytes from 182.61.200.7: icmp_seq=1 ttl=54 time=5.651 ms
~> ping -D www.baidu.com -s 1473
PING www.a.shifen.com (182.61.200.7): 1473 data bytes
ping: sendto: Message too long
ping: sendto: Message too long
扩展
如何避免 UDP 过大,造成 ip 层分片?
- QUIC(Quick UDP Internet Connection)