Exercises — UDP — header, use cases, checksum
Before we start, one shared toolkit — because a few symbols recur in almost every problem and you must never meet them undefined.
Level 1 — Recognition
L1.1 How many bytes is a UDP header, and how many fields does it contain? Name them in order.
L1.2 What is the minimum possible value of the UDP Length field, and what payload does that correspond to?
L1.3 A packet capture shows a UDP datagram with Checksum = 0x0000. What does this tell you?
Recall Solution — L1
L1.1 — The UDP header is 8 bytes, made of 4 fields, each 16 bits (16 bits = 2 bytes, and ). In order: Source Port, Destination Port, Length, Checksum (mnemonic SP-DP-LC).
L1.2 — Length counts header + data. The header alone is 8 bytes and is always present, so the smallest legal value is , which corresponds to a datagram with an empty payload (0 data bytes).
L1.3 — In IPv4 the checksum is optional. A literal 0x0000 in the field is the reserved code meaning "no checksum was computed — do not verify." It does not mean "checksum is zero" (a genuine zero result is transmitted as 0xFFFF instead, freeing 0x0000 for this signal). In IPv6 you'd never see this, because there the checksum is mandatory.
Level 2 — Application
L2.1 A UDP datagram carries 20 bytes of application data. What value goes in the Length field?
L2.2 Compute the one's-complement sum of the two 16-bit words 0xF000 and 0x2000. Show the carry-wrap step.
L2.3 Given the final one's-complement sum 0x3BCC, what checksum value is transmitted?
Recall Solution — L2
L2.1 — Length bytes = 0x001C.
L2.2 — Add normally first:
That result needs a 17th bit (the leading 1), so it overflowed 16 bits. Carry-wrap: strip the top 1 (which is ) and add it back to the low 16 bits:
One's-complement sum . Why bother wrapping? So the overflow carries information back in instead of being lost — that's what keeps the sum symmetric and inside 16 bits.
L2.3 — The transmitted checksum is the bitwise complement (flip every bit) of the sum:
(Check: 0x3BCC = 0011 1011 1100 1100; flip → 1100 0100 0011 0011 = 0xC433.) Transmitted checksum .
Level 3 — Analysis
L3.1 A receiver adds all incoming 16-bit words including the transmitted checksum and gets 0xFFFF. Explain, using the identity , why this proves the arithmetic is consistent.
L3.2 Two 16-bit words in a datagram get corrupted in transit: one word gains , a different word loses . The checksum still passes. Explain precisely why.
L3.3 Why does the UDP checksum cover a pseudo-header containing the source and destination IP addresses, when those live in the IP layer, not the UDP layer? Include the exact byte layout of that pseudo-header.
Recall Solution — L3
L3.1 — Let be the one's-complement sum of all data words. The checksum transmitted is (the bitwise complement, every bit flipped). The receiver re-adds every word plus the checksum:
In one's-complement arithmetic, a number added to its bitwise complement gives all ones: at every bit position exactly one of , has a 1 (they are opposites), so with no position empty. Getting 0xFFFF therefore means the sum the receiver rebuilt equals the sum the sender computed — the data is (probably) intact. Any single flipped bit breaks one column and the total is no longer all-ones. See One's complement arithmetic.
L3.2 — The checksum is a sum. Adding to one word and to another leaves the total unchanged (), so the re-computed sum still matches and the check passes — even though the data is corrupt. This is the fundamental weakness of a 16-bit additive checksum: errors can cancel. It catches most single-bit flips but is not a cryptographic guarantee.
L3.3 — IP delivers to a machine by its address, but a corrupted or misrouted address could deliver a datagram to the wrong host, and UDP's own header has no way to notice. By folding the IP addresses into the checksum (the pseudo-header), a wrong destination IP makes the checksum fail at the wrong receiver, so it drops the datagram. The IPv4 pseudo-header is 12 bytes, laid out as 16-bit words:
Note the zero pad byte sitting before the protocol number: the protocol is only 8 bits, but the checksum works on 16-bit words, so an all-zero byte is prepended to make protocol land in a clean 16-bit word (0x0011, since ). That pad byte is 0x00, so it contributes nothing to the sum — it exists purely for alignment. This is a deliberate layering "violation" — Transport peeking at IP addresses — accepted because misdelivery detection is worth it.
Level 4 — Synthesis
L4.1 Full checksum computation. Given three 16-bit words 0x4500, 0xF6CB, 0x0000, compute the transmitted UDP checksum, then verify it at the receiver. Show every carry-wrap.
L4.2 A designer wants to send a 512-byte DNS response. Compare the total bytes on the wire from the Transport layer down to just above IP for UDP versus a hypothetical TCP that needed a 3-packet handshake before the data. Assume UDP header = 8 B, TCP header = 20 B, and each handshake packet carries only its 20 B TCP header (no payload). Which is leaner and by how many bytes?
L4.3 A UDP payload is 3 bytes: 0x12, 0x34, 0x56 (an odd byte count). Show how the padding rule turns this into 16-bit words and compute the one's-complement sum of the payload words (ignore header/pseudo-header for this drill).

