UDP is the simplest transport protocol in terms of implementation and delivery, It is a no-frills/bare-bones transport protocol that simply takes the application message data (maximum size of 64KB) from the sender application and tries to deliver the full message in one go to the receiver application. It will deliver this message in full, and not in multiple parts. It is up to the application to retrieve the full message or only partial content. For example, if the sender sends a message of length 2000 bytes, the receiver may provide only a 500-byte buffer. In this case, when the receiver retrieves the message, the remaining 1500 bytes will be discarded by UDP when delivering the message to the receiver application, and even subsequent message retrieval by the receiver application be unable to retrieve these lost bytes. (The subsequent message retrieval will get the contents from the sender’s next message, if any). This feature of UDP – delivering the entire message in one go – is termed as message-oriented delivery service. When the size of the message exceeds frame size of network link layer, it is the responsibility of the UDP layer to split the given message into multiple fragments and reassemble these at the receiver’s end. Even in this case, the protocol will deliver a single, complete message in full to the receiver.
For convenience, let us assume that the Client program runs on machine Hc (10.1.1.3) and Server program runs on machine Hs (10.1.1.1), as shown in Figure 1. Readers are requested to use the IP addresses as applicable to their setup under experimentation. To ensure that network connectivity is proper, first ensure that Hs is reachable from Hc by using ping (i.e. ping –c2 10.1.1.1), which sends two ICMP Requests and receives two ICMP Replies.
It should be noted that if the link between the Client and switch S1 (or the Server and switch S2) is broken, the Client (or Server) will detect that the network is down and may shut down applications that are making use of the network interface connected to the switch. We therefore require two switches so that we can break the link between them to simulate a network breakdown.
UDP Message Orientation
We will carry out a few exercises to understand message-oriented delivery. The Client program will send a total of C messages at a fixed interval delay of D seconds, where the size of each message is X bytes. To easily distinguish between messages, the first message will consist of the letter ‘A’ repeated X times, the second message will consist of X the letter ‘B’ repeated X times, and so on.
Since the Client application sends X bytes of application data, the UDP protocol will deliver it as a single message (provided it is not lost). The Server program will read Y bytes on the UDP socket and display the same on the console. If Y is less than X, then UDP will deliver only Y bytes to the Server application and will discard the remaining X – Y bytes. Thus, we expect the Server to display letter ‘A’ Y times (from the first message), then letter ‘B’ Y times (from the second message), and so on. This will demonstrate that X – Y copies of ‘A’ have indeed been discarded. (Thus, it is up to the application – the Server in this case – to provide an adequately sized buffer to receive the message.) If Y is greater than or equal to X, then the Server will read the entire UDP message of X bytes in a single read. The UDP layer will not combine data from two separate UDP messages into one at the receiver end. Thus first read by UDP Server will display X copies of ‘A’, followed by X copies of ‘B’, and so on. Thus, this exercise demonstrates that UDP honours message boundaries and delivers messages in full.
When the application data exceeds the size of a packet that can traverse on a link, the application packet needs to be split into multiple fragments. The maximum payload size of data in an Ethernet frame is 1500 bytes (including 20 bytes overhead of IP layer and 8 bytes overhead of UDP layer). Thus, any application layer packet of larger size (more than 1472 bytes) needs to be fragmented accordingly before its transmission. When X. is more than 1472 bytes, this datagram will be fragmented into multiple messages, first message carrying 1472 bytes of application data (first fragment will have 8 bytes of UDP header as well), 2nd fragment carrying 1480 bytes of application data and so on.. Here, too, UDP honours message boundaries even when messages are split into multiple fragments at the network layer transmission. At the receiving end, UDP (along with IP layer) ensures that the message fragments are reassembled and delivered as a single message. If even one of the message fragments is not received, UDP will not deliver the partially received message (i.e., the entire message will be discarded and treated as lost).
An experimental exercise illustrating this concept is described in Exercise 1.
UDP Packet Loss
UDP is generally known for its unreliable delivery. If a packet gets lost during network traversal for any reason, UDP will not make any efforts to retransmit the lost data packet. Similarly, if packet is corrupted during traversal on the network in a manner that can be detected by UDP’s checksum method (explained in the next section), this packet will be discarded at the receiver’s side and will be treated at par with a lost packet. Because UDP does not make any effort to recover such packets, it is called a “no frills/bare bones” protocol.
To understand this concept, consider the following experiment where the Client application sends 10 UDP packets at intervals of 5 seconds, starting at time T0. Thus, the 10th packet will be transmitted at time T0+45. We now introduce a disturbance in the network (by breaking the link between switches S1 and S2) at time (say) T0+16, and we restore the link at time (say) T0+32. By analyzing the packets received at other end, we can study how UDP handles packets when it encounters the network breakdown. Recall that UDP does not do any retransmission. For the duration when the link breaks down (between T0+16 and T0+32), packets 5 to 7 will be lost – they will not be received at the other end. Thus, the server will only display packets numbered 1 to 4, and then packets 8 to 10. This exercise demonstrates that no error recovery takes place at the UDP transport layer.
The experimental exercise to demonstrate working of this concept is described in Exercise 2.
UDP Integrity Check
Even though UDP is unreliable, it still tries to ensure that it delivers uncorrupted data to the other end using a 16-bit checksum. The entire packet (including UDP headers, pseudo-headers – which includes source and destination IP addresses, protocol, and length field – as well as application data) is split into 16-bit words. The checksum is computed by adding all these 16-bit words, adding back the overflow/carry bit(s), if any, and then taking 1’s complement of the result.
Let us understand this calculation with an example. Figure 2 below provides the values of the various fields used in the checksum computation: the source IP address, the destination IP address, the protocol (the value for UDP is
0x11), the source port, the destination port, the length (twice: once in the pseudo header, and once in the UDP header), and the application data (16 bits at a time).
Figure 2: UDP Checksum Computation
UDP uses pseudo-headers in computing checksum values to avoid misdirected deliveries i.e., packets delivered to a destination application different from the intended recipient application. To understand the role of pseudo-headers, consider a network setup as shown in Figure 3. Suppose an application on Hb sends a UDP message to Ha using only UDP headers and data (i.e., without using pseudo-headers to compute the checksum). Thus, the sender Hb will use only UDP source-port, destination-port, length and data values to compute the checksum. This packet is forwarded to Router R for further delivery. Let us assume that Router R has some bug, and while forwarding the packet from its input interface to its output interface, it erroneously modifies the destination address to that of Hc. (Such a bug is unlikely today, as router code has matured over last 30+ years that TCP/IP has been in existence.) After this modification, the packet is transmitted with its applicable IP layer checksum and link layer error checking. Since the IP layer and link layer checksums are computed after the change of IP address by the router, these checksums will pass and this packet will be (erroneously) delivered to Hc. If another application is running on Hc and is accepting the packets on the same port number which was used by the application on host Hb, this application will receive and process the misdirected packet. The checksum at Hc will pass successfully since it uses only source and destination port and data. Such a scenario is called misdirected delivery.
To avoid this scenario of misdirected delivery, pseudo-headers (involving IP address of source and destination nodes) are used in the UDP transport protocol checksum computation.
Figure 3: Possible Misdirected Delivery
With pseudo-headers, when Hb sends a UDP packet to Ha, it computes the checksum using the application data, the source and destination ports, the packet length, the source IP (Hb) and the destination IP (Ha). This packet will be delivered to router R for further forwarding. This time, if R errs and once again modifies the destination address to Hc, the packet will be delivered to Hc as the error check at the IP and link layers will pass through. However, when Hc receives this packet, it will compute its own checksum using the application data, UDP headers, source IP of Ha and destination IP of Hc (and not that of Hb). This checksum value will (almost certainly) be different from the checksum received in the UDP header. In this case, Hc will discard the packet i.e., the packet will be lost but at least it will not be wrongly delivered to an application on an unintended host.
In addition to avoiding misdirected delivery, the UDP checksum performs a basic integrity check on application data. In case errors are detected, it discards such the packets. However, this integrity check is not foolproof, as the following example shows. Suppose the sender transmits the application data
“Computer” (ASCII representation in 16-bit chunks:
0x436F 6D70 7574 6572) to the receiver and computes the checksum. For simplicity, let us ignore headers in the calculation of the checksum:
0x436F + 6D70 + 7574 + 6572 = 0x18BC5. After adding the overflow carry value ‘1’ back to restrict checksum value to 16 bits, the value becomes
0x8BC6. The 1’s complement of this value is
0x7439, which will be the checksum value.
A deeper examination of this checksum computation shows that if the value
0xFFFF is added to
0x18BC5, the new value will be
0x28BC4. When the overflow carry value ‘2’ is added to restrict the checksum to 16 bits, the value is
0x8BC6 – the same as before adding
0xFFFF. Naturally, the 1’s complement value is once again
0x7439. Thus, if one can find some character sequence that will add up to the value
0xFFFF, then these two messages will have same checksum values.
While working out on such a character sequence, one should take into account the ‘length’ field used in both UDP headers and pseudo-headers (Figure 2) . For instance, consider the character sequence
“UQUQUQ” whose ASCII code corresponds to
0x5551 5551 5551. Since this sequence contains 6 characters, this will increase the message length by 6. As length is used twice in the checksum computation (once in UDP header and once in the pseudo-header), so the length itself will add 12 (decimal) or
0x0C to the computation. Thus, when adding the character sequence
“UQUQUQ”, the checksum computation involve an extra addition of
0x5551 + 5551 + 5551 + 0x0C = 0xFFFF. This implies that if a man in the middle attacker modifies the data packet by appending this sequence at the beginning of data or at the end, then as long as the original data length is even, the checksum value of these two data packets will be identical and the UDP integrity check will fail. This concept is explored experimentally in Exercise 3.
UDP Server Not running
Consider the situation when the UDP Server application is down (e.g., crashed or not yet started) and the UDP Client application is unaware of this. When the UDP Client (sender) sends a message to the Server (receiver) application, these packets are discarded when received by the host because there is no receiver at the UDP layer listening on the destination port specified by the sender. However, the receiver host does inform the sender host of this non-delivery of the UDP packet. This error communication is sent using the ICMP (Internet Control Message Protocol)  error message “Port Not Reachable”. This error message is sent and received at the IP layer, and it will thus not be delivered to an application that is just using transport layer connectivity. To process such messages at the network layer, the application program should work with raw sockets (at the IP layer). Readers are encouraged to explore programming with raw sockets to enhance their understanding.
The experimental exercise to understand the behaviour of the Client (sender) application when the Server (receiver) application is not running is described in Exercise 7.
Since UDP does not provide any packet ordering and (almost) no information on packet loss, this protocol is useful for applications that primarily work in a query/response mode. The functionality of these applications should be tolerant to packet loss. Two key Internet applications that work with such requirements are Domain Name Service (DNS)  and Network Management. Both applications send a UDP request, and when they receive the response, they act upon it. In case a response is not received, the service is not provided. DNS requests are independent of each other, and hence no ordering is needed. For example, when a user opens two browser windows and enters www.google.com and www.yahoo.com the browser will send two independent DNS requests and process their responses accordingly. If one of the responses is received and the other is not, the browser will display the former web-page and will independently display an error for the latter page.
Applications that require continuous exchange of data packets in a specified order need to establish their own protocol to deal with packet loss and out-of-order delivery. A typical mechanism is to add the sequence number (or some sort of identification number) to each packet so that the receiver can process the received packets in the correct order. Further, the application must establish acknowledgement and timeout mechanisms so that the sender can retransmit the packets in case of packet loss and/or corruption. Implementing this timeout and retransmission of packets as well as sequence numbers of packets is a big overhead. To avoid burdening each application with this overhead, TCP provides reliable delivery of data. We now explore several concepts related to TCP.