remove version in all files
[dpdk.git] / app / test / test_ring.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
33  */
34
35 #include <string.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <inttypes.h>
41 #include <errno.h>
42 #include <sys/queue.h>
43
44 #include <rte_common.h>
45 #include <rte_log.h>
46 #include <rte_memory.h>
47 #include <rte_memzone.h>
48 #include <rte_launch.h>
49 #include <rte_cycles.h>
50 #include <rte_tailq.h>
51 #include <rte_eal.h>
52 #include <rte_per_lcore.h>
53 #include <rte_lcore.h>
54 #include <rte_atomic.h>
55 #include <rte_branch_prediction.h>
56 #include <rte_malloc.h>
57 #include <rte_ring.h>
58 #include <rte_random.h>
59 #include <rte_common.h>
60 #include <rte_errno.h>
61
62 #include <cmdline_parse.h>
63
64 #include "test.h"
65
66 /*
67  * Ring
68  * ====
69  *
70  * #. Basic tests: done on one core:
71  *
72  *    - Using single producer/single consumer functions:
73  *
74  *      - Enqueue one object, two objects, MAX_BULK objects
75  *      - Dequeue one object, two objects, MAX_BULK objects
76  *      - Check that dequeued pointers are correct
77  *
78  *    - Using multi producers/multi consumers functions:
79  *
80  *      - Enqueue one object, two objects, MAX_BULK objects
81  *      - Dequeue one object, two objects, MAX_BULK objects
82  *      - Check that dequeued pointers are correct
83  *
84  *    - Test watermark and default bulk enqueue/dequeue:
85  *
86  *      - Set watermark
87  *      - Set default bulk value
88  *      - Enqueue objects, check that -EDQUOT is returned when
89  *        watermark is exceeded
90  *      - Check that dequeued pointers are correct
91  *
92  * #. Check quota and watermark
93  *
94  *    - Start a loop on another lcore that will enqueue and dequeue
95  *      objects in a ring. It will monitor the value of quota (default
96  *      bulk count) and watermark.
97  *    - At the same time, change the quota and the watermark on the
98  *      master lcore.
99  *    - The slave lcore will check that bulk count changes from 4 to
100  *      8, and watermark changes from 16 to 32.
101  *
102  * #. Performance tests.
103  *
104  *    This test is done on the following configurations:
105  *
106  *    - One core enqueuing, one core dequeuing
107  *    - One core enqueuing, other cores dequeuing
108  *    - One core dequeuing, other cores enqueuing
109  *    - Half of the cores enqueuing, the other half dequeuing
110  *
111  *    When only one core enqueues/dequeues, the test is done with the
112  *    SP/SC functions in addition to the MP/MC functions.
113  *
114  *    The test is done with different bulk size.
115  *
116  *    On each core, the test enqueues or dequeues objects during
117  *    TIME_S seconds. The number of successes and failures are stored on
118  *    each core, then summed and displayed.
119  *
120  *    The test checks that the number of enqueues is equal to the
121  *    number of dequeues.
122  */
123
124 #define RING_SIZE 4096
125 #define MAX_BULK 32
126 #define N 65536
127 #define TIME_S 5
128
129 static rte_atomic32_t synchro;
130
131 static unsigned bulk_enqueue;
132 static unsigned bulk_dequeue;
133 static struct rte_ring *r;
134
135 struct test_stats {
136         unsigned enq_success ;
137         unsigned enq_quota;
138         unsigned enq_fail;
139
140         unsigned deq_success;
141         unsigned deq_fail;
142 } __rte_cache_aligned;
143
144 static struct test_stats test_stats[RTE_MAX_LCORE];
145
146 #define DEFINE_ENQUEUE_FUNCTION(name, enq_code)                 \
147 static int                                                      \
148 name(__attribute__((unused)) void *arg)                         \
149 {                                                               \
150         unsigned success = 0;                                   \
151         unsigned quota = 0;                                     \
152         unsigned fail = 0;                                      \
153         unsigned i;                                             \
154         unsigned long dummy_obj;                                \
155         void *obj_table[MAX_BULK];                              \
156         int ret;                                                \
157         unsigned lcore_id = rte_lcore_id();                     \
158         uint64_t start_cycles, end_cycles;                      \
159         uint64_t time_diff = 0, hz = rte_get_hpet_hz();         \
160                                                                 \
161         /* init dummy object table */                           \
162         for (i = 0; i< MAX_BULK; i++) {                         \
163                 dummy_obj = lcore_id + 0x1000 + i;              \
164                 obj_table[i] = (void *)dummy_obj;               \
165         }                                                       \
166                                                                 \
167         /* wait synchro for slaves */                           \
168         if (lcore_id != rte_get_master_lcore())                 \
169                 while (rte_atomic32_read(&synchro) == 0);       \
170                                                                 \
171         start_cycles = rte_get_hpet_cycles();                   \
172                                                                 \
173         /* enqueue as many object as possible */                \
174         while (time_diff/hz < TIME_S) {                         \
175                 for (i = 0; likely(i < N); i++) {               \
176                         ret = enq_code;                         \
177                         if (ret == 0)                           \
178                                 success++;                      \
179                         else if (ret == -EDQUOT)                \
180                                 quota++;                        \
181                         else                                    \
182                                 fail++;                         \
183                 }                                               \
184                 end_cycles = rte_get_hpet_cycles();             \
185                 time_diff = end_cycles - start_cycles;          \
186         }                                                       \
187                                                                 \
188         /* write statistics in a shared structure */            \
189         test_stats[lcore_id].enq_success = success;             \
190         test_stats[lcore_id].enq_quota = quota;                 \
191         test_stats[lcore_id].enq_fail = fail;                   \
192                                                                 \
193         return 0;                                               \
194 }
195
196 #define DEFINE_DEQUEUE_FUNCTION(name, deq_code)                 \
197 static int                                                      \
198 name(__attribute__((unused)) void *arg)                         \
199 {                                                               \
200         unsigned success = 0;                                   \
201         unsigned fail = 0;                                      \
202         unsigned i;                                             \
203         void *obj_table[MAX_BULK];                              \
204         int ret;                                                \
205         unsigned lcore_id = rte_lcore_id();                     \
206         uint64_t start_cycles, end_cycles;                      \
207         uint64_t time_diff = 0, hz = rte_get_hpet_hz();         \
208                                                                 \
209         /* wait synchro for slaves */                           \
210         if (lcore_id != rte_get_master_lcore())                 \
211                 while (rte_atomic32_read(&synchro) == 0);       \
212                                                                 \
213         start_cycles = rte_get_hpet_cycles();                   \
214                                                                 \
215         /* dequeue as many object as possible */                \
216         while (time_diff/hz < TIME_S) {                         \
217                 for (i = 0; likely(i < N); i++) {               \
218                         ret = deq_code;                         \
219                         if (ret == 0)                           \
220                                 success++;                      \
221                         else                                    \
222                                 fail++;                         \
223                 }                                               \
224                 end_cycles = rte_get_hpet_cycles();             \
225                 time_diff = end_cycles - start_cycles;          \
226         }                                                       \
227                                                                 \
228         /* write statistics in a shared structure */            \
229         test_stats[lcore_id].deq_success = success;             \
230         test_stats[lcore_id].deq_fail = fail;                   \
231                                                                 \
232         return 0;                                               \
233 }
234
235 DEFINE_ENQUEUE_FUNCTION(test_ring_per_core_sp_enqueue,
236                         rte_ring_sp_enqueue_bulk(r, obj_table, bulk_enqueue))
237
238 DEFINE_DEQUEUE_FUNCTION(test_ring_per_core_sc_dequeue,
239                         rte_ring_sc_dequeue_bulk(r, obj_table, bulk_dequeue))
240
241 DEFINE_ENQUEUE_FUNCTION(test_ring_per_core_mp_enqueue,
242                         rte_ring_mp_enqueue_bulk(r, obj_table, bulk_enqueue))
243
244 DEFINE_DEQUEUE_FUNCTION(test_ring_per_core_mc_dequeue,
245                         rte_ring_mc_dequeue_bulk(r, obj_table, bulk_dequeue))
246
247 #define TEST_RING_VERIFY(exp)                                           \
248         if (!(exp)) {                                                   \
249                 printf("error at %s:%d\tcondition " #exp " failed\n",   \
250                     __func__, __LINE__);                                \
251                 rte_ring_dump(r);                                       \
252                 return (-1);                                            \
253         }
254
255 #define TEST_RING_FULL_EMTPY_ITER       8
256
257
258 static int
259 launch_cores(unsigned enq_core_count, unsigned deq_core_count, int sp, int sc)
260 {
261         void *obj;
262         unsigned lcore_id;
263         unsigned rate, deq_remain = 0;
264         unsigned enq_total, deq_total;
265         struct test_stats sum;
266         int (*enq_f)(void *);
267         int (*deq_f)(void *);
268         unsigned cores = enq_core_count + deq_core_count;
269         int ret;
270
271         rte_atomic32_set(&synchro, 0);
272
273         printf("ring_autotest e/d_core=%u,%u e/d_bulk=%u,%u ",
274                enq_core_count, deq_core_count, bulk_enqueue, bulk_dequeue);
275         printf("sp=%d sc=%d ", sp, sc);
276
277         /* set enqueue function to be used */
278         if (sp)
279                 enq_f = test_ring_per_core_sp_enqueue;
280         else
281                 enq_f = test_ring_per_core_mp_enqueue;
282
283         /* set dequeue function to be used */
284         if (sc)
285                 deq_f = test_ring_per_core_sc_dequeue;
286         else
287                 deq_f = test_ring_per_core_mc_dequeue;
288
289         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
290                 if (enq_core_count != 0) {
291                         enq_core_count--;
292                         rte_eal_remote_launch(enq_f, NULL, lcore_id);
293                 }
294                 if (deq_core_count != 1) {
295                         deq_core_count--;
296                         rte_eal_remote_launch(deq_f, NULL, lcore_id);
297                 }
298         }
299
300         memset(test_stats, 0, sizeof(test_stats));
301
302         /* start synchro and launch test on master */
303         rte_atomic32_set(&synchro, 1);
304         ret = deq_f(NULL);
305
306         /* wait all cores */
307         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
308                 if (cores == 1)
309                         break;
310                 cores--;
311                 if (rte_eal_wait_lcore(lcore_id) < 0)
312                         ret = -1;
313         }
314
315         memset(&sum, 0, sizeof(sum));
316         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
317                 sum.enq_success += test_stats[lcore_id].enq_success;
318                 sum.enq_quota += test_stats[lcore_id].enq_quota;
319                 sum.enq_fail += test_stats[lcore_id].enq_fail;
320                 sum.deq_success += test_stats[lcore_id].deq_success;
321                 sum.deq_fail += test_stats[lcore_id].deq_fail;
322         }
323
324         /* empty the ring */
325         while (rte_ring_sc_dequeue(r, &obj) == 0)
326                 deq_remain += 1;
327
328         if (ret < 0) {
329                 printf("per-lcore test returned -1\n");
330                 return -1;
331         }
332
333         enq_total = (sum.enq_success * bulk_enqueue) +
334                 (sum.enq_quota * bulk_enqueue);
335         deq_total = (sum.deq_success * bulk_dequeue) + deq_remain;
336
337         rate = deq_total/TIME_S;
338
339         printf("rate_persec=%u\n", rate);
340
341         if (enq_total != deq_total) {
342                 printf("invalid enq/deq_success counter: %u %u\n",
343                        enq_total, deq_total);
344                 return -1;
345         }
346
347         return 0;
348 }
349
350 static int
351 do_one_ring_test2(unsigned enq_core_count, unsigned deq_core_count,
352                   unsigned n_enq_bulk, unsigned n_deq_bulk)
353 {
354         int sp, sc;
355         int do_sp, do_sc;
356         int ret;
357
358         bulk_enqueue = n_enq_bulk;
359         bulk_dequeue = n_deq_bulk;
360
361         do_sp = (enq_core_count == 1) ? 1 : 0;
362         do_sc = (deq_core_count  == 1) ? 1 : 0;
363
364         for (sp = 0; sp <= do_sp; sp ++) {
365                 for (sc = 0; sc <= do_sc; sc ++) {
366                         ret = launch_cores(enq_core_count,
367                                            deq_core_count,
368                                            sp, sc);
369                         if (ret < 0)
370                                 return -1;
371                 }
372         }
373         return 0;
374 }
375
376 static int
377 do_one_ring_test(unsigned enq_core_count, unsigned deq_core_count)
378 {
379         unsigned bulk_enqueue_tab[] = { 1, 2, 4, 32, 0 };
380         unsigned bulk_dequeue_tab[] = { 1, 2, 4, 32, 0 };
381         unsigned *bulk_enqueue_ptr;
382         unsigned *bulk_dequeue_ptr;
383         int ret;
384
385         for (bulk_enqueue_ptr = bulk_enqueue_tab;
386              *bulk_enqueue_ptr;
387              bulk_enqueue_ptr++) {
388
389                 for (bulk_dequeue_ptr = bulk_dequeue_tab;
390                      *bulk_dequeue_ptr;
391                      bulk_dequeue_ptr++) {
392
393                         ret = do_one_ring_test2(enq_core_count, deq_core_count,
394                                                 *bulk_enqueue_ptr,
395                                                 *bulk_dequeue_ptr);
396                         if (ret < 0)
397                                 return -1;
398                 }
399         }
400         return 0;
401 }
402
403 static int
404 check_quota_and_watermark(__attribute__((unused)) void *dummy)
405 {
406         uint64_t hz = rte_get_hpet_hz();
407         void *obj_table[MAX_BULK];
408         unsigned watermark, watermark_old = 16;
409         uint64_t cur_time, end_time;
410         int64_t diff = 0;
411         int i, ret;
412         unsigned quota, quota_old = 4;
413
414         /* init the object table */
415         memset(obj_table, 0, sizeof(obj_table));
416         end_time = rte_get_hpet_cycles() + (hz * 2);
417
418         /* check that bulk and watermark are 4 and 32 (respectively) */
419         while (diff >= 0) {
420
421                 /* read quota, the only change allowed is from 4 to 8 */
422                 quota = rte_ring_get_bulk_count(r);
423                 if (quota != quota_old && (quota_old != 4 || quota != 8)) {
424                         printf("Bad quota change %u -> %u\n", quota_old,
425                                quota);
426                         return -1;
427                 }
428                 quota_old = quota;
429
430                 /* add in ring until we reach watermark */
431                 ret = 0;
432                 for (i = 0; i < 16; i ++) {
433                         if (ret != 0)
434                                 break;
435                         ret = rte_ring_enqueue_bulk(r, obj_table, quota);
436                 }
437
438                 if (ret != -EDQUOT) {
439                         printf("Cannot enqueue objects, or watermark not "
440                                "reached (ret=%d)\n", ret);
441                         return -1;
442                 }
443
444                 /* read watermark, the only change allowed is from 16 to 32 */
445                 watermark = i * quota;
446                 if (watermark != watermark_old &&
447                     (watermark_old != 16 || watermark != 32)) {
448                         printf("Bad watermark change %u -> %u\n", watermark_old,
449                                watermark);
450                         return -1;
451                 }
452                 watermark_old = watermark;
453
454                 /* dequeue objects from ring */
455                 while (i--) {
456                         ret = rte_ring_dequeue_bulk(r, obj_table, quota);
457                         if (ret != 0) {
458                                 printf("Cannot dequeue (ret=%d)\n", ret);
459                                 return -1;
460                         }
461                 }
462
463                 cur_time = rte_get_hpet_cycles();
464                 diff = end_time - cur_time;
465         }
466
467         if (watermark_old != 32 || quota_old != 8) {
468                 printf("quota or watermark was not updated (q=%u wm=%u)\n",
469                        quota_old, watermark_old);
470                 return -1;
471         }
472
473         return 0;
474 }
475
476 static int
477 test_quota_and_watermark(void)
478 {
479         unsigned lcore_id = rte_lcore_id();
480         unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1);
481
482         printf("Test quota and watermark live modification\n");
483
484         rte_ring_set_bulk_count(r, 4);
485         rte_ring_set_water_mark(r, 16);
486
487         /* launch a thread that will enqueue and dequeue, checking
488          * watermark and quota */
489         rte_eal_remote_launch(check_quota_and_watermark, NULL, lcore_id2);
490
491         rte_delay_ms(1000);
492         rte_ring_set_bulk_count(r, 8);
493         rte_ring_set_water_mark(r, 32);
494         rte_delay_ms(1000);
495
496         if (rte_eal_wait_lcore(lcore_id2) < 0)
497                 return -1;
498
499         return 0;
500 }
501 /* Test for catch on invalid watermark values */
502 static int
503 test_set_watermark( void ){
504         unsigned count;
505         int setwm;
506
507         struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex");
508         if(r == NULL){
509                 printf( " ring lookup failed\n" );
510                 goto error;
511         }
512         count = r->prod.size*2;
513         setwm = rte_ring_set_water_mark(r, count);
514         if (setwm != -EINVAL){
515                 printf("Test failed to detect invalid watermark count value\n");
516                 goto error;
517         }
518
519         count = 0;
520         setwm = rte_ring_set_water_mark(r, count);
521         if (r->prod.watermark != r->prod.size) {
522                 printf("Test failed to detect invalid watermark count value\n");
523                 goto error;
524         }
525         return 0;
526
527 error:
528         return -1;
529 }
530
531 /*
532  * helper routine for test_ring_basic
533  */
534 static int
535 test_ring_basic_full_empty(void * const src[], void *dst[])
536 {
537         unsigned i, rand;
538         const unsigned rsz = RING_SIZE - 1;
539
540         printf("Basic full/empty test\n");
541
542         for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) {
543
544                 /* random shift in the ring */
545                 rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
546                 printf("%s: iteration %u, random shift: %u;\n",
547                     __func__, i, rand);
548                 TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src,
549                     rand));
550                 TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rand));
551
552                 /* fill the ring */
553                 TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src,
554                     rsz));
555                 TEST_RING_VERIFY(0 == rte_ring_free_count(r));
556                 TEST_RING_VERIFY(rsz == rte_ring_count(r));
557                 TEST_RING_VERIFY(rte_ring_full(r));
558                 TEST_RING_VERIFY(0 == rte_ring_empty(r));
559
560                 /* empty the ring */
561                 TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rsz));
562                 TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
563                 TEST_RING_VERIFY(0 == rte_ring_count(r));
564                 TEST_RING_VERIFY(0 == rte_ring_full(r));
565                 TEST_RING_VERIFY(rte_ring_empty(r));
566
567                 /* check data */
568                 TEST_RING_VERIFY(0 == memcmp(src, dst, rsz));
569                 rte_ring_dump(r);
570         }
571         return (0);
572 }
573
574 static int
575 test_ring_basic(void)
576 {
577         void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
578         int ret;
579         unsigned i, n;
580
581         /* alloc dummy object pointers */
582         src = malloc(RING_SIZE*2*sizeof(void *));
583         if (src == NULL)
584                 goto fail;
585
586         for (i = 0; i < RING_SIZE*2 ; i++) {
587                 src[i] = (void *)(unsigned long)i;
588         }
589         cur_src = src;
590
591         /* alloc some room for copied objects */
592         dst = malloc(RING_SIZE*2*sizeof(void *));
593         if (dst == NULL)
594                 goto fail;
595
596         memset(dst, 0, RING_SIZE*2*sizeof(void *));
597         cur_dst = dst;
598
599         printf("enqueue 1 obj\n");
600         ret = rte_ring_sp_enqueue_bulk(r, cur_src, 1);
601         cur_src += 1;
602         if (ret != 0)
603                 goto fail;
604
605         printf("enqueue 2 objs\n");
606         ret = rte_ring_sp_enqueue_bulk(r, cur_src, 2);
607         cur_src += 2;
608         if (ret != 0)
609                 goto fail;
610
611         printf("enqueue MAX_BULK objs\n");
612         ret = rte_ring_sp_enqueue_bulk(r, cur_src, MAX_BULK);
613         cur_src += MAX_BULK;
614         if (ret != 0)
615                 goto fail;
616
617         printf("dequeue 1 obj\n");
618         ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 1);
619         cur_dst += 1;
620         if (ret != 0)
621                 goto fail;
622
623         printf("dequeue 2 objs\n");
624         ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 2);
625         cur_dst += 2;
626         if (ret != 0)
627                 goto fail;
628
629         printf("dequeue MAX_BULK objs\n");
630         ret = rte_ring_sc_dequeue_bulk(r, cur_dst, MAX_BULK);
631         cur_dst += MAX_BULK;
632         if (ret != 0)
633                 goto fail;
634
635         /* check data */
636         if (memcmp(src, dst, cur_dst - dst)) {
637                 test_hexdump("src", src, cur_src - src);
638                 test_hexdump("dst", dst, cur_dst - dst);
639                 printf("data after dequeue is not the same\n");
640                 goto fail;
641         }
642         cur_src = src;
643         cur_dst = dst;
644
645         printf("enqueue 1 obj\n");
646         ret = rte_ring_mp_enqueue_bulk(r, cur_src, 1);
647         cur_src += 1;
648         if (ret != 0)
649                 goto fail;
650
651         printf("enqueue 2 objs\n");
652         ret = rte_ring_mp_enqueue_bulk(r, cur_src, 2);
653         cur_src += 2;
654         if (ret != 0)
655                 goto fail;
656
657         printf("enqueue MAX_BULK objs\n");
658         ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK);
659         cur_src += MAX_BULK;
660         if (ret != 0)
661                 goto fail;
662
663         printf("dequeue 1 obj\n");
664         ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 1);
665         cur_dst += 1;
666         if (ret != 0)
667                 goto fail;
668
669         printf("dequeue 2 objs\n");
670         ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 2);
671         cur_dst += 2;
672         if (ret != 0)
673                 goto fail;
674
675         printf("dequeue MAX_BULK objs\n");
676         ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK);
677         cur_dst += MAX_BULK;
678         if (ret != 0)
679                 goto fail;
680
681         /* check data */
682         if (memcmp(src, dst, cur_dst - dst)) {
683                 test_hexdump("src", src, cur_src - src);
684                 test_hexdump("dst", dst, cur_dst - dst);
685                 printf("data after dequeue is not the same\n");
686                 goto fail;
687         }
688         cur_src = src;
689         cur_dst = dst;
690
691         printf("fill and empty the ring\n");
692         for (i = 0; i<RING_SIZE/MAX_BULK; i++) {
693                 ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK);
694                 cur_src += MAX_BULK;
695                 if (ret != 0)
696                         goto fail;
697                 ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK);
698                 cur_dst += MAX_BULK;
699                 if (ret != 0)
700                         goto fail;
701         }
702
703         /* check data */
704         if (memcmp(src, dst, cur_dst - dst)) {
705                 test_hexdump("src", src, cur_src - src);
706                 test_hexdump("dst", dst, cur_dst - dst);
707                 printf("data after dequeue is not the same\n");
708                 goto fail;
709         }
710
711         if (test_ring_basic_full_empty(src, dst) != 0)
712                 goto fail;
713
714         cur_src = src;
715         cur_dst = dst;
716
717         printf("test watermark and default bulk enqueue / dequeue\n");
718         rte_ring_set_bulk_count(r, 16);
719         rte_ring_set_water_mark(r, 20);
720         n = rte_ring_get_bulk_count(r);
721         if (n != 16) {
722                 printf("rte_ring_get_bulk_count() returned %u instead "
723                        "of 16\n", n);
724                 goto fail;
725         }
726
727         cur_src = src;
728         cur_dst = dst;
729         ret = rte_ring_enqueue_bulk(r, cur_src, n);
730         cur_src += 16;
731         if (ret != 0) {
732                 printf("Cannot enqueue\n");
733                 goto fail;
734         }
735         ret = rte_ring_enqueue_bulk(r, cur_src, n);
736         cur_src += 16;
737         if (ret != -EDQUOT) {
738                 printf("Watermark not exceeded\n");
739                 goto fail;
740         }
741         ret = rte_ring_dequeue_bulk(r, cur_dst, n);
742         cur_dst += 16;
743         if (ret != 0) {
744                 printf("Cannot dequeue\n");
745                 goto fail;
746         }
747         ret = rte_ring_dequeue_bulk(r, cur_dst, n);
748         cur_dst += 16;
749         if (ret != 0) {
750                 printf("Cannot dequeue2\n");
751                 goto fail;
752         }
753
754         /* check data */
755         if (memcmp(src, dst, cur_dst - dst)) {
756                 test_hexdump("src", src, cur_src - src);
757                 test_hexdump("dst", dst, cur_dst - dst);
758                 printf("data after dequeue is not the same\n");
759                 goto fail;
760         }
761         cur_src = src;
762         cur_dst = dst;
763
764         if (src)
765                 free(src);
766         if (dst)
767                 free(dst);
768         return 0;
769
770  fail:
771         if (src)
772                 free(src);
773         if (dst)
774                 free(dst);
775         return -1;
776 }
777
778 /*
779  * it will always fail to create ring with a wrong ring size number in this function
780  */
781 static int
782 test_ring_creation_with_wrong_size(void)
783 {
784         struct rte_ring * rp = NULL;
785
786         rp = rte_ring_create("test_bad_ring_size", RING_SIZE+1, SOCKET_ID_ANY, 0);
787         if (NULL != rp) {
788                 return -1;
789         }
790
791         return 0;
792 }
793
794 /*
795  * it tests if it would always fail to create ring with an used ring name
796  */
797 static int
798 test_ring_creation_with_an_used_name(void)
799 {
800         struct rte_ring * rp;
801
802         rp = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0);
803         if (NULL != rp)
804                 return -1;
805
806         return 0;
807 }
808
809 /*
810  * Test to if a non-power of 2 count causes the create
811  * function to fail correctly
812  */
813 static int
814 test_create_count_odd(void)
815 {
816         struct rte_ring *r = rte_ring_create("test_ring_count",
817                         4097, SOCKET_ID_ANY, 0 );
818         if(r != NULL){
819                 return -1;
820         }
821         return 0;
822 }
823
824 static int
825 test_lookup_null(void)
826 {
827         struct rte_ring *rlp = rte_ring_lookup("ring_not_found");
828         if (rlp ==NULL)
829         if (rte_errno != ENOENT){
830                 printf( "test failed to returnn error on null pointer\n");
831                 return -1;
832         }
833         return 0;
834 }
835
836 /*
837  * it tests some more basic ring operations
838  */
839 static int
840 test_ring_basic_ex(void)
841 {
842         int ret = -1;
843         unsigned i;
844         struct rte_ring * rp;
845         void **obj = NULL;
846
847         obj = (void **)rte_zmalloc("test_ring_basic_ex_malloc", (RING_SIZE * sizeof(void *)), 0);
848         if (obj == NULL) {
849                 printf("test_ring_basic_ex fail to rte_malloc\n");
850                 goto fail_test;
851         }
852
853         rp = rte_ring_create("test_ring_basic_ex", RING_SIZE, SOCKET_ID_ANY, 0);
854         if (rp == NULL) {
855                 printf("test_ring_basic_ex fail to create ring\n");
856                 goto fail_test;
857         }
858
859         if (rte_ring_lookup("test_ring_basic_ex") != rp) {
860                 goto fail_test;
861         }
862
863         if (rte_ring_empty(rp) != 1) {
864                 printf("test_ring_basic_ex ring is not empty but it should be\n");
865                 goto fail_test;
866         }
867
868         printf("%u ring entries are now free\n", rte_ring_free_count(rp));
869
870         for (i = 0; i < RING_SIZE; i ++) {
871                 rte_ring_enqueue(rp, obj[i]);
872         }
873
874         if (rte_ring_full(rp) != 1) {
875                 printf("test_ring_basic_ex ring is not full but it should be\n");
876                 goto fail_test;
877         }
878
879         for (i = 0; i < RING_SIZE; i ++) {
880                 rte_ring_dequeue(rp, &obj[i]);
881         }
882
883         if (rte_ring_empty(rp) != 1) {
884                 printf("test_ring_basic_ex ring is not empty but it should be\n");
885                 goto fail_test;
886         }
887
888         ret = 0;
889 fail_test:
890         if (obj != NULL)
891                 rte_free(obj);
892
893         return ret;
894 }
895
896 int
897 test_ring(void)
898 {
899         unsigned enq_core_count, deq_core_count;
900
901         /* some more basic operations */
902         if (test_ring_basic_ex() < 0)
903                 return -1;
904
905         rte_atomic32_init(&synchro);
906
907         if (r == NULL)
908                 r = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0);
909         if (r == NULL)
910                 return -1;
911
912         /* retrieve the ring from its name */
913         if (rte_ring_lookup("test") != r) {
914                 printf("Cannot lookup ring from its name\n");
915                 return -1;
916         }
917
918         /* basic operations */
919         if (test_ring_basic() < 0)
920                 return -1;
921
922         /* basic operations */
923         if (test_quota_and_watermark() < 0)
924                 return -1;
925
926         if ( test_set_watermark() < 0){
927                 printf ("Test failed to detect invalid parameter\n");
928                 return -1;
929         }
930         else
931                 printf ( "Test detected forced bad watermark values\n");
932
933         if ( test_create_count_odd() < 0){
934                         printf ("Test failed to detect odd count\n");
935                         return -1;
936                 }
937                 else
938                         printf ( "Test detected odd count\n");
939
940         if ( test_lookup_null() < 0){
941                                 printf ("Test failed to detect NULL ring lookup\n");
942                                 return -1;
943                         }
944                         else
945                                 printf ( "Test detected NULL ring lookup \n");
946
947
948         printf("start performance tests\n");
949
950         /* one lcore for enqueue, one for dequeue */
951         enq_core_count = 1;
952         deq_core_count = 1;
953         if (do_one_ring_test(enq_core_count, deq_core_count) < 0)
954                 return -1;
955
956         /* max cores for enqueue, one for dequeue */
957         enq_core_count = rte_lcore_count() - 1;
958         deq_core_count = 1;
959         if (do_one_ring_test(enq_core_count, deq_core_count) < 0)
960                 return -1;
961
962         /* max cores for dequeue, one for enqueue */
963         enq_core_count = 1;
964         deq_core_count = rte_lcore_count() - 1;
965         if (do_one_ring_test(enq_core_count, deq_core_count) < 0)
966                 return -1;
967
968         /* half for enqueue and half for dequeue */
969         enq_core_count = rte_lcore_count() / 2;
970         deq_core_count = rte_lcore_count() / 2;
971         if (do_one_ring_test(enq_core_count, deq_core_count) < 0)
972                 return -1;
973
974         /* test of creating ring with wrong size */
975         if (test_ring_creation_with_wrong_size() < 0)
976                 return -1;
977
978         /* test of creation ring with an used name */
979         if (test_ring_creation_with_an_used_name() < 0)
980                 return -1;
981
982         /* dump the ring status */
983         rte_ring_list_dump();
984
985         return 0;
986 }