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:
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 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:
- 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). - Complement the sum: flip every bit of
0x453cto get the checksum field,0xbac3. This is what gets placed in the packet. - 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.
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.