build: remove makefiles
[dpdk.git] / app / test / test_ring.c
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);