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