LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 11-21-2010, 06:58 AM   #1
mattd9
LQ Newbie
 
Registered: Nov 2010
Posts: 3

Rep: Reputation: 0
UDP Checksum Algorithm


I am trying to compute a UDP checksum via what the UDF RFC suggests.
From what I have learned the checksum is on a pseudo header and a combined UDP header and data. Essentially the checksum should cover, where all of the fields are in network/bigendian order:

Pseudo Header:
source(32bits) + dest(32bits) + zeros(8bits) + protocol(8bits) + udplength(16bits)

UDP and Data:
source_port(16bits) + dest_port(16bits) + length(16bits) + zeros(16bits)
+ data(384 bits)

To achieve the checsum I copy the pseudo header and the udp+data into one byte array. I then traverse that byte array in blocks of 4 bytes until I reach the end of the array. I compute as follows:
[I]
unsigned short buffer[sizeof(psedudo) + sizeof(udp_and_data)];

/* The data is copied from pseudo and udp_and_data into buffer */

sum = 0;
for (i=0; i<sizeof(buffer); i+=2)
sum += ~(buffer + buffer[i+1]);

return ~sum;


I return the 1's complement. Unfortunately I have yet to get tcpdump to report this as a valid calculation.

I have tried numerous approaches found online, and even some pieces of the Linux kernel to no avail. Any help would be appreciated.

-Matt
 
Old 11-21-2010, 09:15 PM   #2
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
Code:
traverse that byte array in blocks of 4 bytes until I reach the end of the array
Presumably you mean blocks of 2 bytes, since it is a 16 bit sum.

Code:
sum += ~(buffer + buffer[i+1]);
You should be adding words (big endian), not bytes. And why the complement operator here?

Code:
return ~sum;
You haven't added back in the carries (the sum is a ones-complement sum; since most languages provide only a twos-complement addition, you have to add the carries back in to emulate a ones-complement sum).

Last edited by neonsignal; 11-21-2010 at 09:16 PM.
 
Old 11-22-2010, 03:24 PM   #3
jefro
Moderator
 
Registered: Mar 2008
Posts: 21,939

Rep: Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619Reputation: 3619
Some nics offload checksum.
 
Old 11-23-2010, 07:50 AM   #4
mattd9
LQ Newbie
 
Registered: Nov 2010
Posts: 3

Original Poster
Rep: Reputation: 0
Thanks for all the help. Following is the algorithm I am using on a 64bit x86 machine. I am still not having much luck with it.

Code:
static uint16_t udp_checksum(
    const struct iphdr  *ip,
    const struct udphdr *udp,
    const data_pkt      *foo)
{
    pseudo_hdr ps_hdr = {0};
    uint8_t    data[sizeof(pseudo_hdr) + sizeof(struct udphdr) + sizeof(data_pkt)] = {0};

    ps_hdr.source = ip->saddr;
    ps_hdr.dest = ip->daddr;
    ps_hdr.protocol = IPPROTO_UDP;
    ps_hdr.udp_length = udp->len;

    memcpy(data, &ps_hdr, sizeof(pseudo_hdr));
    memcpy(data + sizeof(pseudo_hdr), udp, sizeof(struct udphdr));
    memcpy(data + sizeof(pseudo_hdr) + sizeof(struct udphdr), ntp, sizeof(data_pkt));

    return csum((uint16_t *)data, sizeof(data)/2);
}

/* Not my code */
unsigned short csum (unsigned short *buf, int nwords)
{
    unsigned long sum;

    for (sum = 0; nwords > 0; nwords--)
        sum += *buf++;

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
}
 
Old 11-23-2010, 05:21 PM   #5
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
The checksum code is now valid.

If you are still having problems with the actual packet, then one possibility is that it is an endian issue (because presumably you are working on a little-endian, and the packets have to be constructed big-endian). The endian direction doesn't affect the checksum; the checksum is the same no matter what order the bytes are in (since it just does additions, which are commutative).

The other possibility, being on a 64 bit machine, is that you have alignment issues. It is worth printing out the sizeof values of your structures, just to make sure they are the size you think they are.

What are your structure definitions? Do you have any sample data to compare with?
 
Old 11-24-2010, 05:02 AM   #6
mattd9
LQ Newbie
 
Registered: Nov 2010
Posts: 3

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by neonsignal View Post
The checksum code is now valid.

If you are still having problems with the actual packet, then one possibility is that it is an endian issue (because presumably you are working on a little-endian, and the packets have to be constructed big-endian). The endian direction doesn't affect the checksum; the checksum is the same no matter what order the bytes are in (since it just does additions, which are commutative).

The other possibility, being on a 64 bit machine, is that you have alignment issues. It is worth printing out the sizeof values of your structures, just to make sure they are the size you think they are.

What are your structure definitions? Do you have any sample data to compare with?
neonsignal,
Ok, I'm baffled. It now works. Thanks for the positive vibes. I'm in Melbourne too ;-)

-Matt
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Network boot returns "UDP Checksum Error" iainr Linux - Networking 1 08-06-2009 01:58 PM
Enable UDP checksum rafismx Linux - Newbie 0 02-29-2008 06:44 PM
UDP checksum icortazar3 Linux - Networking 1 12-19-2007 02:13 AM
UDP: Short Packets: and UDP bad checksum: entries in dmesg minutes2memories Linux - Networking 2 02-26-2006 07:28 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 08:13 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration