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