When looking for documentation on Ethernet, one can easily find that the frame includes a Frame Check Sequence. This is a bunch of bits that allow the receiver to verify the frame. If the frame somehow got corrupted on its way from sender to receiver, the FCS will not match the frame data and the receiver will discard the corrupt frame. Exactly how this FCS is calculated is not that easy to find.

The FCS used by Ethernet is a Cyclic Redunancy Check. The CRC algorithm has some very nice features for this application:

  • It is very efficiently implemented in hardware using shift registers
  • If sutably designed, it be tuned to detect pretty much every random alteration in the data. Note that the alterations should be random. CRCs are very weak hash functions in the cryptographic sense: it is very easy to generate a message with a predetermined CRC.

How CRCs work

CRCs are much like the remainder of a division. The message is the numerator; the denominator is chosen but fixed number. Here is an example with message “123456789” and denominator 3:

123456789 / 3 = 41152263 with remainder 0

Transmitted message: 123456789; 0

If the message (or the checksum) somehow got corrupted, the receiver will notice:

Received message:123446789; 0

123446789 / 3 = 41148926 with remainder 2

A real CRC works similar, but has some differences:

  • The message is a bunch of bits instead of a number
  • The result of the division is not needed, only the remainder is needed; this allows some optimizations in the algorithm
  • Computers love to work in binary, not decimal. In binary, you can define another type of division which has very similar properties, but is much faster to calculate

This page (local copy) has a very thorough explanation on what a CRC exactly is, including the different algorithms to calculate them. You can try the different algorithms on this page.

The Ethernet CRC

Ethernet uses a 32 bit long CRC with polynomial 0x04C11DB7.

Depending on your implementation, you can either initialize the CRC-register to 0x46AF6449 and feed in the unmodified data; or you can initialize the register to 0x00000000 and complement the first 32 bits of the data.

Since Ethernet transmits bytes with their least-significant bit first, the CRC uses this same, reflected, order: the first bits of byte 0x33 are two 1s.

After all data-bits are passed through the CRC, push an additional 32 bits of zero’s. This assures that the last 32bits of the message are pushed completely through the register. Finally, complement the content of the register, i.e. XOR it with 0xFFFFFFFF.

The register now contains the CRC in order if you want to transmit the CRC right away: high polynomial coeficient first. In case you want to add it to your data, remember to reflect each byte from its least-significant-bit-first order to the normal most-significant-bit first order.

This page lists a full ethernet frame, including CRC (correctly reflected from the actual register).