Friday, November 21, 2008

AVRnet : IP, ICMP, TCP, UDP checksum calculation

I'll explain about IP, ICMP, TCP checksum calculation on AVRnet's source code and use software_checksum function for reference to this article.

Code:
WORD software_checksum(BYTE *rxtx_buffer, WORD len, DWORD sum)
{
// build the sum of 16bit words
while(len>1)
{
sum += 0xFFFF & (*rxtx_buffer<<8|*(rxtx_buffer+1));
rxtx_buffer+=2;
len-=2;
}
// if there is a byte left then add it (padded with zero)
if (len)
{
sum += (0xFF & *rxtx_buffer)<<8;
}
// now calculate the sum over the bytes in the sum
// until the result is only 16bit long
while (sum>>16)
{
sum = (sum & 0xFFFF)+(sum >> 16);
}
// build 1's complement:
return( (WORD) sum ^ 0xFFFF);
}
Function arguments
  • BYTE *rxtx_buffer is a pointer, it's point to receive/transmit buffer at begin of data for checksum calculation, example &rxtx_buffer[ IP_P ]
  • WORD len is a length (in bytes) of data for checksum calculation, example sizeof(IP_HEADER)
  • DWORD sum is an initial checksum value, this argument for TCP's checksum only for IP and ICMP it's should be zero
Return value
  • This function will be return a 16-bits checksum value
How does function work?
Function will be calculate sum of 16-bits data until a len variable less than 2-bytes.

Code:
// build the sum of 16bit words
while(len>1)
{
sum += 0xFFFF & (*rxtx_buffer<<8|*(rxtx_buffer+1));
rxtx_buffer+=2;
len-=2;
}


If a len variable is an odd number, add zero to low byte.

Code:
// if there is a byte left then add it (padded with zero)
if (len)
{
sum += (0xFF & *rxtx_buffer)<<8;
}


If length of the result more than 16-bits, try to sum the result in 16-bits only.

Code:
// now calculate the sum over the bytes in the sum
// until the result is only 16bit long
while (sum>>16)
{
sum = (sum & 0xFFFF)+(sum >> 16);
}


IP checksum is the 16-bits one's complement checksum of the IP header and IP options, a checksum filed must be cleared before calculate new checksum.

Code:
ตัวอย่างการคำนวณค่า checksum ของ IP Header.



45 00
+ 00 34 = 4534
+ 48 18 = 8d4c
+ 40 00 = cd4c
+ 40 06 = 10d52
+ 00 00 = 10d52
+ 0a 01 = 11753
+ 01 4c = 1189f
+ 0a 01 = 122a0
+ 01 01 = 123a1

23a1 + 0001 = 23a2

1's complement of 23a2 = dc5d




ICMP checksum is the 16-bit one's complement of the sum of the ICMP message starting with the Type field. The checksum field should be cleared to zero before generating the checksum.



TCP checksum is the 16-bits checksum on the tcp header (including, of course, any tcp options that are present), data, and a 96 bit pseudo header made up of:



Protocol and tcp length will be pass to function by DWORD sum argument. The checksum field is the 16 bit one's complement of the sum of all 16 bit words in the header. For purposes of computing the checksum, the value of the checksum field is zero." (At least, according to rfc 791).



UDP checksum is the 16-bits one's complement of sum of a pseudo header of information from the IP header, the UDP header, and the data, padded as needed with zero bytes at the end to make a multiple of two bytes. If the checksum is cleared to zero, then checksuming is disabled. If the computed checksum is zero, then this field must be set to 0xFFFF.
When transported by IPv4, the pseudo header contains the following fields:







Contact : MSN : www.Stats.in.th

No comments: