1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <stdint.h> 10 #include <inttypes.h> 11 #include <errno.h> 12 #include <sys/queue.h> 13 14 #include <rte_common.h> 15 #include <rte_log.h> 16 #include <rte_memory.h> 17 #include <rte_launch.h> 18 #include <rte_cycles.h> 19 #include <rte_eal.h> 20 #include <rte_per_lcore.h> 21 #include <rte_lcore.h> 22 #include <rte_atomic.h> 23 #include <rte_branch_prediction.h> 24 #include <rte_malloc.h> 25 #include <rte_ring.h> 26 #include <rte_ring_elem.h> 27 #include <rte_random.h> 28 #include <rte_errno.h> 29 #include <rte_hexdump.h> 30 31 #include "test.h" 32 #include "test_ring.h" 33 34 /* 35 * Ring 36 * ==== 37 * 38 * #. Functional tests. Tests single/bulk/burst, default/SPSC/MPMC, 39 * legacy/custom element size (4B, 8B, 16B, 20B) APIs. 40 * Some tests incorporate unaligned addresses for objects. 41 * The enqueued/dequeued data is validated for correctness. 42 * 43 * #. Performance tests are in test_ring_perf.c 44 */ 45 46 #define RING_SIZE 4096 47 #define MAX_BULK 32 48 49 #define TEST_RING_VERIFY(exp) \ 50 if (!(exp)) { \ 51 printf("error at %s:%d\tcondition " #exp " failed\n", \ 52 __func__, __LINE__); \ 53 rte_ring_dump(stdout, r); \ 54 return -1; \ 55 } 56 57 #define TEST_RING_FULL_EMTPY_ITER 8 58 59 static const int esize[] = {-1, 4, 8, 16, 20}; 60 61 static const struct { 62 const char *desc; 63 uint32_t api_type; 64 uint32_t create_flags; 65 struct { 66 unsigned int (*flegacy)(struct rte_ring *r, 67 void * const *obj_table, unsigned int n, 68 unsigned int *free_space); 69 unsigned int (*felem)(struct rte_ring *r, const void *obj_table, 70 unsigned int esize, unsigned int n, 71 unsigned int *free_space); 72 } enq; 73 struct { 74 unsigned int (*flegacy)(struct rte_ring *r, 75 void **obj_table, unsigned int n, 76 unsigned int *available); 77 unsigned int (*felem)(struct rte_ring *r, void *obj_table, 78 unsigned int esize, unsigned int n, 79 unsigned int *available); 80 } deq; 81 } test_enqdeq_impl[] = { 82 { 83 .desc = "MP/MC sync mode", 84 .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, 85 .create_flags = 0, 86 .enq = { 87 .flegacy = rte_ring_enqueue_bulk, 88 .felem = rte_ring_enqueue_bulk_elem, 89 }, 90 .deq = { 91 .flegacy = rte_ring_dequeue_bulk, 92 .felem = rte_ring_dequeue_bulk_elem, 93 }, 94 }, 95 { 96 .desc = "SP/SC sync mode", 97 .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_SPSC, 98 .create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ, 99 .enq = { 100 .flegacy = rte_ring_sp_enqueue_bulk, 101 .felem = rte_ring_sp_enqueue_bulk_elem, 102 }, 103 .deq = { 104 .flegacy = rte_ring_sc_dequeue_bulk, 105 .felem = rte_ring_sc_dequeue_bulk_elem, 106 }, 107 }, 108 { 109 .desc = "MP/MC sync mode", 110 .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_MPMC, 111 .create_flags = 0, 112 .enq = { 113 .flegacy = rte_ring_mp_enqueue_bulk, 114 .felem = rte_ring_mp_enqueue_bulk_elem, 115 }, 116 .deq = { 117 .flegacy = rte_ring_mc_dequeue_bulk, 118 .felem = rte_ring_mc_dequeue_bulk_elem, 119 }, 120 }, 121 { 122 .desc = "MP_RTS/MC_RTS sync mode", 123 .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, 124 .create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ, 125 .enq = { 126 .flegacy = rte_ring_enqueue_bulk, 127 .felem = rte_ring_enqueue_bulk_elem, 128 }, 129 .deq = { 130 .flegacy = rte_ring_dequeue_bulk, 131 .felem = rte_ring_dequeue_bulk_elem, 132 }, 133 }, 134 { 135 .desc = "MP_HTS/MC_HTS sync mode", 136 .api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF, 137 .create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ, 138 .enq = { 139 .flegacy = rte_ring_enqueue_bulk, 140 .felem = rte_ring_enqueue_bulk_elem, 141 }, 142 .deq = { 143 .flegacy = rte_ring_dequeue_bulk, 144 .felem = rte_ring_dequeue_bulk_elem, 145 }, 146 }, 147 { 148 .desc = "MP/MC sync mode", 149 .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, 150 .create_flags = 0, 151 .enq = { 152 .flegacy = rte_ring_enqueue_burst, 153 .felem = rte_ring_enqueue_burst_elem, 154 }, 155 .deq = { 156 .flegacy = rte_ring_dequeue_burst, 157 .felem = rte_ring_dequeue_burst_elem, 158 }, 159 }, 160 { 161 .desc = "SP/SC sync mode", 162 .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_SPSC, 163 .create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ, 164 .enq = { 165 .flegacy = rte_ring_sp_enqueue_burst, 166 .felem = rte_ring_sp_enqueue_burst_elem, 167 }, 168 .deq = { 169 .flegacy = rte_ring_sc_dequeue_burst, 170 .felem = rte_ring_sc_dequeue_burst_elem, 171 }, 172 }, 173 { 174 .desc = "MP/MC sync mode", 175 .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_MPMC, 176 .create_flags = 0, 177 .enq = { 178 .flegacy = rte_ring_mp_enqueue_burst, 179 .felem = rte_ring_mp_enqueue_burst_elem, 180 }, 181 .deq = { 182 .flegacy = rte_ring_mc_dequeue_burst, 183 .felem = rte_ring_mc_dequeue_burst_elem, 184 }, 185 }, 186 { 187 .desc = "MP_RTS/MC_RTS sync mode", 188 .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, 189 .create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ, 190 .enq = { 191 .flegacy = rte_ring_enqueue_burst, 192 .felem = rte_ring_enqueue_burst_elem, 193 }, 194 .deq = { 195 .flegacy = rte_ring_dequeue_burst, 196 .felem = rte_ring_dequeue_burst_elem, 197 }, 198 }, 199 { 200 .desc = "MP_HTS/MC_HTS sync mode", 201 .api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF, 202 .create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ, 203 .enq = { 204 .flegacy = rte_ring_enqueue_burst, 205 .felem = rte_ring_enqueue_burst_elem, 206 }, 207 .deq = { 208 .flegacy = rte_ring_dequeue_burst, 209 .felem = rte_ring_dequeue_burst_elem, 210 }, 211 }, 212 }; 213 214 static unsigned int 215 test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n, 216 unsigned int test_idx) 217 { 218 if (esize == -1) 219 return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL); 220 else 221 return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n, 222 NULL); 223 } 224 225 static unsigned int 226 test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n, 227 unsigned int test_idx) 228 { 229 if (esize == -1) 230 return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL); 231 else 232 return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n, 233 NULL); 234 } 235 236 static void** 237 test_ring_inc_ptr(void **obj, int esize, unsigned int n) 238 { 239 /* Legacy queue APIs? */ 240 if ((esize) == -1) 241 return ((void **)obj) + n; 242 else 243 return (void **)(((uint32_t *)obj) + 244 (n * esize / sizeof(uint32_t))); 245 } 246 247 static void 248 test_ring_mem_init(void *obj, unsigned int count, int esize) 249 { 250 unsigned int i; 251 252 /* Legacy queue APIs? */ 253 if (esize == -1) 254 for (i = 0; i < count; i++) 255 ((void **)obj)[i] = (void *)(unsigned long)i; 256 else 257 for (i = 0; i < (count * esize / sizeof(uint32_t)); i++) 258 ((uint32_t *)obj)[i] = i; 259 } 260 261 static void 262 test_ring_print_test_string(const char *istr, unsigned int api_type, int esize) 263 { 264 printf("\n%s: ", istr); 265 266 if (esize == -1) 267 printf("legacy APIs: "); 268 else 269 printf("elem APIs: element size %dB ", esize); 270 271 if (api_type == TEST_RING_IGNORE_API_TYPE) 272 return; 273 274 if (api_type & TEST_RING_THREAD_DEF) 275 printf(": default enqueue/dequeue: "); 276 else if (api_type & TEST_RING_THREAD_SPSC) 277 printf(": SP/SC: "); 278 else if (api_type & TEST_RING_THREAD_MPMC) 279 printf(": MP/MC: "); 280 281 if (api_type & TEST_RING_ELEM_SINGLE) 282 printf("single\n"); 283 else if (api_type & TEST_RING_ELEM_BULK) 284 printf("bulk\n"); 285 else if (api_type & TEST_RING_ELEM_BURST) 286 printf("burst\n"); 287 } 288 289 /* 290 * Various negative test cases. 291 */ 292 static int 293 test_ring_negative_tests(void) 294 { 295 struct rte_ring *rp = NULL; 296 struct rte_ring *rt = NULL; 297 unsigned int i; 298 299 /* Test with esize not a multiple of 4 */ 300 rp = test_ring_create("test_bad_element_size", 23, 301 RING_SIZE + 1, SOCKET_ID_ANY, 0); 302 if (rp != NULL) { 303 printf("Test failed to detect invalid element size\n"); 304 goto test_fail; 305 } 306 307 308 for (i = 0; i < RTE_DIM(esize); i++) { 309 /* Test if ring size is not power of 2 */ 310 rp = test_ring_create("test_bad_ring_size", esize[i], 311 RING_SIZE + 1, SOCKET_ID_ANY, 0); 312 if (rp != NULL) { 313 printf("Test failed to detect odd count\n"); 314 goto test_fail; 315 } 316 317 /* Test if ring size is exceeding the limit */ 318 rp = test_ring_create("test_bad_ring_size", esize[i], 319 RTE_RING_SZ_MASK + 1, SOCKET_ID_ANY, 0); 320 if (rp != NULL) { 321 printf("Test failed to detect limits\n"); 322 goto test_fail; 323 } 324 325 /* Tests if lookup returns NULL on non-existing ring */ 326 rp = rte_ring_lookup("ring_not_found"); 327 if (rp != NULL && rte_errno != ENOENT) { 328 printf("Test failed to detect NULL ring lookup\n"); 329 goto test_fail; 330 } 331 332 /* Test to if a non-power of 2 count causes the create 333 * function to fail correctly 334 */ 335 rp = test_ring_create("test_ring_count", esize[i], 4097, 336 SOCKET_ID_ANY, 0); 337 if (rp != NULL) 338 goto test_fail; 339 340 rp = test_ring_create("test_ring_negative", esize[i], RING_SIZE, 341 SOCKET_ID_ANY, 342 RING_F_SP_ENQ | RING_F_SC_DEQ); 343 if (rp == NULL) { 344 printf("test_ring_negative fail to create ring\n"); 345 goto test_fail; 346 } 347 348 if (rte_ring_lookup("test_ring_negative") != rp) 349 goto test_fail; 350 351 if (rte_ring_empty(rp) != 1) { 352 printf("test_ring_nagative ring is not empty but it should be\n"); 353 goto test_fail; 354 } 355 356 /* Tests if it would always fail to create ring with an used 357 * ring name. 358 */ 359 rt = test_ring_create("test_ring_negative", esize[i], RING_SIZE, 360 SOCKET_ID_ANY, 0); 361 if (rt != NULL) 362 goto test_fail; 363 364 rte_ring_free(rp); 365 rp = NULL; 366 } 367 368 return 0; 369 370 test_fail: 371 372 rte_ring_free(rp); 373 return -1; 374 } 375 376 /* 377 * Burst and bulk operations with sp/sc, mp/mc and default (during creation) 378 * Random number of elements are enqueued and dequeued. 379 */ 380 static int 381 test_ring_burst_bulk_tests1(unsigned int test_idx) 382 { 383 struct rte_ring *r; 384 void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; 385 int ret; 386 unsigned int i, j; 387 int rand; 388 const unsigned int rsz = RING_SIZE - 1; 389 390 for (i = 0; i < RTE_DIM(esize); i++) { 391 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, 392 test_enqdeq_impl[test_idx].api_type, esize[i]); 393 394 /* Create the ring */ 395 r = test_ring_create("test_ring_burst_bulk_tests", esize[i], 396 RING_SIZE, SOCKET_ID_ANY, 397 test_enqdeq_impl[test_idx].create_flags); 398 399 /* alloc dummy object pointers */ 400 src = test_ring_calloc(RING_SIZE * 2, esize[i]); 401 if (src == NULL) 402 goto fail; 403 test_ring_mem_init(src, RING_SIZE * 2, esize[i]); 404 cur_src = src; 405 406 /* alloc some room for copied objects */ 407 dst = test_ring_calloc(RING_SIZE * 2, esize[i]); 408 if (dst == NULL) 409 goto fail; 410 cur_dst = dst; 411 412 printf("Random full/empty test\n"); 413 414 for (j = 0; j != TEST_RING_FULL_EMTPY_ITER; j++) { 415 /* random shift in the ring */ 416 rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL); 417 printf("%s: iteration %u, random shift: %u;\n", 418 __func__, i, rand); 419 ret = test_ring_enq_impl(r, cur_src, esize[i], rand, 420 test_idx); 421 TEST_RING_VERIFY(ret != 0); 422 423 ret = test_ring_deq_impl(r, cur_dst, esize[i], rand, 424 test_idx); 425 TEST_RING_VERIFY(ret == rand); 426 427 /* fill the ring */ 428 ret = test_ring_enq_impl(r, cur_src, esize[i], rsz, 429 test_idx); 430 TEST_RING_VERIFY(ret != 0); 431 432 TEST_RING_VERIFY(rte_ring_free_count(r) == 0); 433 TEST_RING_VERIFY(rsz == rte_ring_count(r)); 434 TEST_RING_VERIFY(rte_ring_full(r)); 435 TEST_RING_VERIFY(rte_ring_empty(r) == 0); 436 437 /* empty the ring */ 438 ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz, 439 test_idx); 440 TEST_RING_VERIFY(ret == (int)rsz); 441 TEST_RING_VERIFY(rsz == rte_ring_free_count(r)); 442 TEST_RING_VERIFY(rte_ring_count(r) == 0); 443 TEST_RING_VERIFY(rte_ring_full(r) == 0); 444 TEST_RING_VERIFY(rte_ring_empty(r)); 445 446 /* check data */ 447 TEST_RING_VERIFY(memcmp(src, dst, rsz) == 0); 448 } 449 450 /* Free memory before test completed */ 451 rte_ring_free(r); 452 rte_free(src); 453 rte_free(dst); 454 r = NULL; 455 src = NULL; 456 dst = NULL; 457 } 458 459 return 0; 460 fail: 461 rte_ring_free(r); 462 rte_free(src); 463 rte_free(dst); 464 return -1; 465 } 466 467 /* 468 * Burst and bulk operations with sp/sc, mp/mc and default (during creation) 469 * Sequence of simple enqueues/dequeues and validate the enqueued and 470 * dequeued data. 471 */ 472 static int 473 test_ring_burst_bulk_tests2(unsigned int test_idx) 474 { 475 struct rte_ring *r; 476 void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; 477 int ret; 478 unsigned int i; 479 480 for (i = 0; i < RTE_DIM(esize); i++) { 481 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, 482 test_enqdeq_impl[test_idx].api_type, esize[i]); 483 484 /* Create the ring */ 485 r = test_ring_create("test_ring_burst_bulk_tests", esize[i], 486 RING_SIZE, SOCKET_ID_ANY, 487 test_enqdeq_impl[test_idx].create_flags); 488 489 /* alloc dummy object pointers */ 490 src = test_ring_calloc(RING_SIZE * 2, esize[i]); 491 if (src == NULL) 492 goto fail; 493 test_ring_mem_init(src, RING_SIZE * 2, esize[i]); 494 cur_src = src; 495 496 /* alloc some room for copied objects */ 497 dst = test_ring_calloc(RING_SIZE * 2, esize[i]); 498 if (dst == NULL) 499 goto fail; 500 cur_dst = dst; 501 502 printf("enqueue 1 obj\n"); 503 ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx); 504 if (ret != 1) 505 goto fail; 506 cur_src = test_ring_inc_ptr(cur_src, esize[i], 1); 507 508 printf("enqueue 2 objs\n"); 509 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx); 510 if (ret != 2) 511 goto fail; 512 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); 513 514 printf("enqueue MAX_BULK objs\n"); 515 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, 516 test_idx); 517 if (ret != MAX_BULK) 518 goto fail; 519 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK); 520 521 printf("dequeue 1 obj\n"); 522 ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx); 523 if (ret != 1) 524 goto fail; 525 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1); 526 527 printf("dequeue 2 objs\n"); 528 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx); 529 if (ret != 2) 530 goto fail; 531 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); 532 533 printf("dequeue MAX_BULK objs\n"); 534 ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK, 535 test_idx); 536 if (ret != MAX_BULK) 537 goto fail; 538 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK); 539 540 /* check data */ 541 if (memcmp(src, dst, cur_dst - dst)) { 542 rte_hexdump(stdout, "src", src, cur_src - src); 543 rte_hexdump(stdout, "dst", dst, cur_dst - dst); 544 printf("data after dequeue is not the same\n"); 545 goto fail; 546 } 547 548 /* Free memory before test completed */ 549 rte_ring_free(r); 550 rte_free(src); 551 rte_free(dst); 552 r = NULL; 553 src = NULL; 554 dst = NULL; 555 } 556 557 return 0; 558 fail: 559 rte_ring_free(r); 560 rte_free(src); 561 rte_free(dst); 562 return -1; 563 } 564 565 /* 566 * Burst and bulk operations with sp/sc, mp/mc and default (during creation) 567 * Enqueue and dequeue to cover the entire ring length. 568 */ 569 static int 570 test_ring_burst_bulk_tests3(unsigned int test_idx) 571 { 572 struct rte_ring *r; 573 void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; 574 int ret; 575 unsigned int i, j; 576 577 for (i = 0; i < RTE_DIM(esize); i++) { 578 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, 579 test_enqdeq_impl[test_idx].api_type, esize[i]); 580 581 /* Create the ring */ 582 r = test_ring_create("test_ring_burst_bulk_tests", esize[i], 583 RING_SIZE, SOCKET_ID_ANY, 584 test_enqdeq_impl[test_idx].create_flags); 585 586 /* alloc dummy object pointers */ 587 src = test_ring_calloc(RING_SIZE * 2, esize[i]); 588 if (src == NULL) 589 goto fail; 590 test_ring_mem_init(src, RING_SIZE * 2, esize[i]); 591 cur_src = src; 592 593 /* alloc some room for copied objects */ 594 dst = test_ring_calloc(RING_SIZE * 2, esize[i]); 595 if (dst == NULL) 596 goto fail; 597 cur_dst = dst; 598 599 printf("fill and empty the ring\n"); 600 for (j = 0; j < RING_SIZE / MAX_BULK; j++) { 601 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, 602 test_idx); 603 if (ret != MAX_BULK) 604 goto fail; 605 cur_src = test_ring_inc_ptr(cur_src, esize[i], 606 MAX_BULK); 607 608 ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK, 609 test_idx); 610 if (ret != MAX_BULK) 611 goto fail; 612 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 613 MAX_BULK); 614 } 615 616 /* check data */ 617 if (memcmp(src, dst, cur_dst - dst)) { 618 rte_hexdump(stdout, "src", src, cur_src - src); 619 rte_hexdump(stdout, "dst", dst, cur_dst - dst); 620 printf("data after dequeue is not the same\n"); 621 goto fail; 622 } 623 624 /* Free memory before test completed */ 625 rte_ring_free(r); 626 rte_free(src); 627 rte_free(dst); 628 r = NULL; 629 src = NULL; 630 dst = NULL; 631 } 632 633 return 0; 634 fail: 635 rte_ring_free(r); 636 rte_free(src); 637 rte_free(dst); 638 return -1; 639 } 640 641 /* 642 * Burst and bulk operations with sp/sc, mp/mc and default (during creation) 643 * Enqueue till the ring is full and dequeue till the ring becomes empty. 644 */ 645 static int 646 test_ring_burst_bulk_tests4(unsigned int test_idx) 647 { 648 struct rte_ring *r; 649 void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; 650 int ret; 651 unsigned int i, j; 652 unsigned int api_type, num_elems; 653 654 api_type = test_enqdeq_impl[test_idx].api_type; 655 656 for (i = 0; i < RTE_DIM(esize); i++) { 657 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc, 658 test_enqdeq_impl[test_idx].api_type, esize[i]); 659 660 /* Create the ring */ 661 r = test_ring_create("test_ring_burst_bulk_tests", esize[i], 662 RING_SIZE, SOCKET_ID_ANY, 663 test_enqdeq_impl[test_idx].create_flags); 664 665 /* alloc dummy object pointers */ 666 src = test_ring_calloc(RING_SIZE * 2, esize[i]); 667 if (src == NULL) 668 goto fail; 669 test_ring_mem_init(src, RING_SIZE * 2, esize[i]); 670 cur_src = src; 671 672 /* alloc some room for copied objects */ 673 dst = test_ring_calloc(RING_SIZE * 2, esize[i]); 674 if (dst == NULL) 675 goto fail; 676 cur_dst = dst; 677 678 printf("Test enqueue without enough memory space\n"); 679 for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) { 680 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, 681 test_idx); 682 if (ret != MAX_BULK) 683 goto fail; 684 cur_src = test_ring_inc_ptr(cur_src, esize[i], 685 MAX_BULK); 686 } 687 688 printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n"); 689 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx); 690 if (ret != 2) 691 goto fail; 692 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2); 693 694 printf("Enqueue the remaining entries = MAX_BULK - 3\n"); 695 /* Bulk APIs enqueue exact number of elements */ 696 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK) 697 num_elems = MAX_BULK - 3; 698 else 699 num_elems = MAX_BULK; 700 /* Always one free entry left */ 701 ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems, 702 test_idx); 703 if (ret != MAX_BULK - 3) 704 goto fail; 705 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3); 706 707 printf("Test if ring is full\n"); 708 if (rte_ring_full(r) != 1) 709 goto fail; 710 711 printf("Test enqueue for a full entry\n"); 712 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK, 713 test_idx); 714 if (ret != 0) 715 goto fail; 716 717 printf("Test dequeue without enough objects\n"); 718 for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) { 719 ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK, 720 test_idx); 721 if (ret != MAX_BULK) 722 goto fail; 723 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 724 MAX_BULK); 725 } 726 727 /* Available memory space for the exact MAX_BULK entries */ 728 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx); 729 if (ret != 2) 730 goto fail; 731 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2); 732 733 /* Bulk APIs enqueue exact number of elements */ 734 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK) 735 num_elems = MAX_BULK - 3; 736 else 737 num_elems = MAX_BULK; 738 ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems, 739 test_idx); 740 if (ret != MAX_BULK - 3) 741 goto fail; 742 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3); 743 744 printf("Test if ring is empty\n"); 745 /* Check if ring is empty */ 746 if (rte_ring_empty(r) != 1) 747 goto fail; 748 749 /* check data */ 750 if (memcmp(src, dst, cur_dst - dst)) { 751 rte_hexdump(stdout, "src", src, cur_src - src); 752 rte_hexdump(stdout, "dst", dst, cur_dst - dst); 753 printf("data after dequeue is not the same\n"); 754 goto fail; 755 } 756 757 /* Free memory before test completed */ 758 rte_ring_free(r); 759 rte_free(src); 760 rte_free(dst); 761 r = NULL; 762 src = NULL; 763 dst = NULL; 764 } 765 766 return 0; 767 fail: 768 rte_ring_free(r); 769 rte_free(src); 770 rte_free(dst); 771 return -1; 772 } 773 774 /* 775 * Test default, single element, bulk and burst APIs 776 */ 777 static int 778 test_ring_basic_ex(void) 779 { 780 int ret = -1; 781 unsigned int i, j; 782 struct rte_ring *rp = NULL; 783 void *obj = NULL; 784 785 for (i = 0; i < RTE_DIM(esize); i++) { 786 obj = test_ring_calloc(RING_SIZE, esize[i]); 787 if (obj == NULL) { 788 printf("%s: failed to alloc memory\n", __func__); 789 goto fail_test; 790 } 791 792 rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE, 793 SOCKET_ID_ANY, 794 RING_F_SP_ENQ | RING_F_SC_DEQ); 795 if (rp == NULL) { 796 printf("%s: failed to create ring\n", __func__); 797 goto fail_test; 798 } 799 800 if (rte_ring_lookup("test_ring_basic_ex") != rp) { 801 printf("%s: failed to find ring\n", __func__); 802 goto fail_test; 803 } 804 805 if (rte_ring_empty(rp) != 1) { 806 printf("%s: ring is not empty but it should be\n", 807 __func__); 808 goto fail_test; 809 } 810 811 printf("%u ring entries are now free\n", 812 rte_ring_free_count(rp)); 813 814 for (j = 0; j < RING_SIZE; j++) { 815 test_ring_enqueue(rp, obj, esize[i], 1, 816 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 817 } 818 819 if (rte_ring_full(rp) != 1) { 820 printf("%s: ring is not full but it should be\n", 821 __func__); 822 goto fail_test; 823 } 824 825 for (j = 0; j < RING_SIZE; j++) { 826 test_ring_dequeue(rp, obj, esize[i], 1, 827 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 828 } 829 830 if (rte_ring_empty(rp) != 1) { 831 printf("%s: ring is not empty but it should be\n", 832 __func__); 833 goto fail_test; 834 } 835 836 /* Following tests use the configured flags to decide 837 * SP/SC or MP/MC. 838 */ 839 /* Covering the ring burst operation */ 840 ret = test_ring_enqueue(rp, obj, esize[i], 2, 841 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); 842 if (ret != 2) { 843 printf("%s: rte_ring_enqueue_burst fails\n", __func__); 844 goto fail_test; 845 } 846 847 ret = test_ring_dequeue(rp, obj, esize[i], 2, 848 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); 849 if (ret != 2) { 850 printf("%s: rte_ring_dequeue_burst fails\n", __func__); 851 goto fail_test; 852 } 853 854 /* Covering the ring bulk operation */ 855 ret = test_ring_enqueue(rp, obj, esize[i], 2, 856 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK); 857 if (ret != 2) { 858 printf("%s: rte_ring_enqueue_bulk fails\n", __func__); 859 goto fail_test; 860 } 861 862 ret = test_ring_dequeue(rp, obj, esize[i], 2, 863 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK); 864 if (ret != 2) { 865 printf("%s: rte_ring_dequeue_bulk fails\n", __func__); 866 goto fail_test; 867 } 868 869 rte_ring_free(rp); 870 rte_free(obj); 871 rp = NULL; 872 obj = NULL; 873 } 874 875 return 0; 876 877 fail_test: 878 rte_ring_free(rp); 879 if (obj != NULL) 880 rte_free(obj); 881 882 return -1; 883 } 884 885 /* 886 * Basic test cases with exact size ring. 887 */ 888 static int 889 test_ring_with_exact_size(void) 890 { 891 struct rte_ring *std_r = NULL, *exact_sz_r = NULL; 892 void *obj_orig; 893 void *obj; 894 const unsigned int ring_sz = 16; 895 unsigned int i, j; 896 int ret = -1; 897 898 for (i = 0; i < RTE_DIM(esize); i++) { 899 test_ring_print_test_string("Test exact size ring", 900 TEST_RING_IGNORE_API_TYPE, 901 esize[i]); 902 903 /* alloc object pointers. Allocate one extra object 904 * and create an unaligned address. 905 */ 906 obj_orig = test_ring_calloc(17, esize[i]); 907 if (obj_orig == NULL) 908 goto test_fail; 909 obj = ((char *)obj_orig) + 1; 910 911 std_r = test_ring_create("std", esize[i], ring_sz, 912 rte_socket_id(), 913 RING_F_SP_ENQ | RING_F_SC_DEQ); 914 if (std_r == NULL) { 915 printf("%s: error, can't create std ring\n", __func__); 916 goto test_fail; 917 } 918 exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz, 919 rte_socket_id(), 920 RING_F_SP_ENQ | RING_F_SC_DEQ | 921 RING_F_EXACT_SZ); 922 if (exact_sz_r == NULL) { 923 printf("%s: error, can't create exact size ring\n", 924 __func__); 925 goto test_fail; 926 } 927 928 /* 929 * Check that the exact size ring is bigger than the 930 * standard ring 931 */ 932 if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) { 933 printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n", 934 __func__, 935 rte_ring_get_size(std_r), 936 rte_ring_get_size(exact_sz_r)); 937 goto test_fail; 938 } 939 /* 940 * check that the exact_sz_ring can hold one more element 941 * than the standard ring. (16 vs 15 elements) 942 */ 943 for (j = 0; j < ring_sz - 1; j++) { 944 test_ring_enqueue(std_r, obj, esize[i], 1, 945 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 946 test_ring_enqueue(exact_sz_r, obj, esize[i], 1, 947 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 948 } 949 ret = test_ring_enqueue(std_r, obj, esize[i], 1, 950 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 951 if (ret != -ENOBUFS) { 952 printf("%s: error, unexpected successful enqueue\n", 953 __func__); 954 goto test_fail; 955 } 956 ret = test_ring_enqueue(exact_sz_r, obj, esize[i], 1, 957 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE); 958 if (ret == -ENOBUFS) { 959 printf("%s: error, enqueue failed\n", __func__); 960 goto test_fail; 961 } 962 963 /* check that dequeue returns the expected number of elements */ 964 ret = test_ring_dequeue(exact_sz_r, obj, esize[i], ring_sz, 965 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST); 966 if (ret != (int)ring_sz) { 967 printf("%s: error, failed to dequeue expected nb of elements\n", 968 __func__); 969 goto test_fail; 970 } 971 972 /* check that the capacity function returns expected value */ 973 if (rte_ring_get_capacity(exact_sz_r) != ring_sz) { 974 printf("%s: error, incorrect ring capacity reported\n", 975 __func__); 976 goto test_fail; 977 } 978 979 rte_free(obj_orig); 980 rte_ring_free(std_r); 981 rte_ring_free(exact_sz_r); 982 obj_orig = NULL; 983 std_r = NULL; 984 exact_sz_r = NULL; 985 } 986 987 return 0; 988 989 test_fail: 990 rte_free(obj_orig); 991 rte_ring_free(std_r); 992 rte_ring_free(exact_sz_r); 993 return -1; 994 } 995 996 static int 997 test_ring(void) 998 { 999 int32_t rc; 1000 unsigned int i; 1001 1002 /* Negative test cases */ 1003 if (test_ring_negative_tests() < 0) 1004 goto test_fail; 1005 1006 /* Some basic operations */ 1007 if (test_ring_basic_ex() < 0) 1008 goto test_fail; 1009 1010 if (test_ring_with_exact_size() < 0) 1011 goto test_fail; 1012 1013 /* Burst and bulk operations with sp/sc, mp/mc and default. 1014 * The test cases are split into smaller test cases to 1015 * help clang compile faster. 1016 */ 1017 for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) { 1018 1019 1020 rc = test_ring_burst_bulk_tests1(i); 1021 if (rc < 0) 1022 goto test_fail; 1023 1024 rc = test_ring_burst_bulk_tests2(i); 1025 if (rc < 0) 1026 goto test_fail; 1027 1028 rc = test_ring_burst_bulk_tests3(i); 1029 if (rc < 0) 1030 goto test_fail; 1031 1032 rc = test_ring_burst_bulk_tests4(i); 1033 if (rc < 0) 1034 goto test_fail; 1035 } 1036 1037 /* dump the ring status */ 1038 rte_ring_list_dump(stdout); 1039 1040 return 0; 1041 1042 test_fail: 1043 1044 return -1; 1045 } 1046 1047 REGISTER_TEST_COMMAND(ring_autotest, test_ring); 1048