Welcome back, gentle reader. Last month I provided a brief introduction to packet filtering under Linux -- how to get your Linux box to drop specific network packets which pass through it. This month I'm going to do something I wouldn't ordinarily, but hey, I was busy working on the next-generation packet filtering stuff when the deadline for this column hit me; just don't tell the editors and maybe we can get away with it :).
In this column I will discuss packet fragments. Fragments have historically presented us with a number of problems and we need to understand what they are.
In my previous column, I wrote about messages on the Internet being broken up into "packets", each one containing a "header", with administrative details (where the packet is from, where it's going to, what type of packet it is, etc.), and a "body", containing what we actually want to send.
An example of an IP (Internet Protocol) header is shown in Figure 1. The header contains a number of fields, the most important of which are:
1) IP Version Number: The current Internet Protocol is version 4.
2) Source Address: The IP Address from which the packet is being sent.
3) Destination Address: The IP Address to which the packet is going.
4) Protocol: The type of packet being sent; the most common is TCP (Transmission Control Protocol), used for Web traffic and e-mail.
Of course, the less commonly used fields are the ones most likely to cause problems for network implementations; problems with the important fields show up immediately.
Every type of network has a Maximum Transmission Unit, or "MTU". This specifies how large a single packet can be on that type of network. For an Ethernet, it is 1500 bytes. For many dial-up PPP connections, it is configurable: often 296 bytes. A packet traversing a large network like the Internet may be too big for certain segments of the network. It is then the responsibility of the devices connecting those segments to split the packet up into "fragments".
For example, Figure 2A shows an IP packet with a total size of 1500 bytes (20-bytes for the IP header, and 1480 bytes for the body). If this packet hit a link with a MTU of 296 bytes, it would be fragmented into 296 byte packets and look like Figure 2B. Note that each fragment gets a complete IP header, plus a section of the body.
Now, instead of receiving one packet of 1500 bytes (1480 data bytes plus 20 bytes of IP header), we receive six packets of 1600 bytes total (1480 data bytes plus 120 bytes of IP headers). This means more network traffic and a greater chance of lost packets (most protocols allow for lost packets, but it slows them down significantly).
Modern TCP implementations (such as Linux's) go to great lengths to avoid sending packets that need fragmentation. They do this by using the other of the two flags in the IP header, called "Don't Fragment" (DF): if this is set, then a packet needing fragmentation will be dropped and a special "destination-unreachable" packet will be sent back to the source. This packet contains the reason why the destination was unreachable (in this case, "fragmentation needed and DF set"), and the MTU of the path which required fragmentation. If a "destination unreachable" packet is received, the source will then transmit a smaller packet, which will fit down that path. This is called "Path MTU discovery".