4.5 フラグメントヘッダー (Fragment Header)
Fragment ヘッダーは、IPv6 の送信元が宛先までのパスの MTU より大きいパケットを送信するために使用します。(注意: IPv4 とは異なり、IPv6 ではフラグメント化は送信元ノードのみが行い、パケット配送経路上のルーターは行いません — 第 5 節を参照。)Fragment ヘッダーは直前のヘッダーの 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 フラグ (M flag) — 1 = 後続フラグメントあり、0 = 最後のフラグメント。
識別子 (Identification) — 32 ビット。以下の説明を参照。
宛先までのパスの MTU より大きいパケットを送信するために、送信元ノードはパケットをフラグメントに分割し、各フラグメントを個別のパケットとして送信し、受信側で再組み立てします。
フラグメント化する各パケットに対して、送信元ノードは Identification 値を生成します。この Identification は、同じ Source Address と Destination Address を持つ最近*送信された他のフラグメント化パケットの識別子と異なっていなければなりません。Routing ヘッダーが存在する場合、対象となる Destination Address は最終宛先のアドレスです。
*「最近」とは、送信元から宛先までの転送時間と、同じパケットの他のフラグメントと再組み立てを待つ時間を含む、パケットの最大可能生存期間内を意味します。ただし、送信元ノードが最大パケット生存期間を知っている必要はありません。代わりに、
Identification値を単純な 32 ビットの「ラップアラウンド (wrap-around)」カウンターとして維持し、パケットをフラグメント化するたびにインクリメントすることでこの要件を満たせると仮定されます。ノードに対して単一のカウンターを維持するか、複数のカウンター(例えば、ノードの各可能な送信元アドレスに対して一つ、または各アクティブな(送信元アドレス、宛先アドレス)の組み合わせに対して一つ)を維持するかは実装の選択です。
元のパケット構造
初期の大きな未フラグメント化パケットを「元のパケット (original packet)」と呼び、以下のように二つの部分から構成されると考えます。
original packet:
+------------------+----------------------//-----------------------+
| Unfragmentable | Fragmentable |
| Part | Part |
+------------------+----------------------//-----------------------+
Unfragmentable Part(フラグメント化不可部分) は、IPv6 ヘッダーと、宛先に到達する途中でノードが処理しなければならない拡張ヘッダー(すなわち、Routing ヘッダーが存在する場合はそれまでのすべてのヘッダー、なければ Hop-by-Hop Options ヘッダーが存在する場合はそれまで、なければ拡張ヘッダーなし)で構成されます。
Fragmentable Part(フラグメント化可能部分) は、パケットの残りの部分、すなわち最終宛先ノードのみが処理する必要がある拡張ヘッダー、上位層ヘッダー、およびデータで構成されます。
元のパケットの Fragmentable Part はフラグメントに分割され、各フラグメント(最後の「最右端 (rightmost)」フラグメントを除く)の長さは 8 オクテットの整数倍です。これらのフラグメントは個別の「フラグメントパケット (fragment packets)」として送信されます。
fragment packets:
+------------------+--------+--------------+
| Unfragmentable |Fragment| first |
| Part | Header | fragment |
+------------------+--------+--------------+
+------------------+--------+--------------+
| Unfragmentable |Fragment| second |
| Part | Header | fragment |
+------------------+--------+--------------+
o
o
+------------------+--------+----------+
| Unfragmentable |Fragment| last |
| Part | Header | fragment |
+------------------+--------+----------+
フラグメントパケットの構成
各フラグメントパケットは以下の部分から構成されます。
(1) 元のパケットの Unfragmentable Part。ただし、元の IPv6 ヘッダーの Payload Length はこのフラグメントパケットの長さのみを含むように変更され(IPv6 ヘッダー自体の長さは除く)、Unfragmentable Part の最後のヘッダーの Next Header フィールドは 44 に変更されます。
(2) Fragment ヘッダー。以下を含みます。
- 元のパケットの Fragmentable Part の最初のヘッダーを識別する
Next Header値。 - 元のパケットの Fragmentable Part の先頭からのフラグメントオフセット(8 オクテット単位)を含む
Fragment Offset。最初の「最左端 (leftmost)」フラグメントのFragment Offsetは 0 です。 - フラグメントが最後の「最右端 (rightmost)」フラグメントであれば M フラグ値 0、そうでなければ 1。
- 元のパケットに対して生成された
Identification値。
(3) フラグメント自体。
フラグメントの長さは、生成されるフラグメントパケットがパケットの宛先までのパスの MTU に収まるように選択されなければなりません。
再組み立てプロセス
宛先では、フラグメントパケットは以下のように元の未フラグメント化形式に再組み立てされます。
reassembled original packet:
+------------------+----------------------//------------------------+
| Unfragmentable | Fragmentable |
| Part | Part |
+------------------+----------------------//------------------------+
再組み立てを制御するルールは以下の通りです。
元のパケットは、同じ Source Address、Destination Address、および Fragment Identification を持つフラグメントパケットからのみ再組み立てされます。
再組み立てされたパケットの Unfragmentable Part は、最初のフラグメントパケット(Fragment Offset がゼロのもの)の Fragment ヘッダーまでのすべてのヘッダーで構成され、以下の二つの変更が加えられます。
- Unfragmentable Part の最後のヘッダーの
Next Headerフィールドは、最初のフラグメントの Fragment ヘッダーのNext Headerフィールドから取得されます。 - 再組み立てされたパケットの
Payload Lengthは、Unfragmentable Part の長さと最後のフラグメントの長さおよびオフセットから計算されます。
PL.orig = PL.first - FL.first - 8 + (8 * FO.last) + FL.last
ここで
PL.orig = 再組み立てされたパケットの Payload Length フィールド
PL.first = 最初のフラグメントパケットの Payload Length フィールド
FL.first = 最初のフラグメントパケットの Fragment ヘッダーに続くフラグメントの長さ
FO.last = 最後のフラグメントパケットの Fragment ヘッダーの Fragment Offset フィールド
FL.last = 最後のフラグメントパケットの Fragment ヘッダーに続くフラグメントの長さ
再組み立てされたパケットの Fragmentable Part は、各フラグメントパケットの Fragment ヘッダーに続くフラグメントから構築されます。Fragment ヘッダーは最終的な再組み立てされたパケットには存在しません。
エラー条件
フラグメント化されたパケットの再組み立て中に以下のエラー条件が発生する可能性があります。
タイムアウトエラー: 最初のフラグメントが到着してから 60 秒以内にパケットの再組み立てを完了するのに十分なフラグメントが受信されない場合、再組み立てを放棄し、受信済みのすべてのフラグメントを破棄しなければなりません。最初のフラグメント(Fragment Offset がゼロのもの)が受信済みの場合、そのフラグメントの送信元に ICMP Time Exceeded — Fragment Reassembly Time Exceeded メッセージを送信すべきです。
長さエラー: フラグメントの長さ(フラグメントパケットの Payload Length フィールドから導出)が 8 オクテットの倍数でなく、かつそのフラグメントの M フラグが 1 の場合、そのフラグメントを破棄し、フラグメントの送信元に ICMP Parameter Problem, Code 0 メッセージを送信し、フラグメントパケットの Payload Length フィールドを指すべきです。
超大パケットエラー: フラグメントの長さとオフセットにより、そのフラグメントから再組み立てされるパケットの Payload Length が 65,535 オクテットを超える場合、そのフラグメントを破棄し、フラグメントの送信元に ICMP Parameter Problem, Code 0 メッセージを送信し、フラグメントパケットの Fragment Offset フィールドを指すべきです。