]> 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 c265e164ebbd97519a8fdf28d0b0fae68c60f31f..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>
@@ -23,6 +8,8 @@
 #include <time.h>
 
 #include "checksum.h"
+#include "network.h"
+#include "prng.h"
 
 struct thread_master *master;
 
@@ -48,8 +35,8 @@ typedef uint16_t testoff_t;
 /* The final reduction phase.
  * 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
@@ -73,8 +60,8 @@ static u_int16_t reduce_ospfd(struct csum_vals *vals, testsz_t len,
 }
 
 /* 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
@@ -97,14 +84,14 @@ static u_int16_t reduce_ospfd1(struct csum_vals *vals, testsz_t len,
 }
 
 /* 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;
+       uint32_t mul;
 
        mul = (len - off) * (c0);
        x = mul - c0 - c1;
@@ -132,14 +119,14 @@ static u_int16_t reduce_isisd(struct csum_vals *vals, testsz_t len,
 }
 
 /* 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;
+       uint32_t mul;
 
        mul = (len - off) * (c0);
        x = mul - c0 - c1;
@@ -167,14 +154,14 @@ static u_int16_t reduce_isisd_yfix(struct csum_vals *vals, testsz_t len,
 }
 
 /* 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;
+       uint32_t mul;
 
        mul = (len - off) * (c0);
        x = mul - c1 - c0;
@@ -202,14 +189,14 @@ static u_int16_t reduce_isisd_mod(struct csum_vals *vals, testsz_t len,
 }
 
 /* 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;
+       uint32_t mul;
 
        mul = (len - off) * (c0);
        x = mul - c0 - c1;
@@ -238,7 +225,7 @@ static u_int16_t reduce_isisd_mody(struct csum_vals *vals, testsz_t len,
 
 struct reductions_t {
        const char *name;
-       u_int16_t (*f)(struct csum_vals *, testsz_t, testoff_t);
+       uint16_t (*f)(struct csum_vals *, testsz_t, testoff_t);
 } reducts[] = {
        {.name = "ospfd", .f = reduce_ospfd},
        {.name = "ospfd-1", .f = reduce_ospfd1},
@@ -250,14 +237,14 @@ struct reductions_t {
 };
 
 /* 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;
+       uint8_t *sp, *ep, *p, *q;
        int c0 = 0, c1 = 0;
        int x, y;
-       u_int16_t checksum, *csum;
+       uint16_t checksum, *csum;
 
-       csum = (u_int16_t *)(buffer + off);
+       csum = (uint16_t *)(buffer + off);
        *(csum) = 0;
 
        sp = buffer;
@@ -301,21 +288,21 @@ static u_int16_t ospfd_checksum(u_char *buffer, testsz_t len, testoff_t off)
 }
 
 /* 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;
+       uint8_t *p;
        int x;
        int y;
-       u_int32_t mul;
-       u_int32_t c0;
-       u_int32_t c1;
-       u_int16_t checksum, *csum;
+       uint32_t mul;
+       uint32_t c0;
+       uint32_t c1;
+       uint16_t checksum, *csum;
        int i, init_len, partial_len;
 
        checksum = 0;
 
-       csum = (u_int16_t *)(buffer + off);
+       csum = (uint16_t *)(buffer + off);
        *(csum) = checksum;
 
        p = buffer;
@@ -369,11 +356,11 @@ static u_int16_t iso_csum_create(u_char *buffer, testsz_t len, testoff_t off)
        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;
+       uint8_t *p;
+       uint32_t c0;
+       uint32_t c1;
        int i, partial_len;
 
        p = buffer;
@@ -403,9 +390,9 @@ static int verify(u_char *buffer, testsz_t len)
 static int /* return checksum in low-order 16 bits */
        in_cksum_optimized(void *parg, int nbytes)
 {
-       u_short *ptr = parg;
+       unsigned short *ptr = parg;
        register long sum;       /* assumes long == 32 bits */
-       register u_short answer; /* assumes u_short == 16 bits */
+       register unsigned short answer; /* assumes unsigned short == 16 bits */
        register int count;
        /*
         * Our algorithm is simple, using a 32-bit accumulator (sum),
@@ -419,7 +406,7 @@ static int /* return checksum in low-order 16 bits */
                sum += *++ptr;
 
        if (nbytes & 1)                    /* Odd */
-               sum += *(u_char *)(++ptr); /* one byte only */
+               sum += *(uint8_t *)(++ptr); /* one byte only */
 
        /*
         * Add back carry outs from top 16 bits to low 16 bits.
@@ -436,7 +423,7 @@ static int /* return checksum in low-order 16 bits */
        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".
         */
@@ -449,7 +436,7 @@ static int /* return checksum in low-order 16 bits */
        }
        /*  Add left-over byte, if any */
        if (count > 0) {
-               sum += *(u_char *)addr;
+               sum += *(uint8_t *)addr;
        }
 
        /*  Fold 32-bit sum to 16 bits */
