IP packet checksum algorithm (carrier)

Source: Internet
Author: User
Tags 04x
IP packet header information format:
+ ------------------------------------------------- +
| Version (4 digits) |
+ ------------------------------------------------- +
| Header length (4 digits) |
+ ------------------------------------------------- +
| Eight-bit service type (ToS) |
+ ------------------------------------------------- +
| Total Packet Length (16 bits) |
+ ------------------------------------------------- +
| ID (16 digits) |
+ ------------------------------------------------- +
| Flag (3 digits) |
+ ------------------------------------------------- +
| Slice offset (13 BITs) |
+ ------------------------------------------------- +
| TTL (8 bits) |
+ ------------------------------------------------- +
| Protocol type (8 bits) |
+ ------------------------------------------------- +
| Header checksum (16 bits) |
+ ------------------------------------------------- +
| Source IP address (32-bit) |
+ ------------------------------------------------- +
| Destination IP address (32-bit) |
+ ------------------------------------------------- +
* IP Option (if any) (32-bit )*
+ ------------------------------------------------- +
* Data *
+ ------------------------------------------------- +

Here we will talk about the first checksum field.
When sending data, in order to calculate the number of IP reported checksum. Follow these steps:
(1) set the IP datagram header to 0, including the checksum field.
(2) regard the header as a number in the unit of 16 bits, and sum binary anticode in sequence.
(3) Save the result to the checksum field.
When receiving data, it is relatively simple to calculate the datagram checksum. follow these steps:
(1) regard the header as a number consisting of 16 bits, and sum the binary inverse code in sequence, including the checksum field.
(2) check whether the calculated checksum result is equal to zero.
(3) If it is equal to zero, it indicates that it is divided, and the verification is correct. Otherwise, the checksum is incorrect. The protocol stack must discard this packet.

First, check the validation algorithm in the Linux 2.6 kernel, which is compiled in assembly language, obviously more efficient. The Code is as follows:
Unsigned short ip_fast_csum (unsigned char * IPH,
Unsigned int IHL)
{
Unsigned int sum;

_ ASM _ volatile __(
"Movl (% 1), % 0; \ n"
"Subl $4, % 2; \ n"
"Jbe 2f; \ n"
"Addl 4 (% 1), % 0; \ n"
"Adcl 8 (% 1), % 0; \ n"
"Adcl 12 (% 1), % 0; \ n"
"1: adcl 16 (% 1), % 0; \ n"
"Lea 4 (% 1), % 1; \ n"
"Decl % 2; \ n"
"JNE 1B; \ n"
"Adcl $0, % 0; \ n"
"Movl % 0, % 2; \ n"
"Shrl $16, % 0; \ n"
"Addw % W2, % W0; \ n"
"Adcl $0, % 0; \ n"
"Notl % 0; \ n"
"2:; \ n"
/* Since the input registers which are loaded with IPH and IHL
Are modified, we must also specify them as outputs, or GCC
Will assume they contain their original values .*/
: "= R" (SUM), "= r" (IPH), "= r" (IHL)
: "1" (IPH), "2" (IHL)
: "Memory ");
Return (SUM );
}

In this function, the first parameter is obviously the first address of the IP datagram, and almost all algorithms are the same. Note that the second parameter directly uses the header length field in the IP data header information and does not need to be converted. Therefore, the speed is faster (the master is considerate ). The usage is provided in the following sample code.

The second algorithm is very common and is written in C language. I have read a lot of code that implements the network protocol stack. This algorithm is the most commonly used. Even if it changes, it is nothing more than reverse and sum. Considering the reason, it is estimated that the portability of C language is better. The following is the implementation of this function:
Unsigned short checksum (unsigned short * Buf, int nword)
{
Unsigned long sum;

For (sum = 0; nword> 0; nword --)
Sum + = * Buf ++;
Sum = (sum> 16) + (sum & 0 xFFFF );
Sum + = (sum> 16 );

Return ~ SUM;
}

Here I want to talk about my painful experience. To study the IP address checksum algorithm, I also write code based on the algorithm, but the results are always 8-bit different, I 've been depressed for a long time. Finally, David L. steven gave me the answer (don't get me wrong, it's the answer found in his book, huh, huh ). That is, most of the machine devices we use are computed using the binary Complement Algorithm. Therefore, simply accumulating the checksum is not the correct result.
The following is an example code of the IP datagram header checksum algorithm:

