Implements changes in checksum alg suggested by Joakim Tjernlund.

This commit is contained in:
Ondrej Zajicek 2010-04-25 19:13:49 +02:00
parent 0ea8fb4abe
commit c1b51598d4

View file

@ -15,26 +15,21 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "checksum.h" #include "checksum.h"
static u16 /* One-complement addition */ static inline u32
add16(u16 sum, u16 x)
{
u16 z = sum + x;
return z + (z < sum);
}
static u32
add32(u32 sum, u32 x) add32(u32 sum, u32 x)
{ {
u32 z = sum + x; u32 z = sum + x;
return z + (z < sum); // return z + (z < sum);
/* add carry */
if (z < x)
z++;
return z;
} }
static u16 static u16
ipsum_calc_block(u16 *x, unsigned len, u16 sum) ipsum_calc_block(u32 *buf, unsigned len, u16 isum)
{ {
int rest;
u32 tmp, *xx;
/* /*
* A few simple facts about the IP checksum (see RFC 1071 for detailed * A few simple facts about the IP checksum (see RFC 1071 for detailed
* discussion): * discussion):
@ -47,27 +42,17 @@ ipsum_calc_block(u16 *x, unsigned len, u16 sum)
* usual alignment requirements and is reasonably fast. * usual alignment requirements and is reasonably fast.
*/ */
ASSERT(!(len % 2)); ASSERT(!(len % 4));
if (!len) if (!len)
return sum; return isum;
len >>= 1;
if ((unsigned long) x & 2) /* Align to 32-bit boundary */ u32 *end = buf + (len >> 2);
{ u32 sum = isum;
sum = add16(sum, *x++); while (buf < end)
len--; sum = add32(sum, *buf++);
}
rest = len & 1; sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
len >>= 1; sum += (sum >> 16); /* add carry */
tmp = 0;
xx = (u32 *) x;
while (len)
{
tmp = add32(tmp, *xx++);
len--;
}
sum = add16(sum, add16(tmp & 0xffff, tmp >> 16U));
if (rest)
sum = add16(sum, *(u16 *) xx);
return sum; return sum;
} }