IPv4 Fragmentation in RFC 791: A Cross-Network Design and Its Reassembly Cost
Read the 1981 IP specification and 1982 reassembly algorithm as a design for heterogeneous packet networks, and note the limits each text sets.
The original Internet Protocol had to carry datagrams across networks that did not agree on packet size. A sender might create a datagram suitable for one network while the next network on the route could carry only a smaller packet. The September 1981 specification, RFC 791, made fragmentation and reassembly one of IP’s two basic functions, alongside addressing. That choice reveals the engineering problem of an early internetwork: a common packet format had to cross heterogeneous links without assuming that every link could carry the same unit intact.
This is a history of the design recorded in RFC 791 and of a follow-on implementation idea in David Clark’s July 1982 RFC 815. It is not advice to force fragmentation on a current production network. Later standards and operating systems add behavior not described in these two documents; the packet fields discussed here are specifically IPv4 fields, not a statement about IPv6.
What IP promised, and what it did not
RFC 791 says IP supplies datagram delivery from a source to a destination across interconnected packet-switched networks. It explicitly does not supply end-to-end reliability, flow control, or sequencing. Fragmentation therefore was not a recovery mechanism that made lost data reliable. It was a way to represent one datagram as smaller pieces for a network with a smaller transmission limit, then reconstruct the original at the destination. A missing piece could still prevent completion. The distinction matters historically: the format made interconnection possible without turning IP into a complete host-to-host transport protocol.
The 1981 document replaced RFC 760, the January 1980 DoD Internet Protocol specification. Its preface says it drew on six earlier ARPA IP editions and revised aspects of addressing, error handling, option codes, and security-related features. That is a documented lineage, not a claim that IP suddenly appeared fully formed in 1981. RFC 791’s fragmentation rules should be read as a particular published design point in that lineage.
A header that can describe pieces
The IPv4 header has a 16-bit Identification value, a three-bit Flags field, and a 13-bit Fragment Offset. The destination uses the source and destination addresses, protocol, and Identification to associate fragments of the same original datagram. The MF flag indicates that more fragments follow; DF prohibits fragmentation. The offset counts units of eight octets, not individual bytes. Consequently, each fragment’s data except the last must break on an eight-octet boundary. An unfragmented datagram has MF=0 and offset zero.
Those details have a practical implication for reading an old packet trace. A fragment at offset 100 begins 800 bytes into the original IP payload, not at byte 100. The Total Length field is the length of that individual IP packet, including its own header; it is not the length of the final reassembled datagram. The options field can also differ among fragments because some options are copied to every fragment while others remain only with the first. A parser that assumes every fragment has an identical header length will confuse header bytes with payload placement.
RFC 791 specifies that when a gateway cannot forward a datagram without making it smaller, it may fragment if DF is clear. If DF is set, fragmentation is not permitted and the datagram may instead be discarded. The document does not say that DF guarantees delivery; it gives the sender a way to prohibit this particular transformation. The specification also sets a baseline: each internet module must be able to forward a 68-octet datagram without further fragmentation, and each destination must be able to receive a 576-octet datagram, whole or reassembled. The latter is a minimum receiving capability, not a claim that every network link had a 576-octet MTU or that larger datagrams were forbidden.
Reassembly moved work to the destination
Fragments may arrive out of order, overlap, duplicate one another, or fail to arrive. RFC 791 includes example reassembly procedures, but their existence did not make the bookkeeping free. The receiver must identify the original datagram, store arriving payload ranges, determine when the final size is known, and avoid handing incomplete data to a higher protocol. It must also decide what to do when a reassembly cannot finish. These tasks follow directly from allowing independent packet delivery across multiple networks.
Clark’s RFC 815 made the implementation problem especially concrete. It introduced a list of missing ranges called holes. Start with the entire datagram missing. Each arriving fragment intersects one or more holes and either removes a hole, shortens it, or splits it into two. When no holes remain, reassembly is complete. Clark describes this as an alternative to RFC 791’s bit-vector example, suitable for some machines. He did not publish a new IP packet format or declare RFC 791’s algorithm invalid. The contribution was an implementation strategy for the same wire contract.
One striking detail is RFC 815’s proposed memory economy: keep a hole descriptor in the not-yet-filled buffer space it describes. That can avoid allocating a separate descriptor structure for every missing span, but it creates an ordering rule. Process the hole list before copying an incoming fragment into the buffer, or the copy may overwrite descriptors still needed to reason about that fragment. The RFC also calls out IP options as a complication: before the fragment containing byte zero arrives, the receiver may not know the eventual header layout because not every option is copied to every fragment.
An illustrative trace, not a live measurement
Suppose a hypothetical IPv4 datagram has a 20-octet header and 2,000 octets of payload, and the next network allows at most 1,000 octets per packet. A fragment can carry no more than 980 payload octets, but non-final fragment payloads must be multiples of eight. One valid division is 976, 976, and 48 payload octets. Their offsets are zero, 122, and 244, because 976 divided by eight is 122. The first two have MF=1, and the last has MF=0; their Total Length values, with 20-octet headers, are 996, 996, and 68. This is arithmetic from the RFC fields, not a packet capture or a claim about any specific network’s MTU.
The example also shows why a fragment list is not merely a list of three ordinary packets. The receiver needs the Identification and addressing context, payload ranges, and last-fragment indication before it can decide that all 2,000 payload octets are present. If the middle fragment never arrives, the others do not form a shorter valid original datagram. If they arrive in reverse order, the fields still permit reconstruction.
RFC 791 and RFC 815 together show two levels of engineering. The former defines interoperable packet fields and minimum capabilities for crossing dissimilar networks. The latter asks how a real receiver can honor that contract without wasteful bookkeeping. That separation between wire design and implementation method is the lasting historical lesson; neither document by itself proves how every deployed host or gateway behaved.
Related:
- ICMP’s Evolving Role: From RFC 792 Error Reports to Path Diagnostics
- January 1, 1983: What ARPANET’s TCP/IP Flag Day Actually Changed
Sources: