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
panic(const char * fmt,...)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
free_mbuf_chain(struct mbuf * m)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 *
allocate_mbuf_chain(char ** lens)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
dump_mbuf(const struct mbuf * m,int len,int off)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
randomise_mbuf_chain(struct mbuf * m)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
mbuf_len(struct mbuf * m)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
main(int argc,char ** argv)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