4.5 Fragment Header (分片报头)
Fragment header 由 IPv6 源使用, 以发送大于到达其目的地的路径 MTU 的分组.(注意: 与 IPv4 不同, IPv6 中的分片仅由源节点执行, 而不是由分组传递路径上的路由器执行 -- 见第 5 节.) Fragment header 由紧邻前一报头中 Next Header 值 44 标识, 并具有以下格式:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Reserved | Fragment Offset |Res|M|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Next Header (下一报头) - 8 位选择器.标识原始分组的 Fragmentable Part (可分片部分) (定义如下) 的初始报头类型.使用与 IPv4 Protocol 字段相同的值 [RFC-1700 et seq.].
Reserved (保留) - 8 位保留字段.发送时初始化为零; 接收时忽略.
Fragment Offset (片偏移量) - 13 位无符号整数.跟随此报头的数据相对于原始分组的 Fragmentable Part 起始位置的偏移量 (以 8 个八位字节为单位).
Res (保留) - 2 位保留字段.发送时初始化为零; 接收时忽略.
M flag (M 标志) - 1 = 还有更多片; 0 = 最后一片.
Identification (标识) - 32 位.见下面的描述.
为了发送对于到达其目的地的路径的 MTU 来说太大的分组, 源节点可以将分组分成片, 并将每个片作为单独的分组发送, 以便在接收方重新组装.
对于每个要分片的分组, 源节点生成一个 Identification 值.该 Identification 必须不同于最近*发送的具有相同 Source Address 和 Destination Address 的任何其他分片分组的标识.如果存在 Routing header, 则关注的 Destination Address 是最终目的地的地址.
*"最近" 是指在分组的最大可能生命期内, 包括从源到目的地的传输时间以及与同一分组的其他片等待重新组装所花费的时间.然而, 不要求源节点知道最大分组生命期.相反, 假设可以通过将
Identification值维护为一个简单的 32 位 "wrap-around (回绕)" 计数器来满足该要求, 每次必须分片分组时递增.是否为节点维护单个计数器, 还是维护多个计数器 (例如, 为节点的每个可能的源地址维护一个, 或为每个活动的 (源地址, 目的地址) 组合维护一个), 是实现选择.
原始分组结构
初始的、大的、未分片的分组称为 "original packet (原始分组)", 它被认为由两部分组成, 如下所示:
original packet:
+------------------+----------------------//-----------------------+
| Unfragmentable | Fragmentable |
| Part | Part |
+------------------+----------------------//-----------------------+
Unfragmentable Part (不可分片部分) 由 IPv6 报头加上在到达目的地的途中必须由节点处理的任何扩展报头组成, 即直到并包括 Routing header (如果存在) 的所有报头, 否则为 Hop-by-Hop Options header (如果存在), 否则没有扩展报头.
Fragmentable Part (可分片部分) 由分组的其余部分组成, 即仅需要由最终目的节点处理的任何扩展报头, 加上上层报头和数据.
原始分组的 Fragmentable Part 被分成片, 每个片 (可能除了最后一个 ("rightmost (最右边)") 片外) 的长度为 8 个八位字节的整数倍.这些片在单独的 "fragment packets (片分组)" 中传输, 如下所示:
original packet:
+------------------+--------------+--------------+--//--+----------+
| Unfragmentable | first | second | | last |
| Part | fragment | fragment | .... | fragment |
+------------------+--------------+--------------+--//--+----------+
fragment packets:
+------------------+--------+--------------+
| Unfragmentable |Fragment| first |
| Part | Header | fragment |
+------------------+--------+--------------+
+------------------+--------+--------------+
| Unfragmentable |Fragment| second |
| Part | Header | fragment |
+------------------+--------+--------------+
o
o
o
+------------------+--------+----------+
| Unfragmentable |Fragment| last |
| Part | Header | fragment |
+------------------+--------+----------+
片分组组成
每个片分组由以下部分组成:
(1) 原始分组的 Unfragmentable Part, 其中原始 IPv6 报头的 Payload Length 被改变为仅包含此片分组的长度 (不包括 IPv6 报头本身的长度), 并且 Unfragmentable Part 的最后一个报头的 Next Header 字段被改为 44.
(2) Fragment header, 包含:
-
标识原始分组的 Fragmentable Part 的第一个报头的
Next Header值. -
包含片偏移量的
Fragment Offset, 该偏移量相对于原始分组的 Fragmentable Part 的起始位置 (以 8 个八位字节为单位).第一个 ("leftmost (最左边)") 片的Fragment Offset为 0. -
如果片是最后一个 ("rightmost (最右边)") 片, 则 M flag 值为 0, 否则 M flag 值为 1.
-
为原始分组生成的
Identification值.
(3) 片本身.
片的长度必须选择使得生成的片分组适合到达分组目的地的路径的 MTU.
重新组装过程
在目的地, 片分组被重新组装成其原始的、未分片的形式, 如下所示:
reassembled original packet:
+------------------+----------------------//------------------------+
| Unfragmentable | Fragmentable |
| Part | Part |
+------------------+----------------------//------------------------+
以下规则控制重新组装:
原始分组仅从具有相同 Source Address、Destination Address 和 Fragment Identification 的片分组重新组装.
重新组装的分组的 Unfragmentable Part 由直到但不包括第一个片分组 (即 Fragment Offset 为零的分组) 的 Fragment header 的所有报头组成, 并进行以下两个更改:
-
Unfragmentable Part 的最后一个报头的
Next Header字段从第一个片的 Fragment header 的Next Header字段获得. -
重新组装的分组的
Payload Length从 Unfragmentable Part 的长度以及最后一个片的长度和偏移量计算.例如, 计算重新组装的原始分组的Payload Length的公式为:
PL.orig = PL.first - FL.first - 8 + (8 * FO.last) + FL.last
where
PL.orig = Payload Length field of reassembled packet.
PL.first = Payload Length field of first fragment packet.
FL.first = length of fragment following Fragment header of
first fragment packet.
FO.last = Fragment Offset field of Fragment header of
last fragment packet.
FL.last = length of fragment following Fragment header of
last fragment packet.
重新组装的分组的 Fragmentable Part 从每个片分组中 Fragment headers 后面的片构造.每个片的长度通过从分组的 Payload Length 中减去 IPv6 报头和片本身之间的报头的长度来计算; 其在 Fragmentable Part 中的相对位置从其 Fragment Offset 值计算.
Fragment header 不存在于最终的、重新组装的分组中.
错误条件
在重新组装分片分组时可能出现以下错误情况:
超时错误: 如果在接收到该分组的第一个到达片后 60 秒内未接收到足够的片来完成分组的重新组装, 则必须放弃该分组的重新组装, 并且必须丢弃已接收到的该分组的所有片.如果已接收到第一个片 (即 Fragment Offset 为零的片), 则应向该片的源发送 ICMP Time Exceeded -- Fragment Reassembly Time Exceeded 消息.
长度错误: 如果片的长度 (从片分组的 Payload Length 字段派生) 不是 8 个八位字节的倍数, 并且该片的 M flag 为 1, 则必须丢弃该片, 并且应向片的源发送 ICMP Parameter Problem, Code 0 消息, 指向片分组的 Payload Length 字段.
超大分组错误: 如果片的长度和偏移量使得从该片重新组装的分组的 Payload Length 将超过 65,535 个八位字节, 则必须丢弃该片, 并且应向片的源发送 ICMP Parameter Problem, Code 0 消息, 指向片分组的 Fragment Offset 字段.
非错误条件
以下情况预计不会发生, 但如果发生则不被视为错误:
报头差异: 同一原始分组的不同片的 Fragment header 之前的报头的数量和内容可能不同.无论在每个片分组中 Fragment header 之前存在什么报头, 都会在分组到达时进行处理, 然后再将片排队等待重新组装.只有 Offset 为零的片分组中的那些报头会保留在重新组装的分组中.
Next Header 差异: 同一原始分组的不同片的 Fragment headers 中的 Next Header 值可能不同.只有 Offset 为零的片分组中的值用于重新组装.