Use some better vaiable names and get rid of add16 as add32 will do just as well. Fold the 32 bit checkum into 16 bits in the end. ---
v2 - bug fix lib/checksum.c | 47 +++++++++++++++++++++++------------------------ 1 files changed, 23 insertions(+), 24 deletions(-) diff --git a/lib/checksum.c b/lib/checksum.c index 2e427a2..9e30bdc 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -15,12 +15,6 @@ #include "nest/bird.h" #include "checksum.h" -static u16 /* One-complement addition */ -add16(u16 sum, u16 x) -{ - u16 z = sum + x; - return z + (z < sum); -} #ifdef __powerpc__ static u32 @@ -42,10 +36,10 @@ add32(u32 sum, u32 x) #endif static u16 -ipsum_calc_block(u16 *x, unsigned len, u16 sum) +ipsum_calc_block(u16 *buf, unsigned len, u16 sum) { int rest; - u32 tmp, *xx; + u32 acc_sum, *buf_u32; /* * A few simple facts about the IP checksum (see RFC 1071 for detailed @@ -62,23 +56,28 @@ ipsum_calc_block(u16 *x, unsigned len, u16 sum) ASSERT(!(len % 2)); if (!len) return sum; - len >>= 1; - if ((unsigned long) x & 2) /* Align to 32-bit boundary */ - { - sum = add16(sum, *x++); - len--; - } + + acc_sum = sum; + if ((u32) buf & 2) { /* Align to 32-bit boundary */ + acc_sum = add32(acc_sum, *buf++); + len =- 2; + } rest = len & 1; - len >>= 1; - tmp = 0; - xx = (u32 *) x; - for (xx--; len; --len); - tmp = add32(tmp, *++xx); - xx++; - sum = add16(sum, add16(tmp & 0xffff, tmp >> 16U)); - if (rest) - sum = add16(sum, *(u16 *) xx); - return sum; + len >>= 2; + buf_u32 = (u32 *) buf; + for(buf_u32--; len; --len) + acc_sum = add32(acc_sum, *++buf_u32); + + if (rest) { + buf = (u16 *)(buf_u32++); + acc_sum = add32(acc_sum, *buf); + } + + /* Add back carry outs from top 16 bits to low 16 bits. + */ + acc_sum = (acc_sum >> 16) + (acc_sum & 0xffff); /* add high-16 to low-16 */ + acc_sum += (acc_sum >> 16); /* add carry */ + return acc_sum; } static u16 -- 1.6.4.4