Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.

0105000 /*       oneC_sum() - One complement's checksum              Author: Kees J. Bot
0105001  *                                                        8 May 1995
0105002  * See RFC 1071, "Computing the Internet checksum"
0105003  */
0105004 
0105005 #include <sys/types.h>
0105006 #include <net/gen/oneCsum.h>
0105007 
0105008 u16_t oneC_sum(U16_t prev, void *data, size_t size)
oneC_sum()

A checksum is used to determine if errors occurred during the transmission of data. The checksum algorithm used by oneC_sum() (which is also the Internet standard) is described by RFC 1071.

Essentially, the algorithm goes through data and adds all the bytes together (using one's complement addition). The high 16 bits of the resulting 32 bit value is then added to the low 16 bits (again, using one's complement addition). The checksum field is then set to the one's complement of this 16 bit sum. (Recall that the one's complement of 0xF0F0 is 0x0F0F.) Since AND'ing any 16 bit number and its 16 bit one's complement will equal 0xFFFF, the checksum of the packet (without the checksum field) AND'ed with the checksum field will equal 0xFFFF (provided the packet was not corrupted after the checksum field was calculated). For example, the checksum of a udp header (including the checksum field) will equal 0xFFFF if the packet was not corrupted in delivery.


From RFC 1071:

In outline, the Internet checksum algorithm is fairly simple:

(1) Adjacent octets to be checksummed are paired to form 16-bit
integers, and the 1's complement sum of these 16-bit integers is
formed.

(2) To generate a checksum, the checksum field itself is cleared,
the 16-bit 1's complement sum is computed over the octets
concerned, and the 1's complement of this sum is placed in the
checksum field.

(3) To check a checksum, the 1's complement sum is computed over the
same set of octets, including the checksum field. If the result
is all 1 bits (-0 in 1's complement arithmetic), the check
succeeds.

Below is a "C" code algorithm that describes the process above. This algorithm is also from RFC 1071. Note that count is the running count of all the bytes in the data and checksum is the return value.



{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;

while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short) addr++;
count -= 2;
}

/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;

/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);

checksum = ~sum;
}



0105009 {
0105010          u8_t *dptr;
0105011          size_t n;
0105012          u16_t word;
0105013          u32_t sum;
0105014          int swap= 0;
0105015 
0105016          sum= prev;
0105017          dptr= data;
0105018          n= size;
0105019 
0105020          swap= ((size_t) dptr & 1);
0105021          if (swap) {
0105022                   sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
0105023                   if (n > 0) {
0105024                            ((u8_t *) &word)[0]= 0;
0105025                            ((u8_t *) &word)[1]= dptr[0];
0105026                            sum+= (u32_t) word;
0105027                            dptr+= 1;
0105028                            n-= 1;
0105029                   }
0105030          }
0105031 
0105032          while (n >= 8) {
0105033                   sum+= (u32_t) ((u16_t *) dptr)[0]
0105034                    + (u32_t) ((u16_t *) dptr)[1]
0105035                    + (u32_t) ((u16_t *) dptr)[2]
0105036                    + (u32_t) ((u16_t *) dptr)[3];
0105037                   dptr+= 8;
0105038                   n-= 8;
0105039          }
0105040 
0105041          while (n >= 2) {
0105042                   sum+= (u32_t) ((u16_t *) dptr)[0];
0105043                   dptr+= 2;
0105044                   n-= 2;
0105045          }
0105046 
0105047          if (n > 0) {
0105048                   ((u8_t *) &word)[0]= dptr[0];
0105049                   ((u8_t *) &word)[1]= 0;
0105050                   sum+= (u32_t) word;
0105051          }
0105052 
0105053          sum= (sum & 0xFFFF) + (sum >> 16);
0105054          if (sum > 0xFFFF) sum++;
0105055 
0105056          if (swap) {
0105057                   sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
0105058          }
0105059          return sum;
0105060 }