[PATCH 4/5] checksum: optimize loop and get rid of add16()
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. Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se> --- lib/checksum.c | 47 +++++++++++++++++++++++------------------------ 1 files changed, 23 insertions(+), 24 deletions(-) diff --git a/lib/checksum.c b/lib/checksum.c index 2e427a2..7b183d9 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 */ + 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++); + 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
The first add op. adds two 16 bit nums which cannot overflow one 32 bits receiver so use plain addition instead. Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se> --- lib/checksum.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib/checksum.c b/lib/checksum.c index 7b183d9..ae759d7 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -59,7 +59,7 @@ ipsum_calc_block(u16 *buf, unsigned len, u16 sum) acc_sum = sum; if ((u32) buf & 2) { /* Align to 32-bit boundary */ - add32(acc_sum, *buf++); + acc_sum += *buf++; /* two 16 bit numbers cannot overflow 32 bits */ len =- 2; } rest = len & 1; -- 1.6.4.4
participants (1)
-
Joakim Tjernlund