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.

info

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.