Faster checksum function.
This commit is contained in:
parent
913f7dc9f2
commit
5e13ffe6f4
2 changed files with 57 additions and 10 deletions
2
TODO
2
TODO
|
@ -32,8 +32,6 @@ Core
|
||||||
|
|
||||||
- OSPF: refuse running on non-multicast devices
|
- OSPF: refuse running on non-multicast devices
|
||||||
|
|
||||||
- lib: use better checksum function
|
|
||||||
|
|
||||||
Cleanup
|
Cleanup
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
- right usage of DBG vs. debug
|
- right usage of DBG vs. debug
|
||||||
|
|
|
@ -11,6 +11,62 @@
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
|
|
||||||
|
static u16 /* One-complement addition */
|
||||||
|
add16(u16 sum, u16 x)
|
||||||
|
{
|
||||||
|
u16 z = sum + x;
|
||||||
|
return z + (z < sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
add32(u32 sum, u32 x)
|
||||||
|
{
|
||||||
|
u32 z = sum + x;
|
||||||
|
return z + (z < sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16
|
||||||
|
ipsum_calc_block(u16 *x, unsigned len, u16 sum)
|
||||||
|
{
|
||||||
|
int rest;
|
||||||
|
u32 tmp, *xx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A few simple facts about the IP checksum (see RFC 1071 for detailed
|
||||||
|
* discussion):
|
||||||
|
*
|
||||||
|
* o It's associative and commutative.
|
||||||
|
* o It's byte order independent.
|
||||||
|
* o It's word size independent.
|
||||||
|
*
|
||||||
|
* This gives us a neat 32-bits-at-a-time algorithm which respects
|
||||||
|
* usual alignment requirements and is reasonably fast.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASSERT(!(len % 2));
|
||||||
|
if (!len)
|
||||||
|
return sum;
|
||||||
|
len >>= 1;
|
||||||
|
if ((unsigned long) x & 2) /* Align to 32-bit boundary */
|
||||||
|
{
|
||||||
|
sum = add16(sum, *x++);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
rest = len & 1;
|
||||||
|
len >>= 1;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static u16
|
static u16
|
||||||
ipsum_calc(void *frag, unsigned len, va_list args)
|
ipsum_calc(void *frag, unsigned len, va_list args)
|
||||||
{
|
{
|
||||||
|
@ -18,14 +74,7 @@ ipsum_calc(void *frag, unsigned len, va_list args)
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
u16 *x = frag;
|
sum = ipsum_calc_block(frag, len, sum);
|
||||||
ASSERT(!(len % 2));
|
|
||||||
while (len)
|
|
||||||
{
|
|
||||||
u16 z = sum + *x++;
|
|
||||||
sum = z + (z < sum);
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
frag = va_arg(args, void *);
|
frag = va_arg(args, void *);
|
||||||
if (!frag)
|
if (!frag)
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue