From c0e2333a0fee8979336f6bbc62156bf57ec0a9a9 Mon Sep 17 00:00:00 2001 From: joerg Date: Thu, 24 Jan 2008 18:12:29 +0000 Subject: [PATCH] Add regression test and benchmark for the upcoming cpu_in_cksum. This is inspired by an older test case written by Charles Hannum. cvs: ---------------------------------------------------------------------- --- regress/sys/net/in_cksum/Makefile | 43 +++++++ regress/sys/net/in_cksum/in_cksum.c | 169 ++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 regress/sys/net/in_cksum/Makefile create mode 100644 regress/sys/net/in_cksum/in_cksum.c diff --git a/regress/sys/net/in_cksum/Makefile b/regress/sys/net/in_cksum/Makefile new file mode 100644 index 000000000000..8ee30b342c1f --- /dev/null +++ b/regress/sys/net/in_cksum/Makefile @@ -0,0 +1,43 @@ +# $NetBSD: Makefile,v 1.1 2008/01/24 18:12:29 joerg Exp $ +# +# To use this, copy / link the cpu_in_cksum.S from the arch subdirectory +# and copy assum.h from the build directory of a kernel. +# + +NOMAN= # defined + +PROG= in_cksum +SRCS= in_cksum.c portable.c cpu_in_cksum.S +WARNS= 3 +AFLAGS= -g + +CPPFLAGS.portable.c= -Dcpu_in_cksum=portable_cpu_in_cksum +CLEANFILES+= portable.c + +.include + +cpu_in_cksum.o: assym.h + +portable.c: ${NETBSDSRCDIR}/sys/netinet/cpu_in_cksum.c + cp ${NETBSDSRCDIR}/sys/netinet/cpu_in_cksum.c $@ + +TIMING_LOOPS= 10000 + +test: + ./in_cksum 16 1 ${TIMING_LOOPS} \ + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + ./in_cksum 16 1 ${TIMING_LOOPS} \ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + ./in_cksum 64 1 ${TIMING_LOOPS} \ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \ + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + ./in_cksum 16 1 ${TIMING_LOOPS} \ + 1 3 1 3 1 3 1 + ./in_cksum 16 1 ${TIMING_LOOPS} 40 + ./in_cksum 16 0 ${TIMING_LOOPS} 2048 + ./in_cksum 16 1 ${TIMING_LOOPS} 1536 + ./in_cksum 16 1 ${TIMING_LOOPS} 576 + ./in_cksum 16 1 ${TIMING_LOOPS} 1536 1536 1536 1536 1536 640 + +.include diff --git a/regress/sys/net/in_cksum/in_cksum.c b/regress/sys/net/in_cksum/in_cksum.c new file mode 100644 index 000000000000..dc736efd85d4 --- /dev/null +++ b/regress/sys/net/in_cksum/in_cksum.c @@ -0,0 +1,169 @@ +/* $NetBSD: in_cksum.c,v 1.1 2008/01/24 18:12:29 joerg Exp $ */ +/*- + * Copyright (c) 2008 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.1 2008/01/24 18:12:29 joerg Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +int portable_cpu_in_cksum(struct mbuf*, int, int, uint32_t); +int cpu_in_cksum(struct mbuf*, int, int, uint32_t); + +static bool random_aligned; + +static void +free_mbuf_chain(struct mbuf *m) +{ + struct mbuf *next; + + if (m == NULL) + return; + + next = m->m_next; + free(m); + free_mbuf_chain(next); +} + +static struct mbuf * +allocate_mbuf_chain(char **lens) +{ + int len, off; + struct mbuf *m; + + if (*lens == NULL) + return NULL; + + len = atoi(*lens); + off = random_aligned ? rand() % 64 : 0; + + m = malloc(sizeof(struct m_hdr) + len + off); + if (m == NULL) + err(EXIT_FAILURE, "malloc failed"); + + m->m_data = (char *)m + sizeof(struct m_hdr) + off; + m->m_len = len; + + m->m_next = allocate_mbuf_chain(lens + 1); + + return m; +} + +static void +randomise_mbuf_chain(struct mbuf *m) +{ + int i, data, len; + + for (i = 0; i < m->m_len; i += sizeof(int)) { + data = rand(); + if (i + sizeof(int) < m->m_len) + len = sizeof(int); + else + len = m->m_len - i; + memcpy(m->m_data + i, &data, len); + } + if (m->m_next) + randomise_mbuf_chain(m->m_next); +} + +static int +mbuf_len(struct mbuf *m) +{ + return m == NULL ? 0 : m->m_len + mbuf_len(m->m_next); +} + +int in_cksum_portable(struct mbuf *, int); +int in_cksum(struct mbuf *, int); + +uint64_t rdtsc(void); + +int +main(int argc, char **argv) +{ + struct rusage res; + struct timeval tv, old_tv; + int loops, old_sum, new_sum, off, len; + long i, iterations; + uint32_t init_sum; + struct mbuf *m; + + if (argc < 4) + err(1, "%s loops unalign iterations ...", argv[0]); + + loops = atoi(argv[1]); + random_aligned = atoi(argv[2]); + iterations = atol(argv[3]); + + for (; loops; --loops) { + if ((m = allocate_mbuf_chain(argv + 4)) == NULL) + continue; + randomise_mbuf_chain(m); + init_sum = rand(); + len = mbuf_len(m); + off = len ? rand() % len : 0; + len -= off; + old_sum = portable_cpu_in_cksum(m, len, off, init_sum); + new_sum = cpu_in_cksum(m, len, off, init_sum); + if (old_sum != new_sum) + errx(1, "comparision failed: %x %x", old_sum, new_sum); + + if (iterations == 0) + continue; + + getrusage(RUSAGE_SELF, &res); + tv = res.ru_utime; + for (i = iterations; i; --i) + (void)portable_cpu_in_cksum(m, len, off, init_sum); + getrusage(RUSAGE_SELF, &res); + timersub(&res.ru_utime, &tv, &old_tv); + printf("portable version: %ld.%06ld\n", (long)old_tv.tv_sec, (long)old_tv.tv_usec); + + getrusage(RUSAGE_SELF, &res); + tv = res.ru_utime; + for (i = iterations; i; --i) + (void)cpu_in_cksum(m, len, off, init_sum); + getrusage(RUSAGE_SELF, &res); + timersub(&res.ru_utime, &tv, &tv); + printf("test version: %ld.%06ld\n", (long)tv.tv_sec, (long)tv.tv_usec); + printf("relative time: %3.f%%\n", + 100 * ((float)tv.tv_sec * 1e6 + tv.tv_usec) / + ((float)old_tv.tv_sec * 1e6 + old_tv.tv_usec + 1)); + + free_mbuf_chain(m); + } + + return 0; +}