本页目录

IPv4 协议

互联网的基石协议——32 位地址空间、分片与重装、TTL 防环、DSCP/ECN 服务质量。即使 IPv6 在推进,IPv4 仍然承载着绝大部分互联网流量,它的每个字段都对应一个工程妥协。

概述

IPv4 是互联网的核心网络层协议,1981 年由 RFC 791 定义。它提供"尽力而为"的无连接数据报传输——不保证到达、不保证顺序、不保证不重复。这些保证由上层 TCP 提供。IPv4 的 32 位地址空间(43 亿地址)在 2011 年耗尽,但通过 NAT 和 CIDR 延续至今。本文聚焦 header 语义、分片/重组、PMTUD 和 QoS 标记(DSCP/ECN)——这些是理解互联网流量工程和故障诊断的基础。

IPv4 Header 逐字段

 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-byte words (最小 5 = 20B, 最大 15 = 60B)
         IHL > 5 → 有 IP options (极少)
DSCP:    DiffServ Code Point — QoS 标记 (6 bits, 替代旧 TOS field)
ECN:     Explicit Congestion Notification (2 bits)
Total Length: IP packet 总长 (含 header + data, 最大 65535B)
Identification: 每个 IP datagram 的唯一 ID (用于分片重组, 复制到所有 fragment)
Flags:
  bit 0: Reserved (永远是 0)
  bit 1: DF (Don't Fragment) — 1 = 路由器不分片, 返回 ICMP "Frag Needed"
  bit 2: MF (More Fragments) — 1 = 后续还有分片, 0 = 最后一片
Fragment Offset: 此 fragment 在原始 datagram 中的位置 (8-byte 单位)
TTL:     Time to Live — 每 hop 减 1, 到 0 时丢弃并回复 ICMP Time Exceeded
Protocol: 1=ICMP, 2=IGMP, 6=TCP, 17=UDP, 47=GRE, 50=ESP, 89=OSPF
Header Checksum: 仅 IP header (TCP/UDP 自己 checksum 覆盖 payload)

Fragmentation

分片的必要性来自"路径上 MTU 可能不同"。但现代网络极力避免 IP 层分片 — PMTUD 让端点发不超过最小 MTU 的包。

分片规则:
  1. 每个 fragment 有完整 IP header (复制自原始 datagram)
  2. 第一个 fragment: offset=0, MF=1 (除非是唯一 fragment)
  3. 中间 fragment: offset>0, MF=1
  4. 最后 fragment:  offset>0, MF=0
  5. 每个 fragment 有相同的 Identification
  6. Fragment offset 以 8 bytes 为单位 — 每个 fragment (except 最后) 的长度必须是 8 的倍数

重组:
  目标收到所有 fragments → 15s timeout → 超时 = 全部丢弃
  重组后的包大小: max offset + last fragment 的 Total Length
  问题: 丢一个 fragment → 整个 datagram 不可用 → 重传由 L4 (TCP) 负责

PMTUD (Path MTU Discovery, RFC 1191)

原理: 发送方设 DF=1 → 中间路由器 MTU 不足 → 丢包 + ICMP "Frag Needed" (type 3, code 4)
     → ICMP 包含下一跳的 MTU → 发送方更新路由缓存 → 重发更小的包

PMTUD black hole:
  ICMP 被过滤 → DF=1 包丢在路径上 → 发送方不知道 → TCP 重传 → 仍然丢 → hang

检测:
  ping -M do -s 1472 1.1.1.1
  如果: ping 通 (小包) 但 -s 1472 不通 → MTU black hole
  一定概率: MSS clamping 不够 → 某些方向通某些不通

缓解:
  TCP MSS clamping: 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):        best effort
CS1-CS7:                    向后兼容 IP Precedence 1-7
AF (Assured Forwarding):    4 classes × 3 drop precedence
  AF11 (0x0A) AF12 AF13, AF21...AF43
  → 拥塞时低 drop probability 的包优先级高
EF (Expedited Forwarding):  0x2E → 最优先, 低延迟队列 (VoIP)

Linux: iptables -j DSCP --set-dscp 0x2e or tc filter with skbedit

ECN (2 bits, RFC 3168)

ECN 用 IP header 中 DSCP 的低 2 bits + TCP header 中的 CWR/ECE flags:

00: Not ECN-capable
10: ECT(0) — ECN-capable transport, 代码点 0
01: ECT(1) — ECN-capable transport, 代码点 1
11: CE — Congestion Experienced (路由器设置!)

流程:
  发送方: ECT(0) or ECT(1) on SYN → 表示"我支持 ECN"
  路由器: 拥塞检测 (队列超过阈值) → 改 ECT 为 CE (而不是丢包!)
  接收方: 看到 CE → 设 TCP header ECE flag in ACK
  发送方: 收到 ECE → 减速 (cwnd 减半) + 设 CWR flag → 接收方停止 ECE

ECN 比丢包的优势:
  - 不丢包 → 不需要重传 → 延迟更低
  - 适合数据中心 (DCTCP = data center TCP, 基于 ECN 做 congestion control)

参考

  • 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 header, fragmentation, DF bit, PMTUD, MTU black hole, DSCP, ECN, congestion notification