# Include <stdio. h>
# Include <stdlib. h>
# Include <Linux/if_ether.h>
# Include <Linux/IP. h>
# Include <sys/socket. h>

# Define eth_p_length 65535
# Define ethernet_max_len 1500
# Define ethernet_min_len 46

Unsigned short ip_fast_csum (unsigned char * IPH, unsigned int IHL );
Unsigned short checksum (unsigned short * Buf, int nword );

//--------------------------------------------------------------------
// Main Function
//
// Do all if it can do
//
//--------------------------------------------------------------------

Int main (INT argc, char * argv [])
{
Int listenfd;
Int nbyte;
Char Buf [eth_p_length];
Struct ethhdr * Eth = NULL;
Struct iphdr * IP = NULL;
Short chk;

//
// Print banner
//
Printf ("\ n \ tsendarp V1.0-scan IP and Mac \ n ");
Printf ("\ tnsfocus-www.nsfocus.com \ n ");
Printf ("\ tby David Zhou \ n ");
Printf ("\ tdate: 2006/01/19 \ n ");

If (listenfd = socket (pf_packet, sock_raw, htons (eth_p_all) <0)
{
Printf ("Call socket () function error \ n ");
Return 1;
}

For (;;)
{
If (nbyte = Recv (listenfd, Buf, eth_p_length, 0)> 0)
{
Struct ethhdr * Eth = (struct ethhdr *) BUF;
If (ntohs (ETH-> h_proto) = eth_p_ip)
{// Ethernet frame
// Print IP sum
IP = (struct iphdr *) & Buf [14];
Printf ("IP checksum = 0x % 04x \ n", ntohs (IP-> check ));
// Verify IP checksum
Chk = checksum (unsigned short *) ip, 10 );
Printf ("verify checksum = 0x % 04x \ n", ntohs (chk ));
//
// Reset check to calc self
//
IP-> check = 0;
// 2.6 kernel
Chk = ip_fast_csum (unsigned char *) ip, IP-> IHL );
Printf ("calc checksum = 0x % 04x-% d \ n", ntohs (chk), IP-> IHL );
// Coustom calc
Chk = checksum (unsigned short *) ip, 10 );
Printf ("calc checksum = 0x % 04x \ n", ntohs (chk ));
}
}
}
Return 0;
}

Unsigned short checksum (unsigned short * Buf, int nword)
{
Unsigned long sum;

For (sum = 0; nword> 0; nword --)
Sum + = * Buf ++;
Sum = (sum> 16) + (sum & 0 xFFFF );
Sum + = (sum> 16 );

Return ~ SUM;
}

/*
* This is a version of ip_compute_csum () optimized for IP headers,
* Which always checksum on 4 octet boundaries.
*
* By Jorge cwik, adapted for Linux
* ARNT Gulbrandsen.
*/
Unsigned short ip_fast_csum (unsigned char * IPH,
Unsigned int IHL)
{
Unsigned int sum;

_ ASM _ volatile __(
"Movl (% 1), % 0; \ n"
"Subl $4, % 2; \ n"
"Jbe 2f; \ n"
"Addl 4 (% 1), % 0; \ n"
"Adcl 8 (% 1), % 0; \ n"
"Adcl 12 (% 1), % 0; \ n"
"1: adcl 16 (% 1), % 0; \ n"
"Lea 4 (% 1), % 1; \ n"
"Decl % 2; \ n"
"JNE 1B; \ n"
"Adcl $0, % 0; \ n"
"Movl % 0, % 2; \ n"
"Shrl $16, % 0; \ n"
"Addw % W2, % W0; \ n"
"Adcl $0, % 0; \ n"
"Notl % 0; \ n"
"2:; \ n"
/* Since the input registers which are loaded with IPH and IHL
Are modified, we must also specify them as outputs, or GCC
Will assume they contain their original values .*/
: "= R" (SUM), "= r" (IPH), "= r" (IHL)
: "1" (IPH), "2" (IHL)
: "Memory ");
Return (SUM );
}

Author: David Zhou original address: http://blog.tom.com/blog/read.php? Bloggerid = 611041 & blogid = 31429

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.