第10章 IP的分片与重装

所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现

本章描述IP分片与重装的实现,包括分片的原因、分片算法、重装过程和重装定时器等。


10.1 引言

什么是分片

分片(Fragmentation):

  • 当IP数据报的大小超过链路的MTU时
  • 把数据报分成多个小的分片
  • 每个分片独立传输
  • 到达目的地后再重装

分片是为了适应不同链路的MTU。


为什么需要分片

为什么需要分片:

  1. 不同链路的MTU不同

    • 以太网MTU=1500
    • SLIP MTU=296
    • 其他链路可能更小
  2. 端到端路径MTU可能很小

    • 路径上最小的MTU
    • 大的分组通不过
  3. IP层负责处理

    • 对上层透明
    • TCP/UDP不用关心

分片让大的分组能通过小MTU的链路。


分片和重装的位置

分片的位置:

  • 发送主机
  • 中间路由器
  • 任何需要转发但MTU不够的地方

重装的位置:

  • 只有目的主机
  • 中间路由器不重装
  • 每个分片独立选路

分片可以在中间,重装只在目的地。


10.2 分片相关的字段

IP首部中的相关字段

IP首部中与分片相关的字段:

字段大小说明
标识(ip_id)16位数据报的唯一标识
标志(ip_off的高3位)3位分片标志
片偏移(ip_off的低13位)13位分片在原数据中的偏移

这三个字段用于分片和重装。


标志位

三个标志位:

位名称说明
第0位(最高位)保留位(RF)保留,必须为0
第1位不分片(DF)1=不分片,0=可以分片
第2位(最低位)更多分片(MF)1=还有更多分片,0=最后一个分片

DF位(Don’t Fragment):

  • 设置了DF位就不能分片
  • MTU不够就丢弃,发ICMP不可达
  • 用于路径MTU发现

MF位(More Fragments):

  • 除了最后一个分片,其他都设置
  • 最后一个分片MF=0
  • 表示是不是最后一个

标志位控制分片的行为。


片偏移

片偏移(Fragment Offset):

  • 13位
  • 以8字节为单位
  • 表示这个分片的数据在原数据中的偏移
  • 第一个分片偏移=0

为什么以8字节为单位:

  • 片偏移只有13位
  • 8字节单位可以表示更大的范围
  • 13位 × 8字节 = 8192字节偏移
  • 加上数据,最大65535字节(IP最大长度)

片偏移以8字节为单位。


标识

标识(Identification):

  • 16位
  • 每个数据报一个唯一的标识
  • 同一个数据报的所有分片标识相同
  • 重装时用标识匹配分片

标识的生成:

  • 发送时递增
  • 每个数据报加1
  • 循环使用

标识用于匹配同一个数据报的分片。


10.3 分片的过程

什么时候分片

触发分片的条件:

  1. 输出接口的MTU小于数据报大小

    • 需要转发或发送
    • 数据报比MTU大
  2. DF位没有设置

    • DF=0才能分片
    • DF=1就不能分

MTU不够且DF=0就分片。


分片算法

分片的算法:

  1. 计算每个分片的大小

    • 不超过MTU
    • 减去IP首部长度
    • 数据部分是8字节的倍数(除了最后一个)
  2. 创建各个分片

    • 复制IP首部
    • 复制对应的数据
    • 设置片偏移
    • 设置MF标志
    • 重新计算检验和
  3. 逐个发送

    • 每个分片独立发送
    • 独立选路

把大的数据报分成小的分片。


分片的例子

例子:

  • 原数据报:4500字节(20字节首部 + 4480字节数据)
  • MTU:1500字节
  • 每个分片数据:1480字节(1500-20)
  • 1480是8的倍数:1480 / 8 = 185

分片结果:

分片偏移数据长度总长度MF位
10148015001
2185148015001
3370152015400

验证:

  • 1480 + 1480 + 1520 = 4480 ✓
  • 偏移1:0
  • 偏移2:1480 / 8 = 185
  • 偏移3:(1480+1480) / 8 = 370

除了最后一个,其他都是最大长度。


10.4 重装的过程

重装的位置

重装只在目的主机:

  • 中间路由器不重装
  • 每个分片独立转发
  • 目的主机收集所有分片
  • 收集齐了再重装

