Thread: weird checksum function

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    7

    weird checksum function

    Hi,

    I'm taking a networking class and my current project is to implement a "reliable data transfer protocol". So we're given a checksum function to both create a checksum for our packets and to check if the packets are error free. My problem is everytime I tried to check, I get a result that says packet has errors.

    Here's the function:
    Code:
    uint16_t checksum(uint16_t *buf, int nwords)
    {
    	uint32_t sum;
    
    	for (sum = 0; nwords > 0; nwords--)
    		sum += *buf++;
    	sum = (sum >> 16) + (sum & 0xffff);
    	sum += (sum >> 16); 
    	return ~sum;
    }
    What I did is: I create a packet (a structure), memset it to 0, add in data/headers, feed the struct into this function and get back a checksum to put in the same packet. I sent the packet to the receiving host. At that end I first save the packet checksum into a temp variable, set the checksum in the packet struct to 0, feed it back in the function and what it returns should be the same as the saved checksum I got from the packet itself. But everytime I do that the results don't match. (btw the checksum field is 16 bits)

    So roughly:
    on sender side:
    Code:
    Packet p;
    memset(&p sizeof(Packet), 0);      .
    //set contents;
    p.checksum = checksum((uint16_t *)&p, sizeof(Packet)/2);
    on receiver side:
    Code:
    uint16_t check = p.checksum;
    p.checksum = 0;
     if (checksum((uint16_t *)&p, sizeof(Packet)/2) != check)
                //corrupted
    From what I see, this checksum function adds up 16 bit words of the packet, add the sum to its upper 16 bit value and the lower 16 bit value, then add that to the upper 16 bit again and returns the complement. I'm still confused as to how this will give me a unique checksum. But my priority right now is to get this to work / use it correctly.

    If anyone can help/comment I'll greatly appreciate it, Thanks!

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Sorry, didn't look to closely. I'd take a closer look if you had a single, simple bit of code that demonstrated the problem.
    Code:
    p.checksum = checksum((uint16_t *)&p, sizeof(Packet)/2);
    Why are you doing sizeof(Packet)/2?

    Many checksums in which the checksum itself is included add to zero.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Have you checked your structure? is it filled exactly as you sent it?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by Dave_Sinkula
    Why are you doing sizeof(Packet)/2?
    He is scanning it in WORDs

    so actually it should be
    Code:
    sizeof(Packet)/sizeof(uint16_t)


    But I'm not sure what about aligning and bytes order
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    Registered User
    Join Date
    Aug 2004
    Posts
    7
    Thanks for the input, I tried dividing by sizeof(uint16_t) but it still doesn't work... Here's a little test program I used to test the function:

    Code:
    #include "saw.h"
    
    uint16_t checksum(uint16_t *buf, int nwords)
    {
    	uint32_t sum;
    
    	for (sum = 0; nwords > 0; nwords--)
    		sum += *buf++;
    	sum = (sum >> 16) + (sum & 0xffff);
    	sum += (sum >> 16); 
    	return ~sum;
    }
    
    int main(int argc, char *argv[]) {
    
    	sawhdr packet;
    	uint16_t check;
    	memset(&packet, sizeof(sawhdr), 0);	
    	packet.type = SYNACK;
    	packet.checksum = checksum((uint16_t *)&packet, sizeof(sawhdr)/sizeof(uint16_t));
    	check = packet.checksum;
    	packet.checksum = 0;
    	if (checksum((uint16_t *)&packet, sizeof(sawhdr)/sizeof(uint16_t)) != check)
    			fprintf(stderr, "checksum bad!!\n");
    	else
    		printf("checksum ok\n");
    }
    And here's the stuff from saw.h that're relevant:
    Code:
    #define SYNACK   1
    
    typedef struct {
    	uint8_t  type;            /* packet type (e.g. SYN, DATA, ACK, FIN)     */
    	uint8_t  seqnum;          /* sequence number of the packet              */
        uint16_t checksum;        /* header and payload checksum                */
        uint8_t data[DATALEN];    /* payload                     */
    	size_t numlen;
    } __attribute__((packed)) sawhdr;
    So when I ran the test program I get "bad checksum..."

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Code:
    void *memset( void *dest, int c, size_t count );
    It means
    Code:
    memset(&packet, sizeof(sawhdr), 0);
    should be
    Code:
    memset(&packet,0,sizeof(sawhdr));
    Last edited by vart; 10-31-2006 at 01:02 AM.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    Your problem is here:

    Code:
    memset(&packet, sizeof(sawhdr), 0);
    you're setting 0 bytes to sizeof(sawhdr)
    change to

    Code:
    memset(&packet, 0, sizeof(sawhdr));

  8. #8
    Registered User
    Join Date
    Aug 2004
    Posts
    7
    Oh DUH....
    I feel stupid now...

    It works now! Thanks...haha..

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Bisection Method function value at root incorrect
    By mr_glass in forum C Programming
    Replies: 3
    Last Post: 11-10-2005, 09:10 AM
  3. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM
  4. I need help with passing pointers in function calls
    By vien_mti in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 10:00 AM