@@ -463,50 +450,92 @@ int main(int argc, char **argv)
 {
 /* 60017 65629 702179 */
 #define MAXDATALEN 60017
-#define BUFSIZE MAXDATALEN + sizeof(u_int16_t)
-       u_char buffer[BUFSIZE];
+#define BUFSIZE MAXDATALEN + sizeof(uint16_t)
+       uint8_t buffer[BUFSIZE];
        int exercise = 0;
 #define EXERCISESTEP 257
-       srandom(time(NULL));
+       struct prng *prng = prng_new(0);
 
        while (1) {
-               u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc;
-               int i, j;
+               uint16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc;
+               int i;
 
                exercise += EXERCISESTEP;
                exercise %= MAXDATALEN;
 
-               for (i = 0; i < exercise; i += sizeof(long int)) {
-                       long int rand = random();
+               printf("\rexercising length %d\033[K", exercise);
 
-                       for (j = sizeof(long int); j > 0; j--)
-                               buffer[i + (sizeof(long int) - j)] =
-                                       (rand >> (j * 8)) & 0xff;
-               }
+               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("verify: in_chksum failed in_csum:%x, in_csum_res:%x,"
-                              "in_csum_rfc %x, len:%d\n",
+                       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);
 
-               ospfd = ospfd_checksum(buffer, exercise + sizeof(u_int16_t),
+               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(u_int16_t)))
-                       printf("verify: ospfd failed\n");
-               isisd = iso_csum_create(buffer, exercise + sizeof(u_int16_t),
+               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(u_int16_t)))
-                       printf("verify: isisd failed\n");
-               lib = fletcher_checksum(buffer, exercise + sizeof(u_int16_t),
+               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(u_int16_t)))
-                       printf("verify: lib failed\n");
+               if (verify(buffer, exercise + sizeof(uint16_t)))
+                       printf("\nverify: lib failed\n");
 
                if (ospfd != lib) {
-                       printf("Mismatch in values at size %u\n"
+                       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",
@@ -522,7 +551,7 @@ int main(int argc, char **argv)
                                for (i = 0; reducts[i].name != NULL; i++) {
                                        ospfd = reducts[i].f(
                                                &ospfd_vals,
-                                               exercise + sizeof(u_int16_t),
+                                               exercise + sizeof(uint16_t),
                                                exercise);
                                        printf("%20s: x: %02x, y %02x, checksum 0x%04x\n",
                                               reducts[i].name,
@@ -531,7 +560,7 @@ int main(int argc, char **argv)
                                }
                        }
 
-                       printf("\n  u_char testdata [] = {\n  ");
+                       printf("\n  uint8_t testdata [] = {\n  ");
                        for (i = 0; i < exercise; i++) {
                                printf("0x%02x,%s", buffer[i],
                                       (i + 1) % 8 ? " " : "\n  ");