xref: /xnu-11417.140.69/tests/skywalk/skt_copy_cksum.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2015-2024 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <libgen.h>
35 #include <machine/endian.h>
36 #include <darwintest.h>
37 
38 #include "skywalk_test_driver.h"
39 #include "skywalk_test_common.h"
40 #include "skywalk_test_utils.h"
41 
42 #define ST_MAX_OFFSET   128
43 #define ST_MIN_LEN      20
44 #define ST_MAX_LEN      (ST_MAX_OFFSET * 2)
45 #define ST_BUFFER_SIZE  (ST_MAX_LEN + ST_MAX_OFFSET)
46 
47 static uint8_t st_src_buffer1[ST_BUFFER_SIZE]  __attribute((aligned(1024)));
48 static uint8_t st_src_buffer2[ST_BUFFER_SIZE / 2]  __attribute((aligned(1024)));
49 static uint8_t st_dst_buffer[ST_BUFFER_SIZE]  __attribute((aligned(1024)));
50 static uint8_t st_ref_buffer[ST_BUFFER_SIZE]  __attribute((aligned(1024)));
51 static time_t the_time;
52 static u_int verbose;
53 
54 
55 /*
56  * Just enough of struct mbuf for m_copydata_sum()
57  */
58 struct mbuf {
59 	void *m_data;
60 	u_int m_len;
61 	struct mbuf *m_next;
62 };
63 #define mtod(m, t)       ((t)((m)->m_data))
64 
65 static uint32_t
__packet_copy_and_sum(const void * src,void * dst,uint32_t len,uint32_t sum0)66 __packet_copy_and_sum(const void *src, void *dst, uint32_t len,
67     uint32_t sum0)
68 {
69 	uint32_t rv = os_copy_and_inet_checksum(src, dst, len, sum0);
70 
71 	return (~rv) & 0xffffu;
72 }
73 
74 static inline uint16_t
packet_fold_sum_final(uint32_t sum)75 packet_fold_sum_final(uint32_t sum)
76 {
77 	sum = (sum >> 16) + (sum & 0xffff);     /* 17-bit */
78 	sum = (sum >> 16) + (sum & 0xffff);     /* 16-bit + carry */
79 	sum = (sum >> 16) + (sum & 0xffff);     /* final carry */
80 	return ~sum & 0xffff;
81 }
82 
83 uint32_t
m_copydata_sum(struct mbuf * m,int off,int len,void * vp,uint32_t initial_sum,boolean_t * odd_start)84 m_copydata_sum(struct mbuf *m, int off, int len, void *vp, uint32_t initial_sum,
85     boolean_t *odd_start)
86 {
87 	boolean_t needs_swap, started_on_odd = FALSE;
88 	int off0 = off, len0 = len;
89 	struct mbuf *m0 = m;
90 	uint64_t sum, partial;
91 	unsigned count, odd;
92 	char *cp = vp;
93 
94 	if (__improbable(off < 0 || len < 0)) {
95 		T_LOG("%s: invalid offset %d or len %d", __func__, off, len);
96 		/* NOTREACHED */
97 		__builtin_unreachable();
98 	}
99 
100 	while (off > 0) {
101 		if (__improbable(m == NULL)) {
102 			T_LOG("%s: invalid mbuf chain %p [off %d, len %d]",
103 			    __func__, m0, off0, len0);
104 			/* NOTREACHED */
105 			__builtin_unreachable();
106 		}
107 		if (off < m->m_len) {
108 			break;
109 		}
110 		off -= m->m_len;
111 		m = m->m_next;
112 	}
113 
114 	if (odd_start) {
115 		started_on_odd = *odd_start;
116 	}
117 	sum = initial_sum;
118 
119 	for (; len > 0; m = m->m_next) {
120 		uint8_t *datap;
121 
122 		if (__improbable(m == NULL)) {
123 			T_LOG("%s: invalid mbuf chain %p [off %d, len %d]",
124 			    __func__, m0, off0, len0);
125 			/* NOTREACHED */
126 			__builtin_unreachable();
127 		}
128 
129 		datap = mtod(m, uint8_t *) + off;
130 		count = m->m_len;
131 
132 		if (__improbable(count == 0)) {
133 			continue;
134 		}
135 
136 		count = MIN(count - off, (unsigned)len);
137 		partial = 0;
138 
139 		if ((uintptr_t)datap & 1) {
140 			/* Align on word boundary */
141 			started_on_odd = !started_on_odd;
142 #if BYTE_ORDER == LITTLE_ENDIAN
143 			partial = *datap << 8;
144 #else /* BYTE_ORDER != LITTLE_ENDIAN */
145 			partial = *datap;
146 #endif /* BYTE_ORDER != LITTLE_ENDIAN */
147 			*cp++ = *datap++;
148 			count -= 1;
149 			len -= 1;
150 		}
151 
152 		needs_swap = started_on_odd;
153 		odd = count & 1u;
154 		count -= odd;
155 
156 		if (count) {
157 			partial = __packet_copy_and_sum(datap,
158 			    cp, count, (uint32_t)partial);
159 			datap += count;
160 			cp += count;
161 			len -= count;
162 			if (__improbable((partial & (3ULL << 62)) != 0)) {
163 				if (needs_swap) {
164 					partial = (partial << 8) +
165 					    (partial >> 56);
166 				}
167 				sum += (partial >> 32);
168 				sum += (partial & 0xffffffff);
169 				partial = 0;
170 			}
171 		}
172 
173 		if (odd) {
174 #if BYTE_ORDER == LITTLE_ENDIAN
175 			partial += *datap;
176 #else /* BYTE_ORDER != LITTLE_ENDIAN */
177 			partial += *datap << 8;
178 #endif /* BYTE_ORDER != LITTLE_ENDIAN */
179 			*cp++ = *datap++;
180 			len -= 1;
181 			started_on_odd = !started_on_odd;
182 		}
183 		off = 0;
184 
185 		if (needs_swap) {
186 			partial = (partial << 8) + (partial >> 24);
187 		}
188 		sum += (partial >> 32) + (partial & 0xffffffff);
189 		/*
190 		 * Reduce sum to allow potential byte swap
191 		 * in the next iteration without carry.
192 		 */
193 		sum = (sum >> 32) + (sum & 0xffffffff);
194 	}
195 
196 	if (odd_start) {
197 		*odd_start = started_on_odd;
198 	}
199 
200 	/* Final fold (reduce 64-bit to 32-bit) */
201 	sum = (sum >> 32) + (sum & 0xffffffff); /* 33-bit */
202 	sum = (sum >> 16) + (sum & 0xffff);     /* 17-bit + carry */
203 
204 	/* return 32-bit partial sum to caller */
205 	return (uint32_t)sum;
206 }
207 
208 /*
209  * This is taken from xnu/bsd/netinet/cpu_in_cksum_gen.c and is used to
210  * generate reference checksums for the source data.
211  */
212 uint32_t
reference_cksum_mbuf(struct mbuf * m,int len,int off,uint32_t initial_sum)213 reference_cksum_mbuf(struct mbuf *m, int len, int off, uint32_t initial_sum)
214 {
215 	int mlen;
216 	uint64_t sum, partial;
217 	uint32_t final_acc;
218 	uint8_t *data;
219 	boolean_t needs_swap, started_on_odd;
220 
221 	needs_swap = FALSE;
222 	started_on_odd = FALSE;
223 	sum = initial_sum;
224 
225 	for (;;) {
226 		if (m == NULL) {
227 			return -1;
228 		}
229 		mlen = m->m_len;
230 		if (mlen > off) {
231 			mlen -= off;
232 			data = m->m_data + off;
233 			goto post_initial_offset;
234 		}
235 		off -= mlen;
236 		if (len == 0) {
237 			break;
238 		}
239 		m = m->m_next;
240 	}
241 
242 	for (; len > 0; m = m->m_next) {
243 		if (m == NULL) {
244 			return -1;
245 		}
246 		mlen = m->m_len;
247 		data = m->m_data;
248 post_initial_offset:
249 		if (mlen == 0) {
250 			continue;
251 		}
252 		if (mlen > len) {
253 			mlen = len;
254 		}
255 		len -= mlen;
256 
257 		partial = 0;
258 		if ((uintptr_t)data & 1) {
259 			/* Align on word boundary */
260 			started_on_odd = !started_on_odd;
261 #if BYTE_ORDER == LITTLE_ENDIAN
262 			partial = *data << 8;
263 #else
264 			partial = *data;
265 #endif
266 			++data;
267 			--mlen;
268 		}
269 		needs_swap = started_on_odd;
270 		if ((uintptr_t)data & 2) {
271 			if (mlen < 2) {
272 				goto trailing_bytes;
273 			}
274 			partial += *(uint16_t *)(void *)data;
275 			data += 2;
276 			mlen -= 2;
277 		}
278 		while (mlen >= 64) {
279 			__builtin_prefetch(data + 32);
280 			__builtin_prefetch(data + 64);
281 			partial += *(uint32_t *)(void *)data;
282 			partial += *(uint32_t *)(void *)(data + 4);
283 			partial += *(uint32_t *)(void *)(data + 8);
284 			partial += *(uint32_t *)(void *)(data + 12);
285 			partial += *(uint32_t *)(void *)(data + 16);
286 			partial += *(uint32_t *)(void *)(data + 20);
287 			partial += *(uint32_t *)(void *)(data + 24);
288 			partial += *(uint32_t *)(void *)(data + 28);
289 			partial += *(uint32_t *)(void *)(data + 32);
290 			partial += *(uint32_t *)(void *)(data + 36);
291 			partial += *(uint32_t *)(void *)(data + 40);
292 			partial += *(uint32_t *)(void *)(data + 44);
293 			partial += *(uint32_t *)(void *)(data + 48);
294 			partial += *(uint32_t *)(void *)(data + 52);
295 			partial += *(uint32_t *)(void *)(data + 56);
296 			partial += *(uint32_t *)(void *)(data + 60);
297 			data += 64;
298 			mlen -= 64;
299 			if (partial & (3ULL << 62)) {
300 				if (needs_swap) {
301 					partial = (partial << 8) +
302 					    (partial >> 56);
303 				}
304 				sum += (partial >> 32);
305 				sum += (partial & 0xffffffff);
306 				partial = 0;
307 			}
308 		}
309 		/*
310 		 * mlen is not updated below as the remaining tests
311 		 * are using bit masks, which are not affected.
312 		 */
313 		if (mlen & 32) {
314 			partial += *(uint32_t *)(void *)data;
315 			partial += *(uint32_t *)(void *)(data + 4);
316 			partial += *(uint32_t *)(void *)(data + 8);
317 			partial += *(uint32_t *)(void *)(data + 12);
318 			partial += *(uint32_t *)(void *)(data + 16);
319 			partial += *(uint32_t *)(void *)(data + 20);
320 			partial += *(uint32_t *)(void *)(data + 24);
321 			partial += *(uint32_t *)(void *)(data + 28);
322 			data += 32;
323 		}
324 		if (mlen & 16) {
325 			partial += *(uint32_t *)(void *)data;
326 			partial += *(uint32_t *)(void *)(data + 4);
327 			partial += *(uint32_t *)(void *)(data + 8);
328 			partial += *(uint32_t *)(void *)(data + 12);
329 			data += 16;
330 		}
331 		if (mlen & 8) {
332 			partial += *(uint32_t *)(void *)data;
333 			partial += *(uint32_t *)(void *)(data + 4);
334 			data += 8;
335 		}
336 		if (mlen & 4) {
337 			partial += *(uint32_t *)(void *)data;
338 			data += 4;
339 		}
340 		if (mlen & 2) {
341 			partial += *(uint16_t *)(void *)data;
342 			data += 2;
343 		}
344 trailing_bytes:
345 		if (mlen & 1) {
346 #if BYTE_ORDER == LITTLE_ENDIAN
347 			partial += *data;
348 #else
349 			partial += *data << 8;
350 #endif
351 			started_on_odd = !started_on_odd;
352 		}
353 
354 		if (needs_swap) {
355 			partial = (partial << 8) + (partial >> 56);
356 		}
357 		sum += (partial >> 32) + (partial & 0xffffffff);
358 		/*
359 		 * Reduce sum to allow potential byte swap
360 		 * in the next iteration without carry.
361 		 */
362 		sum = (sum >> 32) + (sum & 0xffffffff);
363 	}
364 	final_acc = (sum >> 48) + ((sum >> 32) & 0xffff) +
365 	    ((sum >> 16) & 0xffff) + (sum & 0xffff);
366 	final_acc = (final_acc >> 16) + (final_acc & 0xffff);
367 	final_acc = (final_acc >> 16) + (final_acc & 0xffff);
368 
369 	return (~final_acc) & 0xffffu;
370 }
371 
372 static void
randomise_buffer(uint8_t * buffer,u_int len)373 randomise_buffer(uint8_t *buffer, u_int len)
374 {
375 	while (len--) {
376 		*buffer++ = (uint8_t)rand();
377 	}
378 }
379 
380 static uint32_t
reference_cksum_single(u_int offset,u_int len,uint32_t init_sum)381 reference_cksum_single(u_int offset, u_int len, uint32_t init_sum)
382 {
383 	struct mbuf m;
384 
385 	m.m_len = len;
386 	m.m_data = (void *)&st_src_buffer1[offset];
387 	m.m_next = NULL;
388 
389 	return reference_cksum_mbuf(&m, len, 0, init_sum);
390 }
391 
392 static uint32_t
target_cksum_single(u_int soffset,u_int doffset,u_int len,uint32_t init_sum)393 target_cksum_single(u_int soffset, u_int doffset, u_int len, uint32_t init_sum)
394 {
395 	uint32_t rv;
396 
397 	rv = os_copy_and_inet_checksum(&st_src_buffer1[soffset],
398 	    &st_dst_buffer[doffset], len, init_sum);
399 
400 	return rv;
401 }
402 
403 static uint32_t
reference_cksum_multi(u_int offset,u_int len,uint32_t init_sum)404 reference_cksum_multi(u_int offset, u_int len, uint32_t init_sum)
405 {
406 	struct mbuf m[2];
407 
408 	if (len > 1) {
409 		m[0].m_len = len / 2;
410 		m[0].m_data = (void *)&st_src_buffer1[offset];
411 		m[0].m_next = &m[1];
412 		m[1].m_len = len - m[0].m_len;
413 		m[1].m_data = (void *)&st_src_buffer2[offset];
414 		m[1].m_next = NULL;
415 	} else {
416 		m[0].m_len = 1;
417 		m[0].m_data = (void *)&st_src_buffer1[offset];
418 		m[0].m_next = NULL;
419 	}
420 
421 	return reference_cksum_mbuf(&m[0], len, 0, init_sum);
422 }
423 
424 static uint32_t
target_cksum_multi(u_int soffset,u_int doffset,u_int len,uint32_t init_sum)425 target_cksum_multi(u_int soffset, u_int doffset, u_int len, uint32_t init_sum)
426 {
427 	struct mbuf m[2];
428 	uint32_t sum;
429 
430 	if (len > 1) {
431 		m[0].m_len = len / 2;
432 		m[0].m_data = (void *)&st_src_buffer1[soffset];
433 		m[0].m_next = &m[1];
434 		m[1].m_len = len - m[0].m_len;
435 		m[1].m_data = (void *)&st_src_buffer2[soffset];
436 		m[1].m_next = NULL;
437 	} else {
438 		m[0].m_len = 1;
439 		m[0].m_data = (void *)&st_src_buffer1[soffset];
440 		m[0].m_next = NULL;
441 	}
442 
443 	sum = m_copydata_sum(&m[0], 0, len, &st_dst_buffer[doffset],
444 	    init_sum, NULL);
445 
446 	/* Result of m_copydata_sum() requires folding to 16 bits */
447 	sum = (sum >> 16) + (sum & 0xffff);     /* 17-bit */
448 	sum = (sum >> 16) + (sum & 0xffff);     /* 16-bit + carry */
449 	sum = (sum >> 16) + (sum & 0xffff);     /* final carry */
450 
451 	return (~sum) & 0xffffu;
452 }
453 
454 static int
do_test_multi(u_int soffset,u_int doffset,u_int len,uint32_t init_sum)455 do_test_multi(u_int soffset, u_int doffset, u_int len, uint32_t init_sum)
456 {
457 	uint32_t ref_sum, tgt_sum;
458 	u_int m1_len;
459 	int rv;
460 
461 	if (verbose) {
462 		T_LOG("Source offset 0x%03x, Dest offset 0x%03x, "
463 		    "Len %u, init_sum 0x%04x\n", soffset, doffset, len,
464 		    init_sum);
465 	}
466 
467 	ref_sum = reference_cksum_multi(soffset, len, init_sum);
468 	if ((ref_sum & 0xffff0000u) != 0) {
469 		T_LOG("Multi: Source Offset %u, Dest Offset %u, "
470 		    "Len %u, ref_sum: Non-zero upper 16-bits: 0x%08x\n",
471 		    soffset, doffset, len, ref_sum);
472 
473 		return 1;
474 	}
475 
476 	memcpy(st_ref_buffer, st_dst_buffer, sizeof(st_ref_buffer));
477 
478 	m1_len = len / 2;
479 
480 	if (len > 1) {
481 		memcpy(&st_ref_buffer[doffset], &st_src_buffer1[soffset],
482 		    m1_len);
483 		memcpy(&st_ref_buffer[doffset + m1_len],
484 		    &st_src_buffer2[soffset], len - m1_len);
485 		if (verbose) {
486 			sktu_dump_buffer(stderr, "Multi Source1", &st_src_buffer1[soffset],
487 			    m1_len);
488 			sktu_dump_buffer(stderr, "Multi Source2", &st_src_buffer2[soffset],
489 			    len - m1_len);
490 		}
491 	} else {
492 		memcpy(&st_ref_buffer[doffset], &st_src_buffer1[soffset], 1);
493 		if (verbose) {
494 			sktu_dump_buffer(stderr, "Multi Source1", &st_src_buffer1[soffset],
495 			    1);
496 		}
497 	}
498 
499 	if (verbose) {
500 		sktu_dump_buffer(stderr, "Multi Dest, pre-sum", &st_dst_buffer[doffset],
501 		    len);
502 	}
503 
504 	tgt_sum = target_cksum_multi(soffset, doffset, len, init_sum);
505 
506 	if (verbose) {
507 		sktu_dump_buffer(stderr, "Multi Dest, post-sum", &st_dst_buffer[doffset],
508 		    len);
509 		fputc('\n', stderr);
510 	}
511 
512 	rv = 0;
513 
514 	if ((tgt_sum & 0xffff0000u) != 0) {
515 		T_LOG("Multi: Source Offset %u, Dest Offset %u, "
516 		    "Len %u, Target: Non-zero upper 16-bits: 0x%08x\n", soffset,
517 		    doffset, len, ref_sum);
518 
519 		rv = 1;
520 	} else if (ref_sum != tgt_sum) {
521 		T_LOG("Multi: Source Offset %u, Dest Offset %u, "
522 		    "Len %u, Checksum mismatch (ref:0x%04x != tgt:0x%04x)\n",
523 		    soffset, doffset, len, ref_sum, tgt_sum);
524 
525 		rv = 1;
526 	}
527 
528 	if (memcmp(st_dst_buffer, st_ref_buffer, sizeof(st_dst_buffer)) != 0) {
529 		T_LOG("Multi: Source Offset %u, Dest Offset %u, "
530 		    "Len %u, Target: Copy failed\n", soffset, doffset, len);
531 
532 		rv = 1;
533 	} else if (rv != 0) {
534 		T_LOG("Multi: Checksum may have failed, but the copy "
535 		    "succeeded.\n");
536 	}
537 
538 	return rv;
539 }
540 
541 static int
do_test_single(u_int soffset,u_int doffset,u_int len,uint32_t init_sum)542 do_test_single(u_int soffset, u_int doffset, u_int len, uint32_t init_sum)
543 {
544 	uint32_t ref_sum, tgt_sum;
545 	int rv;
546 
547 	if (verbose) {
548 		T_LOG("Source offset 0x%03x, Dest offset 0x%03x, "
549 		    "Len %u, init_sum 0x%04x\n", soffset, doffset, len,
550 		    init_sum);
551 	}
552 
553 	ref_sum = reference_cksum_single(soffset, len, init_sum);
554 	if ((ref_sum & 0xffff0000u) != 0) {
555 		T_LOG("Single: Source Offset %u, Dest Offset %u, "
556 		    "Len %u, ref_sum: Non-zero upper 16-bits: 0x%08x\n",
557 		    soffset, doffset, len, ref_sum);
558 
559 		return 1;
560 	}
561 
562 	memcpy(st_ref_buffer, st_dst_buffer, sizeof(st_ref_buffer));
563 	memcpy(&st_ref_buffer[doffset], &st_src_buffer1[soffset], len);
564 
565 	if (verbose) {
566 		sktu_dump_buffer(stderr, "Single Source", &st_src_buffer1[soffset], len);
567 		sktu_dump_buffer(stderr, "Single Dest, pre-sum", &st_dst_buffer[doffset],
568 		    len);
569 	}
570 
571 	tgt_sum = target_cksum_single(soffset, doffset, len, init_sum);
572 
573 	if (verbose) {
574 		sktu_dump_buffer(stderr, "Single Dest, post-sum", &st_dst_buffer[doffset],
575 		    len);
576 		fputc('\n', stderr);
577 	}
578 
579 	rv = 0;
580 
581 	if ((tgt_sum & 0xffff0000u) != 0) {
582 		T_LOG("Single: Source Offset %u, Dest Offset %u, "
583 		    "Len %u, Target: Non-zero upper 16-bits: 0x%08x\n", soffset,
584 		    doffset, len, ref_sum);
585 
586 		rv = 1;
587 	} else if (ref_sum != tgt_sum) {
588 		T_LOG("Single: Source Offset %u, Dest Offset %u, "
589 		    "Len %u, Checksum mismatch (ref:0x%04x != tgt:0x%04x)\n",
590 		    soffset, doffset, len, ref_sum, tgt_sum);
591 
592 		rv = 1;
593 	}
594 
595 	if (memcmp(st_dst_buffer, st_ref_buffer, sizeof(st_dst_buffer)) != 0) {
596 		T_LOG("Single: Source Offset %u, Dest Offset %u, "
597 		    "Len %u, Target: Copy failed\n", soffset, doffset, len);
598 
599 		rv = 1;
600 	} else if (rv != 0) {
601 		T_LOG("Single: Checksum may have failed, but the "
602 		    "copy succeeded.\n");
603 	}
604 
605 	return rv;
606 }
607 
608 static int
do_test_cksum(u_int soffset,u_int len,uint32_t init_sum)609 do_test_cksum(u_int soffset, u_int len, uint32_t init_sum)
610 {
611 	uint32_t ref_sum, tgt_sum;
612 	int rv;
613 
614 	if (verbose) {
615 		T_LOG("Source offset 0x%03x, "
616 		    "Len %u, init_sum 0x%04x\n", soffset, len, init_sum);
617 	}
618 
619 	ref_sum = reference_cksum_single(soffset, len, init_sum);
620 	if ((ref_sum & 0xffff0000u) != 0) {
621 		T_LOG("Single: Source Offset %u, "
622 		    "Len %u, ref_sum: Non-zero upper 16-bits: 0x%08x\n",
623 		    soffset, len, ref_sum);
624 
625 		return 1;
626 	}
627 
628 	tgt_sum = os_inet_checksum(&st_src_buffer1[soffset], len, init_sum);
629 	tgt_sum = packet_fold_sum_final(tgt_sum);
630 
631 	rv = 0;
632 	if ((tgt_sum & 0xffff0000u) != 0) {
633 		T_LOG("Single: Source Offset %u, "
634 		    "Len %u, Target: Non-zero upper 16-bits: 0x%08x\n",
635 		    soffset, len, ref_sum);
636 
637 		rv = 1;
638 	} else if (ref_sum != tgt_sum) {
639 		T_LOG("Single: Source Offset %u, "
640 		    "Len %u, Checksum mismatch (ref:0x%04x != tgt:0x%04x)\n",
641 		    soffset, len, ref_sum, tgt_sum);
642 
643 		rv = 1;
644 	}
645 	return rv;
646 }
647 
648 static int
skt_copy_cksum_common(int argc,char ** argv,int (* test_func)(u_int,u_int,u_int,uint32_t))649 skt_copy_cksum_common(int argc, char **argv,
650     int (*test_func)(u_int, u_int, u_int, uint32_t))
651 {
652 	uint32_t init_sum;
653 	u_int soffset, doffset;
654 	u_int len;
655 
656 	if (the_time == 0) {
657 		(void) time(&the_time);
658 		srand(the_time);
659 	}
660 
661 	verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
662 
663 	if (verbose) {
664 		T_LOG("st_src_buffer1 %p\n", st_src_buffer1);
665 		T_LOG("st_src_buffer2 %p\n", st_src_buffer2);
666 		T_LOG("st_dst_buffer %p\n", st_dst_buffer);
667 		T_LOG("st_ref_buffer %p\n", st_ref_buffer);
668 	}
669 
670 	randomise_buffer(st_src_buffer1, sizeof(st_src_buffer1));
671 	randomise_buffer(st_src_buffer2, sizeof(st_src_buffer2));
672 	randomise_buffer(st_dst_buffer, sizeof(st_dst_buffer));
673 	memcpy(st_ref_buffer, st_src_buffer1, sizeof(st_ref_buffer));
674 
675 	for (len = ST_MIN_LEN; len <= ST_MAX_LEN; len++) {
676 		for (soffset = 0; soffset < ST_MAX_OFFSET; soffset++) {
677 			for (doffset = 0; doffset < ST_MAX_OFFSET; doffset++) {
678 				init_sum = rand() & 0xffffu;
679 
680 				if (test_func(soffset, doffset, len, init_sum)) {
681 					goto fail;
682 				}
683 			}
684 		}
685 	}
686 
687 	if (verbose) {
688 		T_LOG("Success\n");
689 	}
690 	return 0;
691 
692 fail:
693 	if (verbose) {
694 		T_LOG("Fail\n");
695 	}
696 
697 	return 1;
698 }
699 
700 static int
skt_cksum_common(int argc,char ** argv,int (* test_func)(u_int,u_int,uint32_t))701 skt_cksum_common(int argc, char **argv,
702     int (*test_func)(u_int, u_int, uint32_t))
703 {
704 	uint32_t init_sum;
705 	u_int soffset;
706 	u_int len;
707 
708 	if (the_time == 0) {
709 		(void) time(&the_time);
710 		srand(the_time);
711 	}
712 
713 	verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
714 
715 	if (verbose) {
716 		T_LOG("st_src_buffer1 %p\n", st_src_buffer1);
717 		T_LOG("st_ref_buffer %p\n", st_ref_buffer);
718 	}
719 
720 	randomise_buffer(st_src_buffer1, sizeof(st_src_buffer1));
721 	memcpy(st_ref_buffer, st_src_buffer1, sizeof(st_ref_buffer));
722 
723 	for (len = ST_MIN_LEN; len <= ST_MAX_LEN; len++) {
724 		for (soffset = 0; soffset < ST_MAX_OFFSET; soffset++) {
725 			init_sum = rand() & 0xffffu;
726 			if (test_func(soffset, len, init_sum)) {
727 				goto fail;
728 			}
729 		}
730 	}
731 
732 	if (verbose) {
733 		T_LOG("Success\n");
734 	}
735 	return 0;
736 
737 fail:
738 	if (verbose) {
739 		T_LOG("Fail\n");
740 	}
741 
742 	return 1;
743 }
744 
745 static int
skt_copy_cksum_single_main(int argc,char ** argv)746 skt_copy_cksum_single_main(int argc, char **argv)
747 {
748 	return skt_copy_cksum_common(argc, argv, do_test_single);
749 }
750 
751 static int
skt_copy_cksum_multi_main(int argc,char ** argv)752 skt_copy_cksum_multi_main(int argc, char **argv)
753 {
754 	return skt_copy_cksum_common(argc, argv, do_test_multi);
755 }
756 
757 static int
skt_cksum_main(int argc,char ** argv)758 skt_cksum_main(int argc, char **argv)
759 {
760 	return skt_cksum_common(argc, argv, do_test_cksum);
761 }
762 
763 struct skywalk_test skt_copy_cksum_single = {
764 	"copycksum-single", "test copy/checksum code: single buffer",
765 	SK_FEATURE_SKYWALK,
766 	skt_copy_cksum_single_main, { NULL },
767 	NULL, NULL,
768 };
769 
770 struct skywalk_test skt_copy_cksum_multi = {
771 	"copycksum-multi", "test copy/checksum code: buffer chain",
772 	SK_FEATURE_SKYWALK,
773 	skt_copy_cksum_multi_main, { NULL },
774 	NULL, NULL,
775 };
776 
777 struct skywalk_test skt_cksum = {
778 	"inetcksum", "test checksum code",
779 	SK_FEATURE_SKYWALK,
780 	skt_cksum_main, { NULL },
781 	NULL, NULL,
782 };
783