test/ring: factorize object checks
[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 int
262 test_ring_mem_cmp(void *src, void *dst, unsigned int size)
263 {
264         int ret;
265
266         ret = memcmp(src, dst, size);
267         if (ret) {
268                 rte_hexdump(stdout, "src", src, size);
269                 rte_hexdump(stdout, "dst", dst, size);
270                 printf("data after dequeue is not the same\n");
271         }
272
273         return ret;
274 }
275
276 static void
277 test_ring_print_test_string(const char *istr, unsigned int api_type, int esize)
278 {
279         printf("\n%s: ", istr);
280
281         if (esize == -1)
282                 printf("legacy APIs: ");
283         else
284                 printf("elem APIs: element size %dB ", esize);
285
286         if (api_type == TEST_RING_IGNORE_API_TYPE)
287                 return;
288
289         if (api_type & TEST_RING_THREAD_DEF)
290                 printf(": default enqueue/dequeue: ");
291         else if (api_type & TEST_RING_THREAD_SPSC)
292                 printf(": SP/SC: ");
293         else if (api_type & TEST_RING_THREAD_MPMC)
294                 printf(": MP/MC: ");
295
296         if (api_type & TEST_RING_ELEM_SINGLE)
297                 printf("single\n");
298         else if (api_type & TEST_RING_ELEM_BULK)
299                 printf("bulk\n");
300         else if (api_type & TEST_RING_ELEM_BURST)
301                 printf("burst\n");
302 }
303
304 /*
305  * Various negative test cases.
306  */
307 static int
308 test_ring_negative_tests(void)
309 {
310         struct rte_ring *rp = NULL;
311         struct rte_ring *rt = NULL;
312         unsigned int i;
313
314         /* Test with esize not a multiple of 4 */
315         rp = test_ring_create("test_bad_element_size", 23,
316                                 RING_SIZE + 1, SOCKET_ID_ANY, 0);
317         if (rp != NULL) {
318                 printf("Test failed to detect invalid element size\n");
319                 goto test_fail;
320         }
321
322
323         for (i = 0; i < RTE_DIM(esize); i++) {
324                 /* Test if ring size is not power of 2 */
325                 rp = test_ring_create("test_bad_ring_size", esize[i],
326                                         RING_SIZE + 1, SOCKET_ID_ANY, 0);
327                 if (rp != NULL) {
328                         printf("Test failed to detect odd count\n");
329                         goto test_fail;
330                 }
331
332                 /* Test if ring size is exceeding the limit */
333                 rp = test_ring_create("test_bad_ring_size", esize[i],
334                                         RTE_RING_SZ_MASK + 1, SOCKET_ID_ANY, 0);
335                 if (rp != NULL) {
336                         printf("Test failed to detect limits\n");
337                         goto test_fail;
338                 }
339
340                 /* Tests if lookup returns NULL on non-existing ring */
341                 rp = rte_ring_lookup("ring_not_found");
342                 if (rp != NULL && rte_errno != ENOENT) {
343                         printf("Test failed to detect NULL ring lookup\n");
344                         goto test_fail;
345                 }
346
347                 /* Test to if a non-power of 2 count causes the create
348                  * function to fail correctly
349                  */
350                 rp = test_ring_create("test_ring_count", esize[i], 4097,
351                                         SOCKET_ID_ANY, 0);
352                 if (rp != NULL)
353                         goto test_fail;
354
355                 rp = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
356                                         SOCKET_ID_ANY,
357                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
358                 if (rp == NULL) {
359                         printf("test_ring_negative fail to create ring\n");
360                         goto test_fail;
361                 }
362
363                 if (rte_ring_lookup("test_ring_negative") != rp)
364                         goto test_fail;
365
366                 if (rte_ring_empty(rp) != 1) {
367                         printf("test_ring_nagative ring is not empty but it should be\n");
368                         goto test_fail;
369                 }
370
371                 /* Tests if it would always fail to create ring with an used
372                  * ring name.
373                  */
374                 rt = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
375                                         SOCKET_ID_ANY, 0);
376                 if (rt != NULL)
377                         goto test_fail;
378
379                 rte_ring_free(rp);
380                 rp = NULL;
381         }
382
383         return 0;
384
385 test_fail:
386
387         rte_ring_free(rp);
388         return -1;
389 }
390
391 /*
392  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
393  * Random number of elements are enqueued and dequeued.
394  */
395 static int
396 test_ring_burst_bulk_tests1(unsigned int test_idx)
397 {
398         struct rte_ring *r;
399         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
400         int ret;
401         unsigned int i, j, temp_sz;
402         int rand;
403         const unsigned int rsz = RING_SIZE - 1;
404
405         for (i = 0; i < RTE_DIM(esize); i++) {
406                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
407                         test_enqdeq_impl[test_idx].api_type, esize[i]);
408
409                 /* Create the ring */
410                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
411                                 RING_SIZE, SOCKET_ID_ANY,
412                                 test_enqdeq_impl[test_idx].create_flags);
413
414                 /* alloc dummy object pointers */
415                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
416                 if (src == NULL)
417                         goto fail;
418                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
419                 cur_src = src;
420
421                 /* alloc some room for copied objects */
422                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
423                 if (dst == NULL)
424                         goto fail;
425                 cur_dst = dst;
426
427                 printf("Random full/empty test\n");
428
429                 for (j = 0; j != TEST_RING_FULL_EMTPY_ITER; j++) {
430                         /* random shift in the ring */
431                         rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
432                         printf("%s: iteration %u, random shift: %u;\n",
433                             __func__, i, rand);
434                         ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
435                                                         test_idx);
436                         TEST_RING_VERIFY(ret != 0);
437
438                         ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
439                                                         test_idx);
440                         TEST_RING_VERIFY(ret == rand);
441
442                         /* fill the ring */
443                         ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
444                                                         test_idx);
445                         TEST_RING_VERIFY(ret != 0);
446
447                         TEST_RING_VERIFY(rte_ring_free_count(r) == 0);
448                         TEST_RING_VERIFY(rsz == rte_ring_count(r));
449                         TEST_RING_VERIFY(rte_ring_full(r));
450                         TEST_RING_VERIFY(rte_ring_empty(r) == 0);
451
452                         /* empty the ring */
453                         ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
454                                                         test_idx);
455                         TEST_RING_VERIFY(ret == (int)rsz);
456                         TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
457                         TEST_RING_VERIFY(rte_ring_count(r) == 0);
458                         TEST_RING_VERIFY(rte_ring_full(r) == 0);
459                         TEST_RING_VERIFY(rte_ring_empty(r));
460
461                         /* check data */
462                         temp_sz = rsz * sizeof(void *);
463                         if (esize[i] != -1)
464                                 temp_sz = rsz * esize[i];
465                         TEST_RING_VERIFY(test_ring_mem_cmp(src, dst,
466                                                 temp_sz) == 0);
467                 }
468
469                 /* Free memory before test completed */
470                 rte_ring_free(r);
471                 rte_free(src);
472                 rte_free(dst);
473                 r = NULL;
474                 src = NULL;
475                 dst = NULL;
476         }
477
478         return 0;
479 fail:
480         rte_ring_free(r);
481         rte_free(src);
482         rte_free(dst);
483         return -1;
484 }
485
486 /*
487  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
488  * Sequence of simple enqueues/dequeues and validate the enqueued and
489  * dequeued data.
490  */
491 static int
492 test_ring_burst_bulk_tests2(unsigned int test_idx)
493 {
494         struct rte_ring *r;
495         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
496         int ret;
497         unsigned int i;
498
499         for (i = 0; i < RTE_DIM(esize); i++) {
500                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
501                         test_enqdeq_impl[test_idx].api_type, esize[i]);
502
503                 /* Create the ring */
504                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
505                                 RING_SIZE, SOCKET_ID_ANY,
506                                 test_enqdeq_impl[test_idx].create_flags);
507
508                 /* alloc dummy object pointers */
509                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
510                 if (src == NULL)
511                         goto fail;
512                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
513                 cur_src = src;
514
515                 /* alloc some room for copied objects */
516                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
517                 if (dst == NULL)
518                         goto fail;
519                 cur_dst = dst;
520
521                 printf("enqueue 1 obj\n");
522                 ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
523                 if (ret != 1)
524                         goto fail;
525                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
526
527                 printf("enqueue 2 objs\n");
528                 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
529                 if (ret != 2)
530                         goto fail;
531                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
532
533                 printf("enqueue MAX_BULK objs\n");
534                 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
535                                                 test_idx);
536                 if (ret != MAX_BULK)
537                         goto fail;
538                 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
539
540                 printf("dequeue 1 obj\n");
541                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
542                 if (ret != 1)
543                         goto fail;
544                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
545
546                 printf("dequeue 2 objs\n");
547                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
548                 if (ret != 2)
549                         goto fail;
550                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
551
552                 printf("dequeue MAX_BULK objs\n");
553                 ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
554                                                 test_idx);
555                 if (ret != MAX_BULK)
556                         goto fail;
557                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK);
558
559                 /* check data */
560                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
561                         goto fail;
562
563                 /* Free memory before test completed */
564                 rte_ring_free(r);
565                 rte_free(src);
566                 rte_free(dst);
567                 r = NULL;
568                 src = NULL;
569                 dst = NULL;
570         }
571
572         return 0;
573 fail:
574         rte_ring_free(r);
575         rte_free(src);
576         rte_free(dst);
577         return -1;
578 }
579
580 /*
581  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
582  * Enqueue and dequeue to cover the entire ring length.
583  */
584 static int
585 test_ring_burst_bulk_tests3(unsigned int test_idx)
586 {
587         struct rte_ring *r;
588         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
589         int ret;
590         unsigned int i, j;
591
592         for (i = 0; i < RTE_DIM(esize); i++) {
593                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
594                         test_enqdeq_impl[test_idx].api_type, esize[i]);
595
596                 /* Create the ring */
597                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
598                                 RING_SIZE, SOCKET_ID_ANY,
599                                 test_enqdeq_impl[test_idx].create_flags);
600
601                 /* alloc dummy object pointers */
602                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
603                 if (src == NULL)
604                         goto fail;
605                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
606                 cur_src = src;
607
608                 /* alloc some room for copied objects */
609                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
610                 if (dst == NULL)
611                         goto fail;
612                 cur_dst = dst;
613
614                 printf("fill and empty the ring\n");
615                 for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
616                         ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
617                                                         test_idx);
618                         if (ret != MAX_BULK)
619                                 goto fail;
620                         cur_src = test_ring_inc_ptr(cur_src, esize[i],
621                                                                 MAX_BULK);
622
623                         ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
624                                                         test_idx);
625                         if (ret != MAX_BULK)
626                                 goto fail;
627                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
628                                                                 MAX_BULK);
629                 }
630
631                 /* check data */
632                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
633                         goto fail;
634
635                 /* Free memory before test completed */
636                 rte_ring_free(r);
637                 rte_free(src);
638                 rte_free(dst);
639                 r = NULL;
640                 src = NULL;
641                 dst = NULL;
642         }
643
644         return 0;
645 fail:
646         rte_ring_free(r);
647         rte_free(src);
648         rte_free(dst);
649         return -1;
650 }
651
652 /*
653  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
654  * Enqueue till the ring is full and dequeue till the ring becomes empty.
655  */
656 static int
657 test_ring_burst_bulk_tests4(unsigned int test_idx)
658 {
659         struct rte_ring *r;
660         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
661         int ret;
662         unsigned int i, j;
663         unsigned int api_type, num_elems;
664
665         api_type = test_enqdeq_impl[test_idx].api_type;
666
667         for (i = 0; i < RTE_DIM(esize); i++) {
668                 test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
669                         test_enqdeq_impl[test_idx].api_type, esize[i]);
670
671                 /* Create the ring */
672                 r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
673                                 RING_SIZE, SOCKET_ID_ANY,
674                                 test_enqdeq_impl[test_idx].create_flags);
675
676                 /* alloc dummy object pointers */
677                 src = test_ring_calloc(RING_SIZE * 2, esize[i]);
678                 if (src == NULL)
679                         goto fail;
680                 test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
681                 cur_src = src;
682
683                 /* alloc some room for copied objects */
684                 dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
685                 if (dst == NULL)
686                         goto fail;
687                 cur_dst = dst;
688
689                 printf("Test enqueue without enough memory space\n");
690                 for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
691                         ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
692                                                         test_idx);
693                         if (ret != MAX_BULK)
694                                 goto fail;
695                         cur_src = test_ring_inc_ptr(cur_src, esize[i],
696                                                                 MAX_BULK);
697                 }
698
699                 printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
700                 ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
701                 if (ret != 2)
702                         goto fail;
703                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
704
705                 printf("Enqueue the remaining entries = MAX_BULK - 3\n");
706                 /* Bulk APIs enqueue exact number of elements */
707                 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
708                         num_elems = MAX_BULK - 3;
709                 else
710                         num_elems = MAX_BULK;
711                 /* Always one free entry left */
712                 ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
713                                                 test_idx);
714                 if (ret != MAX_BULK - 3)
715                         goto fail;
716                 cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
717
718                 printf("Test if ring is full\n");
719                 if (rte_ring_full(r) != 1)
720                         goto fail;
721
722                 printf("Test enqueue for a full entry\n");
723                 ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
724                                                 test_idx);
725                 if (ret != 0)
726                         goto fail;
727
728                 printf("Test dequeue without enough objects\n");
729                 for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
730                         ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
731                                                         test_idx);
732                         if (ret != MAX_BULK)
733                                 goto fail;
734                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
735                                                                 MAX_BULK);
736                 }
737
738                 /* Available memory space for the exact MAX_BULK entries */
739                 ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
740                 if (ret != 2)
741                         goto fail;
742                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
743
744                 /* Bulk APIs enqueue exact number of elements */
745                 if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
746                         num_elems = MAX_BULK - 3;
747                 else
748                         num_elems = MAX_BULK;
749                 ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
750                                                 test_idx);
751                 if (ret != MAX_BULK - 3)
752                         goto fail;
753                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
754
755                 printf("Test if ring is empty\n");
756                 /* Check if ring is empty */
757                 if (rte_ring_empty(r) != 1)
758                         goto fail;
759
760                 /* check data */
761                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
762                         goto fail;
763
764                 /* Free memory before test completed */
765                 rte_ring_free(r);
766                 rte_free(src);
767                 rte_free(dst);
768                 r = NULL;
769                 src = NULL;
770                 dst = NULL;
771         }
772
773         return 0;
774 fail:
775         rte_ring_free(r);
776         rte_free(src);
777         rte_free(dst);
778         return -1;
779 }
780
781 /*
782  * Test default, single element, bulk and burst APIs
783  */
784 static int
785 test_ring_basic_ex(void)
786 {
787         int ret = -1;
788         unsigned int i, j;
789         struct rte_ring *rp = NULL;
790         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
791
792         for (i = 0; i < RTE_DIM(esize); i++) {
793                 rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE,
794                                         SOCKET_ID_ANY,
795                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
796                 if (rp == NULL) {
797                         printf("%s: failed to create ring\n", __func__);
798                         goto fail_test;
799                 }
800
801                 /* alloc dummy object pointers */
802                 src = test_ring_calloc(RING_SIZE, esize[i]);
803                 if (src == NULL) {
804                         printf("%s: failed to alloc src memory\n", __func__);
805                         goto fail_test;
806                 }
807                 test_ring_mem_init(src, RING_SIZE, esize[i]);
808                 cur_src = src;
809
810                 /* alloc some room for copied objects */
811                 dst = test_ring_calloc(RING_SIZE, esize[i]);
812                 if (dst == NULL) {
813                         printf("%s: failed to alloc dst memory\n", __func__);
814                         goto fail_test;
815                 }
816                 cur_dst = dst;
817
818                 if (rte_ring_lookup("test_ring_basic_ex") != rp) {
819                         printf("%s: failed to find ring\n", __func__);
820                         goto fail_test;
821                 }
822
823                 if (rte_ring_empty(rp) != 1) {
824                         printf("%s: ring is not empty but it should be\n",
825                                 __func__);
826                         goto fail_test;
827                 }
828
829                 printf("%u ring entries are now free\n",
830                         rte_ring_free_count(rp));
831
832                 for (j = 0; j < RING_SIZE - 1; j++) {
833                         ret = test_ring_enqueue(rp, cur_src, esize[i], 1,
834                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
835                         if (ret != 0) {
836                                 printf("%s: rte_ring_enqueue fails\n",
837                                         __func__);
838                                 goto fail_test;
839                         }
840                         cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
841                 }
842
843                 if (rte_ring_full(rp) != 1) {
844                         printf("%s: ring is not full but it should be\n",
845                                 __func__);
846                         goto fail_test;
847                 }
848
849                 for (j = 0; j < RING_SIZE - 1; j++) {
850                         ret = test_ring_dequeue(rp, cur_dst, esize[i], 1,
851                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
852                         if (ret != 0) {
853                                 printf("%s: rte_ring_dequeue fails\n",
854                                         __func__);
855                                 goto fail_test;
856                         }
857                         cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
858                 }
859
860                 if (rte_ring_empty(rp) != 1) {
861                         printf("%s: ring is not empty but it should be\n",
862                                 __func__);
863                         goto fail_test;
864                 }
865
866                 /* check data */
867                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
868                         goto fail_test;
869
870                 /* Following tests use the configured flags to decide
871                  * SP/SC or MP/MC.
872                  */
873                 /* reset memory of dst */
874                 memset(dst, 0, RTE_PTR_DIFF(cur_dst, dst));
875
876                 /* reset cur_src and cur_dst */
877                 cur_src = src;
878                 cur_dst = dst;
879
880                 /* Covering the ring burst operation */
881                 ret = test_ring_enqueue(rp, cur_src, esize[i], 2,
882                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
883                 if (ret != 2) {
884                         printf("%s: rte_ring_enqueue_burst fails\n", __func__);
885                         goto fail_test;
886                 }
887                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
888
889                 ret = test_ring_dequeue(rp, cur_dst, esize[i], 2,
890                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
891                 if (ret != 2) {
892                         printf("%s: rte_ring_dequeue_burst fails\n", __func__);
893                         goto fail_test;
894                 }
895                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
896
897                 /* Covering the ring bulk operation */
898                 ret = test_ring_enqueue(rp, cur_src, esize[i], 2,
899                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
900                 if (ret != 2) {
901                         printf("%s: rte_ring_enqueue_bulk fails\n", __func__);
902                         goto fail_test;
903                 }
904                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
905
906                 ret = test_ring_dequeue(rp, cur_dst, esize[i], 2,
907                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
908                 if (ret != 2) {
909                         printf("%s: rte_ring_dequeue_bulk fails\n", __func__);
910                         goto fail_test;
911                 }
912                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
913
914                 /* check data */
915                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
916                         goto fail_test;
917
918                 rte_ring_free(rp);
919                 rte_free(src);
920                 rte_free(dst);
921                 rp = NULL;
922                 src = NULL;
923                 dst = NULL;
924         }
925
926         return 0;
927
928 fail_test:
929         rte_ring_free(rp);
930         rte_free(src);
931         rte_free(dst);
932         return -1;
933 }
934
935 /*
936  * Basic test cases with exact size ring.
937  */
938 static int
939 test_ring_with_exact_size(void)
940 {
941         struct rte_ring *std_r = NULL, *exact_sz_r = NULL;
942         void **src_orig = NULL, **dst_orig = NULL;
943         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
944         const unsigned int ring_sz = 16;
945         unsigned int i, j;
946         int ret = -1;
947
948         for (i = 0; i < RTE_DIM(esize); i++) {
949                 test_ring_print_test_string("Test exact size ring",
950                                 TEST_RING_IGNORE_API_TYPE,
951                                 esize[i]);
952
953                 std_r = test_ring_create("std", esize[i], ring_sz,
954                                         rte_socket_id(),
955                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
956                 if (std_r == NULL) {
957                         printf("%s: error, can't create std ring\n", __func__);
958                         goto test_fail;
959                 }
960                 exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz,
961                                 rte_socket_id(),
962                                 RING_F_SP_ENQ | RING_F_SC_DEQ |
963                                 RING_F_EXACT_SZ);
964                 if (exact_sz_r == NULL) {
965                         printf("%s: error, can't create exact size ring\n",
966                                         __func__);
967                         goto test_fail;
968                 }
969
970                 /* alloc object pointers. Allocate one extra object
971                  * and create an unaligned address.
972                  */
973                 src_orig = test_ring_calloc(17, esize[i]);
974                 if (src_orig == NULL)
975                         goto test_fail;
976                 test_ring_mem_init(src_orig, 17, esize[i]);
977                 src = (void **)((uintptr_t)src_orig + 1);
978                 cur_src = src;
979
980                 dst_orig = test_ring_calloc(17, esize[i]);
981                 if (dst_orig == NULL)
982                         goto test_fail;
983                 dst = (void **)((uintptr_t)dst_orig + 1);
984                 cur_dst = dst;
985
986                 /*
987                  * Check that the exact size ring is bigger than the
988                  * standard ring
989                  */
990                 if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) {
991                         printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
992                                         __func__,
993                                         rte_ring_get_size(std_r),
994                                         rte_ring_get_size(exact_sz_r));
995                         goto test_fail;
996                 }
997                 /*
998                  * check that the exact_sz_ring can hold one more element
999                  * than the standard ring. (16 vs 15 elements)
1000                  */
1001                 for (j = 0; j < ring_sz - 1; j++) {
1002                         ret = test_ring_enqueue(std_r, cur_src, esize[i], 1,
1003                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1004                         if (ret != 0) {
1005                                 printf("%s: error, enqueue failed\n", __func__);
1006                                 goto test_fail;
1007                         }
1008                         ret = test_ring_enqueue(exact_sz_r, cur_src, esize[i], 1,
1009                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1010                         if (ret != 0) {
1011                                 printf("%s: error, enqueue failed\n", __func__);
1012                                 goto test_fail;
1013                         }
1014                         cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
1015                 }
1016                 ret = test_ring_enqueue(std_r, cur_src, esize[i], 1,
1017                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1018                 if (ret != -ENOBUFS) {
1019                         printf("%s: error, unexpected successful enqueue\n",
1020                                 __func__);
1021                         goto test_fail;
1022                 }
1023                 ret = test_ring_enqueue(exact_sz_r, cur_src, esize[i], 1,
1024                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
1025                 if (ret == -ENOBUFS) {
1026                         printf("%s: error, enqueue failed\n", __func__);
1027                         goto test_fail;
1028                 }
1029                 cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
1030
1031                 /* check that dequeue returns the expected number of elements */
1032                 ret = test_ring_dequeue(exact_sz_r, cur_dst, esize[i], ring_sz,
1033                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
1034                 if (ret != (int)ring_sz) {
1035                         printf("%s: error, failed to dequeue expected nb of elements\n",
1036                                 __func__);
1037                         goto test_fail;
1038                 }
1039                 cur_dst = test_ring_inc_ptr(cur_dst, esize[i], ring_sz);
1040
1041                 /* check that the capacity function returns expected value */
1042                 if (rte_ring_get_capacity(exact_sz_r) != ring_sz) {
1043                         printf("%s: error, incorrect ring capacity reported\n",
1044                                         __func__);
1045                         goto test_fail;
1046                 }
1047
1048                 /* check data */
1049                 if (test_ring_mem_cmp(src, dst, RTE_PTR_DIFF(cur_dst, dst)))
1050                         goto test_fail;
1051
1052                 rte_free(src_orig);
1053                 rte_free(dst_orig);
1054                 rte_ring_free(std_r);
1055                 rte_ring_free(exact_sz_r);
1056                 src_orig = NULL;
1057                 dst_orig = NULL;
1058                 std_r = NULL;
1059                 exact_sz_r = NULL;
1060         }
1061
1062         return 0;
1063
1064 test_fail:
1065         rte_free(src_orig);
1066         rte_free(dst_orig);
1067         rte_ring_free(std_r);
1068         rte_ring_free(exact_sz_r);
1069         return -1;
1070 }
1071
1072 static int
1073 test_ring(void)
1074 {
1075         int32_t rc;
1076         unsigned int i;
1077
1078         /* Negative test cases */
1079         if (test_ring_negative_tests() < 0)
1080                 goto test_fail;
1081
1082         /* Some basic operations */
1083         if (test_ring_basic_ex() < 0)
1084                 goto test_fail;
1085
1086         if (test_ring_with_exact_size() < 0)
1087                 goto test_fail;
1088
1089         /* Burst and bulk operations with sp/sc, mp/mc and default.
1090          * The test cases are split into smaller test cases to
1091          * help clang compile faster.
1092          */
1093         for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
1094
1095
1096                 rc = test_ring_burst_bulk_tests1(i);
1097                 if (rc < 0)
1098                         goto test_fail;
1099
1100                 rc = test_ring_burst_bulk_tests2(i);
1101                 if (rc < 0)
1102                         goto test_fail;
1103
1104                 rc = test_ring_burst_bulk_tests3(i);
1105                 if (rc < 0)
1106                         goto test_fail;
1107
1108                 rc = test_ring_burst_bulk_tests4(i);
1109                 if (rc < 0)
1110                         goto test_fail;
1111         }
1112
1113         /* dump the ring status */
1114         rte_ring_list_dump(stdout);
1115
1116         return 0;
1117
1118 test_fail:
1119
1120         return -1;
1121 }
1122
1123 REGISTER_TEST_COMMAND(ring_autotest, test_ring);