Re: Incremental update of TCP Checksum

From: Vishwas Raman
Date: Tue Sep 16 2003 - 18:36:32 EST


Jamie Lokier wrote:
Richard B. Johnson wrote:

If I were to modify a low byte somewhere by subtracting 1,
would I know that the new checksum, excluding the inversion,
was 0x0000? No. It could be 0xffff.


You're right about information being thrown away, but wrong because IP
checksums are more rigidly defined than that.

RFC1624 was written because the earlier RFC actually got this wrong.

As long as at least one of the checksummed words is known to be
non-zero, 0x0000 is not a possible value. This is true of all IP checksums.

There is only one possible value of the non-complemented sum: 0xffff.

So when you subtract 1 from 0x0001, you get 0xffff.

To do this right, instead of subtracting a word, you add the
complement of the word. After carry-folding, this works out right.

Vishwas Raman wrote:

Are you then suggesting that instead of trying to do an incremental update of the tcp checksum, I set it to 0 and recalculate it from scratch? But I thought that doing that was a big performance hit. Isn't it?


You don't need to recalculate the sum. All routers modify the IP
header checksum when they decrement the TTL of a packet - it's a
widely used algorithm. Equation 3 from RFC1624 is correct :)

I was also under the belief that RFC1624 was handling this correctly.


Your code looks fine to me. Are you sure you're verifying the
checksum correctly?


This is how I am verifying the checksum. It seems to work in other cases. (by the way, I am working with the 2.4.20 kernel src code)

/* I do this check for only packets that are less than or equal to 76 bytes in length. And I make sure the packets that I am dealing with are less than this length */

int tcpFailoverVerifyChecksum(struct sk_buff* skb)
{
int len = skb->len - sizeof(struct iphdr);
retValue = tcp_v4_check(skb->h.th, len,
skb->nh.iph->saddr, skb->nh.iph->daddr,
csum_partial((char *)skb->h.th, len, 0));
return retValue;
}

Is the above function right? If not, what is the right way to verify the checksum of a tcp packet?




while (cksum >> 16)
{
cksum = (cksum & 0xffff) + (cksum >> 16);
}


In general you need to add back the carry bits at most twice, btw.

cksum = (cksum & 0xffff) + (cksum >> 16);
cksum += (cksum >> 16);

Ok...I will make the change... Thks...




-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/