xref: /openbmc/linux/tools/testing/selftests/bpf/xskxceiver.c (revision f540d44e05cf2f324697ba375235da2d7c92743c)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2020 Intel Corporation. */
3 
4 /*
5  * Some functions in this program are taken from
6  * Linux kernel samples/bpf/xdpsock* and modified
7  * for use.
8  *
9  * See test_xsk.sh for detailed information on test topology
10  * and prerequisite network setup.
11  *
12  * This test program contains two threads, each thread is single socket with
13  * a unique UMEM. It validates in-order packet delivery and packet content
14  * by sending packets to each other.
15  *
16  * Tests Information:
17  * ------------------
18  * These selftests test AF_XDP SKB and Native/DRV modes using veth
19  * Virtual Ethernet interfaces.
20  *
21  * For each mode, the following tests are run:
22  *    a. nopoll - soft-irq processing in run-to-completion mode
23  *    b. poll - using poll() syscall
24  *    c. Socket Teardown
25  *       Create a Tx and a Rx socket, Tx from one socket, Rx on another. Destroy
26  *       both sockets, then repeat multiple times. Only nopoll mode is used
27  *    d. Bi-directional sockets
28  *       Configure sockets as bi-directional tx/rx sockets, sets up fill and
29  *       completion rings on each socket, tx/rx in both directions. Only nopoll
30  *       mode is used
31  *    e. Statistics
32  *       Trigger some error conditions and ensure that the appropriate statistics
33  *       are incremented. Within this test, the following statistics are tested:
34  *       i.   rx dropped
35  *            Increase the UMEM frame headroom to a value which results in
36  *            insufficient space in the rx buffer for both the packet and the headroom.
37  *       ii.  tx invalid
38  *            Set the 'len' field of tx descriptors to an invalid value (umem frame
39  *            size + 1).
40  *       iii. rx ring full
41  *            Reduce the size of the RX ring to a fraction of the fill ring size.
42  *       iv.  fill queue empty
43  *            Do not populate the fill queue and then try to receive pkts.
44  *    f. bpf_link resource persistence
45  *       Configure sockets at indexes 0 and 1, run a traffic on queue ids 0,
46  *       then remove xsk sockets from queue 0 on both veth interfaces and
47  *       finally run a traffic on queues ids 1
48  *    g. unaligned mode
49  *    h. tests for invalid and corner case Tx descriptors so that the correct ones
50  *       are discarded and let through, respectively.
51  *    i. 2K frame size tests
52  *    j. If multi-buffer is supported, send 9k packets divided into 3 frames
53  *
54  * Total tests: 12
55  *
56  * Flow:
57  * -----
58  * - Single process spawns two threads: Tx and Rx
59  * - Each of these two threads attach to a veth interface
60  * - Each thread creates one AF_XDP socket connected to a unique umem for each
61  *   veth interface
62  * - Tx thread Transmits a number of packets from veth<xxxx> to veth<yyyy>
63  * - Rx thread verifies if all packets were received and delivered in-order,
64  *   and have the right content
65  *
66  * Enable/disable packet dump mode:
67  * --------------------------
68  * To enable L2 - L4 headers and payload dump of each packet on STDOUT, add
69  * parameter -D to params array in test_xsk.sh, i.e. params=("-S" "-D")
70  */
71 
72 #define _GNU_SOURCE
73 #include <assert.h>
74 #include <fcntl.h>
75 #include <errno.h>
76 #include <getopt.h>
77 #include <asm/barrier.h>
78 #include <linux/if_link.h>
79 #include <linux/if_ether.h>
80 #include <linux/mman.h>
81 #include <linux/netdev.h>
82 #include <arpa/inet.h>
83 #include <net/if.h>
84 #include <locale.h>
85 #include <poll.h>
86 #include <pthread.h>
87 #include <signal.h>
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #include <stddef.h>
92 #include <sys/mman.h>
93 #include <sys/socket.h>
94 #include <sys/time.h>
95 #include <sys/types.h>
96 #include <time.h>
97 #include <unistd.h>
98 
99 #include "xsk_xdp_progs.skel.h"
100 #include "xsk.h"
101 #include "xskxceiver.h"
102 #include <bpf/bpf.h>
103 #include <linux/filter.h>
104 #include "../kselftest.h"
105 #include "xsk_xdp_metadata.h"
106 
107 static const char *MAC1 = "\x00\x0A\x56\x9E\xEE\x62";
108 static const char *MAC2 = "\x00\x0A\x56\x9E\xEE\x61";
109 
110 static void __exit_with_error(int error, const char *file, const char *func, int line)
111 {
112 	ksft_test_result_fail("[%s:%s:%i]: ERROR: %d/\"%s\"\n", file, func, line, error,
113 			      strerror(error));
114 	ksft_exit_xfail();
115 }
116 
117 #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__)
118 #define busy_poll_string(test) (test)->ifobj_tx->busy_poll ? "BUSY-POLL " : ""
119 static char *mode_string(struct test_spec *test)
120 {
121 	switch (test->mode) {
122 	case TEST_MODE_SKB:
123 		return "SKB";
124 	case TEST_MODE_DRV:
125 		return "DRV";
126 	case TEST_MODE_ZC:
127 		return "ZC";
128 	default:
129 		return "BOGUS";
130 	}
131 }
132 
133 static void report_failure(struct test_spec *test)
134 {
135 	if (test->fail)
136 		return;
137 
138 	ksft_test_result_fail("FAIL: %s %s%s\n", mode_string(test), busy_poll_string(test),
139 			      test->name);
140 	test->fail = true;
141 }
142 
143 /* The payload is a word consisting of a packet sequence number in the upper
144  * 16-bits and a intra packet data sequence number in the lower 16 bits. So the 3rd packet's
145  * 5th word of data will contain the number (2<<16) | 4 as they are numbered from 0.
146  */
147 static void write_payload(void *dest, u32 pkt_nb, u32 start, u32 size)
148 {
149 	u32 *ptr = (u32 *)dest, i;
150 
151 	start /= sizeof(*ptr);
152 	size /= sizeof(*ptr);
153 	for (i = 0; i < size; i++)
154 		ptr[i] = htonl(pkt_nb << 16 | (i + start));
155 }
156 
157 static void gen_eth_hdr(struct ifobject *ifobject, struct ethhdr *eth_hdr)
158 {
159 	memcpy(eth_hdr->h_dest, ifobject->dst_mac, ETH_ALEN);
160 	memcpy(eth_hdr->h_source, ifobject->src_mac, ETH_ALEN);
161 	eth_hdr->h_proto = htons(ETH_P_LOOPBACK);
162 }
163 
164 static bool is_umem_valid(struct ifobject *ifobj)
165 {
166 	return !!ifobj->umem->umem;
167 }
168 
169 static u32 mode_to_xdp_flags(enum test_mode mode)
170 {
171 	return (mode == TEST_MODE_SKB) ? XDP_FLAGS_SKB_MODE : XDP_FLAGS_DRV_MODE;
172 }
173 
174 static u64 umem_size(struct xsk_umem_info *umem)
175 {
176 	return umem->num_frames * umem->frame_size;
177 }
178 
179 static int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void *buffer,
180 			      u64 size)
181 {
182 	struct xsk_umem_config cfg = {
183 		.fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS,
184 		.comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS,
185 		.frame_size = umem->frame_size,
186 		.frame_headroom = umem->frame_headroom,
187 		.flags = XSK_UMEM__DEFAULT_FLAGS
188 	};
189 	int ret;
190 
191 	if (umem->unaligned_mode)
192 		cfg.flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG;
193 
194 	ret = xsk_umem__create(&umem->umem, buffer, size,
195 			       &umem->fq, &umem->cq, &cfg);
196 	if (ret)
197 		return ret;
198 
199 	umem->buffer = buffer;
200 	if (ifobj->shared_umem && ifobj->rx_on) {
201 		umem->base_addr = umem_size(umem);
202 		umem->next_buffer = umem_size(umem);
203 	}
204 
205 	return 0;
206 }
207 
208 static u64 umem_alloc_buffer(struct xsk_umem_info *umem)
209 {
210 	u64 addr;
211 
212 	addr = umem->next_buffer;
213 	umem->next_buffer += umem->frame_size;
214 	if (umem->next_buffer >= umem->base_addr + umem_size(umem))
215 		umem->next_buffer = umem->base_addr;
216 
217 	return addr;
218 }
219 
220 static void umem_reset_alloc(struct xsk_umem_info *umem)
221 {
222 	umem->next_buffer = 0;
223 }
224 
225 static void enable_busy_poll(struct xsk_socket_info *xsk)
226 {
227 	int sock_opt;
228 
229 	sock_opt = 1;
230 	if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_PREFER_BUSY_POLL,
231 		       (void *)&sock_opt, sizeof(sock_opt)) < 0)
232 		exit_with_error(errno);
233 
234 	sock_opt = 20;
235 	if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL,
236 		       (void *)&sock_opt, sizeof(sock_opt)) < 0)
237 		exit_with_error(errno);
238 
239 	sock_opt = BATCH_SIZE;
240 	if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL_BUDGET,
241 		       (void *)&sock_opt, sizeof(sock_opt)) < 0)
242 		exit_with_error(errno);
243 }
244 
245 static int __xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem,
246 				  struct ifobject *ifobject, bool shared)
247 {
248 	struct xsk_socket_config cfg = {};
249 	struct xsk_ring_cons *rxr;
250 	struct xsk_ring_prod *txr;
251 
252 	xsk->umem = umem;
253 	cfg.rx_size = xsk->rxqsize;
254 	cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
255 	cfg.bind_flags = ifobject->bind_flags;
256 	if (shared)
257 		cfg.bind_flags |= XDP_SHARED_UMEM;
258 	if (ifobject->pkt_stream && ifobject->mtu > MAX_ETH_PKT_SIZE)
259 		cfg.bind_flags |= XDP_USE_SG;
260 
261 	txr = ifobject->tx_on ? &xsk->tx : NULL;
262 	rxr = ifobject->rx_on ? &xsk->rx : NULL;
263 	return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg);
264 }
265 
266 static bool ifobj_zc_avail(struct ifobject *ifobject)
267 {
268 	size_t umem_sz = DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE;
269 	int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
270 	struct xsk_socket_info *xsk;
271 	struct xsk_umem_info *umem;
272 	bool zc_avail = false;
273 	void *bufs;
274 	int ret;
275 
276 	bufs = mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
277 	if (bufs == MAP_FAILED)
278 		exit_with_error(errno);
279 
280 	umem = calloc(1, sizeof(struct xsk_umem_info));
281 	if (!umem) {
282 		munmap(bufs, umem_sz);
283 		exit_with_error(ENOMEM);
284 	}
285 	umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
286 	ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
287 	if (ret)
288 		exit_with_error(-ret);
289 
290 	xsk = calloc(1, sizeof(struct xsk_socket_info));
291 	if (!xsk)
292 		goto out;
293 	ifobject->bind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;
294 	ifobject->rx_on = true;
295 	xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
296 	ret = __xsk_configure_socket(xsk, umem, ifobject, false);
297 	if (!ret)
298 		zc_avail = true;
299 
300 	xsk_socket__delete(xsk->xsk);
301 	free(xsk);
302 out:
303 	munmap(umem->buffer, umem_sz);
304 	xsk_umem__delete(umem->umem);
305 	free(umem);
306 	return zc_avail;
307 }
308 
309 static struct option long_options[] = {
310 	{"interface", required_argument, 0, 'i'},
311 	{"busy-poll", no_argument, 0, 'b'},
312 	{"verbose", no_argument, 0, 'v'},
313 	{0, 0, 0, 0}
314 };
315 
316 static void usage(const char *prog)
317 {
318 	const char *str =
319 		"  Usage: %s [OPTIONS]\n"
320 		"  Options:\n"
321 		"  -i, --interface      Use interface\n"
322 		"  -v, --verbose        Verbose output\n"
323 		"  -b, --busy-poll      Enable busy poll\n";
324 
325 	ksft_print_msg(str, prog);
326 }
327 
328 static bool validate_interface(struct ifobject *ifobj)
329 {
330 	if (!strcmp(ifobj->ifname, ""))
331 		return false;
332 	return true;
333 }
334 
335 static void parse_command_line(struct ifobject *ifobj_tx, struct ifobject *ifobj_rx, int argc,
336 			       char **argv)
337 {
338 	struct ifobject *ifobj;
339 	u32 interface_nb = 0;
340 	int option_index, c;
341 
342 	opterr = 0;
343 
344 	for (;;) {
345 		c = getopt_long(argc, argv, "i:vb", long_options, &option_index);
346 		if (c == -1)
347 			break;
348 
349 		switch (c) {
350 		case 'i':
351 			if (interface_nb == 0)
352 				ifobj = ifobj_tx;
353 			else if (interface_nb == 1)
354 				ifobj = ifobj_rx;
355 			else
356 				break;
357 
358 			memcpy(ifobj->ifname, optarg,
359 			       min_t(size_t, MAX_INTERFACE_NAME_CHARS, strlen(optarg)));
360 
361 			ifobj->ifindex = if_nametoindex(ifobj->ifname);
362 			if (!ifobj->ifindex)
363 				exit_with_error(errno);
364 
365 			interface_nb++;
366 			break;
367 		case 'v':
368 			opt_verbose = true;
369 			break;
370 		case 'b':
371 			ifobj_tx->busy_poll = true;
372 			ifobj_rx->busy_poll = true;
373 			break;
374 		default:
375 			usage(basename(argv[0]));
376 			ksft_exit_xfail();
377 		}
378 	}
379 }
380 
381 static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
382 			     struct ifobject *ifobj_rx)
383 {
384 	u32 i, j;
385 
386 	for (i = 0; i < MAX_INTERFACES; i++) {
387 		struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx;
388 
389 		ifobj->xsk = &ifobj->xsk_arr[0];
390 		ifobj->use_poll = false;
391 		ifobj->use_fill_ring = true;
392 		ifobj->release_rx = true;
393 		ifobj->validation_func = NULL;
394 		ifobj->use_metadata = false;
395 
396 		if (i == 0) {
397 			ifobj->rx_on = false;
398 			ifobj->tx_on = true;
399 			ifobj->pkt_stream = test->tx_pkt_stream_default;
400 		} else {
401 			ifobj->rx_on = true;
402 			ifobj->tx_on = false;
403 			ifobj->pkt_stream = test->rx_pkt_stream_default;
404 		}
405 
406 		memset(ifobj->umem, 0, sizeof(*ifobj->umem));
407 		ifobj->umem->num_frames = DEFAULT_UMEM_BUFFERS;
408 		ifobj->umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
409 
410 		for (j = 0; j < MAX_SOCKETS; j++) {
411 			memset(&ifobj->xsk_arr[j], 0, sizeof(ifobj->xsk_arr[j]));
412 			ifobj->xsk_arr[j].rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
413 		}
414 	}
415 
416 	test->ifobj_tx = ifobj_tx;
417 	test->ifobj_rx = ifobj_rx;
418 	test->current_step = 0;
419 	test->total_steps = 1;
420 	test->nb_sockets = 1;
421 	test->fail = false;
422 	test->mtu = MAX_ETH_PKT_SIZE;
423 	test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog;
424 	test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk;
425 	test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog;
426 	test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk;
427 }
428 
429 static void test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
430 			   struct ifobject *ifobj_rx, enum test_mode mode)
431 {
432 	struct pkt_stream *tx_pkt_stream;
433 	struct pkt_stream *rx_pkt_stream;
434 	u32 i;
435 
436 	tx_pkt_stream = test->tx_pkt_stream_default;
437 	rx_pkt_stream = test->rx_pkt_stream_default;
438 	memset(test, 0, sizeof(*test));
439 	test->tx_pkt_stream_default = tx_pkt_stream;
440 	test->rx_pkt_stream_default = rx_pkt_stream;
441 
442 	for (i = 0; i < MAX_INTERFACES; i++) {
443 		struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx;
444 
445 		ifobj->bind_flags = XDP_USE_NEED_WAKEUP;
446 		if (mode == TEST_MODE_ZC)
447 			ifobj->bind_flags |= XDP_ZEROCOPY;
448 		else
449 			ifobj->bind_flags |= XDP_COPY;
450 	}
451 
452 	test->mode = mode;
453 	__test_spec_init(test, ifobj_tx, ifobj_rx);
454 }
455 
456 static void test_spec_reset(struct test_spec *test)
457 {
458 	__test_spec_init(test, test->ifobj_tx, test->ifobj_rx);
459 }
460 
461 static void test_spec_set_name(struct test_spec *test, const char *name)
462 {
463 	strncpy(test->name, name, MAX_TEST_NAME_SIZE);
464 }
465 
466 static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx,
467 				   struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx,
468 				   struct bpf_map *xskmap_tx)
469 {
470 	test->xdp_prog_rx = xdp_prog_rx;
471 	test->xdp_prog_tx = xdp_prog_tx;
472 	test->xskmap_rx = xskmap_rx;
473 	test->xskmap_tx = xskmap_tx;
474 }
475 
476 static int test_spec_set_mtu(struct test_spec *test, int mtu)
477 {
478 	int err;
479 
480 	if (test->ifobj_rx->mtu != mtu) {
481 		err = xsk_set_mtu(test->ifobj_rx->ifindex, mtu);
482 		if (err)
483 			return err;
484 		test->ifobj_rx->mtu = mtu;
485 	}
486 	if (test->ifobj_tx->mtu != mtu) {
487 		err = xsk_set_mtu(test->ifobj_tx->ifindex, mtu);
488 		if (err)
489 			return err;
490 		test->ifobj_tx->mtu = mtu;
491 	}
492 
493 	return 0;
494 }
495 
496 static void pkt_stream_reset(struct pkt_stream *pkt_stream)
497 {
498 	if (pkt_stream)
499 		pkt_stream->current_pkt_nb = 0;
500 }
501 
502 static struct pkt *pkt_stream_get_next_tx_pkt(struct pkt_stream *pkt_stream)
503 {
504 	if (pkt_stream->current_pkt_nb >= pkt_stream->nb_pkts)
505 		return NULL;
506 
507 	return &pkt_stream->pkts[pkt_stream->current_pkt_nb++];
508 }
509 
510 static struct pkt *pkt_stream_get_next_rx_pkt(struct pkt_stream *pkt_stream, u32 *pkts_sent)
511 {
512 	while (pkt_stream->current_pkt_nb < pkt_stream->nb_pkts) {
513 		(*pkts_sent)++;
514 		if (pkt_stream->pkts[pkt_stream->current_pkt_nb].valid)
515 			return &pkt_stream->pkts[pkt_stream->current_pkt_nb++];
516 		pkt_stream->current_pkt_nb++;
517 	}
518 	return NULL;
519 }
520 
521 static void pkt_stream_delete(struct pkt_stream *pkt_stream)
522 {
523 	free(pkt_stream->pkts);
524 	free(pkt_stream);
525 }
526 
527 static void pkt_stream_restore_default(struct test_spec *test)
528 {
529 	struct pkt_stream *tx_pkt_stream = test->ifobj_tx->pkt_stream;
530 	struct pkt_stream *rx_pkt_stream = test->ifobj_rx->pkt_stream;
531 
532 	if (tx_pkt_stream != test->tx_pkt_stream_default) {
533 		pkt_stream_delete(test->ifobj_tx->pkt_stream);
534 		test->ifobj_tx->pkt_stream = test->tx_pkt_stream_default;
535 	}
536 
537 	if (rx_pkt_stream != test->rx_pkt_stream_default) {
538 		pkt_stream_delete(test->ifobj_rx->pkt_stream);
539 		test->ifobj_rx->pkt_stream = test->rx_pkt_stream_default;
540 	}
541 }
542 
543 static struct pkt_stream *__pkt_stream_alloc(u32 nb_pkts)
544 {
545 	struct pkt_stream *pkt_stream;
546 
547 	pkt_stream = calloc(1, sizeof(*pkt_stream));
548 	if (!pkt_stream)
549 		return NULL;
550 
551 	pkt_stream->pkts = calloc(nb_pkts, sizeof(*pkt_stream->pkts));
552 	if (!pkt_stream->pkts) {
553 		free(pkt_stream);
554 		return NULL;
555 	}
556 
557 	pkt_stream->nb_pkts = nb_pkts;
558 	return pkt_stream;
559 }
560 
561 static bool pkt_continues(const struct xdp_desc *desc)
562 {
563 	return desc->options & XDP_PKT_CONTD;
564 }
565 
566 static u32 ceil_u32(u32 a, u32 b)
567 {
568 	return (a + b - 1) / b;
569 }
570 
571 static u32 pkt_nb_frags(u32 frame_size, struct pkt *pkt)
572 {
573 	if (!pkt || !pkt->valid)
574 		return 1;
575 	return ceil_u32(pkt->len, frame_size);
576 }
577 
578 static void pkt_set(struct xsk_umem_info *umem, struct pkt *pkt, int offset, u32 len)
579 {
580 	pkt->offset = offset;
581 	pkt->len = len;
582 	if (len > MAX_ETH_JUMBO_SIZE)
583 		pkt->valid = false;
584 	else
585 		pkt->valid = true;
586 }
587 
588 static u32 pkt_get_buffer_len(struct xsk_umem_info *umem, u32 len)
589 {
590 	return ceil_u32(len, umem->frame_size) * umem->frame_size;
591 }
592 
593 static struct pkt_stream *pkt_stream_generate(struct xsk_umem_info *umem, u32 nb_pkts, u32 pkt_len)
594 {
595 	struct pkt_stream *pkt_stream;
596 	u32 i;
597 
598 	pkt_stream = __pkt_stream_alloc(nb_pkts);
599 	if (!pkt_stream)
600 		exit_with_error(ENOMEM);
601 
602 	pkt_stream->nb_pkts = nb_pkts;
603 	pkt_stream->max_pkt_len = pkt_len;
604 	for (i = 0; i < nb_pkts; i++) {
605 		struct pkt *pkt = &pkt_stream->pkts[i];
606 
607 		pkt_set(umem, pkt, 0, pkt_len);
608 		pkt->pkt_nb = i;
609 	}
610 
611 	return pkt_stream;
612 }
613 
614 static struct pkt_stream *pkt_stream_clone(struct xsk_umem_info *umem,
615 					   struct pkt_stream *pkt_stream)
616 {
617 	return pkt_stream_generate(umem, pkt_stream->nb_pkts, pkt_stream->pkts[0].len);
618 }
619 
620 static void pkt_stream_replace(struct test_spec *test, u32 nb_pkts, u32 pkt_len)
621 {
622 	struct pkt_stream *pkt_stream;
623 
624 	pkt_stream = pkt_stream_generate(test->ifobj_tx->umem, nb_pkts, pkt_len);
625 	test->ifobj_tx->pkt_stream = pkt_stream;
626 	pkt_stream = pkt_stream_generate(test->ifobj_rx->umem, nb_pkts, pkt_len);
627 	test->ifobj_rx->pkt_stream = pkt_stream;
628 }
629 
630 static void __pkt_stream_replace_half(struct ifobject *ifobj, u32 pkt_len,
631 				      int offset)
632 {
633 	struct xsk_umem_info *umem = ifobj->umem;
634 	struct pkt_stream *pkt_stream;
635 	u32 i;
636 
637 	pkt_stream = pkt_stream_clone(umem, ifobj->pkt_stream);
638 	for (i = 1; i < ifobj->pkt_stream->nb_pkts; i += 2)
639 		pkt_set(umem, &pkt_stream->pkts[i], offset, pkt_len);
640 
641 	ifobj->pkt_stream = pkt_stream;
642 }
643 
644 static void pkt_stream_replace_half(struct test_spec *test, u32 pkt_len, int offset)
645 {
646 	__pkt_stream_replace_half(test->ifobj_tx, pkt_len, offset);
647 	__pkt_stream_replace_half(test->ifobj_rx, pkt_len, offset);
648 }
649 
650 static void pkt_stream_receive_half(struct test_spec *test)
651 {
652 	struct xsk_umem_info *umem = test->ifobj_rx->umem;
653 	struct pkt_stream *pkt_stream = test->ifobj_tx->pkt_stream;
654 	u32 i;
655 
656 	test->ifobj_rx->pkt_stream = pkt_stream_generate(umem, pkt_stream->nb_pkts,
657 							 pkt_stream->pkts[0].len);
658 	pkt_stream = test->ifobj_rx->pkt_stream;
659 	for (i = 1; i < pkt_stream->nb_pkts; i += 2)
660 		pkt_stream->pkts[i].valid = false;
661 }
662 
663 static u64 pkt_get_addr(struct pkt *pkt, struct xsk_umem_info *umem)
664 {
665 	if (!pkt->valid)
666 		return pkt->offset;
667 	return pkt->offset + umem_alloc_buffer(umem);
668 }
669 
670 static void pkt_stream_cancel(struct pkt_stream *pkt_stream)
671 {
672 	pkt_stream->current_pkt_nb--;
673 }
674 
675 static void pkt_generate(struct ifobject *ifobject, u64 addr, u32 len, u32 pkt_nb,
676 			 u32 bytes_written)
677 {
678 	void *data = xsk_umem__get_data(ifobject->umem->buffer, addr);
679 
680 	if (len < MIN_PKT_SIZE)
681 		return;
682 
683 	if (!bytes_written) {
684 		gen_eth_hdr(ifobject, data);
685 
686 		len -= PKT_HDR_SIZE;
687 		data += PKT_HDR_SIZE;
688 	} else {
689 		bytes_written -= PKT_HDR_SIZE;
690 	}
691 
692 	write_payload(data, pkt_nb, bytes_written, len);
693 }
694 
695 static void __pkt_stream_generate_custom(struct ifobject *ifobj,
696 					 struct pkt *pkts, u32 nb_pkts)
697 {
698 	struct pkt_stream *pkt_stream;
699 	u32 i;
700 
701 	pkt_stream = __pkt_stream_alloc(nb_pkts);
702 	if (!pkt_stream)
703 		exit_with_error(ENOMEM);
704 
705 	for (i = 0; i < nb_pkts; i++) {
706 		struct pkt *pkt = &pkt_stream->pkts[i];
707 
708 		pkt->offset = pkts[i].offset;
709 		pkt->len = pkts[i].len;
710 		pkt->pkt_nb = i;
711 		pkt->valid = pkts[i].valid;
712 		if (pkt->len > pkt_stream->max_pkt_len)
713 			pkt_stream->max_pkt_len = pkt->len;
714 	}
715 
716 	ifobj->pkt_stream = pkt_stream;
717 }
718 
719 static void pkt_stream_generate_custom(struct test_spec *test, struct pkt *pkts, u32 nb_pkts)
720 {
721 	__pkt_stream_generate_custom(test->ifobj_tx, pkts, nb_pkts);
722 	__pkt_stream_generate_custom(test->ifobj_rx, pkts, nb_pkts);
723 }
724 
725 static void pkt_print_data(u32 *data, u32 cnt)
726 {
727 	u32 i;
728 
729 	for (i = 0; i < cnt; i++) {
730 		u32 seqnum, pkt_nb;
731 
732 		seqnum = ntohl(*data) & 0xffff;
733 		pkt_nb = ntohl(*data) >> 16;
734 		fprintf(stdout, "%u:%u ", pkt_nb, seqnum);
735 		data++;
736 	}
737 }
738 
739 static void pkt_dump(void *pkt, u32 len, bool eth_header)
740 {
741 	struct ethhdr *ethhdr = pkt;
742 	u32 i, *data;
743 
744 	if (eth_header) {
745 		/*extract L2 frame */
746 		fprintf(stdout, "DEBUG>> L2: dst mac: ");
747 		for (i = 0; i < ETH_ALEN; i++)
748 			fprintf(stdout, "%02X", ethhdr->h_dest[i]);
749 
750 		fprintf(stdout, "\nDEBUG>> L2: src mac: ");
751 		for (i = 0; i < ETH_ALEN; i++)
752 			fprintf(stdout, "%02X", ethhdr->h_source[i]);
753 
754 		data = pkt + PKT_HDR_SIZE;
755 	} else {
756 		data = pkt;
757 	}
758 
759 	/*extract L5 frame */
760 	fprintf(stdout, "\nDEBUG>> L5: seqnum: ");
761 	pkt_print_data(data, PKT_DUMP_NB_TO_PRINT);
762 	fprintf(stdout, "....");
763 	if (len > PKT_DUMP_NB_TO_PRINT * sizeof(u32)) {
764 		fprintf(stdout, "\n.... ");
765 		pkt_print_data(data + len / sizeof(u32) - PKT_DUMP_NB_TO_PRINT,
766 			       PKT_DUMP_NB_TO_PRINT);
767 	}
768 	fprintf(stdout, "\n---------------------------------------\n");
769 }
770 
771 static bool is_offset_correct(struct xsk_umem_info *umem, struct pkt *pkt, u64 addr)
772 {
773 	u32 headroom = umem->unaligned_mode ? 0 : umem->frame_headroom;
774 	u32 offset = addr % umem->frame_size, expected_offset;
775 	int pkt_offset = pkt->valid ? pkt->offset : 0;
776 
777 	if (!umem->unaligned_mode)
778 		pkt_offset = 0;
779 
780 	expected_offset = (pkt_offset + headroom + XDP_PACKET_HEADROOM) % umem->frame_size;
781 
782 	if (offset == expected_offset)
783 		return true;
784 
785 	ksft_print_msg("[%s] expected [%u], got [%u]\n", __func__, expected_offset, offset);
786 	return false;
787 }
788 
789 static bool is_metadata_correct(struct pkt *pkt, void *buffer, u64 addr)
790 {
791 	void *data = xsk_umem__get_data(buffer, addr);
792 	struct xdp_info *meta = data - sizeof(struct xdp_info);
793 
794 	if (meta->count != pkt->pkt_nb) {
795 		ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%d]\n",
796 			       __func__, pkt->pkt_nb, meta->count);
797 		return false;
798 	}
799 
800 	return true;
801 }
802 
803 static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u32 expected_pkt_nb,
804 			  u32 bytes_processed)
805 {
806 	u32 seqnum, pkt_nb, *pkt_data, words_to_end, expected_seqnum;
807 	void *data = xsk_umem__get_data(umem->buffer, addr);
808 
809 	addr -= umem->base_addr;
810 
811 	if (addr >= umem->num_frames * umem->frame_size ||
812 	    addr + len > umem->num_frames * umem->frame_size) {
813 		ksft_print_msg("Frag invalid addr: %llx len: %u\n", addr, len);
814 		return false;
815 	}
816 	if (!umem->unaligned_mode && addr % umem->frame_size + len > umem->frame_size) {
817 		ksft_print_msg("Frag crosses frame boundary addr: %llx len: %u\n", addr, len);
818 		return false;
819 	}
820 
821 	pkt_data = data;
822 	if (!bytes_processed) {
823 		pkt_data += PKT_HDR_SIZE / sizeof(*pkt_data);
824 		len -= PKT_HDR_SIZE;
825 	} else {
826 		bytes_processed -= PKT_HDR_SIZE;
827 	}
828 
829 	expected_seqnum = bytes_processed / sizeof(*pkt_data);
830 	seqnum = ntohl(*pkt_data) & 0xffff;
831 	pkt_nb = ntohl(*pkt_data) >> 16;
832 
833 	if (expected_pkt_nb != pkt_nb) {
834 		ksft_print_msg("[%s] expected pkt_nb [%u], got pkt_nb [%u]\n",
835 			       __func__, expected_pkt_nb, pkt_nb);
836 		goto error;
837 	}
838 	if (expected_seqnum != seqnum) {
839 		ksft_print_msg("[%s] expected seqnum at start [%u], got seqnum [%u]\n",
840 			       __func__, expected_seqnum, seqnum);
841 		goto error;
842 	}
843 
844 	words_to_end = len / sizeof(*pkt_data) - 1;
845 	pkt_data += words_to_end;
846 	seqnum = ntohl(*pkt_data) & 0xffff;
847 	expected_seqnum += words_to_end;
848 	if (expected_seqnum != seqnum) {
849 		ksft_print_msg("[%s] expected seqnum at end [%u], got seqnum [%u]\n",
850 			       __func__, expected_seqnum, seqnum);
851 		goto error;
852 	}
853 
854 	return true;
855 
856 error:
857 	pkt_dump(data, len, !bytes_processed);
858 	return false;
859 }
860 
861 static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len)
862 {
863 	if (!pkt) {
864 		ksft_print_msg("[%s] too many packets received\n", __func__);
865 		return false;
866 	}
867 
868 	if (pkt->len != len) {
869 		ksft_print_msg("[%s] expected packet length [%d], got length [%d]\n",
870 			       __func__, pkt->len, len);
871 		pkt_dump(xsk_umem__get_data(buffer, addr), len, true);
872 		return false;
873 	}
874 
875 	return true;
876 }
877 
878 static void kick_tx(struct xsk_socket_info *xsk)
879 {
880 	int ret;
881 
882 	ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
883 	if (ret >= 0)
884 		return;
885 	if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) {
886 		usleep(100);
887 		return;
888 	}
889 	exit_with_error(errno);
890 }
891 
892 static void kick_rx(struct xsk_socket_info *xsk)
893 {
894 	int ret;
895 
896 	ret = recvfrom(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, NULL);
897 	if (ret < 0)
898 		exit_with_error(errno);
899 }
900 
901 static int complete_pkts(struct xsk_socket_info *xsk, int batch_size)
902 {
903 	unsigned int rcvd;
904 	u32 idx;
905 
906 	if (xsk_ring_prod__needs_wakeup(&xsk->tx))
907 		kick_tx(xsk);
908 
909 	rcvd = xsk_ring_cons__peek(&xsk->umem->cq, batch_size, &idx);
910 	if (rcvd) {
911 		if (rcvd > xsk->outstanding_tx) {
912 			u64 addr = *xsk_ring_cons__comp_addr(&xsk->umem->cq, idx + rcvd - 1);
913 
914 			ksft_print_msg("[%s] Too many packets completed\n", __func__);
915 			ksft_print_msg("Last completion address: %llx\n", addr);
916 			return TEST_FAILURE;
917 		}
918 
919 		xsk_ring_cons__release(&xsk->umem->cq, rcvd);
920 		xsk->outstanding_tx -= rcvd;
921 	}
922 
923 	return TEST_PASS;
924 }
925 
926 static int receive_pkts(struct test_spec *test, struct pollfd *fds)
927 {
928 	struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0};
929 	struct pkt_stream *pkt_stream = test->ifobj_rx->pkt_stream;
930 	struct xsk_socket_info *xsk = test->ifobj_rx->xsk;
931 	u32 idx_rx = 0, idx_fq = 0, rcvd, pkts_sent = 0;
932 	struct ifobject *ifobj = test->ifobj_rx;
933 	struct xsk_umem_info *umem = xsk->umem;
934 	struct pkt *pkt;
935 	int ret;
936 
937 	ret = gettimeofday(&tv_now, NULL);
938 	if (ret)
939 		exit_with_error(errno);
940 	timeradd(&tv_now, &tv_timeout, &tv_end);
941 
942 	pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &pkts_sent);
943 	while (pkt) {
944 		u32 frags_processed = 0, nb_frags = 0, pkt_len = 0;
945 		u64 first_addr;
946 
947 		ret = gettimeofday(&tv_now, NULL);
948 		if (ret)
949 			exit_with_error(errno);
950 		if (timercmp(&tv_now, &tv_end, >)) {
951 			ksft_print_msg("ERROR: [%s] Receive loop timed out\n", __func__);
952 			return TEST_FAILURE;
953 		}
954 
955 		kick_rx(xsk);
956 		if (ifobj->use_poll) {
957 			ret = poll(fds, 1, POLL_TMOUT);
958 			if (ret < 0)
959 				exit_with_error(errno);
960 
961 			if (!ret) {
962 				if (!is_umem_valid(test->ifobj_tx))
963 					return TEST_PASS;
964 
965 				ksft_print_msg("ERROR: [%s] Poll timed out\n", __func__);
966 				return TEST_FAILURE;
967 
968 			}
969 
970 			if (!(fds->revents & POLLIN))
971 				continue;
972 		}
973 
974 		rcvd = xsk_ring_cons__peek(&xsk->rx, BATCH_SIZE, &idx_rx);
975 		if (!rcvd)
976 			continue;
977 
978 		if (ifobj->use_fill_ring) {
979 			ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq);
980 			while (ret != rcvd) {
981 				if (ret < 0)
982 					exit_with_error(-ret);
983 				if (xsk_ring_prod__needs_wakeup(&umem->fq)) {
984 					ret = poll(fds, 1, POLL_TMOUT);
985 					if (ret < 0)
986 						exit_with_error(errno);
987 				}
988 				ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq);
989 			}
990 		}
991 
992 		while (frags_processed < rcvd) {
993 			const struct xdp_desc *desc = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++);
994 			u64 addr = desc->addr, orig;
995 
996 			orig = xsk_umem__extract_addr(addr);
997 			addr = xsk_umem__add_offset_to_addr(addr);
998 
999 			if (!is_frag_valid(umem, addr, desc->len, pkt->pkt_nb, pkt_len) ||
1000 			    !is_offset_correct(umem, pkt, addr) ||
1001 			    (ifobj->use_metadata && !is_metadata_correct(pkt, umem->buffer, addr)))
1002 				return TEST_FAILURE;
1003 
1004 			if (!nb_frags++)
1005 				first_addr = addr;
1006 			frags_processed++;
1007 			pkt_len += desc->len;
1008 			if (ifobj->use_fill_ring)
1009 				*xsk_ring_prod__fill_addr(&umem->fq, idx_fq++) = orig;
1010 
1011 			if (pkt_continues(desc))
1012 				continue;
1013 
1014 			/* The complete packet has been received */
1015 			if (!is_pkt_valid(pkt, umem->buffer, first_addr, pkt_len) ||
1016 			    !is_offset_correct(umem, pkt, addr))
1017 				return TEST_FAILURE;
1018 
1019 			pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &pkts_sent);
1020 			nb_frags = 0;
1021 			pkt_len = 0;
1022 		}
1023 
1024 		if (nb_frags) {
1025 			/* In the middle of a packet. Start over from beginning of packet. */
1026 			idx_rx -= nb_frags;
1027 			xsk_ring_cons__cancel(&xsk->rx, nb_frags);
1028 			if (ifobj->use_fill_ring) {
1029 				idx_fq -= nb_frags;
1030 				xsk_ring_prod__cancel(&umem->fq, nb_frags);
1031 			}
1032 			frags_processed -= nb_frags;
1033 		}
1034 
1035 		if (ifobj->use_fill_ring)
1036 			xsk_ring_prod__submit(&umem->fq, frags_processed);
1037 		if (ifobj->release_rx)
1038 			xsk_ring_cons__release(&xsk->rx, frags_processed);
1039 
1040 		pthread_mutex_lock(&pacing_mutex);
1041 		pkts_in_flight -= pkts_sent;
1042 		pthread_mutex_unlock(&pacing_mutex);
1043 		pkts_sent = 0;
1044 	}
1045 
1046 	return TEST_PASS;
1047 }
1048 
1049 static int __send_pkts(struct ifobject *ifobject, struct pollfd *fds, bool timeout)
1050 {
1051 	u32 i, idx = 0, valid_pkts = 0, valid_frags = 0, buffer_len;
1052 	struct pkt_stream *pkt_stream = ifobject->pkt_stream;
1053 	struct xsk_socket_info *xsk = ifobject->xsk;
1054 	struct xsk_umem_info *umem = ifobject->umem;
1055 	bool use_poll = ifobject->use_poll;
1056 	int ret;
1057 
1058 	buffer_len = pkt_get_buffer_len(umem, pkt_stream->max_pkt_len);
1059 	/* pkts_in_flight might be negative if many invalid packets are sent */
1060 	if (pkts_in_flight >= (int)((umem_size(umem) - BATCH_SIZE * buffer_len) / buffer_len)) {
1061 		kick_tx(xsk);
1062 		return TEST_CONTINUE;
1063 	}
1064 
1065 	while (xsk_ring_prod__reserve(&xsk->tx, BATCH_SIZE, &idx) < BATCH_SIZE) {
1066 		if (use_poll) {
1067 			ret = poll(fds, 1, POLL_TMOUT);
1068 			if (timeout) {
1069 				if (ret < 0) {
1070 					ksft_print_msg("ERROR: [%s] Poll error %d\n",
1071 						       __func__, errno);
1072 					return TEST_FAILURE;
1073 				}
1074 				if (ret == 0)
1075 					return TEST_PASS;
1076 				break;
1077 			}
1078 			if (ret <= 0) {
1079 				ksft_print_msg("ERROR: [%s] Poll error %d\n",
1080 					       __func__, errno);
1081 				return TEST_FAILURE;
1082 			}
1083 		}
1084 
1085 		complete_pkts(xsk, BATCH_SIZE);
1086 	}
1087 
1088 	for (i = 0; i < BATCH_SIZE; i++) {
1089 		struct pkt *pkt = pkt_stream_get_next_tx_pkt(pkt_stream);
1090 		u32 nb_frags, bytes_written = 0;
1091 
1092 		if (!pkt)
1093 			break;
1094 
1095 		nb_frags = pkt_nb_frags(umem->frame_size, pkt);
1096 		if (nb_frags > BATCH_SIZE - i) {
1097 			pkt_stream_cancel(pkt_stream);
1098 			xsk_ring_prod__cancel(&xsk->tx, BATCH_SIZE - i);
1099 			break;
1100 		}
1101 
1102 		if (pkt->valid) {
1103 			valid_pkts++;
1104 			valid_frags += nb_frags;
1105 		}
1106 
1107 		while (nb_frags--) {
1108 			struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i);
1109 
1110 			tx_desc->addr = pkt_get_addr(pkt, ifobject->umem);
1111 			if (nb_frags) {
1112 				tx_desc->len = umem->frame_size;
1113 				tx_desc->options = XDP_PKT_CONTD;
1114 				i++;
1115 			} else {
1116 				tx_desc->len = pkt->len - bytes_written;
1117 				tx_desc->options = 0;
1118 			}
1119 			if (pkt->valid)
1120 				pkt_generate(ifobject, tx_desc->addr, tx_desc->len, pkt->pkt_nb,
1121 					     bytes_written);
1122 			bytes_written += tx_desc->len;
1123 		}
1124 	}
1125 
1126 	pthread_mutex_lock(&pacing_mutex);
1127 	pkts_in_flight += valid_pkts;
1128 	pthread_mutex_unlock(&pacing_mutex);
1129 
1130 	xsk_ring_prod__submit(&xsk->tx, i);
1131 	xsk->outstanding_tx += valid_frags;
1132 
1133 	if (use_poll) {
1134 		ret = poll(fds, 1, POLL_TMOUT);
1135 		if (ret <= 0) {
1136 			if (ret == 0 && timeout)
1137 				return TEST_PASS;
1138 
1139 			ksft_print_msg("ERROR: [%s] Poll error %d\n", __func__, ret);
1140 			return TEST_FAILURE;
1141 		}
1142 	}
1143 
1144 	if (!timeout) {
1145 		if (complete_pkts(xsk, i))
1146 			return TEST_FAILURE;
1147 
1148 		usleep(10);
1149 		return TEST_PASS;
1150 	}
1151 
1152 	return TEST_CONTINUE;
1153 }
1154 
1155 static void wait_for_tx_completion(struct xsk_socket_info *xsk)
1156 {
1157 	while (xsk->outstanding_tx)
1158 		complete_pkts(xsk, BATCH_SIZE);
1159 }
1160 
1161 static int send_pkts(struct test_spec *test, struct ifobject *ifobject)
1162 {
1163 	struct pkt_stream *pkt_stream = ifobject->pkt_stream;
1164 	bool timeout = !is_umem_valid(test->ifobj_rx);
1165 	struct pollfd fds = { };
1166 	u32 ret;
1167 
1168 	fds.fd = xsk_socket__fd(ifobject->xsk->xsk);
1169 	fds.events = POLLOUT;
1170 
1171 	while (pkt_stream->current_pkt_nb < pkt_stream->nb_pkts) {
1172 		ret = __send_pkts(ifobject, &fds, timeout);
1173 		if (ret == TEST_CONTINUE && !test->fail)
1174 			continue;
1175 		if ((ret || test->fail) && !timeout)
1176 			return TEST_FAILURE;
1177 		if (ret == TEST_PASS && timeout)
1178 			return ret;
1179 	}
1180 
1181 	wait_for_tx_completion(ifobject->xsk);
1182 	return TEST_PASS;
1183 }
1184 
1185 static int get_xsk_stats(struct xsk_socket *xsk, struct xdp_statistics *stats)
1186 {
1187 	int fd = xsk_socket__fd(xsk), err;
1188 	socklen_t optlen, expected_len;
1189 
1190 	optlen = sizeof(*stats);
1191 	err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, stats, &optlen);
1192 	if (err) {
1193 		ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n",
1194 			       __func__, -err, strerror(-err));
1195 		return TEST_FAILURE;
1196 	}
1197 
1198 	expected_len = sizeof(struct xdp_statistics);
1199 	if (optlen != expected_len) {
1200 		ksft_print_msg("[%s] getsockopt optlen error. Expected: %u got: %u\n",
1201 			       __func__, expected_len, optlen);
1202 		return TEST_FAILURE;
1203 	}
1204 
1205 	return TEST_PASS;
1206 }
1207 
1208 static int validate_rx_dropped(struct ifobject *ifobject)
1209 {
1210 	struct xsk_socket *xsk = ifobject->xsk->xsk;
1211 	struct xdp_statistics stats;
1212 	int err;
1213 
1214 	kick_rx(ifobject->xsk);
1215 
1216 	err = get_xsk_stats(xsk, &stats);
1217 	if (err)
1218 		return TEST_FAILURE;
1219 
1220 	/* The receiver calls getsockopt after receiving the last (valid)
1221 	 * packet which is not the final packet sent in this test (valid and
1222 	 * invalid packets are sent in alternating fashion with the final
1223 	 * packet being invalid). Since the last packet may or may not have
1224 	 * been dropped already, both outcomes must be allowed.
1225 	 */
1226 	if (stats.rx_dropped == ifobject->pkt_stream->nb_pkts / 2 ||
1227 	    stats.rx_dropped == ifobject->pkt_stream->nb_pkts / 2 - 1)
1228 		return TEST_PASS;
1229 
1230 	return TEST_FAILURE;
1231 }
1232 
1233 static int validate_rx_full(struct ifobject *ifobject)
1234 {
1235 	struct xsk_socket *xsk = ifobject->xsk->xsk;
1236 	struct xdp_statistics stats;
1237 	int err;
1238 
1239 	usleep(1000);
1240 	kick_rx(ifobject->xsk);
1241 
1242 	err = get_xsk_stats(xsk, &stats);
1243 	if (err)
1244 		return TEST_FAILURE;
1245 
1246 	if (stats.rx_ring_full)
1247 		return TEST_PASS;
1248 
1249 	return TEST_FAILURE;
1250 }
1251 
1252 static int validate_fill_empty(struct ifobject *ifobject)
1253 {
1254 	struct xsk_socket *xsk = ifobject->xsk->xsk;
1255 	struct xdp_statistics stats;
1256 	int err;
1257 
1258 	usleep(1000);
1259 	kick_rx(ifobject->xsk);
1260 
1261 	err = get_xsk_stats(xsk, &stats);
1262 	if (err)
1263 		return TEST_FAILURE;
1264 
1265 	if (stats.rx_fill_ring_empty_descs)
1266 		return TEST_PASS;
1267 
1268 	return TEST_FAILURE;
1269 }
1270 
1271 static int validate_tx_invalid_descs(struct ifobject *ifobject)
1272 {
1273 	struct xsk_socket *xsk = ifobject->xsk->xsk;
1274 	int fd = xsk_socket__fd(xsk);
1275 	struct xdp_statistics stats;
1276 	socklen_t optlen;
1277 	int err;
1278 
1279 	optlen = sizeof(stats);
1280 	err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen);
1281 	if (err) {
1282 		ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n",
1283 			       __func__, -err, strerror(-err));
1284 		return TEST_FAILURE;
1285 	}
1286 
1287 	if (stats.tx_invalid_descs != ifobject->pkt_stream->nb_pkts / 2) {
1288 		ksft_print_msg("[%s] tx_invalid_descs incorrect. Got [%u] expected [%u]\n",
1289 			       __func__, stats.tx_invalid_descs, ifobject->pkt_stream->nb_pkts);
1290 		return TEST_FAILURE;
1291 	}
1292 
1293 	return TEST_PASS;
1294 }
1295 
1296 static void xsk_configure_socket(struct test_spec *test, struct ifobject *ifobject,
1297 				 struct xsk_umem_info *umem, bool tx)
1298 {
1299 	int i, ret;
1300 
1301 	for (i = 0; i < test->nb_sockets; i++) {
1302 		bool shared = (ifobject->shared_umem && tx) ? true : !!i;
1303 		u32 ctr = 0;
1304 
1305 		while (ctr++ < SOCK_RECONF_CTR) {
1306 			ret = __xsk_configure_socket(&ifobject->xsk_arr[i], umem,
1307 						     ifobject, shared);
1308 			if (!ret)
1309 				break;
1310 
1311 			/* Retry if it fails as xsk_socket__create() is asynchronous */
1312 			if (ctr >= SOCK_RECONF_CTR)
1313 				exit_with_error(-ret);
1314 			usleep(USLEEP_MAX);
1315 		}
1316 		if (ifobject->busy_poll)
1317 			enable_busy_poll(&ifobject->xsk_arr[i]);
1318 	}
1319 }
1320 
1321 static void thread_common_ops_tx(struct test_spec *test, struct ifobject *ifobject)
1322 {
1323 	xsk_configure_socket(test, ifobject, test->ifobj_rx->umem, true);
1324 	ifobject->xsk = &ifobject->xsk_arr[0];
1325 	ifobject->xskmap = test->ifobj_rx->xskmap;
1326 	memcpy(ifobject->umem, test->ifobj_rx->umem, sizeof(struct xsk_umem_info));
1327 	ifobject->umem->base_addr = 0;
1328 }
1329 
1330 static void xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_stream *pkt_stream,
1331 				   bool fill_up)
1332 {
1333 	u32 rx_frame_size = umem->frame_size - XDP_PACKET_HEADROOM;
1334 	u32 idx = 0, filled = 0, buffers_to_fill, nb_pkts;
1335 	int ret;
1336 
1337 	if (umem->num_frames < XSK_RING_PROD__DEFAULT_NUM_DESCS)
1338 		buffers_to_fill = umem->num_frames;
1339 	else
1340 		buffers_to_fill = XSK_RING_PROD__DEFAULT_NUM_DESCS;
1341 
1342 	ret = xsk_ring_prod__reserve(&umem->fq, buffers_to_fill, &idx);
1343 	if (ret != buffers_to_fill)
1344 		exit_with_error(ENOSPC);
1345 
1346 	while (filled < buffers_to_fill) {
1347 		struct pkt *pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &nb_pkts);
1348 		u64 addr;
1349 		u32 i;
1350 
1351 		for (i = 0; i < pkt_nb_frags(rx_frame_size, pkt); i++) {
1352 			if (!pkt) {
1353 				if (!fill_up)
1354 					break;
1355 				addr = filled * umem->frame_size + umem->base_addr;
1356 			} else if (pkt->offset >= 0) {
1357 				addr = pkt->offset % umem->frame_size + umem_alloc_buffer(umem);
1358 			} else {
1359 				addr = pkt->offset + umem_alloc_buffer(umem);
1360 			}
1361 
1362 			*xsk_ring_prod__fill_addr(&umem->fq, idx++) = addr;
1363 			if (++filled >= buffers_to_fill)
1364 				break;
1365 		}
1366 	}
1367 	xsk_ring_prod__submit(&umem->fq, filled);
1368 	xsk_ring_prod__cancel(&umem->fq, buffers_to_fill - filled);
1369 
1370 	pkt_stream_reset(pkt_stream);
1371 	umem_reset_alloc(umem);
1372 }
1373 
1374 static void thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
1375 {
1376 	u64 umem_sz = ifobject->umem->num_frames * ifobject->umem->frame_size;
1377 	int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
1378 	LIBBPF_OPTS(bpf_xdp_query_opts, opts);
1379 	void *bufs;
1380 	int ret;
1381 
1382 	if (ifobject->umem->unaligned_mode)
1383 		mmap_flags |= MAP_HUGETLB | MAP_HUGE_2MB;
1384 
1385 	if (ifobject->shared_umem)
1386 		umem_sz *= 2;
1387 
1388 	bufs = mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
1389 	if (bufs == MAP_FAILED)
1390 		exit_with_error(errno);
1391 
1392 	ret = xsk_configure_umem(ifobject, ifobject->umem, bufs, umem_sz);
1393 	if (ret)
1394 		exit_with_error(-ret);
1395 
1396 	xsk_configure_socket(test, ifobject, ifobject->umem, false);
1397 
1398 	ifobject->xsk = &ifobject->xsk_arr[0];
1399 
1400 	if (!ifobject->rx_on)
1401 		return;
1402 
1403 	xsk_populate_fill_ring(ifobject->umem, ifobject->pkt_stream, ifobject->use_fill_ring);
1404 
1405 	ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk);
1406 	if (ret)
1407 		exit_with_error(errno);
1408 }
1409 
1410 static void *worker_testapp_validate_tx(void *arg)
1411 {
1412 	struct test_spec *test = (struct test_spec *)arg;
1413 	struct ifobject *ifobject = test->ifobj_tx;
1414 	int err;
1415 
1416 	if (test->current_step == 1) {
1417 		if (!ifobject->shared_umem)
1418 			thread_common_ops(test, ifobject);
1419 		else
1420 			thread_common_ops_tx(test, ifobject);
1421 	}
1422 
1423 	print_verbose("Sending %d packets on interface %s\n", ifobject->pkt_stream->nb_pkts,
1424 		      ifobject->ifname);
1425 	err = send_pkts(test, ifobject);
1426 
1427 	if (!err && ifobject->validation_func)
1428 		err = ifobject->validation_func(ifobject);
1429 	if (err)
1430 		report_failure(test);
1431 
1432 	pthread_exit(NULL);
1433 }
1434 
1435 static void *worker_testapp_validate_rx(void *arg)
1436 {
1437 	struct test_spec *test = (struct test_spec *)arg;
1438 	struct ifobject *ifobject = test->ifobj_rx;
1439 	struct pollfd fds = { };
1440 	int err;
1441 
1442 	if (test->current_step == 1) {
1443 		thread_common_ops(test, ifobject);
1444 	} else {
1445 		xsk_clear_xskmap(ifobject->xskmap);
1446 		err = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk);
1447 		if (err) {
1448 			printf("Error: Failed to update xskmap, error %s\n", strerror(-err));
1449 			exit_with_error(-err);
1450 		}
1451 	}
1452 
1453 	fds.fd = xsk_socket__fd(ifobject->xsk->xsk);
1454 	fds.events = POLLIN;
1455 
1456 	pthread_barrier_wait(&barr);
1457 
1458 	err = receive_pkts(test, &fds);
1459 
1460 	if (!err && ifobject->validation_func)
1461 		err = ifobject->validation_func(ifobject);
1462 	if (err)
1463 		report_failure(test);
1464 
1465 	pthread_exit(NULL);
1466 }
1467 
1468 static u64 ceil_u64(u64 a, u64 b)
1469 {
1470 	return (a + b - 1) / b;
1471 }
1472 
1473 static void testapp_clean_xsk_umem(struct ifobject *ifobj)
1474 {
1475 	u64 umem_sz = ifobj->umem->num_frames * ifobj->umem->frame_size;
1476 
1477 	if (ifobj->shared_umem)
1478 		umem_sz *= 2;
1479 
1480 	umem_sz = ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE;
1481 	xsk_umem__delete(ifobj->umem->umem);
1482 	munmap(ifobj->umem->buffer, umem_sz);
1483 }
1484 
1485 static void handler(int signum)
1486 {
1487 	pthread_exit(NULL);
1488 }
1489 
1490 static bool xdp_prog_changed_rx(struct test_spec *test)
1491 {
1492 	struct ifobject *ifobj = test->ifobj_rx;
1493 
1494 	return ifobj->xdp_prog != test->xdp_prog_rx || ifobj->mode != test->mode;
1495 }
1496 
1497 static bool xdp_prog_changed_tx(struct test_spec *test)
1498 {
1499 	struct ifobject *ifobj = test->ifobj_tx;
1500 
1501 	return ifobj->xdp_prog != test->xdp_prog_tx || ifobj->mode != test->mode;
1502 }
1503 
1504 static void xsk_reattach_xdp(struct ifobject *ifobj, struct bpf_program *xdp_prog,
1505 			     struct bpf_map *xskmap, enum test_mode mode)
1506 {
1507 	int err;
1508 
1509 	xsk_detach_xdp_program(ifobj->ifindex, mode_to_xdp_flags(ifobj->mode));
1510 	err = xsk_attach_xdp_program(xdp_prog, ifobj->ifindex, mode_to_xdp_flags(mode));
1511 	if (err) {
1512 		printf("Error attaching XDP program\n");
1513 		exit_with_error(-err);
1514 	}
1515 
1516 	if (ifobj->mode != mode && (mode == TEST_MODE_DRV || mode == TEST_MODE_ZC))
1517 		if (!xsk_is_in_mode(ifobj->ifindex, XDP_FLAGS_DRV_MODE)) {
1518 			ksft_print_msg("ERROR: XDP prog not in DRV mode\n");
1519 			exit_with_error(EINVAL);
1520 		}
1521 
1522 	ifobj->xdp_prog = xdp_prog;
1523 	ifobj->xskmap = xskmap;
1524 	ifobj->mode = mode;
1525 }
1526 
1527 static void xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_rx,
1528 				 struct ifobject *ifobj_tx)
1529 {
1530 	if (xdp_prog_changed_rx(test))
1531 		xsk_reattach_xdp(ifobj_rx, test->xdp_prog_rx, test->xskmap_rx, test->mode);
1532 
1533 	if (!ifobj_tx || ifobj_tx->shared_umem)
1534 		return;
1535 
1536 	if (xdp_prog_changed_tx(test))
1537 		xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode);
1538 }
1539 
1540 static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1,
1541 				      struct ifobject *ifobj2)
1542 {
1543 	pthread_t t0, t1;
1544 	int err;
1545 
1546 	if (test->mtu > MAX_ETH_PKT_SIZE) {
1547 		if (test->mode == TEST_MODE_ZC && (!ifobj1->multi_buff_zc_supp ||
1548 						   (ifobj2 && !ifobj2->multi_buff_zc_supp))) {
1549 			ksft_test_result_skip("Multi buffer for zero-copy not supported.\n");
1550 			return TEST_SKIP;
1551 		}
1552 		if (test->mode != TEST_MODE_ZC && (!ifobj1->multi_buff_supp ||
1553 						   (ifobj2 && !ifobj2->multi_buff_supp))) {
1554 			ksft_test_result_skip("Multi buffer not supported.\n");
1555 			return TEST_SKIP;
1556 		}
1557 	}
1558 	err = test_spec_set_mtu(test, test->mtu);
1559 	if (err) {
1560 		ksft_print_msg("Error, could not set mtu.\n");
1561 		exit_with_error(err);
1562 	}
1563 
1564 	if (ifobj2) {
1565 		if (pthread_barrier_init(&barr, NULL, 2))
1566 			exit_with_error(errno);
1567 		pkt_stream_reset(ifobj2->pkt_stream);
1568 	}
1569 
1570 	test->current_step++;
1571 	pkt_stream_reset(ifobj1->pkt_stream);
1572 	pkts_in_flight = 0;
1573 
1574 	signal(SIGUSR1, handler);
1575 	/*Spawn RX thread */
1576 	pthread_create(&t0, NULL, ifobj1->func_ptr, test);
1577 
1578 	if (ifobj2) {
1579 		pthread_barrier_wait(&barr);
1580 		if (pthread_barrier_destroy(&barr))
1581 			exit_with_error(errno);
1582 
1583 		/*Spawn TX thread */
1584 		pthread_create(&t1, NULL, ifobj2->func_ptr, test);
1585 
1586 		pthread_join(t1, NULL);
1587 	}
1588 
1589 	if (!ifobj2)
1590 		pthread_kill(t0, SIGUSR1);
1591 	else
1592 		pthread_join(t0, NULL);
1593 
1594 	if (test->total_steps == test->current_step || test->fail) {
1595 		if (ifobj2)
1596 			xsk_socket__delete(ifobj2->xsk->xsk);
1597 		xsk_socket__delete(ifobj1->xsk->xsk);
1598 		testapp_clean_xsk_umem(ifobj1);
1599 		if (ifobj2 && !ifobj2->shared_umem)
1600 			testapp_clean_xsk_umem(ifobj2);
1601 	}
1602 
1603 	return !!test->fail;
1604 }
1605 
1606 static int testapp_validate_traffic(struct test_spec *test)
1607 {
1608 	struct ifobject *ifobj_rx = test->ifobj_rx;
1609 	struct ifobject *ifobj_tx = test->ifobj_tx;
1610 
1611 	if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp) ||
1612 	    (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) {
1613 		ksft_test_result_skip("No huge pages present.\n");
1614 		return TEST_SKIP;
1615 	}
1616 
1617 	xsk_attach_xdp_progs(test, ifobj_rx, ifobj_tx);
1618 	return __testapp_validate_traffic(test, ifobj_rx, ifobj_tx);
1619 }
1620 
1621 static int testapp_validate_traffic_single_thread(struct test_spec *test, struct ifobject *ifobj)
1622 {
1623 	return __testapp_validate_traffic(test, ifobj, NULL);
1624 }
1625 
1626 static int testapp_teardown(struct test_spec *test)
1627 {
1628 	int i;
1629 
1630 	test_spec_set_name(test, "TEARDOWN");
1631 	for (i = 0; i < MAX_TEARDOWN_ITER; i++) {
1632 		if (testapp_validate_traffic(test))
1633 			return TEST_FAILURE;
1634 		test_spec_reset(test);
1635 	}
1636 
1637 	return TEST_PASS;
1638 }
1639 
1640 static void swap_directions(struct ifobject **ifobj1, struct ifobject **ifobj2)
1641 {
1642 	thread_func_t tmp_func_ptr = (*ifobj1)->func_ptr;
1643 	struct ifobject *tmp_ifobj = (*ifobj1);
1644 
1645 	(*ifobj1)->func_ptr = (*ifobj2)->func_ptr;
1646 	(*ifobj2)->func_ptr = tmp_func_ptr;
1647 
1648 	*ifobj1 = *ifobj2;
1649 	*ifobj2 = tmp_ifobj;
1650 }
1651 
1652 static int testapp_bidi(struct test_spec *test)
1653 {
1654 	int res;
1655 
1656 	test_spec_set_name(test, "BIDIRECTIONAL");
1657 	test->ifobj_tx->rx_on = true;
1658 	test->ifobj_rx->tx_on = true;
1659 	test->total_steps = 2;
1660 	if (testapp_validate_traffic(test))
1661 		return TEST_FAILURE;
1662 
1663 	print_verbose("Switching Tx/Rx vectors\n");
1664 	swap_directions(&test->ifobj_rx, &test->ifobj_tx);
1665 	res = __testapp_validate_traffic(test, test->ifobj_rx, test->ifobj_tx);
1666 
1667 	swap_directions(&test->ifobj_rx, &test->ifobj_tx);
1668 	return res;
1669 }
1670 
1671 static void swap_xsk_resources(struct ifobject *ifobj_tx, struct ifobject *ifobj_rx)
1672 {
1673 	int ret;
1674 
1675 	xsk_socket__delete(ifobj_tx->xsk->xsk);
1676 	xsk_socket__delete(ifobj_rx->xsk->xsk);
1677 	ifobj_tx->xsk = &ifobj_tx->xsk_arr[1];
1678 	ifobj_rx->xsk = &ifobj_rx->xsk_arr[1];
1679 
1680 	ret = xsk_update_xskmap(ifobj_rx->xskmap, ifobj_rx->xsk->xsk);
1681 	if (ret)
1682 		exit_with_error(errno);
1683 }
1684 
1685 static int testapp_bpf_res(struct test_spec *test)
1686 {
1687 	test_spec_set_name(test, "BPF_RES");
1688 	test->total_steps = 2;
1689 	test->nb_sockets = 2;
1690 	if (testapp_validate_traffic(test))
1691 		return TEST_FAILURE;
1692 
1693 	swap_xsk_resources(test->ifobj_tx, test->ifobj_rx);
1694 	return testapp_validate_traffic(test);
1695 }
1696 
1697 static int testapp_headroom(struct test_spec *test)
1698 {
1699 	test_spec_set_name(test, "UMEM_HEADROOM");
1700 	test->ifobj_rx->umem->frame_headroom = UMEM_HEADROOM_TEST_SIZE;
1701 	return testapp_validate_traffic(test);
1702 }
1703 
1704 static int testapp_stats_rx_dropped(struct test_spec *test)
1705 {
1706 	test_spec_set_name(test, "STAT_RX_DROPPED");
1707 	if (test->mode == TEST_MODE_ZC) {
1708 		ksft_test_result_skip("Can not run RX_DROPPED test for ZC mode\n");
1709 		return TEST_SKIP;
1710 	}
1711 
1712 	pkt_stream_replace_half(test, MIN_PKT_SIZE * 4, 0);
1713 	test->ifobj_rx->umem->frame_headroom = test->ifobj_rx->umem->frame_size -
1714 		XDP_PACKET_HEADROOM - MIN_PKT_SIZE * 3;
1715 	pkt_stream_receive_half(test);
1716 	test->ifobj_rx->validation_func = validate_rx_dropped;
1717 	return testapp_validate_traffic(test);
1718 }
1719 
1720 static int testapp_stats_tx_invalid_descs(struct test_spec *test)
1721 {
1722 	test_spec_set_name(test, "STAT_TX_INVALID");
1723 	pkt_stream_replace_half(test, XSK_UMEM__INVALID_FRAME_SIZE, 0);
1724 	test->ifobj_tx->validation_func = validate_tx_invalid_descs;
1725 	return testapp_validate_traffic(test);
1726 }
1727 
1728 static int testapp_stats_rx_full(struct test_spec *test)
1729 {
1730 	test_spec_set_name(test, "STAT_RX_FULL");
1731 	pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE);
1732 	test->ifobj_rx->pkt_stream = pkt_stream_generate(test->ifobj_rx->umem,
1733 							 DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
1734 
1735 	test->ifobj_rx->xsk->rxqsize = DEFAULT_UMEM_BUFFERS;
1736 	test->ifobj_rx->release_rx = false;
1737 	test->ifobj_rx->validation_func = validate_rx_full;
1738 	return testapp_validate_traffic(test);
1739 }
1740 
1741 static int testapp_stats_fill_empty(struct test_spec *test)
1742 {
1743 	test_spec_set_name(test, "STAT_RX_FILL_EMPTY");
1744 	pkt_stream_replace(test, DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE);
1745 	test->ifobj_rx->pkt_stream = pkt_stream_generate(test->ifobj_rx->umem,
1746 							 DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE);
1747 
1748 	test->ifobj_rx->use_fill_ring = false;
1749 	test->ifobj_rx->validation_func = validate_fill_empty;
1750 	return testapp_validate_traffic(test);
1751 }
1752 
1753 static int testapp_unaligned(struct test_spec *test)
1754 {
1755 	test_spec_set_name(test, "UNALIGNED_MODE");
1756 	test->ifobj_tx->umem->unaligned_mode = true;
1757 	test->ifobj_rx->umem->unaligned_mode = true;
1758 	/* Let half of the packets straddle a 4K buffer boundary */
1759 	pkt_stream_replace_half(test, MIN_PKT_SIZE, -MIN_PKT_SIZE / 2);
1760 
1761 	return testapp_validate_traffic(test);
1762 }
1763 
1764 static int testapp_single_pkt(struct test_spec *test)
1765 {
1766 	struct pkt pkts[] = {{0, MIN_PKT_SIZE, 0, true}};
1767 
1768 	pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts));
1769 	return testapp_validate_traffic(test);
1770 }
1771 
1772 static int testapp_multi_buffer(struct test_spec *test)
1773 {
1774 	test_spec_set_name(test, "RUN_TO_COMPLETION_9K_PACKETS");
1775 	test->mtu = MAX_ETH_JUMBO_SIZE;
1776 	pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE);
1777 
1778 	return testapp_validate_traffic(test);
1779 }
1780 
1781 static int testapp_invalid_desc(struct test_spec *test)
1782 {
1783 	struct xsk_umem_info *umem = test->ifobj_tx->umem;
1784 	u64 umem_size = umem->num_frames * umem->frame_size;
1785 	struct pkt pkts[] = {
1786 		/* Zero packet address allowed */
1787 		{0, MIN_PKT_SIZE, 0, true},
1788 		/* Allowed packet */
1789 		{0, MIN_PKT_SIZE, 0, true},
1790 		/* Straddling the start of umem */
1791 		{-2, MIN_PKT_SIZE, 0, false},
1792 		/* Packet too large */
1793 		{0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false},
1794 		/* Up to end of umem allowed */
1795 		{umem_size - MIN_PKT_SIZE - 2 * umem->frame_size, MIN_PKT_SIZE, 0, true},
1796 		/* After umem ends */
1797 		{umem_size, MIN_PKT_SIZE, 0, false},
1798 		/* Straddle the end of umem */
1799 		{umem_size - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false},
1800 		/* Straddle a 4K boundary */
1801 		{0x1000 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false},
1802 		/* Straddle a 2K boundary */
1803 		{0x800 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, true},
1804 		/* Valid packet for synch so that something is received */
1805 		{0, MIN_PKT_SIZE, 0, true}};
1806 
1807 	if (umem->unaligned_mode) {
1808 		/* Crossing a page boundary allowed */
1809 		pkts[7].valid = true;
1810 	}
1811 	if (umem->frame_size == XSK_UMEM__DEFAULT_FRAME_SIZE / 2) {
1812 		/* Crossing a 2K frame size boundary not allowed */
1813 		pkts[8].valid = false;
1814 	}
1815 
1816 	if (test->ifobj_tx->shared_umem) {
1817 		pkts[4].offset += umem_size;
1818 		pkts[5].offset += umem_size;
1819 		pkts[6].offset += umem_size;
1820 	}
1821 
1822 	pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts));
1823 	return testapp_validate_traffic(test);
1824 }
1825 
1826 static int testapp_xdp_drop(struct test_spec *test)
1827 {
1828 	struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
1829 	struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
1830 
1831 	test_spec_set_name(test, "XDP_DROP_HALF");
1832 	test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_drop, skel_tx->progs.xsk_xdp_drop,
1833 			       skel_rx->maps.xsk, skel_tx->maps.xsk);
1834 
1835 	pkt_stream_receive_half(test);
1836 	return testapp_validate_traffic(test);
1837 }
1838 
1839 static int testapp_xdp_metadata_count(struct test_spec *test)
1840 {
1841 	struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
1842 	struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
1843 	struct bpf_map *data_map;
1844 	int count = 0;
1845 	int key = 0;
1846 
1847 	test_spec_set_name(test, "XDP_METADATA_COUNT");
1848 	test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_populate_metadata,
1849 			       skel_tx->progs.xsk_xdp_populate_metadata,
1850 			       skel_rx->maps.xsk, skel_tx->maps.xsk);
1851 	test->ifobj_rx->use_metadata = true;
1852 
1853 	data_map = bpf_object__find_map_by_name(skel_rx->obj, "xsk_xdp_.bss");
1854 	if (!data_map || !bpf_map__is_internal(data_map))
1855 		exit_with_error(ENOMEM);
1856 
1857 	if (bpf_map_update_elem(bpf_map__fd(data_map), &key, &count, BPF_ANY))
1858 		exit_with_error(errno);
1859 
1860 	return testapp_validate_traffic(test);
1861 }
1862 
1863 static int testapp_poll_txq_tmout(struct test_spec *test)
1864 {
1865 	test_spec_set_name(test, "POLL_TXQ_FULL");
1866 
1867 	test->ifobj_tx->use_poll = true;
1868 	/* create invalid frame by set umem frame_size and pkt length equal to 2048 */
1869 	test->ifobj_tx->umem->frame_size = 2048;
1870 	pkt_stream_replace(test, 2 * DEFAULT_PKT_CNT, 2048);
1871 	return testapp_validate_traffic_single_thread(test, test->ifobj_tx);
1872 }
1873 
1874 static int testapp_poll_rxq_tmout(struct test_spec *test)
1875 {
1876 	test_spec_set_name(test, "POLL_RXQ_EMPTY");
1877 	test->ifobj_rx->use_poll = true;
1878 	return testapp_validate_traffic_single_thread(test, test->ifobj_rx);
1879 }
1880 
1881 static int xsk_load_xdp_programs(struct ifobject *ifobj)
1882 {
1883 	ifobj->xdp_progs = xsk_xdp_progs__open_and_load();
1884 	if (libbpf_get_error(ifobj->xdp_progs))
1885 		return libbpf_get_error(ifobj->xdp_progs);
1886 
1887 	return 0;
1888 }
1889 
1890 static void xsk_unload_xdp_programs(struct ifobject *ifobj)
1891 {
1892 	xsk_xdp_progs__destroy(ifobj->xdp_progs);
1893 }
1894 
1895 /* Simple test */
1896 static bool hugepages_present(void)
1897 {
1898 	size_t mmap_sz = 2 * DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE;
1899 	void *bufs;
1900 
1901 	bufs = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
1902 		    MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, MAP_HUGE_2MB);
1903 	if (bufs == MAP_FAILED)
1904 		return false;
1905 
1906 	mmap_sz = ceil_u64(mmap_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE;
1907 	munmap(bufs, mmap_sz);
1908 	return true;
1909 }
1910 
1911 static void init_iface(struct ifobject *ifobj, const char *dst_mac, const char *src_mac,
1912 		       thread_func_t func_ptr)
1913 {
1914 	LIBBPF_OPTS(bpf_xdp_query_opts, query_opts);
1915 	int err;
1916 
1917 	memcpy(ifobj->dst_mac, dst_mac, ETH_ALEN);
1918 	memcpy(ifobj->src_mac, src_mac, ETH_ALEN);
1919 
1920 	ifobj->func_ptr = func_ptr;
1921 
1922 	err = xsk_load_xdp_programs(ifobj);
1923 	if (err) {
1924 		printf("Error loading XDP program\n");
1925 		exit_with_error(err);
1926 	}
1927 
1928 	if (hugepages_present())
1929 		ifobj->unaligned_supp = true;
1930 
1931 	err = bpf_xdp_query(ifobj->ifindex, XDP_FLAGS_DRV_MODE, &query_opts);
1932 	if (err) {
1933 		ksft_print_msg("Error querrying XDP capabilities\n");
1934 		exit_with_error(-err);
1935 	}
1936 	if (query_opts.feature_flags & NETDEV_XDP_ACT_RX_SG)
1937 		ifobj->multi_buff_supp = true;
1938 	if (query_opts.feature_flags & NETDEV_XDP_ACT_XSK_ZEROCOPY)
1939 		if (query_opts.xdp_zc_max_segs > 1)
1940 			ifobj->multi_buff_zc_supp = true;
1941 }
1942 
1943 static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_type type)
1944 {
1945 	int ret = TEST_SKIP;
1946 
1947 	switch (type) {
1948 	case TEST_TYPE_STATS_RX_DROPPED:
1949 		ret = testapp_stats_rx_dropped(test);
1950 		break;
1951 	case TEST_TYPE_STATS_TX_INVALID_DESCS:
1952 		ret = testapp_stats_tx_invalid_descs(test);
1953 		break;
1954 	case TEST_TYPE_STATS_RX_FULL:
1955 		ret = testapp_stats_rx_full(test);
1956 		break;
1957 	case TEST_TYPE_STATS_FILL_EMPTY:
1958 		ret = testapp_stats_fill_empty(test);
1959 		break;
1960 	case TEST_TYPE_TEARDOWN:
1961 		ret = testapp_teardown(test);
1962 		break;
1963 	case TEST_TYPE_BIDI:
1964 		ret = testapp_bidi(test);
1965 		break;
1966 	case TEST_TYPE_BPF_RES:
1967 		ret = testapp_bpf_res(test);
1968 		break;
1969 	case TEST_TYPE_RUN_TO_COMPLETION:
1970 		test_spec_set_name(test, "RUN_TO_COMPLETION");
1971 		ret = testapp_validate_traffic(test);
1972 		break;
1973 	case TEST_TYPE_RUN_TO_COMPLETION_MB:
1974 		ret = testapp_multi_buffer(test);
1975 		break;
1976 	case TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT:
1977 		test_spec_set_name(test, "RUN_TO_COMPLETION_SINGLE_PKT");
1978 		ret = testapp_single_pkt(test);
1979 		break;
1980 	case TEST_TYPE_RUN_TO_COMPLETION_2K_FRAME:
1981 		test_spec_set_name(test, "RUN_TO_COMPLETION_2K_FRAME_SIZE");
1982 		test->ifobj_tx->umem->frame_size = 2048;
1983 		test->ifobj_rx->umem->frame_size = 2048;
1984 		pkt_stream_replace(test, DEFAULT_PKT_CNT, MIN_PKT_SIZE);
1985 		ret = testapp_validate_traffic(test);
1986 		break;
1987 	case TEST_TYPE_RX_POLL:
1988 		test->ifobj_rx->use_poll = true;
1989 		test_spec_set_name(test, "POLL_RX");
1990 		ret = testapp_validate_traffic(test);
1991 		break;
1992 	case TEST_TYPE_TX_POLL:
1993 		test->ifobj_tx->use_poll = true;
1994 		test_spec_set_name(test, "POLL_TX");
1995 		ret = testapp_validate_traffic(test);
1996 		break;
1997 	case TEST_TYPE_POLL_TXQ_TMOUT:
1998 		ret = testapp_poll_txq_tmout(test);
1999 		break;
2000 	case TEST_TYPE_POLL_RXQ_TMOUT:
2001 		ret = testapp_poll_rxq_tmout(test);
2002 		break;
2003 	case TEST_TYPE_ALIGNED_INV_DESC:
2004 		test_spec_set_name(test, "ALIGNED_INV_DESC");
2005 		ret = testapp_invalid_desc(test);
2006 		break;
2007 	case TEST_TYPE_ALIGNED_INV_DESC_2K_FRAME:
2008 		test_spec_set_name(test, "ALIGNED_INV_DESC_2K_FRAME_SIZE");
2009 		test->ifobj_tx->umem->frame_size = 2048;
2010 		test->ifobj_rx->umem->frame_size = 2048;
2011 		ret = testapp_invalid_desc(test);
2012 		break;
2013 	case TEST_TYPE_UNALIGNED_INV_DESC:
2014 		test_spec_set_name(test, "UNALIGNED_INV_DESC");
2015 		test->ifobj_tx->umem->unaligned_mode = true;
2016 		test->ifobj_rx->umem->unaligned_mode = true;
2017 		ret = testapp_invalid_desc(test);
2018 		break;
2019 	case TEST_TYPE_UNALIGNED_INV_DESC_4K1_FRAME: {
2020 		u64 page_size, umem_size;
2021 
2022 		test_spec_set_name(test, "UNALIGNED_INV_DESC_4K1_FRAME_SIZE");
2023 		/* Odd frame size so the UMEM doesn't end near a page boundary. */
2024 		test->ifobj_tx->umem->frame_size = 4001;
2025 		test->ifobj_rx->umem->frame_size = 4001;
2026 		test->ifobj_tx->umem->unaligned_mode = true;
2027 		test->ifobj_rx->umem->unaligned_mode = true;
2028 		/* This test exists to test descriptors that staddle the end of
2029 		 * the UMEM but not a page.
2030 		 */
2031 		page_size = sysconf(_SC_PAGESIZE);
2032 		umem_size = test->ifobj_tx->umem->num_frames * test->ifobj_tx->umem->frame_size;
2033 		assert(umem_size % page_size > MIN_PKT_SIZE);
2034 		assert(umem_size % page_size < page_size - MIN_PKT_SIZE);
2035 		ret = testapp_invalid_desc(test);
2036 		break;
2037 	}
2038 	case TEST_TYPE_UNALIGNED:
2039 		ret = testapp_unaligned(test);
2040 		break;
2041 	case TEST_TYPE_HEADROOM:
2042 		ret = testapp_headroom(test);
2043 		break;
2044 	case TEST_TYPE_XDP_DROP_HALF:
2045 		ret = testapp_xdp_drop(test);
2046 		break;
2047 	case TEST_TYPE_XDP_METADATA_COUNT:
2048 		ret = testapp_xdp_metadata_count(test);
2049 		break;
2050 	default:
2051 		break;
2052 	}
2053 
2054 	if (ret == TEST_PASS)
2055 		ksft_test_result_pass("PASS: %s %s%s\n", mode_string(test), busy_poll_string(test),
2056 				      test->name);
2057 	pkt_stream_restore_default(test);
2058 }
2059 
2060 static struct ifobject *ifobject_create(void)
2061 {
2062 	struct ifobject *ifobj;
2063 
2064 	ifobj = calloc(1, sizeof(struct ifobject));
2065 	if (!ifobj)
2066 		return NULL;
2067 
2068 	ifobj->xsk_arr = calloc(MAX_SOCKETS, sizeof(*ifobj->xsk_arr));
2069 	if (!ifobj->xsk_arr)
2070 		goto out_xsk_arr;
2071 
2072 	ifobj->umem = calloc(1, sizeof(*ifobj->umem));
2073 	if (!ifobj->umem)
2074 		goto out_umem;
2075 
2076 	return ifobj;
2077 
2078 out_umem:
2079 	free(ifobj->xsk_arr);
2080 out_xsk_arr:
2081 	free(ifobj);
2082 	return NULL;
2083 }
2084 
2085 static void ifobject_delete(struct ifobject *ifobj)
2086 {
2087 	free(ifobj->umem);
2088 	free(ifobj->xsk_arr);
2089 	free(ifobj);
2090 }
2091 
2092 static bool is_xdp_supported(int ifindex)
2093 {
2094 	int flags = XDP_FLAGS_DRV_MODE;
2095 
2096 	LIBBPF_OPTS(bpf_link_create_opts, opts, .flags = flags);
2097 	struct bpf_insn insns[2] = {
2098 		BPF_MOV64_IMM(BPF_REG_0, XDP_PASS),
2099 		BPF_EXIT_INSN()
2100 	};
2101 	int prog_fd, insn_cnt = ARRAY_SIZE(insns);
2102 	int err;
2103 
2104 	prog_fd = bpf_prog_load(BPF_PROG_TYPE_XDP, NULL, "GPL", insns, insn_cnt, NULL);
2105 	if (prog_fd < 0)
2106 		return false;
2107 
2108 	err = bpf_xdp_attach(ifindex, prog_fd, flags, NULL);
2109 	if (err) {
2110 		close(prog_fd);
2111 		return false;
2112 	}
2113 
2114 	bpf_xdp_detach(ifindex, flags, NULL);
2115 	close(prog_fd);
2116 
2117 	return true;
2118 }
2119 
2120 int main(int argc, char **argv)
2121 {
2122 	struct pkt_stream *rx_pkt_stream_default;
2123 	struct pkt_stream *tx_pkt_stream_default;
2124 	struct ifobject *ifobj_tx, *ifobj_rx;
2125 	int modes = TEST_MODE_SKB + 1;
2126 	u32 i, j, failed_tests = 0;
2127 	struct test_spec test;
2128 	bool shared_netdev;
2129 
2130 	/* Use libbpf 1.0 API mode */
2131 	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
2132 
2133 	ifobj_tx = ifobject_create();
2134 	if (!ifobj_tx)
2135 		exit_with_error(ENOMEM);
2136 	ifobj_rx = ifobject_create();
2137 	if (!ifobj_rx)
2138 		exit_with_error(ENOMEM);
2139 
2140 	setlocale(LC_ALL, "");
2141 
2142 	parse_command_line(ifobj_tx, ifobj_rx, argc, argv);
2143 
2144 	shared_netdev = (ifobj_tx->ifindex == ifobj_rx->ifindex);
2145 	ifobj_tx->shared_umem = shared_netdev;
2146 	ifobj_rx->shared_umem = shared_netdev;
2147 
2148 	if (!validate_interface(ifobj_tx) || !validate_interface(ifobj_rx)) {
2149 		usage(basename(argv[0]));
2150 		ksft_exit_xfail();
2151 	}
2152 
2153 	if (is_xdp_supported(ifobj_tx->ifindex)) {
2154 		modes++;
2155 		if (ifobj_zc_avail(ifobj_tx))
2156 			modes++;
2157 	}
2158 
2159 	init_iface(ifobj_rx, MAC1, MAC2, worker_testapp_validate_rx);
2160 	init_iface(ifobj_tx, MAC2, MAC1, worker_testapp_validate_tx);
2161 
2162 	test_spec_init(&test, ifobj_tx, ifobj_rx, 0);
2163 	tx_pkt_stream_default = pkt_stream_generate(ifobj_tx->umem, DEFAULT_PKT_CNT, MIN_PKT_SIZE);
2164 	rx_pkt_stream_default = pkt_stream_generate(ifobj_rx->umem, DEFAULT_PKT_CNT, MIN_PKT_SIZE);
2165 	if (!tx_pkt_stream_default || !rx_pkt_stream_default)
2166 		exit_with_error(ENOMEM);
2167 	test.tx_pkt_stream_default = tx_pkt_stream_default;
2168 	test.rx_pkt_stream_default = rx_pkt_stream_default;
2169 
2170 	ksft_set_plan(modes * TEST_TYPE_MAX);
2171 
2172 	for (i = 0; i < modes; i++) {
2173 		for (j = 0; j < TEST_TYPE_MAX; j++) {
2174 			test_spec_init(&test, ifobj_tx, ifobj_rx, i);
2175 			run_pkt_test(&test, i, j);
2176 			usleep(USLEEP_MAX);
2177 
2178 			if (test.fail)
2179 				failed_tests++;
2180 		}
2181 	}
2182 
2183 	pkt_stream_delete(tx_pkt_stream_default);
2184 	pkt_stream_delete(rx_pkt_stream_default);
2185 	xsk_unload_xdp_programs(ifobj_tx);
2186 	xsk_unload_xdp_programs(ifobj_rx);
2187 	ifobject_delete(ifobj_tx);
2188 	ifobject_delete(ifobj_rx);
2189 
2190 	if (failed_tests)
2191 		ksft_exit_fail();
2192 	else
2193 		ksft_exit_pass();
2194 }
2195