On this page

ICMP and PMTUD

The control plane of the Internet — ICMP is not just for ping; it is the engine for PMTUD (Path MTU Discovery) and the feedback channel for unreachable routes. The PMTUD "black hole" failure — where firewalls block ICMP, causing TCP to hang — is the most classic troubleshooting case at the L2-L4 boundary.

Overview

ICMP (Internet Control Message Protocol) is the diagnostic and control auxiliary layer for the IP protocol. It is not a transport protocol — it does not carry application data — but rather a channel for network devices to report errors (unreachable, timeout) and exchange information (echo request/response). Ping and traceroute are the most common ICMP tools. PMTUD (Path MTU Discovery) uses ICMP "Fragmentation Needed" messages to inform the sender of the minimum MTU along the path — this is more efficient than blind fragmentation, but when ICMP is filtered by firewalls, it can lead to silent failures (MTU black hole).

ICMPv4 Message Structure

ICMP is a subordinate protocol of IP (protocol=1, encapsulated in IP packets):

[IP Header | ICMP Type (1B) | Code (1B) | Checksum (2B) | ICMP Body]

Major Type Categories:
  0:    Echo Reply
  3:    Destination Unreachable (codes: 0=Net, 1=Host, 3=Port, 4=Frag Needed, 13=Administratively Prohibited)
  5:    Redirect (codes: 0=Net, 1=Host)
  8:    Echo Request (ping)
  11:   Time Exceeded (codes: 0=TTL expired in transit, 1=Fragment reassembly timeout)
  12:   Parameter Problem (codes: 0=IP header bad, 1=Required option missing)

Destination Unreachable (type 3)

Code 4 (Fragmentation Needed) is the most critical — it is the sole signal for PMTUD:

RFC 1191 extends the body of the code 4 message:
  [unused 2B][Next-Hop MTU 2B][original IP header + first 8B of payload]
  → Next-Hop MTU = MTU of the next hop (e.g., 1492 for PPPoE)
  → Original IP header + first 8B → allows the sender to match which connection it belongs to

Ping

Echo Request (type 8) → Echo Reply (type 0):

Identifier (2B): Usually = process PID (Unix ping) — used to match reply and request
Sequence Number (2B): Increments (each probe +1)
Data: Variable (Unix: default 56B, padded to 64B including ICMP header)

TTL Interpretation:
  $ ping 1.1.1.1 → reply: ttl=57
  → Initial TTL (default for this host) = 64 (Linux)
  → 64 - 57 = 7 hops away

  $ ping 1.1.1.1 → reply: ttl=119
  → Sender's initial TTL = 128 (Windows)

  → Can infer target OS: Linux/Unix = 64, Windows = 128, Solaris = 255

ping -M do (DF bit):
  Test PMTUD: Send large packet + DF=1 → If MTU somewhere along the path < packet size → Frag Needed or timeout

Traceroute

Gradually increases TTL → each hop returns ICMP Time Exceeded (type 11, code 0):

traceroute 1.1.1.1:
  Probe 1: TTL=1, UDP dst port 33434 → Router_1 drops + replies with ICMP Time Exceeded
  Probe 2: TTL=2, UDP dst port 33435 → Router_2 drops + replies with ICMP Time Exceeded
  Probe 3: TTL=3, UDP dst port 33436 → Destination (1.1.1.1): Port Unreachable (ICMP Port Unreachable)
  → End

  Per-hop 3 probes: Detects multipath per hop (possibly 3 different IPs corresponding to different paths)

IPv6 traceroute: Uses UDP or ICMPv6 Echo, mechanism is the same

PMTUD: Complete Flow

Sender: TCP connection to server, MSS=1460, DF=1
  1. Data packet sent by server: size=1500B (MSS 1460 + TCP header 20 + IP header 20)
  2. Intermediate router: interface MTU = 1492 (PPPoE) → drops packet + sends ICMP Frag Needed (code 4, MTU=1492)
  3. Sender: Receives ICMP → updates routing cache PMTU = 1492 → retransmits smaller packet (MSS 1452 = 1492 - 40B TCP+IP)
  4. Subsequent packets: MSS=1452 → no longer triggers PMTUD

PMTU Cache:
  ip route get <dst> → cache mtu xxx
  Linux: per-route PMTU, 10 min expiry → re-probe after expiration

Blacklist/Workaround:
  TCP MTU probing: tcp_mtu_probing=1 → When TCP retransmissions occur consecutively,
  automatically attempts to reduce MSS (does not wait for ICMP, preventing issues when ICMP is filtered)

  sysctl net.ipv4.tcp_mtu_probing=1

IPv6 PMTUD (RFC 8201):
  Same principle, uses ICMPv6 Packet Too Big (type 2, code 0)
  But IPv6 header is fixed at 40B → MTU calculation is simpler

References

  • RFC: 792, 4443, 1191, 8201
  • Tools: ping -M do, traceroute -T -p 443 (TCP), tracepath, mtr
  • Source Code: net/ipv4/icmp.c, net/ipv6/icmp.c

Keywords: ICMP, Destination Unreachable, ping, traceroute, PMTUD, Frag Needed, MTU black hole, MSS clamping