Recall Solution — L4
L4.1 — First map the symbols to the given words so nothing is unnamed: let , , . The figure above walks these exact steps: each labelled row is one line of this solution, and the coloured arrows mark the carry-wrap (teal) and the final complement (plum) so you can see which operation each transition is. Follow it top-to-bottom alongside the text.
- Add (): . Overflowed 16 bits (leading
1). - Carry-wrap: drop the
1(i.e. ), add it back to the low word: . - Add (): . No carry.
- Complement: ← transmitted checksum (the plum arrow in the figure).
- Receiver check: re-add the running sum and the checksum: ✓ all ones → accept.
L4.2 — Count bytes of transport-layer overhead + data:
- UDP: one datagram = B total, and only 8 B of that is overhead.
- TCP: handshake = 3 packets 20 B B, then the data segment B. Total B, with 80 B of overhead ( handshake header).
- UDP is leaner by bytes, and it also avoids the 1 round-trip delay of the handshake — which is why real DNS uses UDP first. Compare TCP.
L4.3 — We have 3 bytes: 0x12 0x34 0x56. Grouping into 16-bit words = 2 bytes each, the first pair is 0x12 0x34 = 0x1234. The third byte 0x56 is left without a partner (odd count), so we apply the padding rule: append a virtual zero byte 0x00, giving the second word 0x56 0x00 = 0x5600. This pad is not transmitted; it only completes the arithmetic. Now sum:
No overflow, so no carry-wrap. One's-complement sum of the payload . (Had we forgotten the pad, 0x56 alone as a low byte would give the same 0x5600 here — but with a nonzero high byte in the last word, dropping the pad would silently change the sum. Always pad to be safe.)
Level 5 — Mastery
L5.1 You are designing a real-time multiplayer game sending 60 position-updates per second. Justify choosing UDP over TCP, and describe what reliability (if any) you must build yourself and why partial reliability is acceptable.
L5.2 QUIC runs on top of UDP yet provides ordered, reliable, encrypted streams — everything UDP lacks. Explain why the designers built on UDP instead of TCP, given that UDP "throws away" reliability.
Recall Solution — L5
L5.1 — Choose UDP because timeliness beats completeness: a position update that arrives late is worse than useless — the object has already moved, so a retransmitted old packet just wastes bandwidth and stalls newer data (TCP's in-order guarantee causes head-of-line blocking: one lost packet freezes everything behind it). What you build yourself:
- Sequence numbers in your own payload, so you can discard stale updates and never act on an out-of-order old one.
- No retransmission of position — the next of 60/sec updates supersedes any lost one within ~16 ms.
- Selective reliability only for events that must land (e.g. "player fired", "player died"): re-send just those with your own ACK. Partial reliability is acceptable because most packets are self-correcting (superseded quickly); only rare state-changing events need guaranteed delivery.
L5.2 — QUIC builds on UDP for three reasons: (1) Deployability — UDP passes through existing routers, NATs, and firewalls that only understand IP + the two common transports; inventing a brand-new transport protocol number would be blocked everywhere. (2) Userspace evolution — TCP lives in the OS kernel and updates slowly; by treating UDP as a thin pipe, QUIC implements congestion control, reliability, and multiplexed streams in userspace, so it can iterate fast. (3) No head-of-line blocking across streams — TCP's single byte-stream stalls all data behind one lost segment; QUIC runs independent streams over UDP datagrams so a loss in one stream doesn't freeze the others. So UDP isn't chosen for its lack of features — it's chosen precisely because it's a minimal, transparent wrapper QUIC can build exactly the features it wants on top of.
Recall One-line self-test
UDP header size ::: 8 bytes, 4 fields of 16 bits each (Source Port, Dest Port, Length, Checksum).
Why carry-wrap in the checksum ::: One's-complement addition recycles the overflow bit instead of discarding it, so no information is lost and the sum stays 16-bit.
What (bitwise complement) does ::: Flips every bit of the 16-bit number; e.g. .
What to do with an odd-length payload before checksumming ::: Append one virtual zero byte (0x00) to make an even byte count; it is not transmitted and adds nothing to the sum.
What 0x0000 in the checksum field means (IPv4) ::: "No checksum computed — skip verification." A genuine zero result is sent as 0xFFFF.