このページの目次

IPv4 プロトコル

インターネットの基盤プロトコル——32ビットアドレス空間、フラグメンテーションと再構成、TTLによるループ防止、DSCP/ECNによるQoS。IPv6の展開が進む中でも、IPv4は依然としてインターネットトラフィックの大部分を担っており、その各フィールドはエンジニアリング上の妥協の産物です。

概要

IPv4 はインターネットの中核となるネットワーク層プロトコルであり、1981年に RFC 791 で定義されました。これは「ベストエフォート」の接続データグラム転送を提供し、到達保証、順序保証、重複排除保証はありません。これらの保証は上位層の TCP によって提供されます。IPv4 の 32 ビットアドレス空間(約43億アドレス)は2011年に枯渇しましたが、NAT や CIDR によって現在も運用されています。本稿では、ヘッダーのセマンティクス、フラグメンテーション/再構成、PMTUD、QoS マーキング(DSCP/ECN)に焦点を当てます。これらはインターネットトラフィックエンジニアリングと障害診断を理解する上で基礎となります。

IPv4 ヘッダー フィールド解説

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version|  IHL  |   DSCP    |ECN|         Total Length          |
|        (4)    |   (6 bits)|(2)|          (16 bits)            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Identification         |Flags|    Fragment Offset       |
|                               | R|DF|MF|    (13 bits, ×8)     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Time to Live (8) | Protocol  |        Header Checksum        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Source Address (32 bits)                   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                 Destination Address (32 bits)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options (if IHL > 5)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Version: 4 (固定)
IHL:     Internet Header Length — 4バイト単位(最小 5 = 20B, 最大 15 = 60B)
         IHL > 5 → IP options あり(稀)
DSCP:    DiffServ Code Point — QoS マーキング(6ビット、旧 TOS フィールドに代わる)
ECN:     Explicit Congestion Notification(2ビット)
Total Length: IPパケットの総長(ヘッダー + データを含む、最大 65535B)
Identification: 各 IP データグラムの一意なID(フラグメンテーション再構成用、フラグメントすべてにコピー)
Flags:
  bit 0: Reserved(常に 0)
  bit 1: DF (Don't Fragment) — 1 = ルータはフラグメンテーションしない、ICMP "Frag Needed" を返す
  bit 2: MF (More Fragments) — 1 = 後続のフラグメントがある、0 = 最後のフラグメント
Fragment Offset: 元のデータグラム内でのこのフラグメントの位置(8バイト単位)
TTL:     Time to Live — ホップごとに 1 減算、0 になると破棄され ICMP Time Exceeded を返信
Protocol: 1=ICMP, 2=IGMP, 6=TCP, 17=UDP, 47=GRE, 50=ESP, 89=OSPF
Header Checksum: IPヘッダーのみ(TCP/UDP は自身のチェックサムでペイロードをカバー)

フラグメンテーション

フラグメンテーションが必要となる理由は、「パス上の MTU が異なる可能性がある」ためです。ただし、現代のネットワークでは IP レベルのフラグメンテーションを極力避ける傾向にあり、PMTUD によりエンドポイントは最小 MTU を超えないパケットを送信します。

フラグメンテーションルール:
  1. 各フラグメントには完全な IP ヘッダーが含まれる(元のデータグラムからコピー)
  2. 最初のフラグメント: offset=0, MF=1(唯一のフラグメントでない限り)
  3. 中間のフラグメント: offset>0, MF=1
  4. 最後のフラグメント: offset>0, MF=0
  5. 各フラグメントは同じ Identification を持つ
  6. フラグメントオフセットは 8 バイト単位 — 各フラグメント(最後を除く)の長さは 8 の倍数でなければならない

再構成:
  宛先がすべてのフラグメントを受信 → 15秒のタイムアウト → タイムアウト発生 = すべて破棄
  再構成後のパケットサイズ: max offset + 最後のフラグメントの Total Length
  問題点: 1つのフラグメントが欠落 → 全体のデータグラムが使用不可 → 再送は L4 (TCP) が担当

PMTUD (Path MTU Discovery, RFC 1191)

原理: 送信側が DF=1 を設定 → 中間ルータで MTU不足 → パケット破棄 + ICMP "Frag Needed" (type 3, code 4)
     → ICMP に次ホップの MTU が含まれる → 送信側がルーティングキャッシュを更新 → より小さなパケットで再送信

PMTUD ブラックホール:
  ICMP がフィルタリングされる → DF=1 のパケットがパス上で破棄される → 送信側はそれを認識しない → TCP 再送 → 依然として破棄 → ハングアップ

検出:
  ping -M do -s 1472 1.1.1.1
  結果: ping は成功(小パケット)だが、-s 1472 では失敗 → MTU ブラックホール
  確率的に: MSS クランプが不十分 → 一部の方向は通信可能、他は不可

緩和策:
  TCP MSS クランプ: iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
  → ICMP がフィルタリングされていても、SYN 時の MSS が小さく設定される → 後続のパケットサイズが小さくなる → フラグメンテーション不要

DSCP と ECN

DSCP (6 bits, RFC 2474)

旧 IP Precedence (3 bits) に代わり、後方互換性を持つ:

Default (CS0, 0x00):        ベストエフォート
CS1-CS7:                    IP Precedence 1-7 に後方互換
AF (Assured Forwarding):    4クラス × 3ドロップ優先度
  AF11 (0x0A) AF12 AF13, AF21...AF43
  → 輻輳時にドロップ確率が低いパケットが優先
EF (Expedited Forwarding):  0x2E → 最優先、低遅延キュー(VoIP用)

Linux: iptables -j DSCP --set-dscp 0x2e または tc filter with skbedit

ECN (2 bits, RFC 3168)

ECN は IP ヘッダーの DSCP 下位 2 ビット + TCP ヘッダーの CWR/ECE フラグを使用:

00: ECN 非対応
10: ECT(0) — ECN 対応トランスポート、コードポイント 0
01: ECT(1) — ECN 対応トランスポート、コードポイント 1
11: CE — 輻輳発生(ルータが設定)

フロー:
  送信側: SYN で ECT(0) または ECT(1) を設定 → 「ECN 対応」を示す
  ルータ: 輻輳検知(キューが閾値超過)→ ECT を CE に変更(パケット破棄ではなく!)
  受信側: CE を検知 → ACK で TCP ヘッダーの ECE フラグを設定
  送信側: ECE を受信 → 減速(cwnd を半減)+ CWR フラグを設定 → 受信側は ECE を停止

ECN の利点(パケット破棄と比較して):
  - パケットが破棄されない → 再送不要 → 遅延が低い
  - データセンターに適している(DCTCP = データセンター用 TCP、ECN に基づく輻輳制御)

参考

  • RFC: 791, 1191, 2474, 3168
  • ソースコード⁠: net/ipv4/ip_input.c (ip_rcv), net/ipv4/ip_fragment.c (フラグメンテーション/再構成)
  • ツール⁠: ping -M do, tracepath, iptables DSCP, sysctl net.ipv4.tcp_ecn

Keywords: IPv4 ヘッダー, フラグメンテーション, DF ビット, PMTUD, MTU ブラックホール, DSCP, ECN, 輻輳通知