test/ring: fix dequeued 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 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 *obj = NULL;
795
796         for (i = 0; i < RTE_DIM(esize); i++) {
797                 obj = test_ring_calloc(RING_SIZE, esize[i]);
798                 if (obj == NULL) {
799                         printf("%s: failed to alloc memory\n", __func__);
800                         goto fail_test;
801                 }
802
803                 rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE,
804                                         SOCKET_ID_ANY,
805                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
806                 if (rp == NULL) {
807                         printf("%s: failed to create ring\n", __func__);
808                         goto fail_test;
809                 }
810
811                 if (rte_ring_lookup("test_ring_basic_ex") != rp) {
812                         printf("%s: failed to find ring\n", __func__);
813                         goto fail_test;
814                 }
815
816                 if (rte_ring_empty(rp) != 1) {
817                         printf("%s: ring is not empty but it should be\n",
818                                 __func__);
819                         goto fail_test;
820                 }
821
822                 printf("%u ring entries are now free\n",
823                         rte_ring_free_count(rp));
824
825                 for (j = 0; j < RING_SIZE - 1; j++) {
826                         test_ring_enqueue(rp, obj, esize[i], 1,
827                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
828                 }
829
830                 if (rte_ring_full(rp) != 1) {
831                         printf("%s: ring is not full but it should be\n",
832                                 __func__);
833                         goto fail_test;
834                 }
835
836                 for (j = 0; j < RING_SIZE - 1; j++) {
837                         test_ring_dequeue(rp, obj, esize[i], 1,
838                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
839                 }
840
841                 if (rte_ring_empty(rp) != 1) {
842                         printf("%s: ring is not empty but it should be\n",
843                                 __func__);
844                         goto fail_test;
845                 }
846
847                 /* Following tests use the configured flags to decide
848                  * SP/SC or MP/MC.
849                  */
850                 /* Covering the ring burst operation */
851                 ret = test_ring_enqueue(rp, obj, esize[i], 2,
852                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
853                 if (ret != 2) {
854                         printf("%s: rte_ring_enqueue_burst fails\n", __func__);
855                         goto fail_test;
856                 }
857
858                 ret = test_ring_dequeue(rp, obj, esize[i], 2,
859                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
860                 if (ret != 2) {
861                         printf("%s: rte_ring_dequeue_burst fails\n", __func__);
862                         goto fail_test;
863                 }
864
865                 /* Covering the ring bulk operation */
866                 ret = test_ring_enqueue(rp, obj, esize[i], 2,
867                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
868                 if (ret != 2) {
869                         printf("%s: rte_ring_enqueue_bulk fails\n", __func__);
870                         goto fail_test;
871                 }
872
873                 ret = test_ring_dequeue(rp, obj, esize[i], 2,
874                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
875                 if (ret != 2) {
876                         printf("%s: rte_ring_dequeue_bulk fails\n", __func__);
877                         goto fail_test;
878                 }
879
880                 rte_ring_free(rp);
881                 rte_free(obj);
882                 rp = NULL;
883                 obj = NULL;
884         }
885
886         return 0;
887
888 fail_test:
889         rte_ring_free(rp);
890         if (obj != NULL)
891                 rte_free(obj);
892
893         return -1;
894 }
895
896 /*
897  * Basic test cases with exact size ring.
898  */
899 static int
900 test_ring_with_exact_size(void)
901 {
902         struct rte_ring *std_r = NULL, *exact_sz_r = NULL;
903         void *obj_orig;
904         void *obj;
905         const unsigned int ring_sz = 16;
906         unsigned int i, j;
907         int ret = -1;
908
909         for (i = 0; i < RTE_DIM(esize); i++) {
910                 test_ring_print_test_string("Test exact size ring",
911                                 TEST_RING_IGNORE_API_TYPE,
912                                 esize[i]);
913
914                 /* alloc object pointers. Allocate one extra object
915                  * and create an unaligned address.
916                  */
917                 obj_orig = test_ring_calloc(17, esize[i]);
918                 if (obj_orig == NULL)
919                         goto test_fail;
920                 obj = ((char *)obj_orig) + 1;
921
922                 std_r = test_ring_create("std", esize[i], ring_sz,
923                                         rte_socket_id(),
924                                         RING_F_SP_ENQ | RING_F_SC_DEQ);
925                 if (std_r == NULL) {
926                         printf("%s: error, can't create std ring\n", __func__);
927                         goto test_fail;
928                 }
929                 exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz,
930                                 rte_socket_id(),
931                                 RING_F_SP_ENQ | RING_F_SC_DEQ |
932                                 RING_F_EXACT_SZ);
933                 if (exact_sz_r == NULL) {
934                         printf("%s: error, can't create exact size ring\n",
935                                         __func__);
936                         goto test_fail;
937                 }
938
939                 /*
940                  * Check that the exact size ring is bigger than the
941                  * standard ring
942                  */
943                 if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) {
944                         printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
945                                         __func__,
946                                         rte_ring_get_size(std_r),
947                                         rte_ring_get_size(exact_sz_r));
948                         goto test_fail;
949                 }
950                 /*
951                  * check that the exact_sz_ring can hold one more element
952                  * than the standard ring. (16 vs 15 elements)
953                  */
954                 for (j = 0; j < ring_sz - 1; j++) {
955                         test_ring_enqueue(std_r, obj, esize[i], 1,
956                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
957                         test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
958                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
959                 }
960                 ret = test_ring_enqueue(std_r, obj, esize[i], 1,
961                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
962                 if (ret != -ENOBUFS) {
963                         printf("%s: error, unexpected successful enqueue\n",
964                                 __func__);
965                         goto test_fail;
966                 }
967                 ret = test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
968                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
969                 if (ret == -ENOBUFS) {
970                         printf("%s: error, enqueue failed\n", __func__);
971                         goto test_fail;
972                 }
973
974                 /* check that dequeue returns the expected number of elements */
975                 ret = test_ring_dequeue(exact_sz_r, obj, esize[i], ring_sz,
976                                 TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
977                 if (ret != (int)ring_sz) {
978                         printf("%s: error, failed to dequeue expected nb of elements\n",
979                                 __func__);
980                         goto test_fail;
981                 }
982
983                 /* check that the capacity function returns expected value */
984                 if (rte_ring_get_capacity(exact_sz_r) != ring_sz) {
985                         printf("%s: error, incorrect ring capacity reported\n",
986                                         __func__);
987                         goto test_fail;
988                 }
989
990                 rte_free(obj_orig);
991                 rte_ring_free(std_r);
992                 rte_ring_free(exact_sz_r);
993                 obj_orig = NULL;
994                 std_r = NULL;
995                 exact_sz_r = NULL;
996         }
997
998         return 0;
999
1000 test_fail:
1001         rte_free(obj_orig);
1002         rte_ring_free(std_r);
1003         rte_ring_free(exact_sz_r);
1004         return -1;
1005 }
1006
1007 static int
1008 test_ring(void)
1009 {
1010         int32_t rc;
1011         unsigned int i;
1012
1013         /* Negative test cases */
1014         if (test_ring_negative_tests() < 0)
1015                 goto test_fail;
1016
1017         /* Some basic operations */
1018         if (test_ring_basic_ex() < 0)
1019                 goto test_fail;
1020
1021         if (test_ring_with_exact_size() < 0)
1022                 goto test_fail;
1023
1024         /* Burst and bulk operations with sp/sc, mp/mc and default.
1025          * The test cases are split into smaller test cases to
1026          * help clang compile faster.
1027          */
1028         for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
1029
1030
1031                 rc = test_ring_burst_bulk_tests1(i);
1032                 if (rc < 0)
1033                         goto test_fail;
1034
1035                 rc = test_ring_burst_bulk_tests2(i);
1036                 if (rc < 0)
1037                         goto test_fail;
1038
1039                 rc = test_ring_burst_bulk_tests3(i);
1040                 if (rc < 0)
1041                         goto test_fail;
1042
1043                 rc = test_ring_burst_bulk_tests4(i);
1044                 if (rc < 0)
1045                         goto test_fail;
1046         }
1047
1048         /* dump the ring status */
1049         rte_ring_list_dump(stdout);
1050
1051         return 0;
1052
1053 test_fail:
1054
1055         return -1;
1056 }
1057
1058 REGISTER_TEST_COMMAND(ring_autotest, test_ring);