Exercises with Datagram Sizes

In this experiment, we will explore the limits on UDP datagram sizes. When you use an application that sends data over UDP, the size of each individual datagram may be limited or modified by the application layer, by the transport layer, or by the network layer.

For this experiment, we will reuse the same network as in the previous section.

Exercise - IP layer limit and fragmentation

In this exercise, we will observe IP fragmentation - when the network layer breaks a large transport-layer PDU into smaller pieces that are less than the maximum transmission unit (MTU) of the link.

First, run

ifconfig eth1

on each host, and make a note of the MTU of the eth1 interface on each.

Now, we’ll verify this value experimentally.

To make it easier to follow the fragments, we will use a human-readable UDP payload. Run

wget https://raw.githubusercontent.com/ffund/tcp-ip-essentials/sp21/lab5/tesla.txt

on “juliet” to download a text file, which we’ll use as the payload source.

On “romeo”, start tcpdump with

sudo tcpdump -env -i eth1 "not tcp"

(Note that we use the "not tcp" filter to exclude the status/information data exchanged by iperf3 over TCP. Also note that we are monitoring the output in real time, rather than saving to a file.)

In a second terminal window on “romeo”, start an iperf3 server with

iperf3 -s

While that is running, on “juliet” run

iperf3 -c romeo -u -k 1 -l 512 --file tesla.txt

to send a UDP datagram with a 512B payload, using part of the tesla.txt file for the payload. (Note that an Ethernet, IP, and UDP header will be added to the payload.) Observe the result in the tcpdump window, where the UDP payload length, IP packet length, and the total size of the Ethernet frame is shown.

(At the beginning of each iperf3 transaction, you may observe two very small packets which establish that the server is listening on the specified port - you should ignore these packets.)

Now we will repeat the iperf3 client command, but increase the length of the payload by modifying the -l argument, until IP fragmentation occurs. Since the MTU is 1500 B, you might try that next:

iperf3 -c romeo -u -k 1 -l 1500  --file tesla.txt

In this case, the datagram will be fragmented, because the MTU refers to the maximum size of the IP-layer packet, including IP and UDP headers which are added to the payload size that we specified. Gradually reduce the payload size until you find the maximum payload size at which fragmentation does not occur.

Stop the tcpdump with Ctrl+C. Then, start a new tcpdump on “romeo” with the capture saved to a file:

sudo tcpdump -i eth1 -w $(hostname -s)-no-ip-fragment.pcap "not tcp"

Make sure the iperf3 server is running on “romeo”. Then, on “juliet”, repeat the iperf3 command to send a UDP datagram with the maximum payload length at which IP fragmentation does not occur.

Stop tcpdump with Ctrl+C. Then, start a new tcpdump with

sudo tcpdump -i eth1 -w $(hostname -s)-ip-fragment.pcap "not tcp"

and on “juliet”, run

iperf3 -c romeo -u -k 1 -l 4321 --file tesla.txt

Stop tcpdump and the iperf3 server with Ctrl+C.

Transfer the packet captures to your laptop with scp.

The Wireshark display for fragmented packets can be confusing, so take special care to interpret it correctly. Use Wireshark to open the packet capture for the case with IP fragmentation. Ignore the two very small packets at the beginning, which are sent by iperf3 to establish that the server is listening on the specified port. After those, you should see several packets that, together, are reassembled by the receiver into a UDP datagram with a 4321 B payload. Please note that:

If you prefer to play back the packet capture with tcpdump, you can use

tcpdump -envX -r romeo-no-ip-fragment.pcap

and

tcpdump -envX -r romeo-ip-fragment.pcap

Lab report: What is the maximum iperf3 payload size (e.g. largest -l argument) that can be sent without IP fragmentation?

Lab report: Explain the maximum iperf3 payload size in terms of MTU and header lengths. What headers are appended to the iperf3 payload, and what size is each header? Describe the total size (including payload + headers) at each layer: application layer, UDP, IP, and Ethernet.

Lab report: What condition is necessary and sufficient to avoid IP fragmentation?

Lab report: Explain the tcpdump output for the iperf3 flow with -l 4321 in terms of the IP header fields (i.e., id, offset, flags, length) that are used in fragmentation.

Exercise - IP+UDP protocol limit

In this exercise, we’ll observe the maximum payload size that can be sent in a UDP datagram. This is a limit imposed by the design of the IP and UDP header, and it applies even when IP fragmentation is allowed.

You’ll need on terminal window open on “romeo” and two open on “juliet”.

First, run

iperf3 -s 

on “romeo”.

On “juliet”, start tcpdump with

sudo tcpdump -en -i eth1 "not tcp"

(Note that we use the "not tcp" filter to exclude the status/information data exchanged by iperf3 over TCP. Also note that we are monitoring the output in real time, rather than saving to a file.)

In the second terminal window on “juliet”, run

iperf3 -c romeo -u -k 1 -l 10000

Re-run the iperf3 client command, but modify the -l argument to increase the length of the payload by 10000 (e.g. to 20000). Repeat until the system refuses to send anything. (It will take fewer than 10 tries, increasing by 10000 each time.)

Lab report: What is the maximum size of the iperf3 UDP payload that the system can send, even when fragmentation is allowed? Explain this value in terms of the header sizes and the “length” header field. (Hint: imagine an interface with a very large MTU, so that there is no IP fragmentation, and the entire payload is sent in a single UDP datagram. How many bits are allocated for the “length” field in the IP header? What is the maximum value that this field can hold? What limitation does this impose on underlying protocol layers?)

Exercise - Application layer limit

Another potential limit on datagram sizes is at the application layer: the application may impose a limit on the size of the data payload it is willing to send. For example, iperf3 works by sending the entire contents of a buffer in a single datagram, and the maximum buffer size that iperf3 is willing to allocate is 1MB.

For this experiment, you’ll need two terminal windows open on “romeo” and one open on “juliet”.

In a terminal window on “romeo”, start an iperf3 server with

iperf3 -s

While that is running, on “juliet” run

iperf3 -c romeo -u -k 1 -l 10M

to ask iperf3 to send a buffer of size 10MB one time, over UDP. Note the error message, which specifies this particular application’s limit.

Other applications may not impose any limit because they send a large quantity of data across multiple datagrams. For example, TFTP (a UDP based file transfer application) works by dividing a large data payload into multiple smaller payloads, and sending a small payload in each datagram.