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