重装只在目的地,中间不重装。


重装的数据结构

重装的数据结构:

  • 每个正在重装的数据报一个结构
  • 包含:
    • 源地址
    • 目的地址
    • 协议
    • 标识
    • 分片链表
    • 定时器
    • 等等

链表组织:

  • 所有正在重装的链接成链表
  • 按源、目的、协议、标识查找
  • 匹配同一个数据报的分片

用数据结构管理正在重装的分片。


重装的步骤

重装的步骤:

  1. 收到分片

    • 检查是不是分片(MF=1 或 偏移>0)
    • 不是分片:直接上交
  2. 查找重装结构

    • 根据源、目的、协议、标识查找
    • 找到:加入对应的链表
    • 没找到:创建新的重装结构
  3. 插入分片

    • 按偏移排序
    • 检查是否重叠
    • 插入到正确的位置
  4. 检查是否完整

    • 所有分片都到了吗?
    • 最后一个分片到了吗?
    • 有没有空隙?
  5. 完整则重装

    • 合并所有分片
    • 重建原数据报
    • 上交上层
    • 释放重装结构

收集所有分片,然后合并。


重装定时器

重装定时器:

  • 每个重装结构有一个定时器
  • 防止分片丢失导致资源泄漏
  • 超时还没收齐就丢弃
  • 可能发送ICMP超时报文

超时时间:

  • 通常是30秒或60秒
  • 不同实现可能不同
  • RFC建议是60秒

定时器防止资源泄漏。


10.5 分片的问题

分片的问题

分片带来的问题:

  1. 性能问题

    • 分片需要开销
    • 重装需要开销
    • 降低性能
  2. 可靠性问题

    • 一个分片丢了,整个数据报就丢了
    • 没有重传机制(IP不保证可靠)
    • TCP会重传整个数据报
  3. 安全问题

    • 分片攻击
    • 重叠分片
    • tiny分片攻击
  4. 效率问题

    • 每个分片都有IP首部
    • 额外的开销
    • 小分片效率低

分片有很多问题,能不分就不分。


路径MTU发现

路径MTU发现(Path MTU Discovery):

  • 发现路径上的最小MTU
  • 发送合适大小的分组
  • 避免分片
  • 用DF位实现

工作原理:

  1. 发送分组,设置DF位
  2. 如果中间MTU不够,路由器丢弃,发ICMP不可达(需要分片)
  3. 收到ICMP后,减小MTU
  4. 重新发送
  5. 直到能通过

路径MTU发现可以避免分片。


10.6 小结

分片概述

  1. 什么是分片

    • 大的数据报分成小的
    • 适应不同的MTU
  2. 为什么需要

    • 不同链路MTU不同
    • 路径MTU可能很小
  3. 位置

    • 分片:发送主机、路由器
    • 重装:只有目的主机

分片相关字段

  1. 标识

    • 16位
    • 同一个数据报相同
    • 用于匹配分片
  2. 标志位

    • RF:保留
    • DF:不分片
    • MF:更多分片
  3. 片偏移

    • 13位
    • 以8字节为单位
    • 数据在原数据中的偏移

分片过程

  1. 触发条件

    • MTU不够
    • DF=0
  2. 分片算法

    • 计算分片大小
    • 创建各个分片
    • 设置偏移和标志
    • 逐个发送

重装过程

  1. 重装位置

    • 只有目的主机
    • 中间不重装
  2. 重装步骤

    • 收到分片
    • 查找重装结构
    • 插入分片
    • 检查完整性
    • 完整则重装
  3. 重装定时器

    • 防止资源泄漏
    • 超时丢弃

分片的问题

  1. 性能问题

    • 分片重装开销
    • 降低性能
  2. 可靠性问题

    • 一个丢了全丢
    • 效率低
  3. 安全问题

    • 分片攻击
    • 重叠分片
  4. 路径MTU发现

    • 避免分片
    • 用DF位实现

关键概念

  1. 分片

    • 大分小
    • 适应MTU
  2. 重装

    • 小合大
    • 只在目的地
  3. 标识、标志、偏移

    • 分片的关键字段
  4. 重装定时器

    • 防止资源泄漏
  5. 路径MTU发现

    • 避免分片
    • 更好的方式

IP分片 MTU