13d6ee46bSPatrick Mooney /*
23d6ee46bSPatrick Mooney * This file and its contents are supplied under the terms of the
33d6ee46bSPatrick Mooney * Common Development and Distribution License ("CDDL"), version 1.0.
43d6ee46bSPatrick Mooney * You may only use this file in accordance with the terms of version
53d6ee46bSPatrick Mooney * 1.0 of the CDDL.
63d6ee46bSPatrick Mooney *
73d6ee46bSPatrick Mooney * A full copy of the text of the CDDL should have accompanied this
83d6ee46bSPatrick Mooney * source. A copy of the CDDL is also available via the Internet at
93d6ee46bSPatrick Mooney * http://www.illumos.org/license/CDDL.
103d6ee46bSPatrick Mooney */
113d6ee46bSPatrick Mooney
123d6ee46bSPatrick Mooney /*
133d6ee46bSPatrick Mooney * Copyright 2025 Oxide Computer Compnay
143d6ee46bSPatrick Mooney */
153d6ee46bSPatrick Mooney
163d6ee46bSPatrick Mooney /*
173d6ee46bSPatrick Mooney * Executor for mac_sw_cksum() ktests.
183d6ee46bSPatrick Mooney *
193d6ee46bSPatrick Mooney * This program builds up the packed nvlist payloads expected by the ktest for
203d6ee46bSPatrick Mooney * mac_sw_cksum(). The caller provides a snoop(1) with one or more packets
213d6ee46bSPatrick Mooney * bearing valid checksums. Along with the checksum types selected (via option
223d6ee46bSPatrick Mooney * flags), it is passed into the ktest, where it is stripped of its checksums
233d6ee46bSPatrick Mooney * and then run through mac_sw_cksum(). The resulting mblk is compared
243d6ee46bSPatrick Mooney * byte-for-byte with the original input to determine if the emulation generated
253d6ee46bSPatrick Mooney * the correct checksums.
263d6ee46bSPatrick Mooney */
273d6ee46bSPatrick Mooney
283d6ee46bSPatrick Mooney #include <stdio.h>
293d6ee46bSPatrick Mooney #include <stdlib.h>
303d6ee46bSPatrick Mooney #include <fcntl.h>
313d6ee46bSPatrick Mooney #include <unistd.h>
323d6ee46bSPatrick Mooney #include <err.h>
333d6ee46bSPatrick Mooney #include <errno.h>
343d6ee46bSPatrick Mooney #include <strings.h>
353d6ee46bSPatrick Mooney #include <netinet/in.h>
363d6ee46bSPatrick Mooney #include <sys/mman.h>
373d6ee46bSPatrick Mooney #include <sys/dlpi.h>
383d6ee46bSPatrick Mooney #include <sys/types.h>
393d6ee46bSPatrick Mooney #include <sys/types32.h>
403d6ee46bSPatrick Mooney #include <sys/stat.h>
413d6ee46bSPatrick Mooney #include <sys/sysmacros.h>
42*1f8b8a01SPatrick Mooney #include <sys/ethernet.h>
433d6ee46bSPatrick Mooney
443d6ee46bSPatrick Mooney #include <libnvpair.h>
453d6ee46bSPatrick Mooney #include <libktest.h>
463d6ee46bSPatrick Mooney
473d6ee46bSPatrick Mooney typedef struct snoop_pkt_hdr {
483d6ee46bSPatrick Mooney uint_t sph_origlen;
493d6ee46bSPatrick Mooney uint_t sph_msglen;
503d6ee46bSPatrick Mooney uint_t sph_totlen;
513d6ee46bSPatrick Mooney uint_t sph_drops;
523d6ee46bSPatrick Mooney #if defined(_LP64)
533d6ee46bSPatrick Mooney struct timeval32 sph_timestamp;
543d6ee46bSPatrick Mooney #else
553d6ee46bSPatrick Mooney #error "ktest is expected to be 64-bit for now"
563d6ee46bSPatrick Mooney #endif
573d6ee46bSPatrick Mooney } snoop_pkt_hdr_t;
583d6ee46bSPatrick Mooney
593d6ee46bSPatrick Mooney typedef struct snoop_file_hdr {
603d6ee46bSPatrick Mooney char sfh_magic[8];
613d6ee46bSPatrick Mooney uint32_t sfh_vers;
623d6ee46bSPatrick Mooney uint32_t sfh_mac_type;
633d6ee46bSPatrick Mooney } snoop_file_hdr_t;
643d6ee46bSPatrick Mooney
653d6ee46bSPatrick Mooney static const char snoop_magic[8] = "snoop\0\0\0";
663d6ee46bSPatrick Mooney static const uint_t snoop_acceptable_vers = 2;
673d6ee46bSPatrick Mooney
683d6ee46bSPatrick Mooney typedef struct pkt_cap_iter {
693d6ee46bSPatrick Mooney int pci_fd;
703d6ee46bSPatrick Mooney const char *pci_base;
713d6ee46bSPatrick Mooney size_t pci_map_sz;
723d6ee46bSPatrick Mooney size_t pci_sz;
733d6ee46bSPatrick Mooney size_t pci_offset;
743d6ee46bSPatrick Mooney } pkt_cap_iter_t;
753d6ee46bSPatrick Mooney
763d6ee46bSPatrick Mooney static pkt_cap_iter_t *
pkt_cap_open(int fd)773d6ee46bSPatrick Mooney pkt_cap_open(int fd)
783d6ee46bSPatrick Mooney {
793d6ee46bSPatrick Mooney struct stat info;
803d6ee46bSPatrick Mooney if (fstat(fd, &info) != 0) {
813d6ee46bSPatrick Mooney return (NULL);
823d6ee46bSPatrick Mooney }
833d6ee46bSPatrick Mooney if (info.st_size < sizeof (snoop_file_hdr_t)) {
843d6ee46bSPatrick Mooney errno = EINVAL;
853d6ee46bSPatrick Mooney return (NULL);
863d6ee46bSPatrick Mooney }
873d6ee46bSPatrick Mooney
883d6ee46bSPatrick Mooney const size_t page_sz = (size_t)sysconf(_SC_PAGESIZE);
893d6ee46bSPatrick Mooney const size_t map_sz = P2ROUNDUP(info.st_size, page_sz);
903d6ee46bSPatrick Mooney void *map = mmap(NULL, map_sz, PROT_READ, MAP_PRIVATE, fd, 0);
913d6ee46bSPatrick Mooney if (map == NULL) {
923d6ee46bSPatrick Mooney return (NULL);
933d6ee46bSPatrick Mooney }
943d6ee46bSPatrick Mooney
953d6ee46bSPatrick Mooney const snoop_file_hdr_t *hdr = (const snoop_file_hdr_t *)map;
963d6ee46bSPatrick Mooney if (bcmp(&hdr->sfh_magic, snoop_magic, sizeof (hdr->sfh_magic)) != 0 ||
973d6ee46bSPatrick Mooney ntohl(hdr->sfh_vers) != snoop_acceptable_vers ||
983d6ee46bSPatrick Mooney ntohl(hdr->sfh_mac_type) != DL_ETHER) {
993d6ee46bSPatrick Mooney (void) munmap(map, map_sz);
1003d6ee46bSPatrick Mooney errno = EINVAL;
1013d6ee46bSPatrick Mooney return (NULL);
1023d6ee46bSPatrick Mooney }
1033d6ee46bSPatrick Mooney
1043d6ee46bSPatrick Mooney struct pkt_cap_iter *iter = malloc(sizeof (struct pkt_cap_iter));
1053d6ee46bSPatrick Mooney if (iter == NULL) {
1063d6ee46bSPatrick Mooney (void) munmap(map, map_sz);
1073d6ee46bSPatrick Mooney errno = ENOMEM;
1083d6ee46bSPatrick Mooney return (NULL);
1093d6ee46bSPatrick Mooney }
1103d6ee46bSPatrick Mooney
1113d6ee46bSPatrick Mooney iter->pci_fd = fd;
1123d6ee46bSPatrick Mooney iter->pci_base = (const char *)map;
1133d6ee46bSPatrick Mooney iter->pci_map_sz = map_sz;
1143d6ee46bSPatrick Mooney iter->pci_sz = info.st_size;
1153d6ee46bSPatrick Mooney iter->pci_offset = sizeof (*hdr);
1163d6ee46bSPatrick Mooney
1173d6ee46bSPatrick Mooney return (iter);
1183d6ee46bSPatrick Mooney }
1193d6ee46bSPatrick Mooney
1203d6ee46bSPatrick Mooney static void
pkt_cap_close(pkt_cap_iter_t * iter)1213d6ee46bSPatrick Mooney pkt_cap_close(pkt_cap_iter_t *iter)
1223d6ee46bSPatrick Mooney {
1233d6ee46bSPatrick Mooney (void) munmap((void *)iter->pci_base, iter->pci_map_sz);
1243d6ee46bSPatrick Mooney (void) close(iter->pci_fd);
1253d6ee46bSPatrick Mooney free(iter);
1263d6ee46bSPatrick Mooney }
1273d6ee46bSPatrick Mooney
1283d6ee46bSPatrick Mooney static bool
pkt_cap_next(pkt_cap_iter_t * iter,const void ** pkt_buf,uint_t * sizep)1293d6ee46bSPatrick Mooney pkt_cap_next(pkt_cap_iter_t *iter, const void **pkt_buf, uint_t *sizep)
1303d6ee46bSPatrick Mooney {
1313d6ee46bSPatrick Mooney size_t remain = iter->pci_sz - iter->pci_offset;
1323d6ee46bSPatrick Mooney
1333d6ee46bSPatrick Mooney if (remain < sizeof (snoop_pkt_hdr_t)) {
1343d6ee46bSPatrick Mooney return (false);
1353d6ee46bSPatrick Mooney }
1363d6ee46bSPatrick Mooney
1373d6ee46bSPatrick Mooney const snoop_pkt_hdr_t *hdr =
1383d6ee46bSPatrick Mooney (const snoop_pkt_hdr_t *)&iter->pci_base[iter->pci_offset];
1393d6ee46bSPatrick Mooney
1403d6ee46bSPatrick Mooney const uint_t msg_sz = ntohl(hdr->sph_msglen);
1413d6ee46bSPatrick Mooney const uint_t total_sz = ntohl(hdr->sph_totlen);
1423d6ee46bSPatrick Mooney if (remain < total_sz || remain < msg_sz) {
1433d6ee46bSPatrick Mooney return (false);
1443d6ee46bSPatrick Mooney }
1453d6ee46bSPatrick Mooney
1463d6ee46bSPatrick Mooney *pkt_buf = (const void *)&hdr[1];
1473d6ee46bSPatrick Mooney *sizep = msg_sz;
1483d6ee46bSPatrick Mooney iter->pci_offset += total_sz;
1493d6ee46bSPatrick Mooney return (true);
1503d6ee46bSPatrick Mooney }
1513d6ee46bSPatrick Mooney
1523d6ee46bSPatrick Mooney static ktest_hdl_t *kthdl = NULL;
1533d6ee46bSPatrick Mooney const char *mac_cksum_cmd = "";
1543d6ee46bSPatrick Mooney
1553d6ee46bSPatrick Mooney struct payload_opts {
1563d6ee46bSPatrick Mooney uint_t po_padding;
1573d6ee46bSPatrick Mooney boolean_t po_cksum_partial;
1583d6ee46bSPatrick Mooney boolean_t po_cksum_full;
1593d6ee46bSPatrick Mooney boolean_t po_cksum_ipv4;
160*1f8b8a01SPatrick Mooney boolean_t po_split_ether;
161*1f8b8a01SPatrick Mooney uint_t po_split_manual;
1623d6ee46bSPatrick Mooney };
1633d6ee46bSPatrick Mooney
1643d6ee46bSPatrick Mooney static char *
build_payload(const void * pkt_buf,uint_t pkt_sz,const struct payload_opts * popts,size_t * payload_sz)1653d6ee46bSPatrick Mooney build_payload(const void *pkt_buf, uint_t pkt_sz,
1663d6ee46bSPatrick Mooney const struct payload_opts *popts, size_t *payload_sz)
1673d6ee46bSPatrick Mooney {
1683d6ee46bSPatrick Mooney nvlist_t *payload = fnvlist_alloc();
1693d6ee46bSPatrick Mooney fnvlist_add_byte_array(payload, "pkt_bytes",
1703d6ee46bSPatrick Mooney (uchar_t *)pkt_buf, pkt_sz);
1713d6ee46bSPatrick Mooney if (popts->po_padding) {
1723d6ee46bSPatrick Mooney fnvlist_add_uint32(payload, "padding", popts->po_padding);
1733d6ee46bSPatrick Mooney }
1743d6ee46bSPatrick Mooney if (popts->po_cksum_partial) {
1753d6ee46bSPatrick Mooney fnvlist_add_boolean(payload, "cksum_partial");
1763d6ee46bSPatrick Mooney }
1773d6ee46bSPatrick Mooney if (popts->po_cksum_full) {
1783d6ee46bSPatrick Mooney fnvlist_add_boolean(payload, "cksum_full");
1793d6ee46bSPatrick Mooney }
1803d6ee46bSPatrick Mooney if (popts->po_cksum_ipv4) {
1813d6ee46bSPatrick Mooney fnvlist_add_boolean(payload, "cksum_ipv4");
1823d6ee46bSPatrick Mooney }
1833d6ee46bSPatrick Mooney
184*1f8b8a01SPatrick Mooney uint_t nsplit = 0;
185*1f8b8a01SPatrick Mooney uint32_t splits[2];
186*1f8b8a01SPatrick Mooney if (popts->po_split_ether) {
187*1f8b8a01SPatrick Mooney splits[nsplit++] = sizeof (struct ether_header);
188*1f8b8a01SPatrick Mooney }
189*1f8b8a01SPatrick Mooney if (popts->po_split_manual != 0) {
190*1f8b8a01SPatrick Mooney splits[nsplit++] = popts->po_split_manual;
191*1f8b8a01SPatrick Mooney }
192*1f8b8a01SPatrick Mooney if (nsplit > 0) {
193*1f8b8a01SPatrick Mooney fnvlist_add_uint32_array(payload, "cksum_splits", splits,
194*1f8b8a01SPatrick Mooney nsplit);
195*1f8b8a01SPatrick Mooney }
196*1f8b8a01SPatrick Mooney
1973d6ee46bSPatrick Mooney char *packed = fnvlist_pack(payload, payload_sz);
1983d6ee46bSPatrick Mooney nvlist_free(payload);
1993d6ee46bSPatrick Mooney
2003d6ee46bSPatrick Mooney return (packed);
2013d6ee46bSPatrick Mooney }
2023d6ee46bSPatrick Mooney
2033d6ee46bSPatrick Mooney static void
mac_cksum_usage(void)2043d6ee46bSPatrick Mooney mac_cksum_usage(void)
2053d6ee46bSPatrick Mooney {
2063d6ee46bSPatrick Mooney (void) fprintf(stderr, "usage: %s [flags] [opts] <cap_file>\n\n"
2073d6ee46bSPatrick Mooney "Flags:\n"
2083d6ee46bSPatrick Mooney "\t-4\temulate HCK_IPV4_HDRCKSUM\n"
2093d6ee46bSPatrick Mooney "\t-f\temulate HCK_FULLCKSUM\t(cannot be used with -p)\n"
2103d6ee46bSPatrick Mooney "\t-p\temulate HCK_PARTIALCKSUM\t(cannot be used with -f)\n"
211*1f8b8a01SPatrick Mooney "\t-e\tsplit mblk after Ethernet header\n"
2123d6ee46bSPatrick Mooney "Options:\n"
2133d6ee46bSPatrick Mooney "\t-b <len>\tpad mblk with <len> bytes (must be even)\n"
214*1f8b8a01SPatrick Mooney "\t-s <len>\tsplit mblk after len bytes (must be even)\n"
215*1f8b8a01SPatrick Mooney "\t\t\tif -e is specified, will be applied after that split\n"
2163d6ee46bSPatrick Mooney "Arguments:\n"
2173d6ee46bSPatrick Mooney "\t<cap_file> is a snoop capture of packets to test.\n"
2183d6ee46bSPatrick Mooney "\tAny TCP or UDP packets (or plain IPv4) are expected to have\n"
2193d6ee46bSPatrick Mooney "\tcorrect checksums. The emulated results will be compared\n"
2203d6ee46bSPatrick Mooney "\tagainst those sums in the packet (assuming them proper)\n",
2213d6ee46bSPatrick Mooney mac_cksum_cmd);
2223d6ee46bSPatrick Mooney exit(EXIT_FAILURE);
2233d6ee46bSPatrick Mooney }
2243d6ee46bSPatrick Mooney
2253d6ee46bSPatrick Mooney int
main(int argc,char * argv[])2263d6ee46bSPatrick Mooney main(int argc, char *argv[])
2273d6ee46bSPatrick Mooney {
2283d6ee46bSPatrick Mooney /* Peel off command name for usage */
2293d6ee46bSPatrick Mooney mac_cksum_cmd = argv[0];
2303d6ee46bSPatrick Mooney argc--;
2313d6ee46bSPatrick Mooney argv++;
2323d6ee46bSPatrick Mooney optind = 0;
2333d6ee46bSPatrick Mooney
2343d6ee46bSPatrick Mooney struct payload_opts popts = { 0 };
2353d6ee46bSPatrick Mooney int c;
236*1f8b8a01SPatrick Mooney while ((c = getopt(argc, argv, "4fpeb:s:")) != -1) {
2373d6ee46bSPatrick Mooney switch (c) {
2383d6ee46bSPatrick Mooney case 'p':
2393d6ee46bSPatrick Mooney popts.po_cksum_partial = B_TRUE;
2403d6ee46bSPatrick Mooney break;
2413d6ee46bSPatrick Mooney case 'f':
2423d6ee46bSPatrick Mooney popts.po_cksum_full = B_TRUE;
2433d6ee46bSPatrick Mooney break;
2443d6ee46bSPatrick Mooney case '4':
2453d6ee46bSPatrick Mooney popts.po_cksum_ipv4 = B_TRUE;
2463d6ee46bSPatrick Mooney break;
2473d6ee46bSPatrick Mooney case 'b':
2483d6ee46bSPatrick Mooney errno = 0;
2493d6ee46bSPatrick Mooney popts.po_padding = strtoul(optarg, NULL, 0);
2503d6ee46bSPatrick Mooney if (errno != 0) {
2513d6ee46bSPatrick Mooney err(EXIT_FAILURE,
2523d6ee46bSPatrick Mooney "invalid padding value %s", optarg);
2533d6ee46bSPatrick Mooney }
2543d6ee46bSPatrick Mooney break;
255*1f8b8a01SPatrick Mooney case 'e':
256*1f8b8a01SPatrick Mooney popts.po_split_ether = B_TRUE;
257*1f8b8a01SPatrick Mooney break;
258*1f8b8a01SPatrick Mooney case 's':
259*1f8b8a01SPatrick Mooney errno = 0;
260*1f8b8a01SPatrick Mooney popts.po_split_manual = strtoul(optarg, NULL, 0);
261*1f8b8a01SPatrick Mooney if (errno != 0) {
262*1f8b8a01SPatrick Mooney err(EXIT_FAILURE,
263*1f8b8a01SPatrick Mooney "invalid split value %s", optarg);
264*1f8b8a01SPatrick Mooney }
265*1f8b8a01SPatrick Mooney break;
266*1f8b8a01SPatrick Mooney
2673d6ee46bSPatrick Mooney case '?':
2683d6ee46bSPatrick Mooney warnx("unknown run option: -%c", optopt);
2693d6ee46bSPatrick Mooney mac_cksum_usage();
2703d6ee46bSPatrick Mooney }
2713d6ee46bSPatrick Mooney }
2723d6ee46bSPatrick Mooney argc -= optind;
2733d6ee46bSPatrick Mooney argv += optind;
2743d6ee46bSPatrick Mooney
2753d6ee46bSPatrick Mooney if (argc != 1) {
2763d6ee46bSPatrick Mooney mac_cksum_usage();
2773d6ee46bSPatrick Mooney }
2783d6ee46bSPatrick Mooney
2793d6ee46bSPatrick Mooney int fd = open(argv[0], O_RDONLY, 0);
2803d6ee46bSPatrick Mooney if (fd < 0) {
2813d6ee46bSPatrick Mooney err(EXIT_FAILURE, "could not open cap file %s", argv[0]);
2823d6ee46bSPatrick Mooney }
2833d6ee46bSPatrick Mooney
2843d6ee46bSPatrick Mooney pkt_cap_iter_t *iter = pkt_cap_open(fd);
2853d6ee46bSPatrick Mooney if (iter == NULL) {
2863d6ee46bSPatrick Mooney err(EXIT_FAILURE, "unrecognized cap file %s", argv[0]);
2873d6ee46bSPatrick Mooney }
2883d6ee46bSPatrick Mooney
2893d6ee46bSPatrick Mooney if (!ktest_mod_load("mac")) {
2903d6ee46bSPatrick Mooney err(EXIT_FAILURE, "could not load mac ktest module");
2913d6ee46bSPatrick Mooney }
2923d6ee46bSPatrick Mooney if ((kthdl = ktest_init()) == NULL) {
2933d6ee46bSPatrick Mooney err(EXIT_FAILURE, "could not initialize libktest");
2943d6ee46bSPatrick Mooney }
2953d6ee46bSPatrick Mooney
2963d6ee46bSPatrick Mooney const void *pkt_buf;
2973d6ee46bSPatrick Mooney uint_t pkt_sz;
2983d6ee46bSPatrick Mooney uint_t count_pass = 0, count_fail = 0, count_skip = 0, idx = 0;
2993d6ee46bSPatrick Mooney while (pkt_cap_next(iter, &pkt_buf, &pkt_sz)) {
3003d6ee46bSPatrick Mooney ktest_run_req_t req = {
3013d6ee46bSPatrick Mooney .krq_module = "mac",
3023d6ee46bSPatrick Mooney .krq_suite = "checksum",
3033d6ee46bSPatrick Mooney .krq_test = "mac_sw_cksum_test",
3043d6ee46bSPatrick Mooney };
3053d6ee46bSPatrick Mooney size_t payload_sz;
3063d6ee46bSPatrick Mooney char *payload =
3073d6ee46bSPatrick Mooney build_payload(pkt_buf, pkt_sz, &popts, &payload_sz);
3083d6ee46bSPatrick Mooney req.krq_input = (uchar_t *)payload;
3093d6ee46bSPatrick Mooney req.krq_input_len = (uint_t)payload_sz;
3103d6ee46bSPatrick Mooney
3113d6ee46bSPatrick Mooney ktest_run_result_t result = { 0 };
3123d6ee46bSPatrick Mooney if (!ktest_run(kthdl, &req, &result)) {
3133d6ee46bSPatrick Mooney err(EXIT_FAILURE, "failure while attempting ktest run");
3143d6ee46bSPatrick Mooney }
3153d6ee46bSPatrick Mooney free(payload);
3163d6ee46bSPatrick Mooney
3173d6ee46bSPatrick Mooney const char *code_name = ktest_code_name(result.krr_code);
3183d6ee46bSPatrick Mooney switch (result.krr_code) {
3193d6ee46bSPatrick Mooney case KTEST_CODE_PASS:
3203d6ee46bSPatrick Mooney count_pass++;
3213d6ee46bSPatrick Mooney break;
3223d6ee46bSPatrick Mooney case KTEST_CODE_SKIP:
3233d6ee46bSPatrick Mooney count_skip++;
3243d6ee46bSPatrick Mooney break;
3253d6ee46bSPatrick Mooney default:
3263d6ee46bSPatrick Mooney count_fail++;
3273d6ee46bSPatrick Mooney break;
3283d6ee46bSPatrick Mooney }
3293d6ee46bSPatrick Mooney (void) printf("%4u\t%s\t(len: %u)\n", idx, code_name, pkt_sz);
3303d6ee46bSPatrick Mooney if (result.krr_msg != NULL) {
3313d6ee46bSPatrick Mooney if (result.krr_code != KTEST_CODE_PASS) {
3323d6ee46bSPatrick Mooney (void) printf("MSG: %s\n", result.krr_msg);
3333d6ee46bSPatrick Mooney }
3343d6ee46bSPatrick Mooney free(result.krr_msg);
3353d6ee46bSPatrick Mooney }
3363d6ee46bSPatrick Mooney idx++;
3373d6ee46bSPatrick Mooney }
3383d6ee46bSPatrick Mooney if (idx == 0) {
3393d6ee46bSPatrick Mooney errx(EXIT_FAILURE, "No valid packets found");
3403d6ee46bSPatrick Mooney } else if (idx != 1) {
3413d6ee46bSPatrick Mooney /* Summarize for > 1 packet */
3423d6ee46bSPatrick Mooney (void) printf("SUMMARY: %u PASS, %u SKIP, %u FAIL\n",
3433d6ee46bSPatrick Mooney count_pass, count_skip, count_fail);
3443d6ee46bSPatrick Mooney }
3453d6ee46bSPatrick Mooney
3463d6ee46bSPatrick Mooney pkt_cap_close(iter);
3473d6ee46bSPatrick Mooney ktest_fini(kthdl);
3483d6ee46bSPatrick Mooney
3493d6ee46bSPatrick Mooney return (idx == count_pass ? EXIT_SUCCESS : EXIT_FAILURE);
3503d6ee46bSPatrick Mooney }
351