1*640235e2SEnji Cooper /* $NetBSD: in_cksum.c,v 1.5 2015/10/18 18:27:25 christos Exp $ */ 2*640235e2SEnji Cooper /*- 3*640235e2SEnji Cooper * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 4*640235e2SEnji Cooper * All rights reserved. 5*640235e2SEnji Cooper * 6*640235e2SEnji Cooper * Redistribution and use in source and binary forms, with or without 7*640235e2SEnji Cooper * modification, are permitted provided that the following conditions 8*640235e2SEnji Cooper * are met: 9*640235e2SEnji Cooper * 10*640235e2SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*640235e2SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*640235e2SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*640235e2SEnji Cooper * notice, this list of conditions and the following disclaimer in 14*640235e2SEnji Cooper * the documentation and/or other materials provided with the 15*640235e2SEnji Cooper * distribution. 16*640235e2SEnji Cooper * 17*640235e2SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*640235e2SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*640235e2SEnji Cooper * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20*640235e2SEnji Cooper * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21*640235e2SEnji Cooper * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22*640235e2SEnji Cooper * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 23*640235e2SEnji Cooper * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24*640235e2SEnji Cooper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25*640235e2SEnji Cooper * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26*640235e2SEnji Cooper * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 27*640235e2SEnji Cooper * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*640235e2SEnji Cooper * SUCH DAMAGE. 29*640235e2SEnji Cooper */ 30*640235e2SEnji Cooper 31*640235e2SEnji Cooper #include <sys/cdefs.h> 32*640235e2SEnji Cooper __KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.5 2015/10/18 18:27:25 christos Exp $"); 33*640235e2SEnji Cooper 34*640235e2SEnji Cooper #include <sys/param.h> 35*640235e2SEnji Cooper #include <sys/mbuf.h> 36*640235e2SEnji Cooper #include <sys/resource.h> 37*640235e2SEnji Cooper #include <err.h> 38*640235e2SEnji Cooper #include <stdbool.h> 39*640235e2SEnji Cooper #include <stdio.h> 40*640235e2SEnji Cooper #include <stdarg.h> 41*640235e2SEnji Cooper #include <unistd.h> 42*640235e2SEnji Cooper #include <stdlib.h> 43*640235e2SEnji Cooper #include <string.h> 44*640235e2SEnji Cooper 45*640235e2SEnji Cooper #define cpu_in_cksum portable_cpu_in_cksum 46*640235e2SEnji Cooper #include "cpu_in_cksum.c" 47*640235e2SEnji Cooper 48*640235e2SEnji Cooper #ifdef HAVE_CPU_IN_CKSUM 49*640235e2SEnji Cooper #undef cpu_in_cksum 50*640235e2SEnji Cooper int cpu_in_cksum(struct mbuf*, int, int, uint32_t); 51*640235e2SEnji Cooper #endif 52*640235e2SEnji Cooper 53*640235e2SEnji Cooper static bool random_aligned; 54*640235e2SEnji Cooper 55*640235e2SEnji Cooper void panic(const char *, ...) __printflike(1, 2); 56*640235e2SEnji Cooper void 57*640235e2SEnji Cooper panic(const char *fmt, ...) 58*640235e2SEnji Cooper { 59*640235e2SEnji Cooper va_list ap; 60*640235e2SEnji Cooper va_start(ap, fmt); 61*640235e2SEnji Cooper verrx(1, fmt, ap); 62*640235e2SEnji Cooper va_end(ap); 63*640235e2SEnji Cooper } 64*640235e2SEnji Cooper 65*640235e2SEnji Cooper static void 66*640235e2SEnji Cooper free_mbuf_chain(struct mbuf *m) 67*640235e2SEnji Cooper { 68*640235e2SEnji Cooper struct mbuf *next; 69*640235e2SEnji Cooper 70*640235e2SEnji Cooper if (m == NULL) 71*640235e2SEnji Cooper return; 72*640235e2SEnji Cooper 73*640235e2SEnji Cooper next = m->m_next; 74*640235e2SEnji Cooper free(m); 75*640235e2SEnji Cooper free_mbuf_chain(next); 76*640235e2SEnji Cooper } 77*640235e2SEnji Cooper 78*640235e2SEnji Cooper static struct mbuf * 79*640235e2SEnji Cooper allocate_mbuf_chain(char **lens) 80*640235e2SEnji Cooper { 81*640235e2SEnji Cooper int len, off; 82*640235e2SEnji Cooper struct mbuf *m; 83*640235e2SEnji Cooper 84*640235e2SEnji Cooper if (*lens == NULL) 85*640235e2SEnji Cooper return NULL; 86*640235e2SEnji Cooper 87*640235e2SEnji Cooper len = atoi(*lens); 88*640235e2SEnji Cooper off = random_aligned ? rand() % 64 : 0; 89*640235e2SEnji Cooper 90*640235e2SEnji Cooper m = malloc(sizeof(struct m_hdr) + len + off); 91*640235e2SEnji Cooper if (m == NULL) 92*640235e2SEnji Cooper err(EXIT_FAILURE, "malloc failed"); 93*640235e2SEnji Cooper 94*640235e2SEnji Cooper m->m_data = (char *)m + sizeof(struct m_hdr) + off; 95*640235e2SEnji Cooper m->m_len = len; 96*640235e2SEnji Cooper 97*640235e2SEnji Cooper m->m_next = allocate_mbuf_chain(lens + 1); 98*640235e2SEnji Cooper 99*640235e2SEnji Cooper return m; 100*640235e2SEnji Cooper } 101*640235e2SEnji Cooper 102*640235e2SEnji Cooper #ifdef MBUFDUMP 103*640235e2SEnji Cooper static void 104*640235e2SEnji Cooper dump_mbuf(const struct mbuf *m, int len, int off) 105*640235e2SEnji Cooper { 106*640235e2SEnji Cooper int x = 0; 107*640235e2SEnji Cooper if (len <= 0) 108*640235e2SEnji Cooper return; 109*640235e2SEnji Cooper 110*640235e2SEnji Cooper printf("Starting len=%d off=%d:\n", len, off); 111*640235e2SEnji Cooper if (off > 0) { 112*640235e2SEnji Cooper for (; m; m = m->m_next) 113*640235e2SEnji Cooper if (off > m->m_len) 114*640235e2SEnji Cooper off -= m->m_len; 115*640235e2SEnji Cooper else 116*640235e2SEnji Cooper break; 117*640235e2SEnji Cooper if (m == NULL || off > m->m_len) 118*640235e2SEnji Cooper errx(1, "out of data"); 119*640235e2SEnji Cooper } 120*640235e2SEnji Cooper 121*640235e2SEnji Cooper unsigned char *ptr = mtod(m, unsigned char *) + off; 122*640235e2SEnji Cooper unsigned char *eptr = ptr + m->m_len; 123*640235e2SEnji Cooper printf("["); 124*640235e2SEnji Cooper for (;;) { 125*640235e2SEnji Cooper if (ptr == eptr) { 126*640235e2SEnji Cooper m = m->m_next; 127*640235e2SEnji Cooper if (m == NULL) 128*640235e2SEnji Cooper errx(1, "out of data"); 129*640235e2SEnji Cooper ptr = mtod(m, unsigned char *); 130*640235e2SEnji Cooper eptr = ptr + m->m_len; 131*640235e2SEnji Cooper printf("]\n["); 132*640235e2SEnji Cooper x = 0; 133*640235e2SEnji Cooper } 134*640235e2SEnji Cooper printf("%.2x ", *ptr++); 135*640235e2SEnji Cooper if (++x % 16 == 0) 136*640235e2SEnji Cooper printf("\n"); 137*640235e2SEnji Cooper if (--len == 0) 138*640235e2SEnji Cooper break; 139*640235e2SEnji Cooper } 140*640235e2SEnji Cooper printf("]\n"); 141*640235e2SEnji Cooper fflush(stdout); 142*640235e2SEnji Cooper } 143*640235e2SEnji Cooper #endif 144*640235e2SEnji Cooper 145*640235e2SEnji Cooper static void 146*640235e2SEnji Cooper randomise_mbuf_chain(struct mbuf *m) 147*640235e2SEnji Cooper { 148*640235e2SEnji Cooper int i, data, len; 149*640235e2SEnji Cooper 150*640235e2SEnji Cooper for (i = 0; i < m->m_len; i += sizeof(int)) { 151*640235e2SEnji Cooper data = rand(); 152*640235e2SEnji Cooper if (i + sizeof(int) < (size_t)m->m_len) 153*640235e2SEnji Cooper len = sizeof(int); 154*640235e2SEnji Cooper else 155*640235e2SEnji Cooper len = m->m_len - i; 156*640235e2SEnji Cooper memcpy(m->m_data + i, &data, len); 157*640235e2SEnji Cooper } 158*640235e2SEnji Cooper if (m->m_next) 159*640235e2SEnji Cooper randomise_mbuf_chain(m->m_next); 160*640235e2SEnji Cooper } 161*640235e2SEnji Cooper 162*640235e2SEnji Cooper static int 163*640235e2SEnji Cooper mbuf_len(struct mbuf *m) 164*640235e2SEnji Cooper { 165*640235e2SEnji Cooper return m == NULL ? 0 : m->m_len + mbuf_len(m->m_next); 166*640235e2SEnji Cooper } 167*640235e2SEnji Cooper 168*640235e2SEnji Cooper int in_cksum_portable(struct mbuf *, int); 169*640235e2SEnji Cooper int in_cksum(struct mbuf *, int); 170*640235e2SEnji Cooper 171*640235e2SEnji Cooper int 172*640235e2SEnji Cooper main(int argc, char **argv) 173*640235e2SEnji Cooper { 174*640235e2SEnji Cooper struct rusage res; 175*640235e2SEnji Cooper struct timeval tv, old_tv; 176*640235e2SEnji Cooper int loops, old_sum, off, len; 177*640235e2SEnji Cooper #ifdef HAVE_CPU_IN_CKSUM 178*640235e2SEnji Cooper int new_sum; 179*640235e2SEnji Cooper #endif 180*640235e2SEnji Cooper long i, iterations; 181*640235e2SEnji Cooper uint32_t init_sum; 182*640235e2SEnji Cooper struct mbuf *m; 183*640235e2SEnji Cooper bool verbose; 184*640235e2SEnji Cooper int c; 185*640235e2SEnji Cooper 186*640235e2SEnji Cooper loops = 16; 187*640235e2SEnji Cooper verbose = false; 188*640235e2SEnji Cooper random_aligned = 0; 189*640235e2SEnji Cooper iterations = 100000; 190*640235e2SEnji Cooper 191*640235e2SEnji Cooper while ((c = getopt(argc, argv, "i:l:u:v")) != -1) { 192*640235e2SEnji Cooper switch (c) { 193*640235e2SEnji Cooper case 'i': 194*640235e2SEnji Cooper iterations = atoi(optarg); 195*640235e2SEnji Cooper break; 196*640235e2SEnji Cooper case 'l': 197*640235e2SEnji Cooper loops = atoi(optarg); 198*640235e2SEnji Cooper break; 199*640235e2SEnji Cooper case 'u': 200*640235e2SEnji Cooper random_aligned = atoi(optarg); 201*640235e2SEnji Cooper break; 202*640235e2SEnji Cooper case 'v': 203*640235e2SEnji Cooper verbose = true; 204*640235e2SEnji Cooper break; 205*640235e2SEnji Cooper default: 206*640235e2SEnji Cooper errx(1, "%s [-l <loops>] [-u <unalign> [-i <iterations> " 207*640235e2SEnji Cooper "[<mbuf-size> ...]", getprogname()); 208*640235e2SEnji Cooper } 209*640235e2SEnji Cooper } 210*640235e2SEnji Cooper 211*640235e2SEnji Cooper for (; loops; --loops) { 212*640235e2SEnji Cooper if ((m = allocate_mbuf_chain(argv + 4)) == NULL) 213*640235e2SEnji Cooper continue; 214*640235e2SEnji Cooper randomise_mbuf_chain(m); 215*640235e2SEnji Cooper init_sum = rand(); 216*640235e2SEnji Cooper len = mbuf_len(m); 217*640235e2SEnji Cooper 218*640235e2SEnji Cooper /* force one loop over all data */ 219*640235e2SEnji Cooper if (loops == 1) 220*640235e2SEnji Cooper off = 0; 221*640235e2SEnji Cooper else 222*640235e2SEnji Cooper off = len ? rand() % len : 0; 223*640235e2SEnji Cooper 224*640235e2SEnji Cooper len -= off; 225*640235e2SEnji Cooper old_sum = portable_cpu_in_cksum(m, len, off, init_sum); 226*640235e2SEnji Cooper #ifdef HAVE_CPU_IN_CKSUM 227*640235e2SEnji Cooper #ifdef MBUFDUMP 228*640235e2SEnji Cooper printf("m->m_len=%d len=%d off=%d\n", m->m_len, len, off); 229*640235e2SEnji Cooper dump_mbuf(m, len, off); 230*640235e2SEnji Cooper #endif 231*640235e2SEnji Cooper new_sum = cpu_in_cksum(m, len, off, init_sum); 232*640235e2SEnji Cooper if (old_sum != new_sum) 233*640235e2SEnji Cooper errx(1, "comparison failed: %x %x", old_sum, new_sum); 234*640235e2SEnji Cooper #else 235*640235e2SEnji Cooper __USE(old_sum); 236*640235e2SEnji Cooper #endif 237*640235e2SEnji Cooper 238*640235e2SEnji Cooper if (iterations == 0) 239*640235e2SEnji Cooper continue; 240*640235e2SEnji Cooper 241*640235e2SEnji Cooper getrusage(RUSAGE_SELF, &res); 242*640235e2SEnji Cooper tv = res.ru_utime; 243*640235e2SEnji Cooper for (i = iterations; i; --i) 244*640235e2SEnji Cooper (void)portable_cpu_in_cksum(m, len, off, init_sum); 245*640235e2SEnji Cooper getrusage(RUSAGE_SELF, &res); 246*640235e2SEnji Cooper timersub(&res.ru_utime, &tv, &old_tv); 247*640235e2SEnji Cooper if (verbose) 248*640235e2SEnji Cooper printf("portable version: %jd.%06jd\n", 249*640235e2SEnji Cooper (intmax_t)old_tv.tv_sec, (intmax_t)old_tv.tv_usec); 250*640235e2SEnji Cooper 251*640235e2SEnji Cooper #ifdef HAVE_CPU_IN_CKSUM 252*640235e2SEnji Cooper getrusage(RUSAGE_SELF, &res); 253*640235e2SEnji Cooper tv = res.ru_utime; 254*640235e2SEnji Cooper for (i = iterations; i; --i) 255*640235e2SEnji Cooper (void)cpu_in_cksum(m, len, off, init_sum); 256*640235e2SEnji Cooper getrusage(RUSAGE_SELF, &res); 257*640235e2SEnji Cooper timersub(&res.ru_utime, &tv, &tv); 258*640235e2SEnji Cooper if (verbose) { 259*640235e2SEnji Cooper printf("test version: %jd.%06jd\n", 260*640235e2SEnji Cooper (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec); 261*640235e2SEnji Cooper printf("relative time: %3.g%%\n", 262*640235e2SEnji Cooper 100 * ((double)tv.tv_sec * 1e6 + tv.tv_usec) / 263*640235e2SEnji Cooper ((double)old_tv.tv_sec * 1e6 + old_tv.tv_usec + 1)); 264*640235e2SEnji Cooper } 265*640235e2SEnji Cooper #endif 266*640235e2SEnji Cooper free_mbuf_chain(m); 267*640235e2SEnji Cooper } 268*640235e2SEnji Cooper 269*640235e2SEnji Cooper return 0; 270*640235e2SEnji Cooper } 271