title: IPv4 header checksum calculation ,what am I missing
body: <p>Been trying to fix this code for a while with no luck,tried different implementations that calculate the IPv4 header checksum,however their output is vastly different from my programs output:</p>
  
  <p>Function I stole from the linux <a href="http://lxr.free-electrons.com/source/arch/x86/include/asm/checksum_64.h#L45" rel="nofollow">kernel</a> to do this:</p>
  
  <pre><code>static inline uint16_t ip_fast_csum(const void *iph, unsigned int ihl){
  
       unsigned int sum;
  
       asm("  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:"
       /* 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 ( uint16_t)sum; }
  </code></pre>
  
  <p>Sample header(bytes):
  45009d4326400406af6cd052ed12ac10a51</p>
  
  <p>Section of my program that calls the above function assigns the checksum to the header and prints the header as well as the checksum:</p>
  
  <pre><code>  newpacket.ipheader-&gt;check = ip_fast_csum ((unsigned short *) newpacket.ipheader, IP4_HDRLEN);
    debug(5,"newpacket checksum set to %0x\r\n",newpacket.ipheader-&gt;check);
    uint8_t *ipbuf=(uint8_t *)newpacket.ipheader;
    for(i=0;i&lt;IP4_HDRLEN;i++){
     debug(5,"%0x",ipbuf[i]); 
    }debug(5,"\n");
  </code></pre>
  
  <p>debug() is just a printf() wrapper, following is sample output:</p>
  
  <pre><code>newpacket checksum set to 6caf
  45009d4326400406af6cd052ed12ac10a51
  </code></pre>
  
  <p>Screencap from what wireshark is telling me:</p>
  
  <p><a href="http://i.stack.imgur.com/Xhn9B.png" rel="nofollow">wiresharkcap</a></p>
  
  <p>Can you help me and tell me what I'm doing wrong?</p>
  
  <p>This is the function I normally use:</p>
  
  <pre><code>inline unsigned short csum (unsigned short *buf, int nwords) {
       unsigned long sum;
  
       for (sum = 0; nwords &gt; 0; nwords--)
            sum += *buf++;
       sum = (sum &gt;&gt; 16) + (sum &amp; 0xffff);
       sum += (sum &gt;&gt; 16);
       return (unsigned short) (~sum);
  }
  </code></pre>
  
  <p>Thanks in advance.</p>