da57032c713bc08a2bea63e1ac6db1d03c9a4b3c
[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                         if (esize[i] == -1) {
448                                 TEST_RING_VERIFY(memcmp(src, dst,
449                                         rsz * sizeof(void *)) == 0);
450                         } else
451                                 TEST_RING_VERIFY(memcmp(src, dst,
452                                         rsz * esize[i]) == 0);
453                 }
454
455                 /* Free memory before test completed */
456                 rte_ring_free(r);
457                 rte_free(src);
458                 rte_free(dst);
459                 r = NULL;
460                 src = NULL;
461                 dst = NULL;
462         }
463
464         return 0;
465 fail:
466         rte_ring_free(r);
467         rte_free(src);
468         rte_free(dst);
469         return -1;
470 }
471
472 /*
473  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
474  * Sequence of simple enqueues/dequeues and validate the enqueued and
475  * dequeued data.
476  */
477 static int
478 test_ring_burst_bulk_tests2(unsigned int test_idx)
479 {
480         struct rte_ring *r;
481         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
482         int ret;
483         unsigned int i;
484
485         for (i = 0; i < RTE_DIM(esize); i++) {
486                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
487                         test_enqdeq_impl[test_idx].api_type, esize[i]);
488
489                 /* Create the ring */
490                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
491                                 RING_SIZE, SOCKET_ID_ANY,
492                                 test_enqdeq_impl[test_idx].create_flags);
493
494                 /* alloc dummy object pointers */
495                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
496                 if (src == NULL)
497                         goto fail;
498                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
499                 cur_src = src;
500
501                 /* alloc some room for copied objects */
502                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
503                 if (dst == NULL)
504                         goto fail;
505                 cur_dst = dst;
506
507                 printf("enqueue 1 obj\n");
508                 ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
509                 if (ret != 1)
510                         goto fail;
511                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
512
513                 printf("enqueue 2 objs\n");
514                 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
515                 if (ret != 2)
516                         goto fail;
517                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
518
519                 printf("enqueue MAX_BULK objs\n");
520                 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
521                                                 test_idx);
522                 if (ret != MAX_BULK)
523                         goto fail;
524                 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
525
526                 printf("dequeue 1 obj\n");
527                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
528                 if (ret != 1)
529                         goto fail;
530                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
531
532                 printf("dequeue 2 objs\n");
533                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
534                 if (ret != 2)
535                         goto fail;
536                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
537
538                 printf("dequeue MAX_BULK objs\n");
539                 ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
540                                                 test_idx);
541                 if (ret != MAX_BULK)
542                         goto fail;
543                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK);
544
545                 /* check data */
546                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
547                         rte_hexdump(stdout, "src", src,
548                                         RTE_PTR_DIFF(cur_src, src));
549                         rte_hexdump(stdout, "dst", dst,
550                                         RTE_PTR_DIFF(cur_dst, dst));
551                         printf("data after dequeue is not the same\n");
552                         goto fail;
553                 }
554
555                 /* Free memory before test completed */
556                 rte_ring_free(r);
557                 rte_free(src);
558                 rte_free(dst);
559                 r = NULL;
560                 src = NULL;
561                 dst = NULL;
562         }
563
564         return 0;
565 fail:
566         rte_ring_free(r);
567         rte_free(src);
568         rte_free(dst);
569         return -1;
570 }
571
572 /*
573  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
574  * Enqueue and dequeue to cover the entire ring length.
575  */
576 static int
577 test_ring_burst_bulk_tests3(unsigned int test_idx)
578 {
579         struct rte_ring *r;
580         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
581         int ret;
582         unsigned int i, j;
583
584         for (i = 0; i < RTE_DIM(esize); i++) {
585                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
586                         test_enqdeq_impl[test_idx].api_type, esize[i]);
587
588                 /* Create the ring */
589                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
590                                 RING_SIZE, SOCKET_ID_ANY,
591                                 test_enqdeq_impl[test_idx].create_flags);
592
593                 /* alloc dummy object pointers */
594                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
595                 if (src == NULL)
596                         goto fail;
597                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
598                 cur_src = src;
599
600                 /* alloc some room for copied objects */
601                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
602                 if (dst == NULL)
603                         goto fail;
604                 cur_dst = dst;
605
606                 printf("fill and empty the ring\n");
607                 for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
608                         ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
609                                                         test_idx);
610                         if (ret != MAX_BULK)
611                                 goto fail;
612                         cur_src = test_ring_inc_ptr(cur_src, esize[i],
613                                                                 MAX_BULK);
614
615                         ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
616                                                         test_idx);
617                         if (ret != MAX_BULK)
618                                 goto fail;
619                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
620                                                                 MAX_BULK);
621                 }
622
623                 /* check data */
624                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
625                         rte_hexdump(stdout, "src", src,
626                                         RTE_PTR_DIFF(cur_src, src));
627                         rte_hexdump(stdout, "dst", dst,
628                                         RTE_PTR_DIFF(cur_dst, dst));
629                         printf("data after dequeue is not the same\n");
630                         goto fail;
631                 }
632
633                 /* Free memory before test completed */
634                 rte_ring_free(r);
635                 rte_free(src);
636                 rte_free(dst);
637                 r = NULL;
638                 src = NULL;
639                 dst = NULL;
640         }
641
642         return 0;
643 fail:
644         rte_ring_free(r);
645         rte_free(src);
646         rte_free(dst);
647         return -1;
648 }
649
650 /*
651  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
652  * Enqueue till the ring is full and dequeue till the ring becomes empty.
653  */
654 static int
655 test_ring_burst_bulk_tests4(unsigned int test_idx)
656 {
657         struct rte_ring *r;
658         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
659         int ret;
660         unsigned int i, j;
661         unsigned int api_type, num_elems;
662
663         api_type = test_enqdeq_impl[test_idx].api_type;
664
665         for (i = 0; i < RTE_DIM(esize); i++) {
666                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
667                         test_enqdeq_impl[test_idx].api_type, esize[i]);
668
669                 /* Create the ring */
670                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
671                                 RING_SIZE, SOCKET_ID_ANY,
672                                 test_enqdeq_impl[test_idx].create_flags);
673
674                 /* alloc dummy object pointers */
675                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
676                 if (src == NULL)
677                         goto fail;
678                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
679                 cur_src = src;
680
681                 /* alloc some room for copied objects */
682                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
683                 if (dst == NULL)
684                         goto fail;
685                 cur_dst = dst;
686
687                 printf("Test enqueue without enough memory space\n");
688                 for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
689                         ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
690                                                         test_idx);
691                         if (ret != MAX_BULK)
692                                 goto fail;
693                         cur_src = test_ring_inc_ptr(cur_src, esize[i],
694                                                                 MAX_BULK);
695                 }
696
697                 printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
698                 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
699                 if (ret != 2)
700                         goto fail;
701                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
702
703                 printf("Enqueue the remaining entries = MAX_BULK - 3\n");
704                 /* Bulk APIs enqueue exact number of elements */
705                 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
706                         num_elems = MAX_BULK - 3;
707                 else
708                         num_elems = MAX_BULK;
709                 /* Always one free entry left */
710                 ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
711                                                 test_idx);
712                 if (ret != MAX_BULK - 3)
713                         goto fail;
714                 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
715
716                 printf("Test if ring is full\n");
717                 if (rte_ring_full(r) != 1)
718                         goto fail;
719
720                 printf("Test enqueue for a full entry\n");
721                 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
722                                                 test_idx);
723                 if (ret != 0)
724                         goto fail;
725
726                 printf("Test dequeue without enough objects\n");
727                 for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
728                         ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
729                                                         test_idx);
730                         if (ret != MAX_BULK)
731                                 goto fail;
732                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
733                                                                 MAX_BULK);
734                 }
735
736                 /* Available memory space for the exact MAX_BULK entries */
737                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
738                 if (ret != 2)
739                         goto fail;
740                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
741
742                 /* Bulk APIs enqueue exact number of elements */
743                 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
744                         num_elems = MAX_BULK - 3;
745                 else
746                         num_elems = MAX_BULK;
747                 ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
748                                                 test_idx);
749                 if (ret != MAX_BULK - 3)
750                         goto fail;
751                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
752
753                 printf("Test if ring is empty\n");
754                 /* Check if ring is empty */
755                 if (rte_ring_empty(r) != 1)
756                         goto fail;
757
758                 /* check data */
759                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
760                         rte_hexdump(stdout, "src", src,
761                                         RTE_PTR_DIFF(cur_src, src));
762                         rte_hexdump(stdout, "dst", dst,
763                                         RTE_PTR_DIFF(cur_dst, dst));
764                         printf("data after dequeue is not the same\n");
765                         goto fail;
766                 }
767
768                 /* Free memory before test completed */
769                 rte_ring_free(r);
770                 rte_free(src);
771                 rte_free(dst);
772                 r = NULL;
773                 src = NULL;
774                 dst = NULL;
775         }
776
777         return 0;
778 fail:
779         rte_ring_free(r);
780         rte_free(src);
781         rte_free(dst);
782         return -1;
783 }
784
785 /*
786  * Test default, single element, bulk and burst APIs
787  */
788 static int
789 test_ring_basic_ex(void)
790 {
791         int ret = -1;
792         unsigned int i, j;
793         struct rte_ring *rp = NULL;
794         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
795
796         for (i = 0; i < RTE_DIM(esize); i++) {
797                 rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE,
798                                         SOCKET_ID_ANY,
799                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
800                 if (rp == NULL) {
801                         printf("%s: failed to create ring\n", __func__);
802                         goto fail_test;
803                 }
804
805                 /* alloc dummy object pointers */
806                 src = test_ring_calloc(RING_SIZE, esize[i]);
807                 if (src == NULL) {
808                         printf("%s: failed to alloc src memory\n", __func__);
809                         goto fail_test;
810                 }
811                 test_ring_mem_init(src, RING_SIZE, esize[i]);
812                 cur_src = src;
813
814                 /* alloc some room for copied objects */
815                 dst = test_ring_calloc(RING_SIZE, esize[i]);
816                 if (dst == NULL) {
817                         printf("%s: failed to alloc dst memory\n", __func__);
818                         goto fail_test;
819                 }
820                 cur_dst = dst;
821
822                 if (rte_ring_lookup("test_ring_basic_ex") != rp) {
823                         printf("%s: failed to find ring\n", __func__);
824                         goto fail_test;
825                 }
826
827                 if (rte_ring_empty(rp) != 1) {
828                         printf("%s: ring is not empty but it should be\n",
829                                 __func__);
830                         goto fail_test;
831                 }
832
833                 printf("%u ring entries are now free\n",
834                         rte_ring_free_count(rp));
835
836                 for (j = 0; j < RING_SIZE - 1; j++) {
837                         ret = test_ring_enqueue(rp, cur_src, esize[i], 1,
838                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
839                         if (ret != 0) {
840                                 printf("%s: rte_ring_enqueue fails\n",
841                                         __func__);
842                                 goto fail_test;
843                         }
844                         cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
845                 }
846
847                 if (rte_ring_full(rp) != 1) {
848                         printf("%s: ring is not full but it should be\n",
849                                 __func__);
850                         goto fail_test;
851                 }
852
853                 for (j = 0; j < RING_SIZE - 1; j++) {
854                         ret = test_ring_dequeue(rp, cur_dst, esize[i], 1,
855                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
856                         if (ret != 0) {
857                                 printf("%s: rte_ring_dequeue fails\n",
858                                         __func__);
859                                 goto fail_test;
860                         }
861                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
862                 }
863
864                 if (rte_ring_empty(rp) != 1) {
865                         printf("%s: ring is not empty but it should be\n",
866                                 __func__);
867                         goto fail_test;
868                 }
869
870                 /* check data */
871                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
872                         rte_hexdump(stdout, "src", src, RTE_PTR_DIFF(cur_src, src));
873                         rte_hexdump(stdout, "dst", dst, RTE_PTR_DIFF(cur_dst, dst));
874                         printf("data after dequeue is not the same\n");
875                         goto fail_test;
876                 }
877
878                 /* Following tests use the configured flags to decide
879                  * SP/SC or MP/MC.
880                  */
881                 /* reset memory of dst */
882                 memset(dst, 0, RTE_PTR_DIFF(cur_dst, dst));
883
884                 /* reset cur_src and cur_dst */
885                 cur_src = src;
886                 cur_dst = dst;
887
888                 /* Covering the ring burst operation */
889                 ret = test_ring_enqueue(rp, cur_src, esize[i], 2,
890                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
891                 if (ret != 2) {
892                         printf("%s: rte_ring_enqueue_burst fails\n", __func__);
893                         goto fail_test;
894                 }
895                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
896
897                 ret = test_ring_dequeue(rp, cur_dst, esize[i], 2,
898                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
899                 if (ret != 2) {
900                         printf("%s: rte_ring_dequeue_burst fails\n", __func__);
901                         goto fail_test;
902                 }
903                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
904
905                 /* Covering the ring bulk operation */
906                 ret = test_ring_enqueue(rp, cur_src, esize[i], 2,
907                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
908                 if (ret != 2) {
909                         printf("%s: rte_ring_enqueue_bulk fails\n", __func__);
910                         goto fail_test;
911                 }
912                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
913
914                 ret = test_ring_dequeue(rp, cur_dst, esize[i], 2,
915                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
916                 if (ret != 2) {
917                         printf("%s: rte_ring_dequeue_bulk fails\n", __func__);
918                         goto fail_test;
919                 }
920                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
921
922                 /* check data */
923                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
924                         rte_hexdump(stdout, "src", src, RTE_PTR_DIFF(cur_src, src));
925                         rte_hexdump(stdout, "dst", dst, RTE_PTR_DIFF(cur_dst, dst));
926                         printf("data after dequeue is not the same\n");
927                         goto fail_test;
928                 }
929
930                 rte_ring_free(rp);
931                 rte_free(src);
932                 rte_free(dst);
933                 rp = NULL;
934                 src = NULL;
935                 dst = NULL;
936         }
937
938         return 0;
939
940 fail_test:
941         rte_ring_free(rp);
942         rte_free(src);
943         rte_free(dst);
944         return -1;
945 }
946
947 /*
948  * Basic test cases with exact size ring.
949  */
950 static int
951 test_ring_with_exact_size(void)
952 {
953         struct rte_ring *std_r = NULL, *exact_sz_r = NULL;
954         void **src_orig = NULL, **dst_orig = NULL;
955         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
956         const unsigned int ring_sz = 16;
957         unsigned int i, j;
958         int ret = -1;
959
960         for (i = 0; i < RTE_DIM(esize); i++) {
961                 test_ring_print_test_string("Test exact size ring",
962                                 TEST_RING_IGNORE_API_TYPE,
963                                 esize[i]);
964
965                 std_r = test_ring_create("std", esize[i], ring_sz,
966                                         rte_socket_id(),
967                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
968                 if (std_r == NULL) {
969                         printf("%s: error, can't create std ring\n", __func__);
970                         goto test_fail;
971                 }
972                 exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz,
973                                 rte_socket_id(),
974                                 RING_F_SP_ENQ | RING_F_SC_DEQ |
975                                 RING_F_EXACT_SZ);
976                 if (exact_sz_r == NULL) {
977                         printf("%s: error, can't create exact size ring\n",
978                                         __func__);
979                         goto test_fail;
980                 }
981
982                 /* alloc object pointers. Allocate one extra object
983                  * and create an unaligned address.
984                  */
985                 src_orig = test_ring_calloc(17, esize[i]);
986                 if (src_orig == NULL)
987                         goto test_fail;
988                 test_ring_mem_init(src_orig, 17, esize[i]);
989                 src = (void **)((uintptr_t)src_orig + 1);
990                 cur_src = src;
991
992                 dst_orig = test_ring_calloc(17, esize[i]);
993                 if (dst_orig == NULL)
994                         goto test_fail;
995                 dst = (void **)((uintptr_t)dst_orig + 1);
996                 cur_dst = dst;
997
998                 /*
999                  * Check that the exact size ring is bigger than the
1000                  * standard ring
1001                  */
1002                 if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) {
1003                         printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
1004                                         __func__,
1005                                         rte_ring_get_size(std_r),
1006                                         rte_ring_get_size(exact_sz_r));
1007                         goto test_fail;
1008                 }
1009                 /*
1010                  * check that the exact_sz_ring can hold one more element
1011                  * than the standard ring. (16 vs 15 elements)
1012                  */
1013                 for (j = 0; j < ring_sz - 1; j++) {
1014                         ret = test_ring_enqueue(std_r, cur_src, esize[i], 1,
1015                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1016                         if (ret != 0) {
1017                                 printf("%s: error, enqueue failed\n", __func__);
1018                                 goto test_fail;
1019                         }
1020                         ret = test_ring_enqueue(exact_sz_r, cur_src, esize[i], 1,
1021                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1022                         if (ret != 0) {
1023                                 printf("%s: error, enqueue failed\n", __func__);
1024                                 goto test_fail;
1025                         }
1026                         cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
1027                 }
1028                 ret = test_ring_enqueue(std_r, cur_src, esize[i], 1,
1029                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1030                 if (ret != -ENOBUFS) {
1031                         printf("%s: error, unexpected successful enqueue\n",
1032                                 __func__);
1033                         goto test_fail;
1034                 }
1035                 ret = test_ring_enqueue(exact_sz_r, cur_src, esize[i], 1,
1036                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1037                 if (ret == -ENOBUFS) {
1038                         printf("%s: error, enqueue failed\n", __func__);
1039                         goto test_fail;
1040                 }
1041                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
1042
1043                 /* check that dequeue returns the expected number of elements */
1044                 ret = test_ring_dequeue(exact_sz_r, cur_dst, esize[i], ring_sz,
1045                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
1046                 if (ret != (int)ring_sz) {
1047                         printf("%s: error, failed to dequeue expected nb of elements\n",
1048                                 __func__);
1049                         goto test_fail;
1050                 }
1051                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], ring_sz);
1052
1053                 /* check that the capacity function returns expected value */
1054                 if (rte_ring_get_capacity(exact_sz_r) != ring_sz) {
1055                         printf("%s: error, incorrect ring capacity reported\n",
1056                                         __func__);
1057                         goto test_fail;
1058                 }
1059
1060                 /* check data */
1061                 if (memcmp(src, dst, RTE_PTR_DIFF(cur_dst, dst))) {
1062                         rte_hexdump(stdout, "src", src, RTE_PTR_DIFF(cur_src, src));
1063                         rte_hexdump(stdout, "dst", dst, RTE_PTR_DIFF(cur_dst, dst));
1064                         printf("data after dequeue is not the same\n");
1065                         goto test_fail;
1066                 }
1067
1068                 rte_free(src_orig);
1069                 rte_free(dst_orig);
1070                 rte_ring_free(std_r);
1071                 rte_ring_free(exact_sz_r);
1072                 src_orig = NULL;
1073                 dst_orig = NULL;
1074                 std_r = NULL;
1075                 exact_sz_r = NULL;
1076         }
1077
1078         return 0;
1079
1080 test_fail:
1081         rte_free(src_orig);
1082         rte_free(dst_orig);
1083         rte_ring_free(std_r);
1084         rte_ring_free(exact_sz_r);
1085         return -1;
1086 }
1087
1088 static int
1089 test_ring(void)
1090 {
1091         int32_t rc;
1092         unsigned int i;
1093
1094         /* Negative test cases */
1095         if (test_ring_negative_tests() < 0)
1096                 goto test_fail;
1097
1098         /* Some basic operations */
1099         if (test_ring_basic_ex() < 0)
1100                 goto test_fail;
1101
1102         if (test_ring_with_exact_size() < 0)
1103                 goto test_fail;
1104
1105         /* Burst and bulk operations with sp/sc, mp/mc and default.
1106          * The test cases are split into smaller test cases to
1107          * help clang compile faster.
1108          */
1109         for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
1110
1111
1112                 rc = test_ring_burst_bulk_tests1(i);
1113                 if (rc < 0)
1114                         goto test_fail;
1115
1116                 rc = test_ring_burst_bulk_tests2(i);
1117                 if (rc < 0)
1118                         goto test_fail;
1119
1120                 rc = test_ring_burst_bulk_tests3(i);
1121                 if (rc < 0)
1122                         goto test_fail;
1123
1124                 rc = test_ring_burst_bulk_tests4(i);
1125                 if (rc < 0)
1126                         goto test_fail;
1127         }
1128
1129         /* dump the ring status */
1130         rte_ring_list_dump(stdout);
1131
1132         return 0;
1133
1134 test_fail:
1135
1136         return -1;
1137 }
1138
1139 REGISTER_TEST_COMMAND(ring_autotest, test_ring);