xref: /freebsd/contrib/netbsd-tests/net/in_cksum/in_cksum.c (revision c22165b4f1f5d38b681921797a44b3ba8c13b7e0)
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