2. IP分片头部结构:分片偏移、MF标志、DF标志、标识符字段详解

IP分片机制是网络层应对链路层MTU限制的核心手段。当IP数据报长度超过出口链路的MTU时,路由器或发送主机必须将原始数据报切割成多个较小的分片,每个分片都携带一个独立的IP头部。理解分片头部中的关键字段,是掌握分片与重组逻辑的基础。

核心要点:IP分片并非在传输层进行,而是在网络层完成。分片后的每个数据报片都拥有独立的IP头部,但仅第一个分片包含完整的传输层头部(如TCP/UDP头部)。分片偏移、MF标志、DF标志和标识符这四个字段共同协作,确保接收端能够正确重组原始数据报。

2.1 IP分片头部字段总览

标准IPv4头部(20字节,不含选项)中,与分片直接相关的字段位于第4-7字节(16位标识符、3位标志、13位片偏移)。下表列出了这些字段的位宽、位置与核心作用:

字段名称 位宽 IP头部偏移 核心作用
标识符(Identification) 16位 4-5字节 唯一标识发送端发出的原始数据报,接收端据此将属于同一数据报的分片归组
DF标志(Don't Fragment) 1位 6字节第2位 置1时禁止分片;若数据报超过MTU,路由器丢弃并返回ICMP差错报文
MF标志(More Fragments) 1位 6字节第3位 置1表示后续还有分片;置0表示当前分片是最后一个
片偏移(Fragment Offset) 13位 6-7字节 指示当前分片在原始数据报中的位置,以8字节为单位
注意:片偏移字段以8字节(64位)为计数单位。这意味着每个分片的数据部分长度必须是8字节的整数倍(最后一个分片除外)。13位片偏移最大可表示8191个偏移单位,对应最大原始数据报长度为8191 × 8 = 65528字节,加上20字节IP头部,正好接近IPv4数据报的65535字节上限。

2.2 标识符字段:分片归组的“身份证”

标识符(Identification)是一个16位的无符号整数,由发送端为每个原始IP数据报分配。当数据报被分片时,所有分片都继承相同的标识符值。接收端根据源IP地址 + 标识符二元组来区分不同数据报的分片集合。

  • 分配策略:通常采用递增计数器,每发送一个数据报,标识符加1。Linux内核中由ip_select_ident()函数生成。
  • 唯一性要求:在分片存活期内,标识符必须唯一。若标识符回绕或重用,可能导致重组错误。
  • 与协议无关:标识符字段对所有上层协议(TCP、UDP、ICMP等)的分片行为一致。
常见误区:标识符不是端口号,也不是序列号。它仅用于分片重组,不提供传输层的可靠传输或顺序控制功能。TCP的序列号在传输层处理,与IP标识符无关。

2.3 DF标志:禁止分片与路径MTU发现

DF(Don't Fragment)标志只有1位,但它在现代网络中扮演着关键角色。当DF=1时,路由器不得对数据报进行分片;若数据报长度超过出接口MTU,路由器直接丢弃该数据报,并向源端发送ICMPv4类型3代码4(需要分片但DF置位)的差错报文。

DF标志的典型应用场景:

  • 路径MTU发现(PMTUD):发送端设置DF=1,通过接收ICMP差错报文来探测整条路径的最小MTU。
  • VPN隧道:隧道封装后数据报长度增加,若内层数据报DF=1,隧道设备无法分片,只能丢弃或返回差错。
  • 实时多媒体:VoIP、视频会议等对延迟敏感的应用通常设置DF=1,避免分片重组引入的延迟和乱序。
性能提示:在高速网络中,分片和重组会消耗大量CPU资源。现代网络协议栈(如Linux GRO/GSO)倾向于避免分片,通过路径MTU发现协商合适的报文大小。DF标志是这一策略的基础。

2.4 MF标志与分片偏移:重组顺序的“拼图”

MF(More Fragments)标志和片偏移(Fragment Offset)共同决定了分片在原始数据报中的位置关系。

MF标志规则:

  • MF=1:当前分片不是最后一个,后续还有更多分片。
  • MF=0:当前分片是最后一个分片(也可能是唯一分片,即未分片的数据报)。

片偏移计算规则:

  • 片偏移 = 当前分片数据起始字节在原始数据报中的偏移量 ÷ 8。
  • 第一个分片的片偏移为0。
  • 每个分片的数据长度必须是8字节的整数倍(最后一个分片除外)。
  • 接收端根据片偏移和分片数据长度,将分片按顺序放入重组缓冲区。

下面是一个分片示例的SVG示意图,展示一个原始数据报被拆分为3个分片时,各字段的取值关系:

IP分片头部字段示例:原始数据报拆分为3个分片 IP分片头部字段示例(原始数据报拆分为3个分片) 原始数据报(标识符=0x1234,总长=1500字节,DF=0,MF=0,片偏移=0) 分片1 标识符=0x1234, MF=1, 片偏移=0 数据长度=600字节(0-599) 分片2 标识符=0x1234, MF=1, 片偏移=75 数据长度=600字节(600-1199) 分片3 标识符=0x1234, MF=0, 片偏移=150 数据长度=300字节(1200-1499) 字段取值说明 • 标识符:三个分片共享相同的标识符0x1234,表示它们属于同一个原始数据报。 • MF标志:分片1和分片2的MF=1(后面还有分片),分片3的MF=0(最后一个分片)。 • 片偏移:分片1偏移=0(起始位置),分片2偏移=75(600÷8=75),分片3偏移=150(1200÷8=150)。 • 数据长度:分片1和分片2各携带600字节(8的整数倍),分片3携带300字节(最后一个分片无需对齐)。 • 重组时,接收端按片偏移从小到大排列分片,直到收到MF=0的分片为止。 • 若分片丢失或超时未到齐,接收端丢弃所有已收到的分片,并可能发送ICMP重组超时报文。

2.5 分片头部字段的完整重组流程

接收端重组分片时,遵循以下步骤:

  1. 分片归类:根据源IP地址和标识符字段,将收到的分片放入对应的重组缓冲区。
  2. 排序:按片偏移从小到大对分片进行排序。
  3. 完整性检查:检查是否收到片偏移为0的分片,以及MF=0的最后一个分片。
  4. 连续性检查:检查分片之间是否存在重叠或空洞。片偏移 + 分片数据长度应等于下一个分片的片偏移。
  5. 重组完成:当所有分片到齐且连续无空洞时,将数据部分按顺序拼接,恢复原始数据报。
Linux内核实现参考:在Linux网络协议栈中,分片重组由net/ipv4/ip_fragment.c中的ip_defrag()函数完成。内核使用哈希表(ipq_hash)管理多个并发的分片队列,每个队列由struct ipq结构体表示,其中保存了标识符、源地址、目的地址、协议等关键信息。

2.6 分片头部字段的常见问题与避坑

问题场景 原因分析 影响与建议
分片重叠攻击 恶意分片设置异常的片偏移,导致重组时数据重叠,绕过防火墙规则 内核应检测重叠分片并丢弃;防火墙启用分片重组检查
分片缓冲区耗尽 大量不完整的分片占用系统内存,导致拒绝服务 限制并发分片队列数量(如/proc/sys/net/ipv4/ipfrag_max_dist)
标识符回绕 高速发送时标识符快速回绕,新旧分片混淆 现代内核使用时间戳辅助区分;增大标识符位宽(IPv6已扩展)
DF标志与隧道封装 隧道设备无法分片DF=1的数据报,导致丢包 隧道入口处清除DF标志,或使用分片封装(如IPsec隧道模式)
性能警告:分片重组是CPU密集型操作,涉及内存拷贝、定时器管理和哈希查找。在高速网络(10Gbps以上)中,应尽量避免分片发生。Linux的GRO(Generic Receive Offload)和GSO(Generic Segmentation Offload)机制正是为了在接收和发送路径上合并/避免分片而设计的,后续章节将详细分析。

通过本节的学习,你应该能够准确理解IP分片头部中标识符、DF标志、MF标志和片偏移四个字段的语义与协作关系。这些字段是后续分析分片重组性能瓶颈、GRO合并策略以及调优方案的基础。