Search code examples
udpchecksum

Why we use 1's complement instead of 2's complement when calculating checksums


When calculating UDP checksums I know that we complement the result and use it to check for errors. But I don't understand why we use 1's complement instead of 2's complement (as shown here). If there are no errors 1's complement results -1 (0xFFFF) and 2's complement results 0 (0x0000).

To check for correct transmission, receiver's CPU must first negate the result then look at the zero flag of ALU. Which costs 1 additional cycle for negation. If 2's complement was used the error checking would be done simply by looking at the zero flag.


Solution

  • That is because using 2's complement may give you a wrong result if the sender and receiver machines have different endianness.

    If we use the example:

    0000 1111 1110 0000 1111 0000 0001 0000

    the checksum with 2's complement calculated on a little-endian machine would be:

    0000 0000 0001 0000

    if we added our original data to this checksum on a big-endian machine we would get:

    0000 0000 1111 1111

    which would suggest that our checksum was wrong even though it was not. However, 1's compliments results are independent of the endianness of the machine so if we were to do the same thing with a 1's complement number our checksum would be:

    0000 0000 0000 1111

    which when added together with the data would get us:

    1111 1111 1111 1111

    which allows the short UDP checksum to work without requiring both the sender and receiver machines to have the same endianness.