1 // SPDX-License-Identifier: GPL-2.0 2 #include <bpf/bpf.h> 3 #include <errno.h> 4 #include <linux/bitmap.h> 5 #include <linux/if_link.h> 6 #include <linux/mman.h> 7 #include <linux/netdev.h> 8 #include <poll.h> 9 #include <pthread.h> 10 #include <signal.h> 11 #include <string.h> 12 #include <sys/mman.h> 13 #include <sys/socket.h> 14 #include <sys/time.h> 15 #include <unistd.h> 16 17 #include "network_helpers.h" 18 #include "test_xsk.h" 19 #include "xsk_xdp_common.h" 20 #include "xsk_xdp_progs.skel.h" 21 22 #define DEFAULT_BATCH_SIZE 64 23 #define MIN_PKT_SIZE 64 24 #define MAX_ETH_JUMBO_SIZE 9000 25 #define MAX_INTERFACES 2 26 #define MAX_TEARDOWN_ITER 10 27 #define MAX_TX_BUDGET_DEFAULT 32 28 #define PKT_DUMP_NB_TO_PRINT 16 29 /* Just to align the data in the packet */ 30 #define PKT_HDR_SIZE (sizeof(struct ethhdr) + 2) 31 #define POLL_TMOUT 1000 32 #define THREAD_TMOUT 3 33 #define UMEM_HEADROOM_TEST_SIZE 128 34 #define XSK_DESC__INVALID_OPTION (0xffff) 35 #define XSK_UMEM__INVALID_FRAME_SIZE (MAX_ETH_JUMBO_SIZE + 1) 36 #define XSK_UMEM__LARGE_FRAME_SIZE (3 * 1024) 37 #define XSK_UMEM__MAX_FRAME_SIZE (4 * 1024) 38 39 static const u8 g_mac[ETH_ALEN] = {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; 40 41 bool opt_verbose; 42 pthread_barrier_t barr; 43 pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER; 44 45 int pkts_in_flight; 46 47 /* The payload is a word consisting of a packet sequence number in the upper 48 * 16-bits and a intra packet data sequence number in the lower 16 bits. So the 3rd packet's 49 * 5th word of data will contain the number (2<<16) | 4 as they are numbered from 0. 50 */ 51 static void write_payload(void *dest, u32 pkt_nb, u32 start, u32 size) 52 { 53 u32 *ptr = (u32 *)dest, i; 54 55 start /= sizeof(*ptr); 56 size /= sizeof(*ptr); 57 for (i = 0; i < size; i++) 58 ptr[i] = htonl(pkt_nb << 16 | (i + start)); 59 } 60 61 static void gen_eth_hdr(struct xsk_socket_info *xsk, struct ethhdr *eth_hdr) 62 { 63 memcpy(eth_hdr->h_dest, xsk->dst_mac, ETH_ALEN); 64 memcpy(eth_hdr->h_source, xsk->src_mac, ETH_ALEN); 65 eth_hdr->h_proto = htons(ETH_P_LOOPBACK); 66 } 67 68 static bool is_umem_valid(struct xsk_socket_info *xsk) 69 { 70 return !!xsk->umem->umem; 71 } 72 73 static u32 mode_to_xdp_flags(enum test_mode mode) 74 { 75 return (mode == TEST_MODE_SKB) ? XDP_FLAGS_SKB_MODE : XDP_FLAGS_DRV_MODE; 76 } 77 78 static u64 umem_size(struct xsk_umem_info *umem) 79 { 80 return umem->num_frames * umem->frame_size; 81 } 82 83 int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void *buffer, 84 u64 size) 85 { 86 struct xsk_umem_config cfg = { 87 .fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS, 88 .comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS, 89 .frame_size = umem->frame_size, 90 .frame_headroom = umem->frame_headroom, 91 .flags = XSK_UMEM__DEFAULT_FLAGS 92 }; 93 int ret; 94 95 if (umem->fill_size) 96 cfg.fill_size = umem->fill_size; 97 98 if (umem->comp_size) 99 cfg.comp_size = umem->comp_size; 100 101 if (umem->unaligned_mode) 102 cfg.flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG; 103 104 ret = xsk_umem__create(&umem->umem, buffer, size, 105 &umem->fq, &umem->cq, &cfg); 106 if (ret) 107 return ret; 108 109 umem->buffer = buffer; 110 if (ifobj->shared_umem && ifobj->rx_on) { 111 umem->base_addr = umem_size(umem); 112 umem->next_buffer = umem_size(umem); 113 } 114 115 return 0; 116 } 117 118 static u64 umem_alloc_buffer(struct xsk_umem_info *umem) 119 { 120 u64 addr; 121 122 addr = umem->next_buffer; 123 umem->next_buffer += umem->frame_size; 124 if (umem->next_buffer >= umem->base_addr + umem_size(umem)) 125 umem->next_buffer = umem->base_addr; 126 127 return addr; 128 } 129 130 static void umem_reset_alloc(struct xsk_umem_info *umem) 131 { 132 umem->next_buffer = 0; 133 } 134 135 static int enable_busy_poll(struct xsk_socket_info *xsk) 136 { 137 int sock_opt; 138 139 sock_opt = 1; 140 if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_PREFER_BUSY_POLL, 141 (void *)&sock_opt, sizeof(sock_opt)) < 0) 142 return -errno; 143 144 sock_opt = 20; 145 if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL, 146 (void *)&sock_opt, sizeof(sock_opt)) < 0) 147 return -errno; 148 149 sock_opt = xsk->batch_size; 150 if (setsockopt(xsk_socket__fd(xsk->xsk), SOL_SOCKET, SO_BUSY_POLL_BUDGET, 151 (void *)&sock_opt, sizeof(sock_opt)) < 0) 152 return -errno; 153 154 return 0; 155 } 156 157 int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, 158 struct ifobject *ifobject, bool shared) 159 { 160 struct xsk_socket_config cfg = {}; 161 struct xsk_ring_cons *rxr; 162 struct xsk_ring_prod *txr; 163 164 xsk->umem = umem; 165 cfg.rx_size = xsk->rxqsize; 166 cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 167 cfg.bind_flags = ifobject->bind_flags; 168 if (shared) 169 cfg.bind_flags |= XDP_SHARED_UMEM; 170 if (ifobject->mtu > MAX_ETH_PKT_SIZE) 171 cfg.bind_flags |= XDP_USE_SG; 172 if (umem->comp_size) 173 cfg.tx_size = umem->comp_size; 174 if (umem->fill_size) 175 cfg.rx_size = umem->fill_size; 176 177 txr = ifobject->tx_on ? &xsk->tx : NULL; 178 rxr = ifobject->rx_on ? &xsk->rx : NULL; 179 return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg); 180 } 181 182 static int set_ring_size(struct ifobject *ifobj) 183 { 184 int ret; 185 u32 ctr = 0; 186 187 while (ctr++ < SOCK_RECONF_CTR) { 188 ret = set_hw_ring_size(ifobj->ifname, &ifobj->ring); 189 if (!ret) 190 break; 191 192 /* Retry if it fails */ 193 if (ctr >= SOCK_RECONF_CTR || errno != EBUSY) 194 return -errno; 195 196 usleep(USLEEP_MAX); 197 } 198 199 return ret; 200 } 201 202 int hw_ring_size_reset(struct ifobject *ifobj) 203 { 204 ifobj->ring.tx_pending = ifobj->set_ring.default_tx; 205 ifobj->ring.rx_pending = ifobj->set_ring.default_rx; 206 return set_ring_size(ifobj); 207 } 208 209 static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx, 210 struct ifobject *ifobj_rx) 211 { 212 u32 i, j; 213 214 for (i = 0; i < MAX_INTERFACES; i++) { 215 struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx; 216 struct xsk_umem_info *umem_real; 217 218 ifobj->xsk = &ifobj->xsk_arr[0]; 219 ifobj->use_poll = false; 220 ifobj->use_fill_ring = true; 221 ifobj->release_rx = true; 222 ifobj->validation_func = NULL; 223 ifobj->use_metadata = false; 224 225 if (i == 0) { 226 ifobj->rx_on = false; 227 ifobj->tx_on = true; 228 } else { 229 ifobj->rx_on = true; 230 ifobj->tx_on = false; 231 } 232 233 umem_real = ifobj->xsk_arr[0].umem_real; 234 memset(umem_real, 0, sizeof(*umem_real)); 235 for (j = 0; j < MAX_SOCKETS; j++) { 236 struct xsk_socket_info *xsk = &ifobj->xsk_arr[j]; 237 238 memset(xsk, 0, sizeof(*xsk)); 239 xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS; 240 if (j == 0) 241 xsk->umem_real = umem_real; 242 xsk->umem = umem_real; 243 xsk->batch_size = DEFAULT_BATCH_SIZE; 244 if (i == 0) 245 xsk->pkt_stream = test->tx_pkt_stream_default; 246 else 247 xsk->pkt_stream = test->rx_pkt_stream_default; 248 249 memcpy(xsk->src_mac, g_mac, ETH_ALEN); 250 memcpy(xsk->dst_mac, g_mac, ETH_ALEN); 251 xsk->src_mac[5] += ((j * 2) + 0); 252 xsk->dst_mac[5] += ((j * 2) + 1); 253 } 254 255 ifobj->xsk->umem->num_frames = DEFAULT_UMEM_BUFFERS; 256 ifobj->xsk->umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE; 257 } 258 259 if (ifobj_tx->hw_ring_size_supp) 260 hw_ring_size_reset(ifobj_tx); 261 262 test->ifobj_tx = ifobj_tx; 263 test->ifobj_rx = ifobj_rx; 264 test->current_step = 0; 265 test->total_steps = 1; 266 test->nb_sockets = 1; 267 test->fail = false; 268 test->set_ring = false; 269 test->adjust_tail = false; 270 test->adjust_tail_support = false; 271 test->mtu = MAX_ETH_PKT_SIZE; 272 test->xdp_prog_rx = ifobj_rx->xdp_progs->progs.xsk_def_prog; 273 test->xskmap_rx = ifobj_rx->xdp_progs->maps.xsk; 274 test->xdp_prog_tx = ifobj_tx->xdp_progs->progs.xsk_def_prog; 275 test->xskmap_tx = ifobj_tx->xdp_progs->maps.xsk; 276 } 277 278 void test_init(struct test_spec *test, struct ifobject *ifobj_tx, 279 struct ifobject *ifobj_rx, enum test_mode mode, 280 const struct test_spec *test_to_run) 281 { 282 struct pkt_stream *tx_pkt_stream; 283 struct pkt_stream *rx_pkt_stream; 284 u32 i; 285 286 tx_pkt_stream = test->tx_pkt_stream_default; 287 rx_pkt_stream = test->rx_pkt_stream_default; 288 memset(test, 0, sizeof(*test)); 289 test->tx_pkt_stream_default = tx_pkt_stream; 290 test->rx_pkt_stream_default = rx_pkt_stream; 291 292 for (i = 0; i < MAX_INTERFACES; i++) { 293 struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx; 294 295 ifobj->bind_flags = XDP_USE_NEED_WAKEUP; 296 if (mode == TEST_MODE_ZC) 297 ifobj->bind_flags |= XDP_ZEROCOPY; 298 else 299 ifobj->bind_flags |= XDP_COPY; 300 } 301 302 memcpy(test->name, test_to_run->name, MAX_TEST_NAME_SIZE); 303 test->test_func = test_to_run->test_func; 304 test->mode = mode; 305 __test_spec_init(test, ifobj_tx, ifobj_rx); 306 } 307 308 static void test_spec_reset(struct test_spec *test) 309 { 310 __test_spec_init(test, test->ifobj_tx, test->ifobj_rx); 311 } 312 313 static void test_spec_set_unaligned(struct test_spec *test) 314 { 315 test->ifobj_tx->xsk->umem->unaligned_mode = true; 316 test->ifobj_rx->xsk->umem->unaligned_mode = true; 317 } 318 319 static void test_spec_set_frame_size(struct test_spec *test, u32 size) 320 { 321 test->ifobj_tx->xsk->umem->frame_size = size; 322 test->ifobj_rx->xsk->umem->frame_size = size; 323 } 324 325 static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx, 326 struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx, 327 struct bpf_map *xskmap_tx) 328 { 329 test->xdp_prog_rx = xdp_prog_rx; 330 test->xdp_prog_tx = xdp_prog_tx; 331 test->xskmap_rx = xskmap_rx; 332 test->xskmap_tx = xskmap_tx; 333 } 334 335 static int test_spec_set_mtu(struct test_spec *test, int mtu) 336 { 337 int err; 338 339 if (test->ifobj_rx->mtu != mtu) { 340 err = xsk_set_mtu(test->ifobj_rx->ifindex, mtu); 341 if (err) 342 return err; 343 test->ifobj_rx->mtu = mtu; 344 } 345 if (test->ifobj_tx->mtu != mtu) { 346 err = xsk_set_mtu(test->ifobj_tx->ifindex, mtu); 347 if (err) 348 return err; 349 test->ifobj_tx->mtu = mtu; 350 } 351 352 return 0; 353 } 354 355 void pkt_stream_reset(struct pkt_stream *pkt_stream) 356 { 357 if (pkt_stream) { 358 pkt_stream->current_pkt_nb = 0; 359 pkt_stream->nb_rx_pkts = 0; 360 } 361 } 362 363 static struct pkt *pkt_stream_get_next_tx_pkt(struct pkt_stream *pkt_stream) 364 { 365 if (pkt_stream->current_pkt_nb >= pkt_stream->nb_pkts) 366 return NULL; 367 368 return &pkt_stream->pkts[pkt_stream->current_pkt_nb++]; 369 } 370 371 static struct pkt *pkt_stream_get_next_rx_pkt(struct pkt_stream *pkt_stream, u32 *pkts_sent) 372 { 373 while (pkt_stream->current_pkt_nb < pkt_stream->nb_pkts) { 374 (*pkts_sent)++; 375 if (pkt_stream->pkts[pkt_stream->current_pkt_nb].valid) 376 return &pkt_stream->pkts[pkt_stream->current_pkt_nb++]; 377 pkt_stream->current_pkt_nb++; 378 } 379 return NULL; 380 } 381 382 void pkt_stream_delete(struct pkt_stream *pkt_stream) 383 { 384 free(pkt_stream->pkts); 385 free(pkt_stream); 386 } 387 388 void pkt_stream_restore_default(struct test_spec *test) 389 { 390 struct pkt_stream *tx_pkt_stream = test->ifobj_tx->xsk->pkt_stream; 391 struct pkt_stream *rx_pkt_stream = test->ifobj_rx->xsk->pkt_stream; 392 393 if (tx_pkt_stream != test->tx_pkt_stream_default) { 394 pkt_stream_delete(test->ifobj_tx->xsk->pkt_stream); 395 test->ifobj_tx->xsk->pkt_stream = test->tx_pkt_stream_default; 396 } 397 398 if (rx_pkt_stream != test->rx_pkt_stream_default) { 399 pkt_stream_delete(test->ifobj_rx->xsk->pkt_stream); 400 test->ifobj_rx->xsk->pkt_stream = test->rx_pkt_stream_default; 401 } 402 } 403 404 static struct pkt_stream *__pkt_stream_alloc(u32 nb_pkts) 405 { 406 struct pkt_stream *pkt_stream; 407 408 pkt_stream = calloc(1, sizeof(*pkt_stream)); 409 if (!pkt_stream) 410 return NULL; 411 412 pkt_stream->pkts = calloc(nb_pkts, sizeof(*pkt_stream->pkts)); 413 if (!pkt_stream->pkts) { 414 free(pkt_stream); 415 return NULL; 416 } 417 418 pkt_stream->nb_pkts = nb_pkts; 419 return pkt_stream; 420 } 421 422 static u32 pkt_nb_frags(u32 frame_size, struct pkt_stream *pkt_stream, struct pkt *pkt) 423 { 424 u32 nb_frags = 1, next_frag; 425 426 if (!pkt) 427 return 1; 428 429 if (!pkt_stream->verbatim) { 430 if (!pkt->valid || !pkt->len) 431 return 1; 432 return ceil_u32(pkt->len, frame_size); 433 } 434 435 /* Search for the end of the packet in verbatim mode */ 436 if (!pkt_continues(pkt->options) || !pkt->valid) 437 return nb_frags; 438 439 next_frag = pkt_stream->current_pkt_nb; 440 pkt++; 441 while (next_frag++ < pkt_stream->nb_pkts) { 442 nb_frags++; 443 if (!pkt_continues(pkt->options) || !pkt->valid) 444 break; 445 pkt++; 446 } 447 return nb_frags; 448 } 449 450 static bool set_pkt_valid(int offset, u32 len) 451 { 452 return len <= MAX_ETH_JUMBO_SIZE; 453 } 454 455 static void pkt_set(struct pkt_stream *pkt_stream, struct pkt *pkt, int offset, u32 len) 456 { 457 pkt->offset = offset; 458 pkt->len = len; 459 pkt->valid = set_pkt_valid(offset, len); 460 } 461 462 static void pkt_stream_pkt_set(struct pkt_stream *pkt_stream, struct pkt *pkt, int offset, u32 len) 463 { 464 bool prev_pkt_valid = pkt->valid; 465 466 pkt_set(pkt_stream, pkt, offset, len); 467 pkt_stream->nb_valid_entries += pkt->valid - prev_pkt_valid; 468 } 469 470 static u32 pkt_get_buffer_len(struct xsk_umem_info *umem, u32 len) 471 { 472 return ceil_u32(len, umem->frame_size) * umem->frame_size; 473 } 474 475 static struct pkt_stream *__pkt_stream_generate(u32 nb_pkts, u32 pkt_len, u32 nb_start, u32 nb_off) 476 { 477 struct pkt_stream *pkt_stream; 478 u32 i; 479 480 pkt_stream = __pkt_stream_alloc(nb_pkts); 481 if (!pkt_stream) 482 return NULL; 483 484 pkt_stream->nb_pkts = nb_pkts; 485 pkt_stream->max_pkt_len = pkt_len; 486 for (i = 0; i < nb_pkts; i++) { 487 struct pkt *pkt = &pkt_stream->pkts[i]; 488 489 pkt_stream_pkt_set(pkt_stream, pkt, 0, pkt_len); 490 pkt->pkt_nb = nb_start + i * nb_off; 491 } 492 493 return pkt_stream; 494 } 495 496 struct pkt_stream *pkt_stream_generate(u32 nb_pkts, u32 pkt_len) 497 { 498 return __pkt_stream_generate(nb_pkts, pkt_len, 0, 1); 499 } 500 501 static struct pkt_stream *pkt_stream_clone(struct pkt_stream *pkt_stream) 502 { 503 return pkt_stream_generate(pkt_stream->nb_pkts, pkt_stream->pkts[0].len); 504 } 505 506 static int pkt_stream_replace_ifobject(struct ifobject *ifobj, u32 nb_pkts, u32 pkt_len) 507 { 508 ifobj->xsk->pkt_stream = pkt_stream_generate(nb_pkts, pkt_len); 509 510 if (!ifobj->xsk->pkt_stream) 511 return -ENOMEM; 512 513 return 0; 514 } 515 516 static int pkt_stream_replace(struct test_spec *test, u32 nb_pkts, u32 pkt_len) 517 { 518 int ret; 519 520 ret = pkt_stream_replace_ifobject(test->ifobj_tx, nb_pkts, pkt_len); 521 if (ret) 522 return ret; 523 524 return pkt_stream_replace_ifobject(test->ifobj_rx, nb_pkts, pkt_len); 525 } 526 527 static int __pkt_stream_replace_half(struct ifobject *ifobj, u32 pkt_len, 528 int offset) 529 { 530 struct pkt_stream *pkt_stream; 531 u32 i; 532 533 pkt_stream = pkt_stream_clone(ifobj->xsk->pkt_stream); 534 if (!pkt_stream) 535 return -ENOMEM; 536 537 for (i = 1; i < ifobj->xsk->pkt_stream->nb_pkts; i += 2) 538 pkt_stream_pkt_set(pkt_stream, &pkt_stream->pkts[i], offset, pkt_len); 539 540 ifobj->xsk->pkt_stream = pkt_stream; 541 542 return 0; 543 } 544 545 static int pkt_stream_replace_half(struct test_spec *test, u32 pkt_len, int offset) 546 { 547 int ret = __pkt_stream_replace_half(test->ifobj_tx, pkt_len, offset); 548 549 if (ret) 550 return ret; 551 552 return __pkt_stream_replace_half(test->ifobj_rx, pkt_len, offset); 553 } 554 555 static int pkt_stream_receive_half(struct test_spec *test) 556 { 557 struct pkt_stream *pkt_stream = test->ifobj_tx->xsk->pkt_stream; 558 u32 i; 559 560 if (test->ifobj_rx->xsk->pkt_stream != test->rx_pkt_stream_default) 561 /* Packet stream has already been replaced so we have to release this one. 562 * The newly created one will be freed by the restore_default() at the 563 * end of the test 564 */ 565 pkt_stream_delete(test->ifobj_rx->xsk->pkt_stream); 566 567 test->ifobj_rx->xsk->pkt_stream = pkt_stream_generate(pkt_stream->nb_pkts, 568 pkt_stream->pkts[0].len); 569 if (!test->ifobj_rx->xsk->pkt_stream) 570 return -ENOMEM; 571 572 pkt_stream = test->ifobj_rx->xsk->pkt_stream; 573 for (i = 1; i < pkt_stream->nb_pkts; i += 2) 574 pkt_stream->pkts[i].valid = false; 575 576 pkt_stream->nb_valid_entries /= 2; 577 578 return 0; 579 } 580 581 static int pkt_stream_even_odd_sequence(struct test_spec *test) 582 { 583 struct pkt_stream *pkt_stream; 584 u32 i; 585 586 for (i = 0; i < test->nb_sockets; i++) { 587 pkt_stream = test->ifobj_tx->xsk_arr[i].pkt_stream; 588 pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2, 589 pkt_stream->pkts[0].len, i, 2); 590 if (!pkt_stream) 591 return -ENOMEM; 592 test->ifobj_tx->xsk_arr[i].pkt_stream = pkt_stream; 593 594 pkt_stream = test->ifobj_rx->xsk_arr[i].pkt_stream; 595 pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2, 596 pkt_stream->pkts[0].len, i, 2); 597 if (!pkt_stream) 598 return -ENOMEM; 599 test->ifobj_rx->xsk_arr[i].pkt_stream = pkt_stream; 600 } 601 602 return 0; 603 } 604 605 static void release_even_odd_sequence(struct test_spec *test) 606 { 607 struct pkt_stream *later_free_tx = test->ifobj_tx->xsk->pkt_stream; 608 struct pkt_stream *later_free_rx = test->ifobj_rx->xsk->pkt_stream; 609 int i; 610 611 for (i = 0; i < test->nb_sockets; i++) { 612 /* later_free_{rx/tx} will be freed by restore_default() */ 613 if (test->ifobj_tx->xsk_arr[i].pkt_stream != later_free_tx) 614 pkt_stream_delete(test->ifobj_tx->xsk_arr[i].pkt_stream); 615 if (test->ifobj_rx->xsk_arr[i].pkt_stream != later_free_rx) 616 pkt_stream_delete(test->ifobj_rx->xsk_arr[i].pkt_stream); 617 } 618 619 } 620 621 static u64 pkt_get_addr(struct pkt *pkt, struct xsk_umem_info *umem) 622 { 623 if (!pkt->valid) 624 return pkt->offset; 625 return pkt->offset + umem_alloc_buffer(umem); 626 } 627 628 static void pkt_stream_cancel(struct pkt_stream *pkt_stream) 629 { 630 pkt_stream->current_pkt_nb--; 631 } 632 633 static void pkt_generate(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, u64 addr, u32 len, 634 u32 pkt_nb, u32 bytes_written) 635 { 636 void *data = xsk_umem__get_data(umem->buffer, addr); 637 638 if (len < MIN_PKT_SIZE) 639 return; 640 641 if (!bytes_written) { 642 gen_eth_hdr(xsk, data); 643 644 len -= PKT_HDR_SIZE; 645 data += PKT_HDR_SIZE; 646 } else { 647 bytes_written -= PKT_HDR_SIZE; 648 } 649 650 write_payload(data, pkt_nb, bytes_written, len); 651 } 652 653 static struct pkt_stream *__pkt_stream_generate_custom(struct ifobject *ifobj, struct pkt *frames, 654 u32 nb_frames, bool verbatim) 655 { 656 u32 i, len = 0, pkt_nb = 0, payload = 0; 657 struct pkt_stream *pkt_stream; 658 659 pkt_stream = __pkt_stream_alloc(nb_frames); 660 if (!pkt_stream) 661 return NULL; 662 663 for (i = 0; i < nb_frames; i++) { 664 struct pkt *pkt = &pkt_stream->pkts[pkt_nb]; 665 struct pkt *frame = &frames[i]; 666 667 pkt->offset = frame->offset; 668 if (verbatim) { 669 *pkt = *frame; 670 pkt->pkt_nb = payload; 671 if (!frame->valid || !pkt_continues(frame->options)) 672 payload++; 673 } else { 674 if (frame->valid) 675 len += frame->len; 676 if (frame->valid && pkt_continues(frame->options)) 677 continue; 678 679 pkt->pkt_nb = pkt_nb; 680 pkt->len = len; 681 pkt->valid = frame->valid; 682 pkt->options = 0; 683 684 len = 0; 685 } 686 687 print_verbose("offset: %d len: %u valid: %u options: %u pkt_nb: %u\n", 688 pkt->offset, pkt->len, pkt->valid, pkt->options, pkt->pkt_nb); 689 690 if (pkt->valid && pkt->len > pkt_stream->max_pkt_len) 691 pkt_stream->max_pkt_len = pkt->len; 692 693 if (pkt->valid) 694 pkt_stream->nb_valid_entries++; 695 696 pkt_nb++; 697 } 698 699 pkt_stream->nb_pkts = pkt_nb; 700 pkt_stream->verbatim = verbatim; 701 return pkt_stream; 702 } 703 704 static int pkt_stream_generate_custom(struct test_spec *test, struct pkt *pkts, u32 nb_pkts) 705 { 706 struct pkt_stream *pkt_stream; 707 708 pkt_stream = __pkt_stream_generate_custom(test->ifobj_tx, pkts, nb_pkts, true); 709 if (!pkt_stream) 710 return -ENOMEM; 711 test->ifobj_tx->xsk->pkt_stream = pkt_stream; 712 713 pkt_stream = __pkt_stream_generate_custom(test->ifobj_rx, pkts, nb_pkts, false); 714 if (!pkt_stream) 715 return -ENOMEM; 716 test->ifobj_rx->xsk->pkt_stream = pkt_stream; 717 718 return 0; 719 } 720 721 static void pkt_print_data(u32 *data, u32 cnt) 722 { 723 u32 i; 724 725 for (i = 0; i < cnt; i++) { 726 u32 seqnum, pkt_nb; 727 728 seqnum = ntohl(*data) & 0xffff; 729 pkt_nb = ntohl(*data) >> 16; 730 ksft_print_msg("%u:%u ", pkt_nb, seqnum); 731 data++; 732 } 733 } 734 735 static void pkt_dump(void *pkt, u32 len, bool eth_header) 736 { 737 struct ethhdr *ethhdr = pkt; 738 u32 i, *data; 739 740 if (eth_header) { 741 /*extract L2 frame */ 742 ksft_print_msg("DEBUG>> L2: dst mac: "); 743 for (i = 0; i < ETH_ALEN; i++) 744 ksft_print_msg("%02X", ethhdr->h_dest[i]); 745 746 ksft_print_msg("\nDEBUG>> L2: src mac: "); 747 for (i = 0; i < ETH_ALEN; i++) 748 ksft_print_msg("%02X", ethhdr->h_source[i]); 749 750 data = pkt + PKT_HDR_SIZE; 751 } else { 752 data = pkt; 753 } 754 755 /*extract L5 frame */ 756 ksft_print_msg("\nDEBUG>> L5: seqnum: "); 757 pkt_print_data(data, PKT_DUMP_NB_TO_PRINT); 758 ksft_print_msg("...."); 759 if (len > PKT_DUMP_NB_TO_PRINT * sizeof(u32)) { 760 ksft_print_msg("\n.... "); 761 pkt_print_data(data + len / sizeof(u32) - PKT_DUMP_NB_TO_PRINT, 762 PKT_DUMP_NB_TO_PRINT); 763 } 764 ksft_print_msg("\n---------------------------------------\n"); 765 } 766 767 static bool is_offset_correct(struct xsk_umem_info *umem, struct pkt *pkt, u64 addr) 768 { 769 u32 headroom = umem->unaligned_mode ? 0 : umem->frame_headroom; 770 u32 offset = addr % umem->frame_size, expected_offset; 771 int pkt_offset = pkt->valid ? pkt->offset : 0; 772 773 if (!umem->unaligned_mode) 774 pkt_offset = 0; 775 776 expected_offset = (pkt_offset + headroom + XDP_PACKET_HEADROOM) % umem->frame_size; 777 778 if (offset == expected_offset) 779 return true; 780 781 ksft_print_msg("[%s] expected [%u], got [%u]\n", __func__, expected_offset, offset); 782 return false; 783 } 784 785 static bool is_metadata_correct(struct pkt *pkt, void *buffer, u64 addr) 786 { 787 void *data = xsk_umem__get_data(buffer, addr); 788 struct xdp_info *meta = data - sizeof(struct xdp_info); 789 790 if (meta->count != pkt->pkt_nb) { 791 ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%llu]\n", 792 __func__, pkt->pkt_nb, 793 (unsigned long long)meta->count); 794 return false; 795 } 796 797 return true; 798 } 799 800 static int is_adjust_tail_supported(struct xsk_xdp_progs *skel_rx, bool *supported) 801 { 802 struct bpf_map *data_map; 803 int adjust_value = 0; 804 int key = 0; 805 int ret; 806 807 data_map = bpf_object__find_map_by_name(skel_rx->obj, "xsk_xdp_.bss"); 808 if (!data_map || !bpf_map__is_internal(data_map)) { 809 ksft_print_msg("Error: could not find bss section of XDP program\n"); 810 return -EINVAL; 811 } 812 813 ret = bpf_map_lookup_elem(bpf_map__fd(data_map), &key, &adjust_value); 814 if (ret) { 815 ksft_print_msg("Error: bpf_map_lookup_elem failed with error %d\n", ret); 816 return ret; 817 } 818 819 /* Set the 'adjust_value' variable to -EOPNOTSUPP in the XDP program if the adjust_tail 820 * helper is not supported. Skip the adjust_tail test case in this scenario. 821 */ 822 *supported = adjust_value != -EOPNOTSUPP; 823 824 return 0; 825 } 826 827 static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u32 expected_pkt_nb, 828 u32 bytes_processed) 829 { 830 u32 seqnum, pkt_nb, *pkt_data, words_to_end, expected_seqnum; 831 void *data = xsk_umem__get_data(umem->buffer, addr); 832 u64 umem_sz = umem_size(umem); 833 834 addr -= umem->base_addr; 835 836 if (addr >= umem_sz || addr + len > umem_sz) { 837 ksft_print_msg("Frag invalid addr: %llx len: %u\n", 838 (unsigned long long)addr, len); 839 return false; 840 } 841 if (!umem->unaligned_mode && addr % umem->frame_size + len > umem->frame_size) { 842 ksft_print_msg("Frag crosses frame boundary addr: %llx len: %u\n", 843 (unsigned long long)addr, len); 844 return false; 845 } 846 847 pkt_data = data; 848 if (!bytes_processed) { 849 pkt_data += PKT_HDR_SIZE / sizeof(*pkt_data); 850 len -= PKT_HDR_SIZE; 851 } else { 852 bytes_processed -= PKT_HDR_SIZE; 853 } 854 855 expected_seqnum = bytes_processed / sizeof(*pkt_data); 856 seqnum = ntohl(*pkt_data) & 0xffff; 857 pkt_nb = ntohl(*pkt_data) >> 16; 858 859 if (expected_pkt_nb != pkt_nb) { 860 ksft_print_msg("[%s] expected pkt_nb [%u], got pkt_nb [%u]\n", 861 __func__, expected_pkt_nb, pkt_nb); 862 goto error; 863 } 864 if (expected_seqnum != seqnum) { 865 ksft_print_msg("[%s] expected seqnum at start [%u], got seqnum [%u]\n", 866 __func__, expected_seqnum, seqnum); 867 goto error; 868 } 869 870 words_to_end = len / sizeof(*pkt_data) - 1; 871 pkt_data += words_to_end; 872 seqnum = ntohl(*pkt_data) & 0xffff; 873 expected_seqnum += words_to_end; 874 if (expected_seqnum != seqnum) { 875 ksft_print_msg("[%s] expected seqnum at end [%u], got seqnum [%u]\n", 876 __func__, expected_seqnum, seqnum); 877 goto error; 878 } 879 880 return true; 881 882 error: 883 pkt_dump(data, len, !bytes_processed); 884 return false; 885 } 886 887 static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len) 888 { 889 if (pkt->len != len) { 890 ksft_print_msg("[%s] expected packet length [%d], got length [%d]\n", 891 __func__, pkt->len, len); 892 pkt_dump(xsk_umem__get_data(buffer, addr), len, true); 893 return false; 894 } 895 896 return true; 897 } 898 899 static u32 load_value(u32 *counter) 900 { 901 return __atomic_load_n(counter, __ATOMIC_ACQUIRE); 902 } 903 904 static bool kick_tx_with_check(struct xsk_socket_info *xsk, int *ret) 905 { 906 u32 max_budget = MAX_TX_BUDGET_DEFAULT; 907 u32 cons, ready_to_send; 908 int delta; 909 910 cons = load_value(xsk->tx.consumer); 911 ready_to_send = load_value(xsk->tx.producer) - cons; 912 *ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); 913 914 delta = load_value(xsk->tx.consumer) - cons; 915 /* By default, xsk should consume exact @max_budget descs at one 916 * send in this case where hitting the max budget limit in while 917 * loop is triggered in __xsk_generic_xmit(). Please make sure that 918 * the number of descs to be sent is larger than @max_budget, or 919 * else the tx.consumer will be updated in xskq_cons_peek_desc() 920 * in time which hides the issue we try to verify. 921 */ 922 if (ready_to_send > max_budget && delta != max_budget) 923 return false; 924 925 return true; 926 } 927 928 int kick_tx(struct xsk_socket_info *xsk) 929 { 930 int ret; 931 932 if (xsk->check_consumer) { 933 if (!kick_tx_with_check(xsk, &ret)) 934 return TEST_FAILURE; 935 } else { 936 ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); 937 } 938 if (ret >= 0) 939 return TEST_PASS; 940 if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) { 941 usleep(100); 942 return TEST_PASS; 943 } 944 return TEST_FAILURE; 945 } 946 947 int kick_rx(struct xsk_socket_info *xsk) 948 { 949 int ret; 950 951 ret = recvfrom(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, NULL); 952 if (ret < 0) 953 return TEST_FAILURE; 954 955 return TEST_PASS; 956 } 957 958 static int complete_pkts(struct xsk_socket_info *xsk, int batch_size) 959 { 960 unsigned int rcvd; 961 u32 idx; 962 int ret; 963 964 if (xsk_ring_prod__needs_wakeup(&xsk->tx)) { 965 ret = kick_tx(xsk); 966 if (ret) 967 return TEST_FAILURE; 968 } 969 970 rcvd = xsk_ring_cons__peek(&xsk->umem->cq, batch_size, &idx); 971 if (rcvd) { 972 if (rcvd > xsk->outstanding_tx) { 973 u64 addr = *xsk_ring_cons__comp_addr(&xsk->umem->cq, idx + rcvd - 1); 974 975 ksft_print_msg("[%s] Too many packets completed\n", __func__); 976 ksft_print_msg("Last completion address: %llx\n", 977 (unsigned long long)addr); 978 return TEST_FAILURE; 979 } 980 981 xsk_ring_cons__release(&xsk->umem->cq, rcvd); 982 xsk->outstanding_tx -= rcvd; 983 } 984 985 return TEST_PASS; 986 } 987 988 static int __receive_pkts(struct test_spec *test, struct xsk_socket_info *xsk) 989 { 990 u32 frags_processed = 0, nb_frags = 0, pkt_len = 0; 991 u32 idx_rx = 0, idx_fq = 0, rcvd, pkts_sent = 0; 992 struct pkt_stream *pkt_stream = xsk->pkt_stream; 993 struct ifobject *ifobj = test->ifobj_rx; 994 struct xsk_umem_info *umem = xsk->umem; 995 struct pollfd fds = { }; 996 struct pkt *pkt; 997 u64 first_addr = 0; 998 int ret; 999 1000 fds.fd = xsk_socket__fd(xsk->xsk); 1001 fds.events = POLLIN; 1002 1003 ret = kick_rx(xsk); 1004 if (ret) 1005 return TEST_FAILURE; 1006 1007 if (ifobj->use_poll) { 1008 ret = poll(&fds, 1, POLL_TMOUT); 1009 if (ret < 0) 1010 return TEST_FAILURE; 1011 1012 if (!ret) { 1013 if (!is_umem_valid(test->ifobj_tx->xsk)) 1014 return TEST_PASS; 1015 1016 ksft_print_msg("ERROR: [%s] Poll timed out\n", __func__); 1017 return TEST_CONTINUE; 1018 } 1019 1020 if (!(fds.revents & POLLIN)) 1021 return TEST_CONTINUE; 1022 } 1023 1024 rcvd = xsk_ring_cons__peek(&xsk->rx, xsk->batch_size, &idx_rx); 1025 if (!rcvd) 1026 return TEST_CONTINUE; 1027 1028 if (ifobj->use_fill_ring) { 1029 ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq); 1030 while (ret != rcvd) { 1031 if (xsk_ring_prod__needs_wakeup(&umem->fq)) { 1032 ret = poll(&fds, 1, POLL_TMOUT); 1033 if (ret < 0) 1034 return TEST_FAILURE; 1035 } 1036 ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq); 1037 } 1038 } 1039 1040 while (frags_processed < rcvd) { 1041 const struct xdp_desc *desc = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++); 1042 u64 addr = desc->addr, orig; 1043 1044 orig = xsk_umem__extract_addr(addr); 1045 addr = xsk_umem__add_offset_to_addr(addr); 1046 1047 if (!nb_frags) { 1048 pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &pkts_sent); 1049 if (!pkt) { 1050 ksft_print_msg("[%s] received too many packets addr: %lx len %u\n", 1051 __func__, addr, desc->len); 1052 return TEST_FAILURE; 1053 } 1054 } 1055 1056 print_verbose("Rx: addr: %lx len: %u options: %u pkt_nb: %u valid: %u\n", 1057 addr, desc->len, desc->options, pkt->pkt_nb, pkt->valid); 1058 1059 if (!is_frag_valid(umem, addr, desc->len, pkt->pkt_nb, pkt_len) || 1060 !is_offset_correct(umem, pkt, addr) || (ifobj->use_metadata && 1061 !is_metadata_correct(pkt, umem->buffer, addr))) 1062 return TEST_FAILURE; 1063 1064 if (!nb_frags++) 1065 first_addr = addr; 1066 frags_processed++; 1067 pkt_len += desc->len; 1068 if (ifobj->use_fill_ring) 1069 *xsk_ring_prod__fill_addr(&umem->fq, idx_fq++) = orig; 1070 1071 if (pkt_continues(desc->options)) 1072 continue; 1073 1074 /* The complete packet has been received */ 1075 if (!is_pkt_valid(pkt, umem->buffer, first_addr, pkt_len) || 1076 !is_offset_correct(umem, pkt, addr)) 1077 return TEST_FAILURE; 1078 1079 pkt_stream->nb_rx_pkts++; 1080 nb_frags = 0; 1081 pkt_len = 0; 1082 } 1083 1084 if (nb_frags) { 1085 /* In the middle of a packet. Start over from beginning of packet. */ 1086 idx_rx -= nb_frags; 1087 xsk_ring_cons__cancel(&xsk->rx, nb_frags); 1088 if (ifobj->use_fill_ring) { 1089 idx_fq -= nb_frags; 1090 xsk_ring_prod__cancel(&umem->fq, nb_frags); 1091 } 1092 frags_processed -= nb_frags; 1093 pkt_stream_cancel(pkt_stream); 1094 pkts_sent--; 1095 } 1096 1097 if (ifobj->use_fill_ring) 1098 xsk_ring_prod__submit(&umem->fq, frags_processed); 1099 if (ifobj->release_rx) 1100 xsk_ring_cons__release(&xsk->rx, frags_processed); 1101 1102 pthread_mutex_lock(&pacing_mutex); 1103 pkts_in_flight -= pkts_sent; 1104 pthread_mutex_unlock(&pacing_mutex); 1105 pkts_sent = 0; 1106 1107 return TEST_CONTINUE; 1108 } 1109 1110 bool all_packets_received(struct test_spec *test, struct xsk_socket_info *xsk, u32 sock_num, 1111 unsigned long *bitmap) 1112 { 1113 struct pkt_stream *pkt_stream = xsk->pkt_stream; 1114 1115 if (!pkt_stream) { 1116 __set_bit(sock_num, bitmap); 1117 return false; 1118 } 1119 1120 if (pkt_stream->nb_rx_pkts == pkt_stream->nb_valid_entries) { 1121 __set_bit(sock_num, bitmap); 1122 if (bitmap_full(bitmap, test->nb_sockets)) 1123 return true; 1124 } 1125 1126 return false; 1127 } 1128 1129 static int receive_pkts(struct test_spec *test) 1130 { 1131 struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0}; 1132 DECLARE_BITMAP(bitmap, test->nb_sockets); 1133 struct xsk_socket_info *xsk; 1134 u32 sock_num = 0; 1135 int res, ret; 1136 1137 bitmap_zero(bitmap, test->nb_sockets); 1138 1139 ret = gettimeofday(&tv_now, NULL); 1140 if (ret) 1141 return TEST_FAILURE; 1142 1143 timeradd(&tv_now, &tv_timeout, &tv_end); 1144 1145 while (1) { 1146 xsk = &test->ifobj_rx->xsk_arr[sock_num]; 1147 1148 if ((all_packets_received(test, xsk, sock_num, bitmap))) 1149 break; 1150 1151 res = __receive_pkts(test, xsk); 1152 if (!(res == TEST_PASS || res == TEST_CONTINUE)) 1153 return res; 1154 1155 ret = gettimeofday(&tv_now, NULL); 1156 if (ret) 1157 return TEST_FAILURE; 1158 1159 if (timercmp(&tv_now, &tv_end, >)) { 1160 ksft_print_msg("ERROR: [%s] Receive loop timed out\n", __func__); 1161 return TEST_FAILURE; 1162 } 1163 sock_num = (sock_num + 1) % test->nb_sockets; 1164 } 1165 1166 return TEST_PASS; 1167 } 1168 1169 static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, bool timeout) 1170 { 1171 u32 i, idx = 0, valid_pkts = 0, valid_frags = 0, buffer_len; 1172 struct pkt_stream *pkt_stream = xsk->pkt_stream; 1173 struct xsk_umem_info *umem = xsk->umem; 1174 bool use_poll = ifobject->use_poll; 1175 struct pollfd fds = { }; 1176 int ret; 1177 1178 buffer_len = pkt_get_buffer_len(umem, pkt_stream->max_pkt_len); 1179 /* pkts_in_flight might be negative if many invalid packets are sent */ 1180 if (pkts_in_flight >= (int)((umem_size(umem) - xsk->batch_size * buffer_len) / 1181 buffer_len)) { 1182 ret = kick_tx(xsk); 1183 if (ret) 1184 return TEST_FAILURE; 1185 return TEST_CONTINUE; 1186 } 1187 1188 fds.fd = xsk_socket__fd(xsk->xsk); 1189 fds.events = POLLOUT; 1190 1191 while (xsk_ring_prod__reserve(&xsk->tx, xsk->batch_size, &idx) < xsk->batch_size) { 1192 if (use_poll) { 1193 ret = poll(&fds, 1, POLL_TMOUT); 1194 if (timeout) { 1195 if (ret < 0) { 1196 ksft_print_msg("ERROR: [%s] Poll error %d\n", 1197 __func__, errno); 1198 return TEST_FAILURE; 1199 } 1200 if (ret == 0) 1201 return TEST_PASS; 1202 break; 1203 } 1204 if (ret <= 0) { 1205 ksft_print_msg("ERROR: [%s] Poll error %d\n", 1206 __func__, errno); 1207 return TEST_FAILURE; 1208 } 1209 } 1210 1211 complete_pkts(xsk, xsk->batch_size); 1212 } 1213 1214 for (i = 0; i < xsk->batch_size; i++) { 1215 struct pkt *pkt = pkt_stream_get_next_tx_pkt(pkt_stream); 1216 u32 nb_frags_left, nb_frags, bytes_written = 0; 1217 1218 if (!pkt) 1219 break; 1220 1221 nb_frags = pkt_nb_frags(umem->frame_size, pkt_stream, pkt); 1222 if (nb_frags > xsk->batch_size - i) { 1223 pkt_stream_cancel(pkt_stream); 1224 xsk_ring_prod__cancel(&xsk->tx, xsk->batch_size - i); 1225 break; 1226 } 1227 nb_frags_left = nb_frags; 1228 1229 while (nb_frags_left--) { 1230 struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i); 1231 1232 tx_desc->addr = pkt_get_addr(pkt, umem); 1233 if (pkt_stream->verbatim) { 1234 tx_desc->len = pkt->len; 1235 tx_desc->options = pkt->options; 1236 } else if (nb_frags_left) { 1237 tx_desc->len = umem->frame_size; 1238 tx_desc->options = XDP_PKT_CONTD; 1239 } else { 1240 tx_desc->len = pkt->len - bytes_written; 1241 tx_desc->options = 0; 1242 } 1243 if (pkt->valid) 1244 pkt_generate(xsk, umem, tx_desc->addr, tx_desc->len, pkt->pkt_nb, 1245 bytes_written); 1246 bytes_written += tx_desc->len; 1247 1248 print_verbose("Tx addr: %llx len: %u options: %u pkt_nb: %u\n", 1249 tx_desc->addr, tx_desc->len, tx_desc->options, pkt->pkt_nb); 1250 1251 if (nb_frags_left) { 1252 i++; 1253 if (pkt_stream->verbatim) 1254 pkt = pkt_stream_get_next_tx_pkt(pkt_stream); 1255 } 1256 } 1257 1258 if (pkt && pkt->valid) { 1259 valid_pkts++; 1260 valid_frags += nb_frags; 1261 } 1262 } 1263 1264 pthread_mutex_lock(&pacing_mutex); 1265 pkts_in_flight += valid_pkts; 1266 pthread_mutex_unlock(&pacing_mutex); 1267 1268 xsk_ring_prod__submit(&xsk->tx, i); 1269 xsk->outstanding_tx += valid_frags; 1270 1271 if (use_poll) { 1272 ret = poll(&fds, 1, POLL_TMOUT); 1273 if (ret <= 0) { 1274 if (ret == 0 && timeout) 1275 return TEST_PASS; 1276 1277 ksft_print_msg("ERROR: [%s] Poll error %d\n", __func__, ret); 1278 return TEST_FAILURE; 1279 } 1280 } 1281 1282 if (!timeout) { 1283 if (complete_pkts(xsk, i)) 1284 return TEST_FAILURE; 1285 1286 usleep(10); 1287 return TEST_PASS; 1288 } 1289 1290 return TEST_CONTINUE; 1291 } 1292 1293 static int wait_for_tx_completion(struct xsk_socket_info *xsk) 1294 { 1295 struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0}; 1296 int ret; 1297 1298 ret = gettimeofday(&tv_now, NULL); 1299 if (ret) 1300 return TEST_FAILURE; 1301 timeradd(&tv_now, &tv_timeout, &tv_end); 1302 1303 while (xsk->outstanding_tx) { 1304 ret = gettimeofday(&tv_now, NULL); 1305 if (ret) 1306 return TEST_FAILURE; 1307 if (timercmp(&tv_now, &tv_end, >)) { 1308 ksft_print_msg("ERROR: [%s] Transmission loop timed out\n", __func__); 1309 return TEST_FAILURE; 1310 } 1311 1312 complete_pkts(xsk, xsk->batch_size); 1313 } 1314 1315 return TEST_PASS; 1316 } 1317 1318 bool all_packets_sent(struct test_spec *test, unsigned long *bitmap) 1319 { 1320 return bitmap_full(bitmap, test->nb_sockets); 1321 } 1322 1323 static int send_pkts(struct test_spec *test, struct ifobject *ifobject) 1324 { 1325 bool timeout = !is_umem_valid(test->ifobj_rx->xsk); 1326 DECLARE_BITMAP(bitmap, test->nb_sockets); 1327 u32 i, ret; 1328 1329 bitmap_zero(bitmap, test->nb_sockets); 1330 1331 while (!(all_packets_sent(test, bitmap))) { 1332 for (i = 0; i < test->nb_sockets; i++) { 1333 struct pkt_stream *pkt_stream; 1334 1335 pkt_stream = ifobject->xsk_arr[i].pkt_stream; 1336 if (!pkt_stream || pkt_stream->current_pkt_nb >= pkt_stream->nb_pkts) { 1337 __set_bit(i, bitmap); 1338 continue; 1339 } 1340 ret = __send_pkts(ifobject, &ifobject->xsk_arr[i], timeout); 1341 if (ret == TEST_CONTINUE && !test->fail) 1342 continue; 1343 1344 if ((ret || test->fail) && !timeout) 1345 return TEST_FAILURE; 1346 1347 if (ret == TEST_PASS && timeout) 1348 return ret; 1349 1350 ret = wait_for_tx_completion(&ifobject->xsk_arr[i]); 1351 if (ret) 1352 return TEST_FAILURE; 1353 } 1354 } 1355 1356 return TEST_PASS; 1357 } 1358 1359 static int get_xsk_stats(struct xsk_socket *xsk, struct xdp_statistics *stats) 1360 { 1361 int fd = xsk_socket__fd(xsk), err; 1362 socklen_t optlen, expected_len; 1363 1364 optlen = sizeof(*stats); 1365 err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, stats, &optlen); 1366 if (err) { 1367 ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n", 1368 __func__, -err, strerror(-err)); 1369 return TEST_FAILURE; 1370 } 1371 1372 expected_len = sizeof(struct xdp_statistics); 1373 if (optlen != expected_len) { 1374 ksft_print_msg("[%s] getsockopt optlen error. Expected: %u got: %u\n", 1375 __func__, expected_len, optlen); 1376 return TEST_FAILURE; 1377 } 1378 1379 return TEST_PASS; 1380 } 1381 1382 static int validate_rx_dropped(struct ifobject *ifobject) 1383 { 1384 struct xsk_socket *xsk = ifobject->xsk->xsk; 1385 struct xdp_statistics stats; 1386 int err; 1387 1388 err = kick_rx(ifobject->xsk); 1389 if (err) 1390 return TEST_FAILURE; 1391 1392 err = get_xsk_stats(xsk, &stats); 1393 if (err) 1394 return TEST_FAILURE; 1395 1396 /* The receiver calls getsockopt after receiving the last (valid) 1397 * packet which is not the final packet sent in this test (valid and 1398 * invalid packets are sent in alternating fashion with the final 1399 * packet being invalid). Since the last packet may or may not have 1400 * been dropped already, both outcomes must be allowed. 1401 */ 1402 if (stats.rx_dropped == ifobject->xsk->pkt_stream->nb_pkts / 2 || 1403 stats.rx_dropped == ifobject->xsk->pkt_stream->nb_pkts / 2 - 1) 1404 return TEST_PASS; 1405 1406 return TEST_FAILURE; 1407 } 1408 1409 static int validate_rx_full(struct ifobject *ifobject) 1410 { 1411 struct xsk_socket *xsk = ifobject->xsk->xsk; 1412 struct xdp_statistics stats; 1413 int err; 1414 1415 usleep(1000); 1416 err = kick_rx(ifobject->xsk); 1417 if (err) 1418 return TEST_FAILURE; 1419 1420 err = get_xsk_stats(xsk, &stats); 1421 if (err) 1422 return TEST_FAILURE; 1423 1424 if (stats.rx_ring_full) 1425 return TEST_PASS; 1426 1427 return TEST_FAILURE; 1428 } 1429 1430 static int validate_fill_empty(struct ifobject *ifobject) 1431 { 1432 struct xsk_socket *xsk = ifobject->xsk->xsk; 1433 struct xdp_statistics stats; 1434 int err; 1435 1436 usleep(1000); 1437 err = kick_rx(ifobject->xsk); 1438 if (err) 1439 return TEST_FAILURE; 1440 1441 err = get_xsk_stats(xsk, &stats); 1442 if (err) 1443 return TEST_FAILURE; 1444 1445 if (stats.rx_fill_ring_empty_descs) 1446 return TEST_PASS; 1447 1448 return TEST_FAILURE; 1449 } 1450 1451 static int validate_tx_invalid_descs(struct ifobject *ifobject) 1452 { 1453 struct xsk_socket *xsk = ifobject->xsk->xsk; 1454 int fd = xsk_socket__fd(xsk); 1455 struct xdp_statistics stats; 1456 socklen_t optlen; 1457 int err; 1458 1459 optlen = sizeof(stats); 1460 err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen); 1461 if (err) { 1462 ksft_print_msg("[%s] getsockopt(XDP_STATISTICS) error %u %s\n", 1463 __func__, -err, strerror(-err)); 1464 return TEST_FAILURE; 1465 } 1466 1467 if (stats.tx_invalid_descs != ifobject->xsk->pkt_stream->nb_pkts / 2) { 1468 ksft_print_msg("[%s] tx_invalid_descs incorrect. Got [%llu] expected [%u]\n", 1469 __func__, 1470 (unsigned long long)stats.tx_invalid_descs, 1471 ifobject->xsk->pkt_stream->nb_pkts); 1472 return TEST_FAILURE; 1473 } 1474 1475 return TEST_PASS; 1476 } 1477 1478 static int xsk_configure(struct test_spec *test, struct ifobject *ifobject, 1479 struct xsk_umem_info *umem, bool tx) 1480 { 1481 int i, ret; 1482 1483 for (i = 0; i < test->nb_sockets; i++) { 1484 bool shared = (ifobject->shared_umem && tx) ? true : !!i; 1485 u32 ctr = 0; 1486 1487 while (ctr++ < SOCK_RECONF_CTR) { 1488 ret = xsk_configure_socket(&ifobject->xsk_arr[i], umem, 1489 ifobject, shared); 1490 if (!ret) 1491 break; 1492 1493 /* Retry if it fails as xsk_socket__create() is asynchronous */ 1494 if (ctr >= SOCK_RECONF_CTR) 1495 return ret; 1496 usleep(USLEEP_MAX); 1497 } 1498 if (ifobject->busy_poll) { 1499 ret = enable_busy_poll(&ifobject->xsk_arr[i]); 1500 if (ret) 1501 return ret; 1502 } 1503 } 1504 1505 return 0; 1506 } 1507 1508 static int thread_common_ops_tx(struct test_spec *test, struct ifobject *ifobject) 1509 { 1510 struct xsk_umem_info *umem_rx, *umem_tx; 1511 int ret; 1512 1513 if (!test->ifobj_rx || !test->ifobj_rx->xsk_arr[0].umem->umem) { 1514 ksft_print_msg("Error: RX UMEM is not initialized before shared-UMEM TX setup\n"); 1515 return -EINVAL; 1516 } 1517 1518 umem_rx = test->ifobj_rx->xsk_arr[0].umem; 1519 umem_tx = ifobject->xsk_arr[0].umem_real; 1520 memcpy(umem_tx, umem_rx, sizeof(*umem_tx)); 1521 umem_tx->base_addr = 0; 1522 umem_tx->next_buffer = 0; 1523 1524 ret = xsk_configure(test, ifobject, umem_tx, true); 1525 if (ret) 1526 return ret; 1527 ifobject->xsk = &ifobject->xsk_arr[0]; 1528 ifobject->xskmap = test->ifobj_rx->xskmap; 1529 1530 return 0; 1531 } 1532 1533 static int xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_stream *pkt_stream, 1534 bool fill_up) 1535 { 1536 u32 rx_frame_size = umem->frame_size - XDP_PACKET_HEADROOM; 1537 u32 idx = 0, filled = 0, buffers_to_fill, nb_pkts; 1538 int ret; 1539 1540 if (umem->num_frames < XSK_RING_PROD__DEFAULT_NUM_DESCS) 1541 buffers_to_fill = umem->num_frames; 1542 else 1543 buffers_to_fill = umem->fill_size; 1544 1545 ret = xsk_ring_prod__reserve(&umem->fq, buffers_to_fill, &idx); 1546 if (ret != buffers_to_fill) 1547 return -ENOSPC; 1548 1549 while (filled < buffers_to_fill) { 1550 struct pkt *pkt = pkt_stream_get_next_rx_pkt(pkt_stream, &nb_pkts); 1551 u64 addr; 1552 u32 i; 1553 1554 for (i = 0; i < pkt_nb_frags(rx_frame_size, pkt_stream, pkt); i++) { 1555 if (!pkt) { 1556 if (!fill_up) 1557 break; 1558 addr = filled * umem->frame_size + umem->base_addr; 1559 } else if (pkt->offset >= 0) { 1560 addr = pkt->offset % umem->frame_size + umem_alloc_buffer(umem); 1561 } else { 1562 addr = pkt->offset + umem_alloc_buffer(umem); 1563 } 1564 1565 *xsk_ring_prod__fill_addr(&umem->fq, idx++) = addr; 1566 if (++filled >= buffers_to_fill) 1567 break; 1568 } 1569 } 1570 xsk_ring_prod__submit(&umem->fq, filled); 1571 xsk_ring_prod__cancel(&umem->fq, buffers_to_fill - filled); 1572 1573 pkt_stream_reset(pkt_stream); 1574 umem_reset_alloc(umem); 1575 1576 return 0; 1577 } 1578 1579 static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject) 1580 { 1581 struct xsk_umem_info *umem = ifobject->xsk->umem; 1582 LIBBPF_OPTS(bpf_xdp_query_opts, opts); 1583 int mmap_flags; 1584 u64 umem_sz, mmap_sz; 1585 void *bufs; 1586 int ret; 1587 u32 i; 1588 1589 umem_sz = umem_size(umem); 1590 mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; 1591 1592 if (umem->unaligned_mode) 1593 mmap_flags |= MAP_HUGETLB | MAP_HUGE_2MB; 1594 1595 if (ifobject->shared_umem) 1596 umem_sz *= 2; 1597 1598 mmap_sz = umem->unaligned_mode ? 1599 ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE : umem_sz; 1600 1601 bufs = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); 1602 if (bufs == MAP_FAILED) 1603 return -errno; 1604 1605 umem->mmap_size = mmap_sz; 1606 1607 ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz); 1608 if (ret) 1609 return ret; 1610 1611 ret = xsk_configure(test, ifobject, umem, false); 1612 if (ret) 1613 return ret; 1614 1615 ifobject->xsk = &ifobject->xsk_arr[0]; 1616 1617 if (!ifobject->rx_on) 1618 return 0; 1619 1620 ret = xsk_populate_fill_ring(umem, ifobject->xsk->pkt_stream, 1621 ifobject->use_fill_ring); 1622 if (ret) 1623 return ret; 1624 1625 for (i = 0; i < test->nb_sockets; i++) { 1626 ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk_arr[i].xsk, i); 1627 if (ret) 1628 return ret; 1629 } 1630 1631 return 0; 1632 } 1633 1634 void *worker_testapp_validate_tx(void *arg) 1635 { 1636 struct test_spec *test = (struct test_spec *)arg; 1637 struct ifobject *ifobject = test->ifobj_tx; 1638 int err; 1639 1640 if (test->current_step == 1) { 1641 if (!ifobject->shared_umem) { 1642 if (thread_common_ops(test, ifobject)) { 1643 test->fail = true; 1644 pthread_exit(NULL); 1645 } 1646 } else { 1647 if (thread_common_ops_tx(test, ifobject)) { 1648 test->fail = true; 1649 pthread_exit(NULL); 1650 } 1651 } 1652 } 1653 1654 err = send_pkts(test, ifobject); 1655 1656 if (!err && ifobject->validation_func) 1657 err = ifobject->validation_func(ifobject); 1658 if (err) 1659 test->fail = true; 1660 1661 pthread_exit(NULL); 1662 } 1663 1664 void *worker_testapp_validate_rx(void *arg) 1665 { 1666 struct test_spec *test = (struct test_spec *)arg; 1667 struct ifobject *ifobject = test->ifobj_rx; 1668 int err; 1669 1670 if (test->current_step == 1) { 1671 err = thread_common_ops(test, ifobject); 1672 } else { 1673 xsk_clear_xskmap(ifobject->xskmap); 1674 err = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, 0); 1675 if (err) 1676 ksft_print_msg("Error: Failed to update xskmap, error %s\n", 1677 strerror(-err)); 1678 } 1679 1680 pthread_barrier_wait(&barr); 1681 1682 /* We leave only now in case of error to avoid getting stuck in the barrier */ 1683 if (err) { 1684 test->fail = true; 1685 pthread_exit(NULL); 1686 } 1687 1688 err = receive_pkts(test); 1689 1690 if (!err && ifobject->validation_func) 1691 err = ifobject->validation_func(ifobject); 1692 1693 if (err) { 1694 if (!test->adjust_tail) { 1695 test->fail = true; 1696 } else { 1697 bool supported; 1698 1699 if (is_adjust_tail_supported(ifobject->xdp_progs, &supported)) 1700 test->fail = true; 1701 else if (!supported) 1702 test->adjust_tail_support = false; 1703 else 1704 test->fail = true; 1705 } 1706 } 1707 1708 pthread_exit(NULL); 1709 } 1710 1711 static void testapp_clean_xsk_umem(struct ifobject *ifobj) 1712 { 1713 struct xsk_umem_info *umem = ifobj->xsk->umem; 1714 1715 xsk_umem__delete(umem->umem); 1716 munmap(umem->buffer, umem->mmap_size); 1717 } 1718 1719 static void handler(int signum) 1720 { 1721 pthread_exit(NULL); 1722 } 1723 1724 static bool xdp_prog_changed_rx(struct test_spec *test) 1725 { 1726 struct ifobject *ifobj = test->ifobj_rx; 1727 1728 return ifobj->xdp_prog != test->xdp_prog_rx || ifobj->mode != test->mode; 1729 } 1730 1731 static bool xdp_prog_changed_tx(struct test_spec *test) 1732 { 1733 struct ifobject *ifobj = test->ifobj_tx; 1734 1735 return ifobj->xdp_prog != test->xdp_prog_tx || ifobj->mode != test->mode; 1736 } 1737 1738 static int xsk_reattach_xdp(struct ifobject *ifobj, struct bpf_program *xdp_prog, 1739 struct bpf_map *xskmap, enum test_mode mode) 1740 { 1741 int err; 1742 1743 xsk_detach_xdp_program(ifobj->ifindex, mode_to_xdp_flags(ifobj->mode)); 1744 err = xsk_attach_xdp_program(xdp_prog, ifobj->ifindex, mode_to_xdp_flags(mode)); 1745 if (err) { 1746 ksft_print_msg("Error attaching XDP program\n"); 1747 return err; 1748 } 1749 1750 if (ifobj->mode != mode && (mode == TEST_MODE_DRV || mode == TEST_MODE_ZC)) 1751 if (!xsk_is_in_mode(ifobj->ifindex, XDP_FLAGS_DRV_MODE)) { 1752 ksft_print_msg("ERROR: XDP prog not in DRV mode\n"); 1753 return -EINVAL; 1754 } 1755 1756 ifobj->xdp_prog = xdp_prog; 1757 ifobj->xskmap = xskmap; 1758 ifobj->mode = mode; 1759 1760 return 0; 1761 } 1762 1763 static int xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_rx, 1764 struct ifobject *ifobj_tx) 1765 { 1766 int err = 0; 1767 1768 if (xdp_prog_changed_rx(test)) { 1769 err = xsk_reattach_xdp(ifobj_rx, test->xdp_prog_rx, test->xskmap_rx, test->mode); 1770 if (err) 1771 return err; 1772 } 1773 1774 if (!ifobj_tx || ifobj_tx->shared_umem) 1775 return 0; 1776 1777 if (xdp_prog_changed_tx(test)) 1778 err = xsk_reattach_xdp(ifobj_tx, test->xdp_prog_tx, test->xskmap_tx, test->mode); 1779 1780 return err; 1781 } 1782 1783 static void clean_sockets(struct test_spec *test, struct ifobject *ifobj) 1784 { 1785 u32 i; 1786 1787 if (!ifobj || !test) 1788 return; 1789 1790 for (i = 0; i < test->nb_sockets; i++) 1791 xsk_socket__delete(ifobj->xsk_arr[i].xsk); 1792 } 1793 1794 static void clean_umem(struct test_spec *test, struct ifobject *ifobj1, struct ifobject *ifobj2) 1795 { 1796 if (!ifobj1) 1797 return; 1798 1799 testapp_clean_xsk_umem(ifobj1); 1800 if (ifobj2 && !ifobj2->shared_umem) 1801 testapp_clean_xsk_umem(ifobj2); 1802 } 1803 1804 static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1, 1805 struct ifobject *ifobj2) 1806 { 1807 pthread_t t0, t1; 1808 int err; 1809 1810 if (test->mtu > MAX_ETH_PKT_SIZE) { 1811 if (test->mode == TEST_MODE_ZC && (!ifobj1->multi_buff_zc_supp || 1812 (ifobj2 && !ifobj2->multi_buff_zc_supp))) { 1813 ksft_print_msg("Multi buffer for zero-copy not supported.\n"); 1814 return TEST_SKIP; 1815 } 1816 if (test->mode != TEST_MODE_ZC && (!ifobj1->multi_buff_supp || 1817 (ifobj2 && !ifobj2->multi_buff_supp))) { 1818 ksft_print_msg("Multi buffer not supported.\n"); 1819 return TEST_SKIP; 1820 } 1821 } 1822 err = test_spec_set_mtu(test, test->mtu); 1823 if (err) { 1824 ksft_print_msg("Error, could not set mtu.\n"); 1825 return TEST_FAILURE; 1826 } 1827 1828 if (ifobj2) { 1829 if (pthread_barrier_init(&barr, NULL, 2)) 1830 return TEST_FAILURE; 1831 pkt_stream_reset(ifobj2->xsk->pkt_stream); 1832 } 1833 1834 test->current_step++; 1835 pkt_stream_reset(ifobj1->xsk->pkt_stream); 1836 pkts_in_flight = 0; 1837 1838 signal(SIGUSR1, handler); 1839 /*Spawn RX thread */ 1840 pthread_create(&t0, NULL, ifobj1->func_ptr, test); 1841 1842 if (ifobj2) { 1843 pthread_barrier_wait(&barr); 1844 if (pthread_barrier_destroy(&barr)) { 1845 pthread_kill(t0, SIGUSR1); 1846 clean_sockets(test, ifobj1); 1847 clean_umem(test, ifobj1, NULL); 1848 return TEST_FAILURE; 1849 } 1850 1851 /*Spawn TX thread */ 1852 pthread_create(&t1, NULL, ifobj2->func_ptr, test); 1853 1854 pthread_join(t1, NULL); 1855 } 1856 1857 if (!ifobj2) 1858 pthread_kill(t0, SIGUSR1); 1859 pthread_join(t0, NULL); 1860 1861 if (test->total_steps == test->current_step || test->fail) { 1862 clean_sockets(test, ifobj1); 1863 clean_sockets(test, ifobj2); 1864 clean_umem(test, ifobj1, ifobj2); 1865 } 1866 1867 if (test->fail) 1868 return TEST_FAILURE; 1869 1870 return TEST_PASS; 1871 } 1872 1873 static int testapp_validate_traffic(struct test_spec *test) 1874 { 1875 struct ifobject *ifobj_rx = test->ifobj_rx; 1876 struct ifobject *ifobj_tx = test->ifobj_tx; 1877 1878 if ((ifobj_rx->xsk->umem->unaligned_mode && !ifobj_rx->unaligned_supp) || 1879 (ifobj_tx->xsk->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) { 1880 ksft_print_msg("No huge pages present.\n"); 1881 return TEST_SKIP; 1882 } 1883 1884 if (test->set_ring) { 1885 if (ifobj_tx->hw_ring_size_supp) { 1886 if (set_ring_size(ifobj_tx)) { 1887 ksft_print_msg("Failed to change HW ring size.\n"); 1888 return TEST_FAILURE; 1889 } 1890 } else { 1891 ksft_print_msg("Changing HW ring size not supported.\n"); 1892 return TEST_SKIP; 1893 } 1894 } 1895 1896 if (xsk_attach_xdp_progs(test, ifobj_rx, ifobj_tx)) 1897 return TEST_FAILURE; 1898 return __testapp_validate_traffic(test, ifobj_rx, ifobj_tx); 1899 } 1900 1901 static int testapp_validate_traffic_single_thread(struct test_spec *test, struct ifobject *ifobj) 1902 { 1903 return __testapp_validate_traffic(test, ifobj, NULL); 1904 } 1905 1906 int testapp_teardown(struct test_spec *test) 1907 { 1908 int i; 1909 1910 for (i = 0; i < MAX_TEARDOWN_ITER; i++) { 1911 if (testapp_validate_traffic(test)) 1912 return TEST_FAILURE; 1913 test_spec_reset(test); 1914 } 1915 1916 return TEST_PASS; 1917 } 1918 1919 static void swap_directions(struct ifobject **ifobj1, struct ifobject **ifobj2) 1920 { 1921 thread_func_t tmp_func_ptr = (*ifobj1)->func_ptr; 1922 struct ifobject *tmp_ifobj = (*ifobj1); 1923 1924 (*ifobj1)->func_ptr = (*ifobj2)->func_ptr; 1925 (*ifobj2)->func_ptr = tmp_func_ptr; 1926 1927 *ifobj1 = *ifobj2; 1928 *ifobj2 = tmp_ifobj; 1929 } 1930 1931 int testapp_bidirectional(struct test_spec *test) 1932 { 1933 int res; 1934 1935 test->ifobj_tx->rx_on = true; 1936 test->ifobj_rx->tx_on = true; 1937 test->total_steps = 2; 1938 if (testapp_validate_traffic(test)) 1939 return TEST_FAILURE; 1940 1941 print_verbose("Switching Tx/Rx direction\n"); 1942 swap_directions(&test->ifobj_rx, &test->ifobj_tx); 1943 res = __testapp_validate_traffic(test, test->ifobj_rx, test->ifobj_tx); 1944 1945 swap_directions(&test->ifobj_rx, &test->ifobj_tx); 1946 return res; 1947 } 1948 1949 static int swap_xsk_resources(struct test_spec *test) 1950 { 1951 int ret; 1952 1953 test->ifobj_tx->xsk_arr[0].pkt_stream = NULL; 1954 test->ifobj_rx->xsk_arr[0].pkt_stream = NULL; 1955 test->ifobj_tx->xsk_arr[1].pkt_stream = test->tx_pkt_stream_default; 1956 test->ifobj_rx->xsk_arr[1].pkt_stream = test->rx_pkt_stream_default; 1957 test->ifobj_tx->xsk = &test->ifobj_tx->xsk_arr[1]; 1958 test->ifobj_rx->xsk = &test->ifobj_rx->xsk_arr[1]; 1959 1960 ret = xsk_update_xskmap(test->ifobj_rx->xskmap, test->ifobj_rx->xsk->xsk, 0); 1961 if (ret) 1962 return TEST_FAILURE; 1963 1964 return TEST_PASS; 1965 } 1966 1967 int testapp_xdp_prog_cleanup(struct test_spec *test) 1968 { 1969 test->total_steps = 2; 1970 test->nb_sockets = 2; 1971 if (testapp_validate_traffic(test)) 1972 return TEST_FAILURE; 1973 1974 if (swap_xsk_resources(test)) { 1975 clean_sockets(test, test->ifobj_rx); 1976 clean_sockets(test, test->ifobj_tx); 1977 clean_umem(test, test->ifobj_rx, test->ifobj_tx); 1978 return TEST_FAILURE; 1979 } 1980 1981 return testapp_validate_traffic(test); 1982 } 1983 1984 int testapp_headroom(struct test_spec *test) 1985 { 1986 test->ifobj_rx->xsk->umem->frame_headroom = UMEM_HEADROOM_TEST_SIZE; 1987 return testapp_validate_traffic(test); 1988 } 1989 1990 int testapp_stats_rx_dropped(struct test_spec *test) 1991 { 1992 struct xsk_umem_info *umem = test->ifobj_rx->xsk->umem; 1993 u32 umem_tr = test->ifobj_tx->umem_tailroom; 1994 1995 if (test->mode == TEST_MODE_ZC) { 1996 ksft_print_msg("Can not run RX_DROPPED test for ZC mode\n"); 1997 return TEST_SKIP; 1998 } 1999 2000 if (pkt_stream_replace_half(test, (MIN_PKT_SIZE * 3) + umem_tr, 0)) 2001 return TEST_FAILURE; 2002 umem->frame_headroom = umem->frame_size - 2003 XDP_PACKET_HEADROOM - (MIN_PKT_SIZE * 2) - umem_tr; 2004 if (pkt_stream_receive_half(test)) 2005 return TEST_FAILURE; 2006 test->ifobj_rx->validation_func = validate_rx_dropped; 2007 return testapp_validate_traffic(test); 2008 } 2009 2010 int testapp_stats_tx_invalid_descs(struct test_spec *test) 2011 { 2012 if (pkt_stream_replace_half(test, XSK_UMEM__INVALID_FRAME_SIZE, 0)) 2013 return TEST_FAILURE; 2014 test->ifobj_tx->validation_func = validate_tx_invalid_descs; 2015 return testapp_validate_traffic(test); 2016 } 2017 2018 int testapp_stats_rx_full(struct test_spec *test) 2019 { 2020 struct pkt_stream *tmp; 2021 2022 tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE); 2023 if (!tmp) 2024 return TEST_FAILURE; 2025 test->ifobj_tx->xsk->pkt_stream = tmp; 2026 2027 tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2028 if (!tmp) 2029 return TEST_FAILURE; 2030 test->ifobj_rx->xsk->pkt_stream = tmp; 2031 2032 test->ifobj_rx->xsk->rxqsize = DEFAULT_UMEM_BUFFERS; 2033 test->ifobj_rx->release_rx = false; 2034 test->ifobj_rx->validation_func = validate_rx_full; 2035 return testapp_validate_traffic(test); 2036 } 2037 2038 int testapp_stats_fill_empty(struct test_spec *test) 2039 { 2040 struct pkt_stream *tmp; 2041 2042 tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS + DEFAULT_UMEM_BUFFERS / 2, MIN_PKT_SIZE); 2043 if (!tmp) 2044 return TEST_FAILURE; 2045 test->ifobj_tx->xsk->pkt_stream = tmp; 2046 2047 tmp = pkt_stream_generate(DEFAULT_UMEM_BUFFERS, MIN_PKT_SIZE); 2048 if (!tmp) 2049 return TEST_FAILURE; 2050 test->ifobj_rx->xsk->pkt_stream = tmp; 2051 2052 test->ifobj_rx->use_fill_ring = false; 2053 test->ifobj_rx->validation_func = validate_fill_empty; 2054 return testapp_validate_traffic(test); 2055 } 2056 2057 int testapp_send_receive_unaligned(struct test_spec *test) 2058 { 2059 test_spec_set_unaligned(test); 2060 /* Let half of the packets straddle a 4K buffer boundary */ 2061 if (pkt_stream_replace_half(test, MIN_PKT_SIZE, -MIN_PKT_SIZE / 2)) 2062 return TEST_FAILURE; 2063 2064 return testapp_validate_traffic(test); 2065 } 2066 2067 int testapp_send_receive_unaligned_mb(struct test_spec *test) 2068 { 2069 test->mtu = MAX_ETH_JUMBO_SIZE; 2070 test_spec_set_unaligned(test); 2071 if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE)) 2072 return TEST_FAILURE; 2073 return testapp_validate_traffic(test); 2074 } 2075 2076 int testapp_single_pkt(struct test_spec *test) 2077 { 2078 struct pkt pkts[] = {{0, MIN_PKT_SIZE, 0, true}}; 2079 2080 if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2081 return TEST_FAILURE; 2082 return testapp_validate_traffic(test); 2083 } 2084 2085 int testapp_send_receive_mb(struct test_spec *test) 2086 { 2087 test->mtu = MAX_ETH_JUMBO_SIZE; 2088 if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE)) 2089 return TEST_FAILURE; 2090 2091 return testapp_validate_traffic(test); 2092 } 2093 2094 int testapp_invalid_desc_mb(struct test_spec *test) 2095 { 2096 struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem; 2097 u64 umem_sz = umem_size(umem); 2098 struct pkt pkts[] = { 2099 /* Valid packet for synch to start with */ 2100 {0, MIN_PKT_SIZE, 0, true, 0}, 2101 /* Zero frame len is not legal */ 2102 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2103 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2104 {0, 0, 0, false, 0}, 2105 /* Invalid address in the second frame */ 2106 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2107 {umem_sz, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2108 /* Invalid len in the middle */ 2109 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2110 {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2111 /* Invalid options in the middle */ 2112 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2113 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XSK_DESC__INVALID_OPTION}, 2114 /* Transmit 2 frags, receive 3 */ 2115 {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, XDP_PKT_CONTD}, 2116 {0, XSK_UMEM__MAX_FRAME_SIZE, 0, true, 0}, 2117 /* Middle frame crosses chunk boundary with small length */ 2118 {0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD}, 2119 {-MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false, 0}, 2120 /* Valid packet for synch so that something is received */ 2121 {0, MIN_PKT_SIZE, 0, true, 0}}; 2122 2123 if (umem->unaligned_mode) { 2124 /* Crossing a chunk boundary allowed */ 2125 pkts[12].valid = true; 2126 pkts[13].valid = true; 2127 } 2128 2129 test->mtu = MAX_ETH_JUMBO_SIZE; 2130 if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2131 return TEST_FAILURE; 2132 return testapp_validate_traffic(test); 2133 } 2134 2135 int testapp_invalid_desc(struct test_spec *test) 2136 { 2137 struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem; 2138 u64 umem_sz = umem_size(umem); 2139 struct pkt pkts[] = { 2140 /* Zero packet address allowed */ 2141 {0, MIN_PKT_SIZE, 0, true}, 2142 /* Allowed packet */ 2143 {0, MIN_PKT_SIZE, 0, true}, 2144 /* Straddling the start of umem */ 2145 {-2, MIN_PKT_SIZE, 0, false}, 2146 /* Packet too large */ 2147 {0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false}, 2148 /* Up to end of umem allowed */ 2149 {umem_sz - MIN_PKT_SIZE - 2 * umem->frame_size, MIN_PKT_SIZE, 0, true}, 2150 /* After umem ends */ 2151 {umem_sz, MIN_PKT_SIZE, 0, false}, 2152 /* Straddle the end of umem */ 2153 {umem_sz - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false}, 2154 /* Straddle a 4K boundary */ 2155 {0x1000 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false}, 2156 /* Straddle a 2K boundary */ 2157 {0x800 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, true}, 2158 /* Valid packet for synch so that something is received */ 2159 {0, MIN_PKT_SIZE, 0, true}}; 2160 2161 if (umem->unaligned_mode) { 2162 /* Crossing a page boundary allowed */ 2163 pkts[7].valid = true; 2164 } 2165 if (umem->frame_size == XSK_UMEM__DEFAULT_FRAME_SIZE / 2) { 2166 /* Crossing a 2K frame size boundary not allowed */ 2167 pkts[8].valid = false; 2168 } 2169 2170 if (test->ifobj_tx->shared_umem) { 2171 pkts[4].offset += umem_sz; 2172 pkts[5].offset += umem_sz; 2173 pkts[6].offset += umem_sz; 2174 } 2175 2176 if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts))) 2177 return TEST_FAILURE; 2178 return testapp_validate_traffic(test); 2179 } 2180 2181 int testapp_xdp_drop(struct test_spec *test) 2182 { 2183 struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2184 struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2185 2186 test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_drop, skel_tx->progs.xsk_xdp_drop, 2187 skel_rx->maps.xsk, skel_tx->maps.xsk); 2188 2189 if (pkt_stream_receive_half(test)) 2190 return TEST_FAILURE; 2191 return testapp_validate_traffic(test); 2192 } 2193 2194 int testapp_xdp_metadata_copy(struct test_spec *test) 2195 { 2196 struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2197 struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2198 2199 test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_populate_metadata, 2200 skel_tx->progs.xsk_xdp_populate_metadata, 2201 skel_rx->maps.xsk, skel_tx->maps.xsk); 2202 test->ifobj_rx->use_metadata = true; 2203 2204 skel_rx->bss->count = 0; 2205 2206 return testapp_validate_traffic(test); 2207 } 2208 2209 int testapp_xdp_shared_umem(struct test_spec *test) 2210 { 2211 struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2212 struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2213 int ret; 2214 2215 test->total_steps = 1; 2216 test->nb_sockets = 2; 2217 2218 test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_shared_umem, 2219 skel_tx->progs.xsk_xdp_shared_umem, 2220 skel_rx->maps.xsk, skel_tx->maps.xsk); 2221 2222 if (pkt_stream_even_odd_sequence(test)) 2223 return TEST_FAILURE; 2224 2225 ret = testapp_validate_traffic(test); 2226 2227 release_even_odd_sequence(test); 2228 2229 return ret; 2230 } 2231 2232 int testapp_poll_txq_tmout(struct test_spec *test) 2233 { 2234 test->ifobj_tx->use_poll = true; 2235 /* create invalid frame by set umem frame_size and pkt length equal to 2048 */ 2236 test->ifobj_tx->xsk->umem->frame_size = 2048; 2237 if (pkt_stream_replace(test, 2 * DEFAULT_PKT_CNT, 2048)) 2238 return TEST_FAILURE; 2239 return testapp_validate_traffic_single_thread(test, test->ifobj_tx); 2240 } 2241 2242 int testapp_poll_rxq_tmout(struct test_spec *test) 2243 { 2244 test->ifobj_rx->use_poll = true; 2245 return testapp_validate_traffic_single_thread(test, test->ifobj_rx); 2246 } 2247 2248 int testapp_too_many_frags(struct test_spec *test) 2249 { 2250 struct pkt *pkts; 2251 u32 max_frags, i; 2252 int ret = TEST_FAILURE; 2253 2254 if (test->mode == TEST_MODE_ZC) { 2255 max_frags = test->ifobj_tx->xdp_zc_max_segs; 2256 } else { 2257 max_frags = test->ifobj_tx->max_skb_frags; 2258 max_frags += 1; 2259 } 2260 2261 pkts = calloc(2 * max_frags + 2, sizeof(struct pkt)); 2262 if (!pkts) 2263 return TEST_FAILURE; 2264 2265 test->mtu = MAX_ETH_JUMBO_SIZE; 2266 2267 /* Valid packet for synch */ 2268 pkts[0].len = MIN_PKT_SIZE; 2269 pkts[0].valid = true; 2270 2271 /* One valid packet with the max amount of frags */ 2272 for (i = 1; i < max_frags + 1; i++) { 2273 pkts[i].len = MIN_PKT_SIZE; 2274 pkts[i].options = XDP_PKT_CONTD; 2275 pkts[i].valid = true; 2276 } 2277 pkts[max_frags].options = 0; 2278 2279 /* An invalid packet with the max amount of frags but signals packet 2280 * continues on the last frag 2281 */ 2282 for (i = max_frags + 1; i < 2 * max_frags + 1; i++) { 2283 pkts[i].len = MIN_PKT_SIZE; 2284 pkts[i].options = XDP_PKT_CONTD; 2285 pkts[i].valid = false; 2286 } 2287 2288 /* Valid packet for synch */ 2289 pkts[2 * max_frags + 1].len = MIN_PKT_SIZE; 2290 pkts[2 * max_frags + 1].valid = true; 2291 2292 if (pkt_stream_generate_custom(test, pkts, 2 * max_frags + 2)) { 2293 free(pkts); 2294 return TEST_FAILURE; 2295 } 2296 2297 ret = testapp_validate_traffic(test); 2298 free(pkts); 2299 return ret; 2300 } 2301 2302 static int xsk_load_xdp_programs(struct ifobject *ifobj) 2303 { 2304 ifobj->xdp_progs = xsk_xdp_progs__open_and_load(); 2305 if (libbpf_get_error(ifobj->xdp_progs)) 2306 return libbpf_get_error(ifobj->xdp_progs); 2307 2308 return 0; 2309 } 2310 2311 /* Simple test */ 2312 static bool hugepages_present(void) 2313 { 2314 size_t mmap_sz = 2 * DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE; 2315 void *bufs; 2316 2317 bufs = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, 2318 MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, MAP_HUGE_2MB); 2319 if (bufs == MAP_FAILED) 2320 return false; 2321 2322 mmap_sz = ceil_u64(mmap_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE; 2323 munmap(bufs, mmap_sz); 2324 return true; 2325 } 2326 2327 int init_iface(struct ifobject *ifobj, thread_func_t func_ptr) 2328 { 2329 LIBBPF_OPTS(bpf_xdp_query_opts, query_opts); 2330 int err; 2331 2332 ifobj->func_ptr = func_ptr; 2333 2334 err = xsk_load_xdp_programs(ifobj); 2335 if (err) { 2336 ksft_print_msg("Error loading XDP program\n"); 2337 return err; 2338 } 2339 2340 if (hugepages_present()) 2341 ifobj->unaligned_supp = true; 2342 2343 err = bpf_xdp_query(ifobj->ifindex, XDP_FLAGS_DRV_MODE, &query_opts); 2344 if (err) { 2345 ksft_print_msg("Error querying XDP capabilities\n"); 2346 return err; 2347 } 2348 if (query_opts.feature_flags & NETDEV_XDP_ACT_RX_SG) 2349 ifobj->multi_buff_supp = true; 2350 if (query_opts.feature_flags & NETDEV_XDP_ACT_XSK_ZEROCOPY) { 2351 if (query_opts.xdp_zc_max_segs > 1) { 2352 ifobj->multi_buff_zc_supp = true; 2353 ifobj->xdp_zc_max_segs = query_opts.xdp_zc_max_segs; 2354 } else { 2355 ifobj->xdp_zc_max_segs = 0; 2356 } 2357 } 2358 2359 return 0; 2360 } 2361 2362 int testapp_send_receive(struct test_spec *test) 2363 { 2364 return testapp_validate_traffic(test); 2365 } 2366 2367 int testapp_send_receive_2k_frame(struct test_spec *test) 2368 { 2369 test_spec_set_frame_size(test, 2048); 2370 if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MIN_PKT_SIZE)) 2371 return TEST_FAILURE; 2372 return testapp_validate_traffic(test); 2373 } 2374 2375 int testapp_poll_rx(struct test_spec *test) 2376 { 2377 test->ifobj_rx->use_poll = true; 2378 return testapp_validate_traffic(test); 2379 } 2380 2381 int testapp_poll_tx(struct test_spec *test) 2382 { 2383 test->ifobj_tx->use_poll = true; 2384 return testapp_validate_traffic(test); 2385 } 2386 2387 int testapp_aligned_inv_desc(struct test_spec *test) 2388 { 2389 return testapp_invalid_desc(test); 2390 } 2391 2392 int testapp_aligned_inv_desc_2k_frame(struct test_spec *test) 2393 { 2394 test_spec_set_frame_size(test, 2048); 2395 return testapp_invalid_desc(test); 2396 } 2397 2398 int testapp_unaligned_inv_desc(struct test_spec *test) 2399 { 2400 test_spec_set_unaligned(test); 2401 return testapp_invalid_desc(test); 2402 } 2403 2404 int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test) 2405 { 2406 u64 page_size, umem_sz; 2407 2408 /* Odd frame size so the UMEM doesn't end near a page boundary. */ 2409 test_spec_set_frame_size(test, 4001); 2410 test_spec_set_unaligned(test); 2411 /* This test exists to test descriptors that staddle the end of 2412 * the UMEM but not a page. 2413 */ 2414 page_size = sysconf(_SC_PAGESIZE); 2415 umem_sz = umem_size(test->ifobj_tx->xsk->umem); 2416 assert(umem_sz % page_size > MIN_PKT_SIZE); 2417 assert(umem_sz % page_size < page_size - MIN_PKT_SIZE); 2418 2419 return testapp_invalid_desc(test); 2420 } 2421 2422 int testapp_aligned_inv_desc_mb(struct test_spec *test) 2423 { 2424 return testapp_invalid_desc_mb(test); 2425 } 2426 2427 int testapp_unaligned_inv_desc_mb(struct test_spec *test) 2428 { 2429 test_spec_set_unaligned(test); 2430 return testapp_invalid_desc_mb(test); 2431 } 2432 2433 int testapp_xdp_metadata(struct test_spec *test) 2434 { 2435 return testapp_xdp_metadata_copy(test); 2436 } 2437 2438 int testapp_xdp_metadata_mb(struct test_spec *test) 2439 { 2440 test->mtu = MAX_ETH_JUMBO_SIZE; 2441 return testapp_xdp_metadata_copy(test); 2442 } 2443 2444 int testapp_hw_sw_min_ring_size(struct test_spec *test) 2445 { 2446 int ret; 2447 2448 test->set_ring = true; 2449 test->total_steps = 2; 2450 test->ifobj_tx->ring.tx_pending = DEFAULT_BATCH_SIZE; 2451 test->ifobj_tx->ring.rx_pending = DEFAULT_BATCH_SIZE * 2; 2452 test->ifobj_tx->xsk->batch_size = 1; 2453 test->ifobj_rx->xsk->batch_size = 1; 2454 ret = testapp_validate_traffic(test); 2455 if (ret) 2456 return ret; 2457 2458 /* Set batch size to hw_ring_size - 1 */ 2459 test->ifobj_tx->xsk->batch_size = DEFAULT_BATCH_SIZE - 1; 2460 test->ifobj_rx->xsk->batch_size = DEFAULT_BATCH_SIZE - 1; 2461 return testapp_validate_traffic(test); 2462 } 2463 2464 int testapp_hw_sw_max_ring_size(struct test_spec *test) 2465 { 2466 u32 max_descs = XSK_RING_PROD__DEFAULT_NUM_DESCS * 4; 2467 int ret; 2468 2469 test->set_ring = true; 2470 test->total_steps = 2; 2471 test->ifobj_tx->ring.tx_pending = test->ifobj_tx->ring.tx_max_pending; 2472 test->ifobj_tx->ring.rx_pending = test->ifobj_tx->ring.rx_max_pending; 2473 test->ifobj_rx->xsk->umem->num_frames = max_descs; 2474 test->ifobj_rx->xsk->umem->fill_size = max_descs; 2475 test->ifobj_rx->xsk->umem->comp_size = max_descs; 2476 test->ifobj_tx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 2477 test->ifobj_rx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; 2478 2479 ret = testapp_validate_traffic(test); 2480 if (ret) 2481 return ret; 2482 2483 /* Set batch_size to 8152 for testing, as the ice HW ignores the 3 lowest bits when 2484 * updating the Rx HW tail register. 2485 */ 2486 test->ifobj_tx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8; 2487 test->ifobj_rx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8; 2488 if (pkt_stream_replace(test, max_descs, MIN_PKT_SIZE)) { 2489 clean_sockets(test, test->ifobj_tx); 2490 clean_sockets(test, test->ifobj_rx); 2491 clean_umem(test, test->ifobj_rx, test->ifobj_tx); 2492 return TEST_FAILURE; 2493 } 2494 2495 return testapp_validate_traffic(test); 2496 } 2497 2498 static int testapp_xdp_adjust_tail(struct test_spec *test, int adjust_value) 2499 { 2500 struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs; 2501 struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs; 2502 2503 test_spec_set_xdp_prog(test, skel_rx->progs.xsk_xdp_adjust_tail, 2504 skel_tx->progs.xsk_xdp_adjust_tail, 2505 skel_rx->maps.xsk, skel_tx->maps.xsk); 2506 2507 skel_rx->bss->adjust_value = adjust_value; 2508 2509 return testapp_validate_traffic(test); 2510 } 2511 2512 static int testapp_adjust_tail(struct test_spec *test, u32 value, u32 pkt_len) 2513 { 2514 int ret; 2515 2516 test->adjust_tail_support = true; 2517 test->adjust_tail = true; 2518 test->total_steps = 1; 2519 2520 ret = pkt_stream_replace_ifobject(test->ifobj_tx, DEFAULT_BATCH_SIZE, pkt_len); 2521 if (ret) 2522 return TEST_FAILURE; 2523 2524 ret = pkt_stream_replace_ifobject(test->ifobj_rx, DEFAULT_BATCH_SIZE, pkt_len + value); 2525 if (ret) 2526 return TEST_FAILURE; 2527 2528 ret = testapp_xdp_adjust_tail(test, value); 2529 if (ret) 2530 return ret; 2531 2532 if (!test->adjust_tail_support) { 2533 ksft_print_msg("%s %sResize pkt with bpf_xdp_adjust_tail() not supported\n", 2534 mode_string(test), busy_poll_string(test)); 2535 return TEST_SKIP; 2536 } 2537 2538 return 0; 2539 } 2540 2541 int testapp_adjust_tail_shrink(struct test_spec *test) 2542 { 2543 /* Shrink by 4 bytes for testing purpose */ 2544 return testapp_adjust_tail(test, -4, MIN_PKT_SIZE * 2); 2545 } 2546 2547 int testapp_adjust_tail_shrink_mb(struct test_spec *test) 2548 { 2549 test->mtu = MAX_ETH_JUMBO_SIZE; 2550 /* Shrink by the frag size */ 2551 return testapp_adjust_tail(test, -XSK_UMEM__MAX_FRAME_SIZE, XSK_UMEM__LARGE_FRAME_SIZE * 2); 2552 } 2553 2554 int testapp_adjust_tail_grow(struct test_spec *test) 2555 { 2556 if (test->mode == TEST_MODE_SKB) 2557 return TEST_SKIP; 2558 2559 /* Grow by 4 bytes for testing purpose */ 2560 return testapp_adjust_tail(test, 4, MIN_PKT_SIZE * 2); 2561 } 2562 2563 int testapp_adjust_tail_grow_mb(struct test_spec *test) 2564 { 2565 u32 grow_size; 2566 2567 if (test->mode == TEST_MODE_SKB) 2568 return TEST_SKIP; 2569 2570 /* worst case scenario is when underlying setup will work on 3k 2571 * buffers, let us account for it; given that we will use 6k as 2572 * pkt_len, expect that it will be broken down to 2 descs each 2573 * with 3k payload; 2574 * 2575 * 4k is truesize, 3k payload, 256 HR, 320 TR; 2576 */ 2577 grow_size = XSK_UMEM__MAX_FRAME_SIZE - 2578 XSK_UMEM__LARGE_FRAME_SIZE - 2579 XDP_PACKET_HEADROOM - 2580 test->ifobj_tx->umem_tailroom; 2581 test->mtu = MAX_ETH_JUMBO_SIZE; 2582 2583 return testapp_adjust_tail(test, grow_size, XSK_UMEM__LARGE_FRAME_SIZE * 2); 2584 } 2585 2586 int testapp_tx_queue_consumer(struct test_spec *test) 2587 { 2588 int nr_packets; 2589 2590 if (test->mode == TEST_MODE_ZC) { 2591 ksft_print_msg("Can not run TX_QUEUE_CONSUMER test for ZC mode\n"); 2592 return TEST_SKIP; 2593 } 2594 2595 nr_packets = MAX_TX_BUDGET_DEFAULT + 1; 2596 if (pkt_stream_replace(test, nr_packets, MIN_PKT_SIZE)) 2597 return TEST_FAILURE; 2598 test->ifobj_tx->xsk->batch_size = nr_packets; 2599 test->ifobj_tx->xsk->check_consumer = true; 2600 2601 return testapp_validate_traffic(test); 2602 } 2603 2604 struct ifobject *ifobject_create(void) 2605 { 2606 struct ifobject *ifobj; 2607 2608 ifobj = calloc(1, sizeof(struct ifobject)); 2609 if (!ifobj) 2610 return NULL; 2611 2612 ifobj->xsk_arr = calloc(MAX_SOCKETS, sizeof(*ifobj->xsk_arr)); 2613 if (!ifobj->xsk_arr) 2614 goto out_xsk_arr; 2615 2616 ifobj->xsk_arr[0].umem_real = calloc(1, sizeof(struct xsk_umem_info)); 2617 if (!ifobj->xsk_arr[0].umem_real) 2618 goto out_umem; 2619 2620 return ifobj; 2621 2622 out_umem: 2623 free(ifobj->xsk_arr); 2624 out_xsk_arr: 2625 free(ifobj); 2626 return NULL; 2627 } 2628 2629 void ifobject_delete(struct ifobject *ifobj) 2630 { 2631 if (ifobj->xsk_arr) 2632 free(ifobj->xsk_arr[0].umem_real); 2633 2634 free(ifobj->xsk_arr); 2635 free(ifobj); 2636 } 2637