[comp.protocols.tcp-ip] TCP/IP Checksums

art@ACC.ARPA (03/26/88)

In <1080@maccs.UUCP> Gordan Palameta provides a discussion of TCP/IP checksums:

 >Of course, the value of the carry bit is not accessible from a
 >higher-level language like C.  A perfectly equivalent method (very
 >suitable if your machine has 32-bit integers) is:
 >
 >  INT32 sum32, word32
 >  INT16 *word;     /* pointer to start of 16-bit words to be summed */
 >
 >  sum32 = 0;
 >
 >  for (i = 0; i < `number of 16-bit words to be summed'; i++)
 >  {
 >    `byte-swap word[i], if necessary (see comments on byte-order)'
 >    `copy word[i] to word32, zero-extended (NOT sign-extended)'
 >              /* (e.g., 0xedcb -> 0x0000edcb, not 0xffffedcb) */
 >    sum32 += word32;
 >  }
 >
 >  sum = `add the two 16-bit halves of sum32 to each other'
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
THIS ADDITION CAN RESULT IN YET ANOTHER CARRY THAT MUST BE ADDED BACK IN IF
IT OCCURS!  This simplest way to do this is to make sure that the upper 16
bits of the accumulator are zeroed before adding carries back in and performing
the carry addition twice. (Another carry cannot happen with the second addition)

 >This works, since the carry bit values for 16-bit addition of the least
 >significant 16-bit word accumulate in the most significant 16-bit word
 >of the 32-bit sum.  (This is probably what you would use on a 68020 --
 >and you can forget about byte-swapping on a 68020 as well).

It also helps that addition is commutative :-).

 >After calculating a one's complement sum, you have to take its one's
 >complement (invert all the bits) to get the actual checksum used in IP,
 >TCP, and UDP (but note that UDP treats a calculated checksum of 0x0000
 >as a special case -- see the RFC).

					Art Berggreen
					art@acc.arpa

------