Skip to main content

Error Detection at the Link Layer

Bits crossing a physical link get corrupted - electrical noise, crosstalk, a weak wireless signal. The link layer's job is to notice. It adds a few redundant bits to each frame so the receiver can tell whether what arrived matches what was sent. This is detection, not usually correction: most link layers simply drop a bad frame and let a higher layer resend it.

The trick everywhere is the same - compute a small summary of the data, send it alongside, and recompute it on the other end. If the summaries disagree, the frame is corrupt.

Parity: one bit of protection​

The simplest scheme is a single parity bit. With even parity, the sender counts the 1s in the data and appends a bit that makes the total even. The receiver counts again: still even means (probably) fine, odd means something flipped.

Step through it, then click a bit to corrupt the frame in transit:

data bitparity bitcorrupted (flipped)
Data bits
Parity
0
The sender has 8 data bits to put on the wire.
phase 0 / 2

A single parity bit catches any odd number of bit errors. Its blind spot is an even number of flips - flip two bits and the count stays even, so the error sails through. Parity is cheap but weak.

Detection versus correction

Detection tells you that an error happened; correction tells you where so you can fix it in place. Correction needs many more redundant bits (Hamming codes, Reed-Solomon). Wired networks lean on cheap detection plus retransmission; correction earns its cost only where resending is expensive - deep space, storage media, some wireless links.

The Internet checksum and CRC​

Two stronger schemes cover the rest of the stack. TCP, UDP, and IP protect their headers with the Internet checksum: treat the data as 16-bit words, add them with one's-complement arithmetic, and send the complement of the sum; the receiver adds everything including the checksum and expects all-ones. It is cheap in software but a fairly weak detector - some error patterns cancel out in the sum. Ethernet, WiFi, and most link layers instead use a cyclic redundancy check (CRC): divide the frame's bits, treated as one huge binary number, by a fixed generator polynomial using XOR division, and append the remainder. An r-bit CRC catches every burst error up to r bits long and all odd numbers of errors - strong detection with simple shift-register hardware, which is why CRC guards real link-layer frames while the cheaper checksum is reserved for software-computed headers higher up the stack.

A worked Internet checksum​

Take two 16-bit words from a header, say 0x4500 and 0x003c:

  1. Add them: 0x4500 + 0x003c = 0x453c. No carry past bit 16, so no end-around carry to fold back in yet (if the sum had overflowed 16 bits, that overflow bit gets added back into the low end - "end-around carry" - before continuing).
  2. Complement the sum: flip every bit of 0x453c to get the checksum field, 0xbac3. This is what gets placed in the packet.
  3. Receiver verifies: add the original words plus the checksum field: 0x4500 + 0x003c + 0xbac3 = 0xffff - all one bits. That all-ones result is exactly what one's-complement addition guarantees whenever nothing changed in transit; any corruption that flips a bit generally breaks that all-ones property and the receiver discards the segment.
Checksum offload makes captured packets look corrupt

Most NICs compute the TCP/UDP/IP checksum in hardware just before the frame leaves the card, to save CPU cycles. Packet-capture tools like tcpdump/Wireshark, however, grab the packet before it reaches the NIC - so outgoing captures on the sending host routinely show a checksum field of 0x0000 or a value that fails validation, even though the frame that actually goes out on the wire is perfectly correct. Engineers unfamiliar with checksum offload burn real debugging time chasing a "corrupted packet" that was never actually corrupt; the fix is to either disable offload (ethtool -K eth0 tx off) while capturing, or just ignore checksum warnings on egress captures from the sending host.