Skip to content

IP Fragmentation(IP 分片)

背景:当 IP 数据包的大小超过 MTU(Maximum Transmission Unit, 最大传输单元)时,IP 层需要对数据进行分片,否则数据包将被丢弃。分片发生在 出方向 的接口上。
参考MTU 介绍

1. IP 分片实例(以太网环境)


分片过程

  • 以太网的默认 MTU1500 字节,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)

分片示意图

IP包分片

分片标志位(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)