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