IPv4 Packet Structure

IPv4 Packet Structure

In TCP/IPv4 packets, there is a TCP (or UDP) packet header, then an IPv4 packet header, then the packet data. Each header is a structured collection of data, including things such as the IPv4 source address (who sent the packet), and the IPv4 destination address (who it was sent to). Why are we getting down to this level of detail? Because some of the big changes from IPv4 to IPv6 have to do with the new and improved IP packet header architecture in IPv6.

IPv4 Packet Header

In this section, we’ll cover the IPv4 packet header.  Here it is:

IPv4 Packet Header

The IP Version field (4 bits) contains the value 4, which in binary is “0100” (you’ll never guess what goes in the first 4 bits of an IPv6 packet header!).

The Header Length field (4 bits) indicates how long the header is, in 32 bit “words”. The minimum value is “5” which would be 160 bits, or 20 bytes. The maximum length is 15, which would be 480 bits, or 60 bytes. If you skip that number of words from the start of the packet, that is where the data starts (this is called the “offset” to the data). This will only ever be greater than 5 if there are options before the data part (which is not common).

The Type of Service field (8 bits) is defined in RFC 2474, “Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 headers”, December 1998. This is used to implement a fairly simple QoS (Quality of Service). QoS involves management of bandwidth by protocol, by sender, or by recipient. For example, you might want to give your VoIP connections a higher priority than your video downloads, or the traffic from your boss higher priority than your co-worker’s traffic. Without QoS, bandwidth is on a first-come-first served basis. 8 bits is not really enough to do a good job on QoS, and DiffServ is not widely implemented in current IPv4 networks. QoS is greatly improved in IPv6.

The Total Length field (16 bits) contains the total length of the packet, including the packet header, in bytes. The minimum length is 20 (20 bytes of header plus 0 bytes of data), and the maximum is 65,535 bytes (since only 16 bits are available to specify this). All network systems must handle packets of at least 576 bytes, but a more typical packet size is 1508 bytes. With IPv4, it is possible for some devices (like routers) to fragment packets (break them apart into multiple smaller packets) if required to get them through a part of the network that can’t handle packets that big. Packets that are fragmented must be reassembled at the other end. Fragmentation and reassembly is one of the messy parts of IPv4 that got cleaned up a lot in IPv6.

The Identification (Fragment ID) field (16 bits) identifies which fragment of a once larger packet this one is, to help in reassembling the fragmented packet later. In IPv6 packet fragmentation is not done by intermediate nodes, so all the header fields related to fragmentation are no longer needed.

The next three bits are flags related to fragmentation. The first is reserved and must be zero (an April Fool’s RFC once defined this as the “evil” bit). The next bit is the DF (Don’t Fragment) flag.  If DF is set, the packet cannot be fragmented (so if such a packet reaches a part of the network that can’t handle one that big, that packet is dropped). The third bit is the MF (More Fragments) flag. If MF is set, there are more fragments to come. Unfragmented packets of course have the MF flag set to zero.

The Fragment Offset field (13 bits) is used in reassembly of fragmented packets. It is measured in 8 byte blocks. The first fragment of a set has an offset of 0. If you had a 2500 byte packet, and it was fragmented into chunks of 1000 bytes or less, you would have three fragments as follows:

Fragment ID MF Flag Total Length Data Size Offset
1 1 1020 1000 0
2 1 1020 1000 125
3 0 520 500 250

The Time To Live (TTL) field (8 bits) is to prevent packets from being shuttled around indefinitely on a network. It was originally intended to be lifetime in seconds, but it has come to be implemented as “hop count”.  This means that every time a packet crosses a switch or router, the hop count is decremented by one. If it reaches zero, the packet is dropped. Typically if this happens, an ICMPv4 message (“time exceeded”) is returned to the packet sender. This mechanism is how the traceroute command works. Its primary purpose is to prevent looping (packets running around in circles).

The Protocol field (8 bits) defines the type of data found in the data portion of the packet. Protocol numbers are not to be confused with ports. Some common protocol numbers are:

1              ICMP     Internet Control Message Protocol (RFC 792)

6              TCP        Transmission Control Protocol (RFC 793)

17           UDP       User Datagram Protocol (RFC 768)

41           IPv6       IPv6 tunneled over IPv4 (RFC 2473)

83           VINES    Banyan Vines IP

89           OSPF     Open Shortest Path First (RFC 1583)

132         SCTP      Streams Control Transmission Protocol

The Header Checksum field (16 bits). The 16-bit one’s complement of the one’s complement sum of all 16 bit words in the header. When computing, the checksum field itself is taken as zero. To validate the checksum, add all 16 bit words in the header together including the transmitted checksum. The result should be 0. If you get any other value, then at least one bit in the packet was corrupted. There are certain multiple bit errors that can cancel out, and hence bad packets can go undetected. Note that since the hop count (TTL) is decremented by one on each hop, the IP Header checksum must be recalculated at each hop. The IP Header Checksum was eliminated in IPv6.

The Source Address field (32 bits) contains the IPv4 address of the sender (may be modified by NAT).

The Destination Address field (32 bits) contains the IPv4 address of the recipient (may be modified by NAT in a reply packet).

Options (0 to 40 bytes) Not often used. Rarely if ever seen “in the wild”. These are not relevant here. If you want the details, read the RFCs.