]> git.proxmox.com Git - mirror_frr.git/blobdiff - tests/lib/test_checksum.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / lib / test_checksum.c
index 267a057ccf57ef6be3290520eabad2556d81ede4..fcb79ee28d0d208db01c382141f145aa33da17c5 100644 (file)
@@ -1,21 +1,6 @@
-/* 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
  * Copyright (C) 2008 Sun Microsystems, Inc.
- *
- * This file is part of Quagga.
- *
- * Quagga is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
 #include <time.h>
 
 #include "checksum.h"
+#include "network.h"
+#include "prng.h"
 
 struct thread_master *master;
 
 struct acc_vals {
-  int c0;
-  int c1;
+       int c0;
+       int c1;
 };
 
 struct csum_vals {
-  struct acc_vals a;
-  int x; 
-  int y;
+       struct acc_vals a;
+       int x;
+       int y;
 };
 
 static struct csum_vals ospfd_vals, isisd_vals;
@@ -46,26 +33,26 @@ typedef uint16_t testoff_t;
 #define MODX                 4102U
 
 /* The final reduction phase.
- * This one should be the original ospfd version 
+ * This one should be the original ospfd version
  */
-static u_int16_t 
-reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_ospfd(struct csum_vals *vals, testsz_t len,
+                            testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
 
-  x = ((len - off - 1) * c0 - c1) % 255;
-  
-  if (x <= 0)
-    x += 255;
-  y = 510 - c0 - x;
-  if (y > 255)
-    y -= 255;
+       x = ((len - off - 1) * c0 - c1) % 255;
 
-   /* take care endian issue. */
-   return htons ((x << 8) + y); 
+       if (x <= 0)
+               x += 255;
+       y = 510 - c0 - x;
+       if (y > 255)
+               y -= 255;
+
+       /* take care endian issue. */
+       return htons((x << 8) + y);
 #undef x
 #undef y
 #undef c0
@@ -73,23 +60,23 @@ reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 /* slightly different concatenation */
-static u_int16_t 
-reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_ospfd1(struct csum_vals *vals, testsz_t len,
+                             testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
 
-  x = ((len - off - 1) * c0 - c1) % 255;
-  if (x <= 0)
-    x += 255;
-  y = 510 - c0 - x;
-  if (y > 255)
-    y -= 255;
+       x = ((len - off - 1) * c0 - c1) % 255;
+       if (x <= 0)
+               x += 255;
+       y = 510 - c0 - x;
+       if (y > 255)
+               y -= 255;
 
-   /* take care endian issue. */
-   return htons ((x << 8) | (y & 0xff)); 
+       /* take care endian issue. */
+       return htons((x << 8) | (y & 0xff));
 #undef x
 #undef y
 #undef c0
@@ -97,33 +84,33 @@ reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 /* original isisd version */
-static u_int16_t 
-reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_isisd(struct csum_vals *vals, testsz_t len,
+                            testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
-  u_int32_t mul;
-  
-  mul = (len - off)*(c0);
-  x = mul - c0 - c1;
-  y = c1 - mul - 1;
+       uint32_t mul;
+
+       mul = (len - off) * (c0);
+       x = mul - c0 - c1;
+       y = c1 - mul - 1;
 
-  if (y > 0)
-    y++;
-  if (x < 0)
-    x--;
+       if (y > 0)
+               y++;
+       if (x < 0)
+               x--;
 
-  x %= 255;
-  y %= 255;
+       x %= 255;
+       y %= 255;
 
-  if (x == 0)
-    x = 255;
-  if (y == 0)
-    y = 1;
+       if (x == 0)
+               x = 255;
+       if (y == 0)
+               y = 1;
 
-  return htons ((x << 8) | (y & 0xff));
+       return htons((x << 8) | (y & 0xff));
 
 #undef x
 #undef y
@@ -132,33 +119,33 @@ reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 /* Is the -1 in y wrong perhaps? */
-static u_int16_t 
-reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_isisd_yfix(struct csum_vals *vals, testsz_t len,
+                                 testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
-  u_int32_t mul;
-  
-  mul = (len - off)*(c0);
-  x = mul - c0 - c1;
-  y = c1 - mul;
+       uint32_t mul;
+
+       mul = (len - off) * (c0);
+       x = mul - c0 - c1;
+       y = c1 - mul;
 
-  if (y > 0)
-    y++;
-  if (x < 0)
-    x--;
+       if (y > 0)
+               y++;
+       if (x < 0)
+               x--;
 
-  x %= 255;
-  y %= 255;
+       x %= 255;
+       y %= 255;
 
-  if (x == 0)
-    x = 255;
-  if (y == 0)
-    y = 1;
+       if (x == 0)
+               x = 255;
+       if (y == 0)
+               y = 1;
 
-  return htons ((x << 8) | (y & 0xff));
+       return htons((x << 8) | (y & 0xff));
 
 #undef x
 #undef y
@@ -167,33 +154,33 @@ reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 /* Move the mods yp */
-static u_int16_t 
-reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_isisd_mod(struct csum_vals *vals, testsz_t len,
+                                testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
-  u_int32_t mul;
-  
-  mul = (len - off)*(c0);
-  x = mul - c1 - c0;
-  y = c1 - mul - 1;
+       uint32_t mul;
 
-  x %= 255;
-  y %= 255;
+       mul = (len - off) * (c0);
+       x = mul - c1 - c0;
+       y = c1 - mul - 1;
 
-  if (y > 0)
-    y++;
-  if (x < 0)
-    x--;
+       x %= 255;
+       y %= 255;
 
-  if (x == 0)
-    x = 255;
-  if (y == 0)
-    y = 1;
+       if (y > 0)
+               y++;
+       if (x < 0)
+               x--;
 
-  return htons ((x << 8) | (y & 0xff));
+       if (x == 0)
+               x = 255;
+       if (y == 0)
+               y = 1;
+
+       return htons((x << 8) | (y & 0xff));
 
 #undef x
 #undef y
@@ -202,33 +189,33 @@ reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 /* Move the mods up + fix y */
-static u_int16_t 
-reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off)
+static uint16_t reduce_isisd_mody(struct csum_vals *vals, testsz_t len,
+                                 testoff_t off)
 {
 #define x vals->x
 #define y vals->y
 #define c0 vals->a.c0
 #define c1 vals->a.c1
-  u_int32_t mul;
-  
-  mul = (len - off)*(c0);
-  x = mul - c0 - c1;
-  y = c1 - mul;
+       uint32_t mul;
+
+       mul = (len - off) * (c0);
+       x = mul - c0 - c1;
+       y = c1 - mul;
 
-  x %= 255;
-  y %= 255;
+       x %= 255;
+       y %= 255;
 
-  if (y > 0)
-    y++;
-  if (x < 0)
-    x--;
+       if (y > 0)
+               y++;
+       if (x < 0)
+               x--;
 
-  if (x == 0)
-    x = 255;
-  if (y == 0)
-    y = 1;
+       if (x == 0)
+               x = 255;
+       if (y == 0)
+               y = 1;
 
-  return htons ((x << 8) | (y & 0xff));
+       return htons((x << 8) | (y & 0xff));
 
 #undef x
 #undef y
@@ -237,184 +224,175 @@ reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off)
 }
 
 struct reductions_t {
-  const char *name;
-  u_int16_t (*f) (struct csum_vals *, testsz_t, testoff_t);
+       const char *name;
+       uint16_t (*f)(struct csum_vals *, testsz_t, testoff_t);
 } reducts[] = {
-  { .name = "ospfd",           .f = reduce_ospfd },
-  { .name = "ospfd-1",         .f = reduce_ospfd1 },
-  { .name = "isisd",           .f = reduce_isisd },
-  { .name = "isisd-yfix",      .f = reduce_isisd_yfix },
-  { .name = "isisd-mod",       .f = reduce_isisd_mod },
-  { .name = "isisd-mody",      .f = reduce_isisd_mody },
-  { NULL, NULL },
+       {.name = "ospfd", .f = reduce_ospfd},
+       {.name = "ospfd-1", .f = reduce_ospfd1},
+       {.name = "isisd", .f = reduce_isisd},
+       {.name = "isisd-yfix", .f = reduce_isisd_yfix},
+       {.name = "isisd-mod", .f = reduce_isisd_mod},
+       {.name = "isisd-mody", .f = reduce_isisd_mody},
+       {NULL, NULL},
 };
 
 /* The original ospfd checksum */
-static u_int16_t
-ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off)
+static uint16_t ospfd_checksum(uint8_t *buffer, testsz_t len, testoff_t off)
 {
-  u_char *sp, *ep, *p, *q;
-  int c0 = 0, c1 = 0;
-  int x, y;
-  u_int16_t checksum, *csum;
-
-  csum = (u_int16_t *) (buffer + off);
-  *(csum) = 0;
-  
-  sp = buffer;
-
-  for (ep = sp + len; sp < ep; sp = q)
-    {
-      q = sp + MODX;
-      if (q > ep)
-        q = ep;
-      for (p = sp; p < q; p++)
-        {
-          c0 += *p;
-          c1 += c0;
-        }
-      c0 %= 255;
-      c1 %= 255;
-    }
-  
-  ospfd_vals.a.c0 = c0;
-  ospfd_vals.a.c1 = c1;
-  
-  //printf ("%s: len %u, off %u, c0 %d, c1 %d\n",
-  //        __func__, len, off, c0, c1);
-
-  x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255;
-  
-  if (x <= 0)
-    x += 255;
-  y = 510 - c0 - x;
-  if (y > 255)
-    y -= 255;
-  
-  ospfd_vals.x = x;
-  ospfd_vals.y = y;
-  
-  buffer[off] = x;
-  buffer[off + 1] = y;
-  
-  /* take care endian issue. */
-  checksum = htons ((x << 8) | (y & 0xff));
-
-  return (checksum);
+       uint8_t *sp, *ep, *p, *q;
+       int c0 = 0, c1 = 0;
+       int x, y;
+       uint16_t checksum, *csum;
+
+       csum = (uint16_t *)(buffer + off);
+       *(csum) = 0;
+
+       sp = buffer;
+
+       for (ep = sp + len; sp < ep; sp = q) {
+               q = sp + MODX;
+               if (q > ep)
+                       q = ep;
+               for (p = sp; p < q; p++) {
+                       c0 += *p;
+                       c1 += c0;
+               }
+               c0 %= 255;
+               c1 %= 255;
+       }
+
+       ospfd_vals.a.c0 = c0;
+       ospfd_vals.a.c1 = c1;
+
+       // printf ("%s: len %u, off %u, c0 %d, c1 %d\n",
+       //        __func__, len, off, c0, c1);
+
+       x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255;
+
+       if (x <= 0)
+               x += 255;
+       y = 510 - c0 - x;
+       if (y > 255)
+               y -= 255;
+
+       ospfd_vals.x = x;
+       ospfd_vals.y = y;
+
+       buffer[off] = x;
+       buffer[off + 1] = y;
+
+       /* take care endian issue. */
+       checksum = htons((x << 8) | (y & 0xff));
+
+       return (checksum);
 }
 
 /* the original, broken isisd checksum */
-static u_int16_t
-iso_csum_create (u_char * buffer, testsz_t len, testoff_t off)
+static uint16_t iso_csum_create(uint8_t *buffer, testsz_t len, testoff_t off)
 {
 
-  u_int8_t *p;
-  int x;
-  int y;
-  u_int32_t mul;
-  u_int32_t c0;
-  u_int32_t c1;
-  u_int16_t checksum, *csum;
-  int i, init_len, partial_len;
-
-  checksum = 0;
-  
-  csum = (u_int16_t *) (buffer + off);
-  *(csum) = checksum;
-  
-  p = buffer;
-  c0 = 0;
-  c1 = 0;
-  init_len = len;
-  
-  while (len != 0)
-    {
-      partial_len = MIN(len, MODX);
-
-      for (i = 0; i < partial_len; i++)
-       {
-         c0 = c0 + *(p++);
-         c1 += c0;
+       uint8_t *p;
+       int x;
+       int y;
+       uint32_t mul;
+       uint32_t c0;
+       uint32_t c1;
+       uint16_t checksum, *csum;
+       int i, init_len, partial_len;
+
+       checksum = 0;
+
+       csum = (uint16_t *)(buffer + off);
+       *(csum) = checksum;
+
+       p = buffer;
+       c0 = 0;
+       c1 = 0;
+       init_len = len;
+
+       while (len != 0) {
+               partial_len = MIN(len, MODX);
+
+               for (i = 0; i < partial_len; i++) {
+                       c0 = c0 + *(p++);
+                       c1 += c0;
+               }
+
+               c0 = c0 % 255;
+               c1 = c1 % 255;
+
+               len -= partial_len;
        }
 
-      c0 = c0 % 255;
-      c1 = c1 % 255;
-
-      len -= partial_len;
-    }
-
-  isisd_vals.a.c0 = c0;
-  isisd_vals.a.c1 = c1;
-  
-  mul = (init_len - off) * c0;
-
-  x = mul - c1 - c0;
-  y = c1 - mul - 1;
-
-  if (y > 0)
-    y++;
-  if (x < 0)
-    x--;
-
-  x %= 255;
-  y %= 255;
-
-  if (x == 0)
-    x = 255;
-  if (y == 0)
-    y = 1;
-  
-  isisd_vals.x = x;
-  isisd_vals.y = y;
-  
-  checksum = htons((x << 8) | (y & 0xFF));
-  
-  *(csum) = checksum;
-  
-  /* return the checksum for user usage */
-  return checksum;
+       isisd_vals.a.c0 = c0;
+       isisd_vals.a.c1 = c1;
+
+       mul = (init_len - off) * c0;
+
+       x = mul - c1 - c0;
+       y = c1 - mul - 1;
+
+       if (y > 0)
+               y++;
+       if (x < 0)
+               x--;
+
+       x %= 255;
+       y %= 255;
+
+       if (x == 0)
+               x = 255;
+       if (y == 0)
+               y = 1;
+
+       isisd_vals.x = x;
+       isisd_vals.y = y;
+
+       checksum = htons((x << 8) | (y & 0xFF));
+
+       *(csum) = checksum;
+
+       /* return the checksum for user usage */
+       return checksum;
 }
 
-static int
-verify (u_char * buffer, testsz_t len)
+static int verify(uint8_t *buffer, testsz_t len)
 {
-  u_int8_t *p;
-  u_int32_t c0;
-  u_int32_t c1;
-  int i, partial_len;
-  p = buffer;
-
-  c0 = 0;
-  c1 = 0;
-
-  while (len)
-    {
-      partial_len = MIN(len, 5803U);
-
-      for (i = 0; i < partial_len; i++)
-        {
-          c0 = c0 + *(p++);
-          c1 += c0;
-        }
-      c0 = c0 % 255;
-      c1 = c1 % 255;
-
-      len -= partial_len;
-    }
-
-  if (c0 == 0 && c1 == 0)
-    return 0;
-
-  return 1;
+       uint8_t *p;
+       uint32_t c0;
+       uint32_t c1;
+       int i, partial_len;
+
+       p = buffer;
+
+       c0 = 0;
+       c1 = 0;
+
+       while (len) {
+               partial_len = MIN(len, 5803U);
+
+               for (i = 0; i < partial_len; i++) {
+                       c0 = c0 + *(p++);
+                       c1 += c0;
+               }
+               c0 = c0 % 255;
+               c1 = c1 % 255;
+
+               len -= partial_len;
+       }
+
+       if (c0 == 0 && c1 == 0)
+               return 0;
+
+       return 1;
 }
 
-static int  /* return checksum in low-order 16 bits */
-in_cksum_optimized(void *parg, int nbytes)
+static int /* return checksum in low-order 16 bits */
+       in_cksum_optimized(void *parg, int nbytes)
 {
-       u_short *ptr = parg;
-       register long           sum;            /* assumes long == 32 bits */
-       register u_short        answer;         /* assumes u_short == 16 bits */
+       unsigned short *ptr = parg;
+       register long sum;       /* assumes long == 32 bits */
+       register unsigned short answer; /* assumes unsigned short == 16 bits */
        register int count;
        /*
         * Our algorithm is simple, using a 32-bit accumulator (sum),
@@ -424,126 +402,171 @@ in_cksum_optimized(void *parg, int nbytes)
 
        sum = 0;
        count = nbytes >> 1; /* div by 2 */
-       for(ptr--; count; --count)
-         sum += *++ptr;
+       for (ptr--; count; --count)
+               sum += *++ptr;
 
-       if (nbytes & 1) /* Odd */
-         sum += *(u_char *)(++ptr);   /* one byte only */
+       if (nbytes & 1)                    /* Odd */
+               sum += *(uint8_t *)(++ptr); /* one byte only */
 
        /*
         * Add back carry outs from top 16 bits to low 16 bits.
         */
 
-       sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
-       sum += (sum >> 16);                     /* add carry */
-       answer = ~sum;          /* ones-complement, then truncate to 16 bits */
-       return(answer);
+       sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
+       sum += (sum >> 16);                 /* add carry */
+       answer = ~sum; /* ones-complement, then truncate to 16 bits */
+       return (answer);
 }
 
 
 static int /* return checksum in low-order 16 bits */
-in_cksum_rfc(void *parg, int count)
+       in_cksum_rfc(void *parg, int count)
 /* from RFC 1071 */
 {
-       u_short *addr = parg;
+       unsigned short *addr = parg;
        /* Compute Internet Checksum for "count" bytes
         *         beginning at location "addr".
         */
-       register long  sum = 0;
+       register long sum = 0;
 
-       while (count > 1)  {
-         /*  This is the inner loop */
-         sum += *addr++;
-         count -= 2;
+       while (count > 1) {
+               /*  This is the inner loop */
+               sum += *addr++;
+               count -= 2;
        }
        /*  Add left-over byte, if any */
        if (count > 0) {
-         sum += *(u_char *)addr;
+               sum += *(uint8_t *)addr;
        }
 
        /*  Fold 32-bit sum to 16 bits */
-       while (sum>>16)
-           sum = (sum & 0xffff) + (sum >> 16);
+       while (sum >> 16)
+               sum = (sum & 0xffff) + (sum >> 16);
        return ~sum;
 }
 
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
 /* 60017 65629 702179 */
 #define MAXDATALEN 60017
-#define BUFSIZE MAXDATALEN + sizeof(u_int16_t)
-  u_char buffer[BUFSIZE];
-  int exercise = 0;
+#define BUFSIZE MAXDATALEN + sizeof(uint16_t)
+       uint8_t buffer[BUFSIZE];
+       int exercise = 0;
 #define EXERCISESTEP 257
-  
-  srandom (time (NULL));
-  
-  while (1) {
-    u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc;
-    int i,j;
-
-    exercise += EXERCISESTEP;
-    exercise %= MAXDATALEN;
-    
-    for (i = 0; i < exercise; i += sizeof (long int)) {
-      long int rand = random ();
-      
-      for (j = sizeof (long int); j > 0; j--)
-        buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff;
-    }
-    
-    in_csum = in_cksum(buffer, exercise);
-    in_csum_res = in_cksum_optimized(buffer, exercise);
-    in_csum_rfc = in_cksum_rfc(buffer, exercise);
-    if (in_csum_res != in_csum || in_csum != in_csum_rfc)
-      printf ("verify: in_chksum failed in_csum:%x, in_csum_res:%x,"
-             "in_csum_rfc %x, len:%d\n", 
-             in_csum, in_csum_res, in_csum_rfc, exercise);
-
-    ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
-    if (verify (buffer, exercise + sizeof(u_int16_t)))
-      printf ("verify: ospfd failed\n");
-    isisd = iso_csum_create (buffer, exercise + sizeof(u_int16_t), exercise);
-    if (verify (buffer, exercise + sizeof(u_int16_t)))
-      printf ("verify: isisd failed\n");
-    lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
-    if (verify (buffer, exercise + sizeof(u_int16_t)))
-      printf ("verify: lib failed\n");
-    
-    if (ospfd != lib) {
-      printf ("Mismatch in values at size %u\n"
-              "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
-              "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
-              "lib: 0x%04x\n",
-              exercise,
-              ospfd, ospfd_vals.a.c0, ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y,
-              isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y,
-              lib
-              );
-      
-      /* Investigate reduction phase discrepencies */
-      if (ospfd_vals.a.c0 == isisd_vals.a.c0
-          && ospfd_vals.a.c1 == isisd_vals.a.c1) {
-        printf ("\n");
-        for (i = 0; reducts[i].name != NULL; i++) {    
-          ospfd = reducts[i].f (&ospfd_vals,
-                                exercise + sizeof (u_int16_t),
-                                exercise);
-          printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n",
-                  reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd);
-        }
-      }
-              
-      printf ("\n  u_char testdata [] = {\n  ");
-      for (i = 0; i < exercise; i++) {
-        printf ("0x%02x,%s",
-                buffer[i],
-                (i + 1) % 8 ? " " : "\n  ");
-      }
-      printf ("\n}\n");
-      exit (1);
-    }
-  }
+       struct prng *prng = prng_new(0);
+
+       while (1) {
+               uint16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc;
+               int i;
+
+               exercise += EXERCISESTEP;
+               exercise %= MAXDATALEN;
+
+               printf("\rexercising length %d\033[K", exercise);
+
+               for (i = 0; i < exercise; i++)
+                       buffer[i] = prng_rand(prng);
+
+               in_csum = in_cksum(buffer, exercise);
+               in_csum_res = in_cksum_optimized(buffer, exercise);
+               in_csum_rfc = in_cksum_rfc(buffer, exercise);
+               if (in_csum_res != in_csum || in_csum != in_csum_rfc)
+                       printf("\nverify: in_chksum failed in_csum:%x, in_csum_res:%x,in_csum_rfc %x, len:%d\n",
+                              in_csum, in_csum_res, in_csum_rfc, exercise);
+
+               struct iovec iov[3];
+               uint16_t in_csum_iov;
+
+               iov[0].iov_base = buffer;
+               iov[0].iov_len = exercise / 2;
+               iov[1].iov_base = buffer + iov[0].iov_len;
+               iov[1].iov_len = exercise - iov[0].iov_len;
+
+               in_csum_iov = in_cksumv(iov, 2);
+               if (in_csum_iov != in_csum)
+                       printf("\nverify: in_cksumv failed, lens: %zu+%zu\n",
+                              iov[0].iov_len, iov[1].iov_len);
+
+               if (exercise >= 6) {
+                       /* force split with byte leftover */
+                       iov[0].iov_base = buffer;
+                       iov[0].iov_len = (exercise / 2) | 1;
+                       iov[1].iov_base = buffer + iov[0].iov_len;
+                       iov[1].iov_len = 2;
+                       iov[2].iov_base = buffer + iov[0].iov_len + 2;
+                       iov[2].iov_len = exercise - iov[0].iov_len - 2;
+
+                       in_csum_iov = in_cksumv(iov, 3);
+                       if (in_csum_iov != in_csum)
+                               printf("\nverify: in_cksumv failed, lens: %zu+%zu+%zu, got %04x, expected %04x\n",
+                                      iov[0].iov_len, iov[1].iov_len,
+                                      iov[2].iov_len, in_csum_iov, in_csum);
+
+                       /* force split without byte leftover */
+                       iov[0].iov_base = buffer;
+                       iov[0].iov_len = (exercise / 2) & ~1UL;
+                       iov[1].iov_base = buffer + iov[0].iov_len;
+                       iov[1].iov_len = 2;
+                       iov[2].iov_base = buffer + iov[0].iov_len + 2;
+                       iov[2].iov_len = exercise - iov[0].iov_len - 2;
+
+                       in_csum_iov = in_cksumv(iov, 3);
+                       if (in_csum_iov != in_csum)
+                               printf("\nverify: in_cksumv failed, lens: %zu+%zu+%zu, got %04x, expected %04x\n",
+                                      iov[0].iov_len, iov[1].iov_len,
+                                      iov[2].iov_len, in_csum_iov, in_csum);
+               }
+
+               if (exercise >= FLETCHER_CHECKSUM_VALIDATE)
+                       continue;
+
+               ospfd = ospfd_checksum(buffer, exercise + sizeof(uint16_t),
+                                      exercise);
+               if (verify(buffer, exercise + sizeof(uint16_t)))
+                       printf("\nverify: ospfd failed\n");
+               isisd = iso_csum_create(buffer, exercise + sizeof(uint16_t),
+                                       exercise);
+               if (verify(buffer, exercise + sizeof(uint16_t)))
+                       printf("\nverify: isisd failed\n");
+               lib = fletcher_checksum(buffer, exercise + sizeof(uint16_t),
+                                       exercise);
+               if (verify(buffer, exercise + sizeof(uint16_t)))
+                       printf("\nverify: lib failed\n");
+
+               if (ospfd != lib) {
+                       printf("\nMismatch in values at size %d\n"
+                              "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
+                              "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
+                              "lib: 0x%04x\n",
+                              exercise, ospfd, ospfd_vals.a.c0,
+                              ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y,
+                              isisd, isisd_vals.a.c0, isisd_vals.a.c1,
+                              isisd_vals.x, isisd_vals.y, lib);
+
+                       /* Investigate reduction phase discrepencies */
+                       if (ospfd_vals.a.c0 == isisd_vals.a.c0
+                           && ospfd_vals.a.c1 == isisd_vals.a.c1) {
+                               printf("\n");
+                               for (i = 0; reducts[i].name != NULL; i++) {
+                                       ospfd = reducts[i].f(
+                                               &ospfd_vals,
+                                               exercise + sizeof(uint16_t),
+                                               exercise);
+                                       printf("%20s: x: %02x, y %02x, checksum 0x%04x\n",
+                                              reducts[i].name,
+                                              ospfd_vals.x & 0xff,
+                                              ospfd_vals.y & 0xff, ospfd);
+                               }
+                       }
+
+                       printf("\n  uint8_t testdata [] = {\n  ");
+                       for (i = 0; i < exercise; i++) {
+                               printf("0x%02x,%s", buffer[i],
+                                      (i + 1) % 8 ? " " : "\n  ");
+                       }
+                       printf("\n}\n");
+                       exit(1);
+               }
+       }
 }