The IP Packet - IPv4 Header, TTL, Protocol Field
- The IPv4 header is a 20-byte fixed layout plus up to 40 bytes of options. The 4-bit IHL counts 32-bit words, so the header is at most 15 x 4 = 60 bytes.
- It is the minimal routing envelope: where from (source), where to (destination), who handles the payload (protocol), and how long it may live (TTL).
- TTL is decremented by every router. When a router cannot forward a packet because TTL has run out, it drops it and sends ICMP type 11, code 0 (time exceeded) to the source. TTL counts hops, not seconds.
- The protocol field is the demux key above IP:
1ICMP,6TCP,17UDP. Ports only mean something after it picks the transport. - The header checksum covers the header only and is recomputed at every hop because TTL changes. IPv6 dropped it.
Mental model
The address label on a parcel, plus a stamp that says "return to sender after 64 hand-offs". The label names where it came from and where it is going, whether the contents are a letter, a package or a postcard (the protocol), and how big the whole parcel is. Every sorting office adds one tick to the stamp. If the stamp fills up, the parcel is binned and a "could not deliver" note goes back to the sender, so a parcel stuck in a loop cannot circle forever.
Where it breaks: a parcel keeps one label for the whole trip. An IP packet's header is rewritten at every hop (TTL goes down, the checksum changes), and the sorting offices work from a table of prefixes, not from reading a street address.
A fixed-layout struct in network byte order that every router parses before it looks at anything else, like the request line of an HTTP message but in binary. The protocol field is a type tag that selects the next parser, the same role as a content-type header. TTL is a hop budget, like a max-redirects counter in an HTTP client that stops redirect loops.
Where it breaks: a max-redirects counter is checked by the client that owns the request. TTL is decremented by third parties along the path, and the packet's author learns about expiry only through a separate ICMP message that may be rate-limited or filtered.
How it works
An IP packet is the IP header followed by the payload (a TCP segment, a UDP datagram, an ICMP message). The layout is defined in RFC 791 section 3.1; the addresses are covered in IP addressing and what a router does with the destination is in forwarding and routing. This page is about everything else in the header.
The fields, with sizes that add up
Each row of the diagram is 4 bytes, so the fixed part is 5 rows x 4 = 20 bytes. The bit widths in row 1 are 4 + 4 + 6 + 2 + 16 = 32, in row 2 are 16 + 3 + 13 = 32, and in row 3 are 8 + 8 + 16 = 32.
| Field | Size | Bytes | What it does |
|---|---|---|---|
| Version | 4 bits | 0 | always 4 for IPv4 (IPv6 uses 6 in the same position) |
| IHL | 4 bits | 0 | header length in 32-bit words; minimum 5, maximum 15 |
| DSCP | 6 bits | 1 | differentiated services code point: the QoS class (RFC 2474) |
| ECN | 2 bits | 1 | explicit congestion notification: ECN-capable, or congestion experienced (RFC 3168) |
| Total length | 16 bits | 2-3 | header plus payload in bytes; at most 65,535 |
| Identification | 16 bits | 4-5 | tags the fragments of one original datagram; see fragmentation |
| Flags | 3 bits | 6 | reserved (must be 0), DF (do not fragment), MF (more fragments) |
| Fragment offset | 13 bits | 6-7 | where this fragment's data starts, in 8-byte units; see fragmentation |
| Time to live | 8 bits | 8 | hop budget, decremented by each router |
| Protocol | 8 bits | 9 | which protocol is in the payload, an IANA-assigned number |
| Header checksum | 16 bits | 10-11 | ones-complement checksum over the header only |
| Source address | 32 bits | 12-15 | sender; see IP addressing |
| Destination address | 32 bits | 16-19 | receiver (or group, or broadcast) |
| Options | 0 to 320 bits | 20-59 | rare; padded to a multiple of 4 bytes |
The same fields as a lookup-only bit diagram live in Header diagrams. The ID, flag and offset mechanics are explained once, on the MTU, MSS and fragmentation page; this page does not repeat them.
Header length. IHL is in 32-bit words. IHL 5 gives 5 x 4 = 20 bytes (no options); IHL 15 gives 15 x 4 = 60 bytes, so options take at most 60 - 20 = 40 bytes. Total length is a 16-bit byte count, so a packet is at most 216 - 1 = 65,535 bytes, and the payload starts at IHL x 4.
Worked example: one packet, byte by byte
A host at 192.0.2.10 sends a TCP segment to 203.0.113.5 (both are documentation addresses from RFC 5737). The packet is a full-size 1500-byte one: 20 bytes of IP header plus 1,480 bytes of payload (a 20-byte TCP header and 1,460 bytes of data). The values are chosen for illustration, including the ID 0x1c46.
| Bytes | Field | Value | Hex |
|---|---|---|---|
| 0 | Version, IHL | 4, 5 | 45 |
| 1 | DSCP, ECN | 0, 0 | 00 |
| 2-3 | Total length | 1500 | 05dc |
| 4-5 | Identification | 7238 (illustrative) | 1c46 |
| 6-7 | Flags, offset | DF set, MF clear, offset 0 | 4000 |
| 8 | TTL | 64 | 40 |
| 9 | Protocol | 6 (TCP) | 06 |
| 10-11 | Checksum | computed below | 1ac6 |
| 12-15 | Source | 192.0.2.10 | c000020a |
| 16-19 | Destination | 203.0.113.5 | cb007105 |
Derivations: 1500 = 5 x 256 + 220 = 0x05dc. The flags and offset word is the flag bits 010 (reserved 0, DF 1, MF 0) followed by 13 zero bits, which is 0100 0000 0000 0000 = 0x4000. The 20 bytes are therefore 45 00 05 dc 1c 46 40 00 40 06 1a c6 c0 00 02 0a cb 00 71 05.
The checksum, by hand. Treat the header as ten 16-bit words with the checksum field set to zero, add them, fold the carry back in, and complement (RFC 791 section 3.1; the Internet checksum method is also worked in error detection and defined in RFC 1071).
| Word | Value | Running sum |
|---|---|---|
| version, IHL, DSCP/ECN | 4500 | 4500 |
| total length | 05dc | 4adc |
| identification | 1c46 | 6722 |
| flags, offset | 4000 | a722 |
| TTL, protocol | 4006 | e728 |
| checksum (zero for now) | 0000 | e728 |
| source, high | c000 | 1a728 |
| source, low | 020a | 1a932 |
| destination, high | cb00 | 2a432 |
| destination, low | 7105 | 2e537 |
The sum is 0x2e537. Fold the carry: 0xe537 + 0x2 = 0xe539. Complement: 0xffff - 0xe539 = 0x1ac6. That is the checksum. To verify, a receiver adds all ten words including the checksum: 0xe539 + 0x1ac6 = 0xffff, and a valid header always sums to all-ones.
What each hop does
A router that forwards this packet decrements TTL and rewrites the checksum; nothing else in the IP header changes (NAT is the common case where an address changes, see NAT). The router also builds a new link-layer frame, as in layers and encapsulation.
After one hop, TTL is 63 (0x3f), so the TTL and protocol word is 0x3f06, not 0x4006. Redo the sum: the total falls by 0x0100, from 0x2e537 to 0x2e437, which folds to 0xe439, and the checksum becomes 0xffff - 0xe439 = 0x1bc6. It went from 1ac6 to 1bc6: the checksum rose by 0x0100 exactly because the data fell by 0x0100.
Routers do not have to redo the whole sum. RFC 1624 gives the incremental update HC' = ~(~HC + ~m + m'), where HC is the old checksum, m the old 16-bit word and m' the new one. Here ~HC = 0xe539, ~m = ~0x4006 = 0xbff9, m' = 0x3f06. Then 0xe539 + 0xbff9 = 0x1a532, which folds to 0xa533; adding 0x3f06 gives 0xe439; complementing gives 0x1bc6, the same answer.
The figure shows TTL as seen on each link: 3, then 2, then 1. R3 cannot forward a packet whose TTL would reach 0, so, as RFC 1812 requires of a router, it discards the packet and sends an ICMP time exceeded message to the source. That message is ICMP type 11, code 0 ("time to live exceeded in transit", RFC 792), and it carries the original IP header plus the first 8 bytes of the payload so the sender can match it to a flow. How traceroute turns that into a path is on the traceroute page.
Deep dive
The header checksum covers the header only
The checksum protects only the 20 to 60 header bytes, not the payload. A corrupted destination address would send the packet to the wrong place, so the header is checked at every hop; payload integrity is left to the transport checksum (TCP, UDP) and the link-layer CRC. Because TTL changes at every hop, the checksum changes at every hop: the router either recomputes it or applies the incremental update from RFC 1624, as worked above.
Why IPv6 dropped it. The IPv6 header has no checksum, so no router has to update one per hop, and UDP over IPv6 makes its own checksum mandatory (RFC 8200 section 8.1) to compensate. The remaining header differences are in IPv6. The argument is that the link-layer CRC and the transport checksum already catch errors, so the per-hop header check adds cost without much added protection.
TTL: defaults and what they reveal
The initial TTL is chosen by the sender's operating system. Linux defaults to 64 (ip_default_ttl in the kernel's ip-sysctl documentation). Windows has long used 128; Microsoft's parameter reference lists it as the DefaultTTL default (the page is written for Windows XP, so confirm on a current system) (Microsoft TCP/IP configuration parameters). Routers and network devices commonly originate packets with 255, but that is vendor-specific, so check the device's documentation instead of assuming it.
Because both the sender's initial TTL and the hop count are unknown to an observer, a packet that arrives with TTL 57 is consistent with an initial 64 and 7 hops, but that is an inference, not a fact. This is the basis of passive OS fingerprinting, and it is why it is only a hint.
RFC 791's wording. The RFC defines TTL as a maximum time in seconds, with each module that handles the packet subtracting at least one. RFC 1812 states the practical rule for routers: decrement by 1 per hop.
The protocol field is the demux key
After IP delivers a packet to the right host, the protocol field selects which handler receives the payload. IANA keeps the registry; the ones you meet most:
| Number | Protocol | Where it shows up |
|---|---|---|
| 1 | ICMP | ping, traceroute, errors; see ICMP |
| 2 | IGMP | IPv4 multicast group membership |
| 6 | TCP | most application traffic; see TCP |
| 17 | UDP | DNS, QUIC, media; see UDP |
| 41 | IPv6 encapsulation | an IPv6 packet carried in an IPv4 packet (6in4 tunnels) |
| 47 | GRE | generic tunnel encapsulation |
| 50 | ESP | IPsec encrypted payload; see VPN and IPsec |
| 89 | OSPF | OSPF talks directly over IP, not over TCP or UDP; see OSPF |
IP picks the transport first (protocol), and the transport picks the socket second (port). Ports only mean something once the protocol has said TCP or UDP, which is why ICMP and OSPF have no ports at all. The second step is covered in ports, sockets and demultiplexing.
DSCP and ECN: the old ToS byte
Byte 1 was the Type of Service byte in RFC 791. RFC 2474 redefined its top 6 bits as the DSCP, a class label that routers map to a queue or drop priority (per-hop behaviour). RFC 3168 assigned the bottom 2 bits to ECN:
| ECN bits | Name | Meaning |
|---|---|---|
00 | Not-ECT | the sender does not support ECN |
10 | ECT(0) | ECN-capable transport |
01 | ECT(1) | ECN-capable transport |
11 | CE | congestion experienced: a router marked the packet instead of dropping it |
With ECN a congested router sets CE rather than dropping, and the receiver echoes it to the sender through the transport header; the reaction is in congestion control. The DSCP and ECN bits are independent: byte 1 = 0x00 in the worked packet means default class and no ECN.
Options are rare and slow
IHL above 5 means options follow the fixed header, padded to a 4-byte boundary, up to 40 bytes. Packets with options are commonly handled on a router's slow path (the general-purpose CPU rather than the forwarding hardware), and RFC 7126 records that operators often filter or drop them. The router alert option (RFC 2113) asks each router on the path to examine the packet more closely, which is one reason such packets get punted. Ordinary web traffic carries none, so 20 bytes is also the typical header.
Total length, MTU and the identification field
Total length is the size of this packet; the MTU is the size a link will carry. A packet longer than the egress link's MTU must be fragmented or dropped, as covered in MTU, MSS and fragmentation. The ID field's modern rule is in RFC 6864: uniqueness matters only for packets that may be fragmented, so an atomic datagram (DF set, not a fragment) can carry any ID.
Textbook vs real world
| The textbook says | Production does | Why |
|---|---|---|
| TTL is the hop count of the path | TTL also drives traceroute, loop protection and rough OS fingerprinting; its starting value is an OS choice | The field only guarantees a hop budget; every use beyond that is a side effect |
| Options extend the header | Many networks filter or slow-path packets with options, so they are almost never used | RFC 7126 documents the filtering because of the slow path and attack surface |
| DSCP marks traffic and the network honours it | Operators often re-mark DSCP at the edge of their network | Each administrative domain defines its own classes, so a mark from outside is not trusted |
| The ID field makes every packet unique | It only has to be unique enough to reassemble fragments | RFC 6864 drops the uniqueness requirement for packets that cannot be fragmented |
| The checksum protects the packet | It protects the header only; the data is protected by the transport checksum | Cheap per-hop check; the end-to-end check belongs to TCP and UDP |
In production
- ECMP load balancing commonly hashes header fields (source and destination address, protocol, and the transport ports, the 5-tuple) so every packet of a flow takes one path and stays in order. RFC 2992 analyses hash-threshold ECMP.
- DSCP marking in operator networks is the mechanism RFC 2474 defines for per-class queueing, and RFC 4594 gives configuration guidelines for service classes.
- BGP TTL security (GTSM) sends BGP packets with TTL 255 and drops any that arrive with a lower value, so an attacker more than one hop away cannot forge a session (RFC 5082).
- Anycast is not visible in the header: the destination is an ordinary unicast address, announced from several places (see BGP).
History and evolution
- 1981 RFC 791 (Jon Postel, ed.) specifies IPv4 with a header checksum, a time-in-seconds TTL and a Type of Service byte. The checksum has stayed in IPv4 ever since.
- 1995 RFC 1812, the router requirements, fixes the practical rule: a router decrements TTL by 1 per hop, so TTL is a hop count in practice.
- 1998 RFC 2474 redefines the ToS byte as DSCP, and 2001 - RFC 3168 takes its last two bits for ECN.
- 2013 RFC 6864 updates the ID field rules for atomic datagrams, so a sender that never fragments need not keep IDs unique.
- Now IPv4 still carries a large share of traffic next to IPv6; Google publishes a live IPv6 adoption graph, so read the current figure there rather than trusting a frozen number.
- Next IPv6 keeps the same ideas with a simpler 40-byte header and no header checksum; see IPv6.
Hands-on
Capture one outgoing request and read the IP line. This is illustrative output in the format tcpdump -v prints; your numbers will differ.
Read it left to right: tos 0x0 is DSCP and ECN, ttl 64 is a Linux-style sender, flags [DF] says it will not be fragmented, proto TCP (6) is the demux key, and length 1500 is total length. 1500 - 20 - 20 = 1460 matches the TCP length. A capture on the sending host may show a bad checksum, because the NIC fills it in after the capture point.
Watch TTL expire on Linux with a one-hop budget (illustrative output):
The address is the first router, which is the sender of the ICMP message. On macOS the TTL flag is -m (-t is a timeout there); on Windows it is -i. For the whole path, traceroute -n example.com repeats this with TTL 1, 2, 3 and so on. In Wireshark, expand the "Internet Protocol Version 4" tree to see each field, including the checksum.
Gotchas
Interview questions
Show answer
The fixed header is 20 bytes. Version (4) and IHL (header length in 32-bit words) come first, then DSCP and ECN for QoS and congestion marks, total length, then identification, flags and fragment offset for fragmentation. TTL limits the hops, protocol names the payload (6 TCP, 17 UDP, 1 ICMP), the header checksum covers the header, and then come the source and destination addresses. Options are optional and rare.
Follow-ups:
- How long can the header be? IHL is 4 bits counting 32-bit words, so at most 15 x 4 = 60 bytes.
- Which fields does fragmentation use? Identification, flags (DF, MF) and fragment offset; see the MTU page.
Show answer
TTL is a hop budget set by the sender and decremented by every router. A router that cannot forward a packet because TTL would reach 0 drops it and sends an ICMP time exceeded message (type 11, code 0) to the source. This stops packets looping forever when routing is broken.
Follow-ups:
- How does traceroute use it? It sends probes with TTL 1, 2, 3 and so on and reads the source address of each ICMP time exceeded reply.
- Is TTL in seconds? No, it is a hop count in practice.
Show answer
It tells the receiving IP layer which protocol the payload belongs to, so the packet is handed to the right handler. Common values are 1 for ICMP, 6 for TCP and 17 for UDP, from the IANA registry. Ports are interpreted only after the protocol selects TCP or UDP.
Follow-ups:
- Why do ICMP and OSPF have no ports? They sit directly on IP and have their own protocol numbers (1 and 89).
- What is protocol 41? An IPv6 packet inside an IPv4 packet.
Show answer
The router builds a new link-layer header (new MAC pair), decrements TTL and updates the header checksum. The source address, destination address, protocol, ID and the payload stay as they were, unless a NAT is on the path and rewrites an address and the transport checksum.
Follow-ups:
- Why must the checksum change? It covers the header, and TTL is in the header.
- How is it updated cheaply? Incrementally, per RFC 1624, from the old and new TTL word.
Show answer
IPv4 included it in 1981 to catch corrupted headers, which would otherwise misroute a packet. It costs every router an update per hop because TTL changes. IPv6 removed it because link-layer CRCs and transport checksums already catch errors, and it simplifies forwarding; to compensate, UDP over IPv6 makes its checksum mandatory.
Follow-ups:
- Does the IPv4 checksum protect the payload? No, header only.
- Does removing it risk misdelivery? The transport checksum includes a pseudo-header with the addresses, so a wrongly delivered packet fails there.
Show answer
When a packet exceeds a link's MTU and DF is clear, the router splits it. All fragments carry the original ID, every fragment except the last has MF set, and each carries its payload's offset in 8-byte units so the receiver can reassemble. If DF is set the router drops the packet and sends ICMP fragmentation needed instead. The mechanics and numbers are on the MTU page.
Follow-ups:
- Why 8-byte units? The offset field is 13 bits, and 213 x 8 = 65,536 bytes covers the 16-bit total length range.
- What does RFC 6864 say about ID? It need not be unique for packets that cannot be fragmented.
Show answer
They split the old Type of Service byte. DSCP (6 bits) labels the traffic class so routers can queue or drop by class. ECN (2 bits) lets a congested router mark a packet instead of dropping it, and the endpoints react through the transport protocol.
Follow-ups:
- Is DSCP trusted across the Internet? Often not; operators re-mark it at their edges.
- What are the four ECN values? 00 Not-ECT, 10 and 01 ECT, 11 congestion experienced.
Fun facts
- The field is called Time to Live because RFC 791 specified it as a time in seconds, with each module that handles the packet subtracting at least one. Practice reduced it to a hop count.
- A valid IPv4 header always sums to
0xffffwhen the checksum is included, so the all-ones result you computed above is the check passing, not an error.
Cheat sheet
- 20 B - minimum IPv4 header (IHL 5); 60 B maximum (IHL 15)
- 65,535 B - maximum total length
- 1 / 6 / 17 - protocol numbers for ICMP, TCP, UDP
- 64 / 128 - default initial TTL on Linux and Windows
- ICMP type 11, code 0 - TTL expired in transit