[PATCH] ipsum_calc_block: Optimize size and speed

Joakim Tjernlund Joakim.Tjernlund at transmode.se
Fri Apr 23 10:02:54 CEST 2010


This is a much simpler and efficent impl. of the IP checksum.
It is a dry port from Quagga and I have not tested it.
---
 lib/checksum.c |   44 +++++++++++---------------------------------
 1 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/lib/checksum.c b/lib/checksum.c
index 33cb386..b836bdb 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -15,25 +15,10 @@
 #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);
-}
-
-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;
+  u32 tmp;
 
   /*
    *  A few simple facts about the IP checksum (see RFC 1071 for detailed
@@ -51,23 +36,16 @@ ipsum_calc_block(u16 *x, unsigned len, u16 sum)
   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);
+  tmp = sum;
+  for(x--; len; --len)
+      tmp += *++x;
+  /*
+   * Add back carry outs from top 16 bits to low 16 bits.
+   */
+  tmp  = (tmp >> 16) + (tmp & 0xffff);    /* add high-16 to low-16 */
+  tmp += (tmp >> 16);                     /* add carry */
+  sum = ~tmp;          /* ones-complement, then truncate to 16 bits */
+
   return sum;
 }
 
-- 
1.6.4.4




More information about the Bird-users mailing list