xref: /dpdk/app/test/test_ring.c (revision c14ef1ec)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <sys/queue.h>
13 
14 #include <rte_common.h>
15 #include <rte_log.h>
16 #include <rte_memory.h>
17 #include <rte_launch.h>
18 #include <rte_cycles.h>
19 #include <rte_eal.h>
20 #include <rte_per_lcore.h>
21 #include <rte_lcore.h>
22 #include <rte_atomic.h>
23 #include <rte_branch_prediction.h>
24 #include <rte_malloc.h>
25 #include <rte_ring.h>
26 #include <rte_ring_elem.h>
27 #include <rte_random.h>
28 #include <rte_errno.h>
29 #include <rte_hexdump.h>
30 
31 #include "test.h"
32 #include "test_ring.h"
33 
34 /*
35  * Ring
36  * ====
37  *
38  * #. Functional tests. Tests single/bulk/burst, default/SPSC/MPMC,
39  *    legacy/custom element size (4B, 8B, 16B, 20B) APIs.
40  *    Some tests incorporate unaligned addresses for objects.
41  *    The enqueued/dequeued data is validated for correctness.
42  *
43  * #. Performance tests are in test_ring_perf.c
44  */
45 
46 #define RING_SIZE 4096
47 #define MAX_BULK 32
48 
49 #define	TEST_RING_VERIFY(exp)						\
50 	if (!(exp)) {							\
51 		printf("error at %s:%d\tcondition " #exp " failed\n",	\
52 		    __func__, __LINE__);				\
53 		rte_ring_dump(stdout, r);				\
54 		return -1;						\
55 	}
56 
57 #define	TEST_RING_FULL_EMTPY_ITER	8
58 
59 static const int esize[] = {-1, 4, 8, 16, 20};
60 
61 static const struct {
62 	const char *desc;
63 	uint32_t api_type;
64 	uint32_t create_flags;
65 	struct {
66 		unsigned int (*flegacy)(struct rte_ring *r,
67 			void * const *obj_table, unsigned int n,
68 			unsigned int *free_space);
69 		unsigned int (*felem)(struct rte_ring *r, const void *obj_table,
70 			unsigned int esize, unsigned int n,
71 			unsigned int *free_space);
72 	} enq;
73 	struct {
74 		unsigned int (*flegacy)(struct rte_ring *r,
75 			void **obj_table, unsigned int n,
76 			unsigned int *available);
77 		unsigned int (*felem)(struct rte_ring *r, void *obj_table,
78 			unsigned int esize, unsigned int n,
79 			unsigned int *available);
80 	} deq;
81 } test_enqdeq_impl[] = {
82 	{
83 		.desc = "MP/MC sync mode",
84 		.api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF,
85 		.create_flags = 0,
86 		.enq = {
87 			.flegacy = rte_ring_enqueue_bulk,
88 			.felem = rte_ring_enqueue_bulk_elem,
89 		},
90 		.deq = {
91 			.flegacy = rte_ring_dequeue_bulk,
92 			.felem = rte_ring_dequeue_bulk_elem,
93 		},
94 	},
95 	{
96 		.desc = "SP/SC sync mode",
97 		.api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_SPSC,
98 		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
99 		.enq = {
100 			.flegacy = rte_ring_sp_enqueue_bulk,
101 			.felem = rte_ring_sp_enqueue_bulk_elem,
102 		},
103 		.deq = {
104 			.flegacy = rte_ring_sc_dequeue_bulk,
105 			.felem = rte_ring_sc_dequeue_bulk_elem,
106 		},
107 	},
108 	{
109 		.desc = "MP/MC sync mode",
110 		.api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_MPMC,
111 		.create_flags = 0,
112 		.enq = {
113 			.flegacy = rte_ring_mp_enqueue_bulk,
114 			.felem = rte_ring_mp_enqueue_bulk_elem,
115 		},
116 		.deq = {
117 			.flegacy = rte_ring_mc_dequeue_bulk,
118 			.felem = rte_ring_mc_dequeue_bulk_elem,
119 		},
120 	},
121 	{
122 		.desc = "MP_RTS/MC_RTS sync mode",
123 		.api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF,
124 		.create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
125 		.enq = {
126 			.flegacy = rte_ring_enqueue_bulk,
127 			.felem = rte_ring_enqueue_bulk_elem,
128 		},
129 		.deq = {
130 			.flegacy = rte_ring_dequeue_bulk,
131 			.felem = rte_ring_dequeue_bulk_elem,
132 		},
133 	},
134 	{
135 		.desc = "MP_HTS/MC_HTS sync mode",
136 		.api_type = TEST_RING_ELEM_BULK | TEST_RING_THREAD_DEF,
137 		.create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
138 		.enq = {
139 			.flegacy = rte_ring_enqueue_bulk,
140 			.felem = rte_ring_enqueue_bulk_elem,
141 		},
142 		.deq = {
143 			.flegacy = rte_ring_dequeue_bulk,
144 			.felem = rte_ring_dequeue_bulk_elem,
145 		},
146 	},
147 	{
148 		.desc = "MP/MC sync mode",
149 		.api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF,
150 		.create_flags = 0,
151 		.enq = {
152 			.flegacy = rte_ring_enqueue_burst,
153 			.felem = rte_ring_enqueue_burst_elem,
154 		},
155 		.deq = {
156 			.flegacy = rte_ring_dequeue_burst,
157 			.felem = rte_ring_dequeue_burst_elem,
158 		},
159 	},
160 	{
161 		.desc = "SP/SC sync mode",
162 		.api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_SPSC,
163 		.create_flags = RING_F_SP_ENQ | RING_F_SC_DEQ,
164 		.enq = {
165 			.flegacy = rte_ring_sp_enqueue_burst,
166 			.felem = rte_ring_sp_enqueue_burst_elem,
167 		},
168 		.deq = {
169 			.flegacy = rte_ring_sc_dequeue_burst,
170 			.felem = rte_ring_sc_dequeue_burst_elem,
171 		},
172 	},
173 	{
174 		.desc = "MP/MC sync mode",
175 		.api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_MPMC,
176 		.create_flags = 0,
177 		.enq = {
178 			.flegacy = rte_ring_mp_enqueue_burst,
179 			.felem = rte_ring_mp_enqueue_burst_elem,
180 		},
181 		.deq = {
182 			.flegacy = rte_ring_mc_dequeue_burst,
183 			.felem = rte_ring_mc_dequeue_burst_elem,
184 		},
185 	},
186 	{
187 		.desc = "MP_RTS/MC_RTS sync mode",
188 		.api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF,
189 		.create_flags = RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
190 		.enq = {
191 			.flegacy = rte_ring_enqueue_burst,
192 			.felem = rte_ring_enqueue_burst_elem,
193 		},
194 		.deq = {
195 			.flegacy = rte_ring_dequeue_burst,
196 			.felem = rte_ring_dequeue_burst_elem,
197 		},
198 	},
199 	{
200 		.desc = "MP_HTS/MC_HTS sync mode",
201 		.api_type = TEST_RING_ELEM_BURST | TEST_RING_THREAD_DEF,
202 		.create_flags = RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
203 		.enq = {
204 			.flegacy = rte_ring_enqueue_burst,
205 			.felem = rte_ring_enqueue_burst_elem,
206 		},
207 		.deq = {
208 			.flegacy = rte_ring_dequeue_burst,
209 			.felem = rte_ring_dequeue_burst_elem,
210 		},
211 	},
212 };
213 
214 static unsigned int
215 test_ring_enq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
216 	unsigned int test_idx)
217 {
218 	if (esize == -1)
219 		return test_enqdeq_impl[test_idx].enq.flegacy(r, obj, n, NULL);
220 	else
221 		return test_enqdeq_impl[test_idx].enq.felem(r, obj, esize, n,
222 			NULL);
223 }
224 
225 static unsigned int
226 test_ring_deq_impl(struct rte_ring *r, void **obj, int esize, unsigned int n,
227 	unsigned int test_idx)
228 {
229 	if (esize == -1)
230 		return test_enqdeq_impl[test_idx].deq.flegacy(r, obj, n, NULL);
231 	else
232 		return test_enqdeq_impl[test_idx].deq.felem(r, obj, esize, n,
233 			NULL);
234 }
235 
236 static void**
237 test_ring_inc_ptr(void **obj, int esize, unsigned int n)
238 {
239 	/* Legacy queue APIs? */
240 	if ((esize) == -1)
241 		return ((void **)obj) + n;
242 	else
243 		return (void **)(((uint32_t *)obj) +
244 					(n * esize / sizeof(uint32_t)));
245 }
246 
247 static void
248 test_ring_mem_init(void *obj, unsigned int count, int esize)
249 {
250 	unsigned int i;
251 
252 	/* Legacy queue APIs? */
253 	if (esize == -1)
254 		for (i = 0; i < count; i++)
255 			((void **)obj)[i] = (void *)(unsigned long)i;
256 	else
257 		for (i = 0; i < (count * esize / sizeof(uint32_t)); i++)
258 			((uint32_t *)obj)[i] = i;
259 }
260 
261 static void
262 test_ring_print_test_string(const char *istr, unsigned int api_type, int esize)
263 {
264 	printf("\n%s: ", istr);
265 
266 	if (esize == -1)
267 		printf("legacy APIs: ");
268 	else
269 		printf("elem APIs: element size %dB ", esize);
270 
271 	if (api_type == TEST_RING_IGNORE_API_TYPE)
272 		return;
273 
274 	if (api_type & TEST_RING_THREAD_DEF)
275 		printf(": default enqueue/dequeue: ");
276 	else if (api_type & TEST_RING_THREAD_SPSC)
277 		printf(": SP/SC: ");
278 	else if (api_type & TEST_RING_THREAD_MPMC)
279 		printf(": MP/MC: ");
280 
281 	if (api_type & TEST_RING_ELEM_SINGLE)
282 		printf("single\n");
283 	else if (api_type & TEST_RING_ELEM_BULK)
284 		printf("bulk\n");
285 	else if (api_type & TEST_RING_ELEM_BURST)
286 		printf("burst\n");
287 }
288 
289 /*
290  * Various negative test cases.
291  */
292 static int
293 test_ring_negative_tests(void)
294 {
295 	struct rte_ring *rp = NULL;
296 	struct rte_ring *rt = NULL;
297 	unsigned int i;
298 
299 	/* Test with esize not a multiple of 4 */
300 	rp = test_ring_create("test_bad_element_size", 23,
301 				RING_SIZE + 1, SOCKET_ID_ANY, 0);
302 	if (rp != NULL) {
303 		printf("Test failed to detect invalid element size\n");
304 		goto test_fail;
305 	}
306 
307 
308 	for (i = 0; i < RTE_DIM(esize); i++) {
309 		/* Test if ring size is not power of 2 */
310 		rp = test_ring_create("test_bad_ring_size", esize[i],
311 					RING_SIZE + 1, SOCKET_ID_ANY, 0);
312 		if (rp != NULL) {
313 			printf("Test failed to detect odd count\n");
314 			goto test_fail;
315 		}
316 
317 		/* Test if ring size is exceeding the limit */
318 		rp = test_ring_create("test_bad_ring_size", esize[i],
319 					RTE_RING_SZ_MASK + 1, SOCKET_ID_ANY, 0);
320 		if (rp != NULL) {
321 			printf("Test failed to detect limits\n");
322 			goto test_fail;
323 		}
324 
325 		/* Tests if lookup returns NULL on non-existing ring */
326 		rp = rte_ring_lookup("ring_not_found");
327 		if (rp != NULL && rte_errno != ENOENT) {
328 			printf("Test failed to detect NULL ring lookup\n");
329 			goto test_fail;
330 		}
331 
332 		/* Test to if a non-power of 2 count causes the create
333 		 * function to fail correctly
334 		 */
335 		rp = test_ring_create("test_ring_count", esize[i], 4097,
336 					SOCKET_ID_ANY, 0);
337 		if (rp != NULL)
338 			goto test_fail;
339 
340 		rp = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
341 					SOCKET_ID_ANY,
342 					RING_F_SP_ENQ | RING_F_SC_DEQ);
343 		if (rp == NULL) {
344 			printf("test_ring_negative fail to create ring\n");
345 			goto test_fail;
346 		}
347 
348 		if (rte_ring_lookup("test_ring_negative") != rp)
349 			goto test_fail;
350 
351 		if (rte_ring_empty(rp) != 1) {
352 			printf("test_ring_nagative ring is not empty but it should be\n");
353 			goto test_fail;
354 		}
355 
356 		/* Tests if it would always fail to create ring with an used
357 		 * ring name.
358 		 */
359 		rt = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
360 					SOCKET_ID_ANY, 0);
361 		if (rt != NULL)
362 			goto test_fail;
363 
364 		rte_ring_free(rp);
365 		rp = NULL;
366 	}
367 
368 	return 0;
369 
370 test_fail:
371 
372 	rte_ring_free(rp);
373 	return -1;
374 }
375 
376 /*
377  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
378  * Random number of elements are enqueued and dequeued.
379  */
380 static int
381 test_ring_burst_bulk_tests1(unsigned int test_idx)
382 {
383 	struct rte_ring *r;
384 	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
385 	int ret;
386 	unsigned int i, j;
387 	int rand;
388 	const unsigned int rsz = RING_SIZE - 1;
389 
390 	for (i = 0; i < RTE_DIM(esize); i++) {
391 		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
392 			test_enqdeq_impl[test_idx].api_type, esize[i]);
393 
394 		/* Create the ring */
395 		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
396 				RING_SIZE, SOCKET_ID_ANY,
397 				test_enqdeq_impl[test_idx].create_flags);
398 
399 		/* alloc dummy object pointers */
400 		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
401 		if (src == NULL)
402 			goto fail;
403 		test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
404 		cur_src = src;
405 
406 		/* alloc some room for copied objects */
407 		dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
408 		if (dst == NULL)
409 			goto fail;
410 		cur_dst = dst;
411 
412 		printf("Random full/empty test\n");
413 
414 		for (j = 0; j != TEST_RING_FULL_EMTPY_ITER; j++) {
415 			/* random shift in the ring */
416 			rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
417 			printf("%s: iteration %u, random shift: %u;\n",
418 			    __func__, i, rand);
419 			ret = test_ring_enq_impl(r, cur_src, esize[i], rand,
420 							test_idx);
421 			TEST_RING_VERIFY(ret != 0);
422 
423 			ret = test_ring_deq_impl(r, cur_dst, esize[i], rand,
424 							test_idx);
425 			TEST_RING_VERIFY(ret == rand);
426 
427 			/* fill the ring */
428 			ret = test_ring_enq_impl(r, cur_src, esize[i], rsz,
429 							test_idx);
430 			TEST_RING_VERIFY(ret != 0);
431 
432 			TEST_RING_VERIFY(rte_ring_free_count(r) == 0);
433 			TEST_RING_VERIFY(rsz == rte_ring_count(r));
434 			TEST_RING_VERIFY(rte_ring_full(r));
435 			TEST_RING_VERIFY(rte_ring_empty(r) == 0);
436 
437 			/* empty the ring */
438 			ret = test_ring_deq_impl(r, cur_dst, esize[i], rsz,
439 							test_idx);
440 			TEST_RING_VERIFY(ret == (int)rsz);
441 			TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
442 			TEST_RING_VERIFY(rte_ring_count(r) == 0);
443 			TEST_RING_VERIFY(rte_ring_full(r) == 0);
444 			TEST_RING_VERIFY(rte_ring_empty(r));
445 
446 			/* check data */
447 			TEST_RING_VERIFY(memcmp(src, dst, rsz) == 0);
448 		}
449 
450 		/* Free memory before test completed */
451 		rte_ring_free(r);
452 		rte_free(src);
453 		rte_free(dst);
454 		r = NULL;
455 		src = NULL;
456 		dst = NULL;
457 	}
458 
459 	return 0;
460 fail:
461 	rte_ring_free(r);
462 	rte_free(src);
463 	rte_free(dst);
464 	return -1;
465 }
466 
467 /*
468  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
469  * Sequence of simple enqueues/dequeues and validate the enqueued and
470  * dequeued data.
471  */
472 static int
473 test_ring_burst_bulk_tests2(unsigned int test_idx)
474 {
475 	struct rte_ring *r;
476 	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
477 	int ret;
478 	unsigned int i;
479 
480 	for (i = 0; i < RTE_DIM(esize); i++) {
481 		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
482 			test_enqdeq_impl[test_idx].api_type, esize[i]);
483 
484 		/* Create the ring */
485 		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
486 				RING_SIZE, SOCKET_ID_ANY,
487 				test_enqdeq_impl[test_idx].create_flags);
488 
489 		/* alloc dummy object pointers */
490 		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
491 		if (src == NULL)
492 			goto fail;
493 		test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
494 		cur_src = src;
495 
496 		/* alloc some room for copied objects */
497 		dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
498 		if (dst == NULL)
499 			goto fail;
500 		cur_dst = dst;
501 
502 		printf("enqueue 1 obj\n");
503 		ret = test_ring_enq_impl(r, cur_src, esize[i], 1, test_idx);
504 		if (ret != 1)
505 			goto fail;
506 		cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
507 
508 		printf("enqueue 2 objs\n");
509 		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
510 		if (ret != 2)
511 			goto fail;
512 		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
513 
514 		printf("enqueue MAX_BULK objs\n");
515 		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
516 						test_idx);
517 		if (ret != MAX_BULK)
518 			goto fail;
519 		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
520 
521 		printf("dequeue 1 obj\n");
522 		ret = test_ring_deq_impl(r, cur_dst, esize[i], 1, test_idx);
523 		if (ret != 1)
524 			goto fail;
525 		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
526 
527 		printf("dequeue 2 objs\n");
528 		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
529 		if (ret != 2)
530 			goto fail;
531 		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
532 
533 		printf("dequeue MAX_BULK objs\n");
534 		ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
535 						test_idx);
536 		if (ret != MAX_BULK)
537 			goto fail;
538 		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK);
539 
540 		/* check data */
541 		if (memcmp(src, dst, cur_dst - dst)) {
542 			rte_hexdump(stdout, "src", src, cur_src - src);
543 			rte_hexdump(stdout, "dst", dst, cur_dst - dst);
544 			printf("data after dequeue is not the same\n");
545 			goto fail;
546 		}
547 
548 		/* Free memory before test completed */
549 		rte_ring_free(r);
550 		rte_free(src);
551 		rte_free(dst);
552 		r = NULL;
553 		src = NULL;
554 		dst = NULL;
555 	}
556 
557 	return 0;
558 fail:
559 	rte_ring_free(r);
560 	rte_free(src);
561 	rte_free(dst);
562 	return -1;
563 }
564 
565 /*
566  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
567  * Enqueue and dequeue to cover the entire ring length.
568  */
569 static int
570 test_ring_burst_bulk_tests3(unsigned int test_idx)
571 {
572 	struct rte_ring *r;
573 	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
574 	int ret;
575 	unsigned int i, j;
576 
577 	for (i = 0; i < RTE_DIM(esize); i++) {
578 		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
579 			test_enqdeq_impl[test_idx].api_type, esize[i]);
580 
581 		/* Create the ring */
582 		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
583 				RING_SIZE, SOCKET_ID_ANY,
584 				test_enqdeq_impl[test_idx].create_flags);
585 
586 		/* alloc dummy object pointers */
587 		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
588 		if (src == NULL)
589 			goto fail;
590 		test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
591 		cur_src = src;
592 
593 		/* alloc some room for copied objects */
594 		dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
595 		if (dst == NULL)
596 			goto fail;
597 		cur_dst = dst;
598 
599 		printf("fill and empty the ring\n");
600 		for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
601 			ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
602 							test_idx);
603 			if (ret != MAX_BULK)
604 				goto fail;
605 			cur_src = test_ring_inc_ptr(cur_src, esize[i],
606 								MAX_BULK);
607 
608 			ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
609 							test_idx);
610 			if (ret != MAX_BULK)
611 				goto fail;
612 			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
613 								MAX_BULK);
614 		}
615 
616 		/* check data */
617 		if (memcmp(src, dst, cur_dst - dst)) {
618 			rte_hexdump(stdout, "src", src, cur_src - src);
619 			rte_hexdump(stdout, "dst", dst, cur_dst - dst);
620 			printf("data after dequeue is not the same\n");
621 			goto fail;
622 		}
623 
624 		/* Free memory before test completed */
625 		rte_ring_free(r);
626 		rte_free(src);
627 		rte_free(dst);
628 		r = NULL;
629 		src = NULL;
630 		dst = NULL;
631 	}
632 
633 	return 0;
634 fail:
635 	rte_ring_free(r);
636 	rte_free(src);
637 	rte_free(dst);
638 	return -1;
639 }
640 
641 /*
642  * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
643  * Enqueue till the ring is full and dequeue till the ring becomes empty.
644  */
645 static int
646 test_ring_burst_bulk_tests4(unsigned int test_idx)
647 {
648 	struct rte_ring *r;
649 	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
650 	int ret;
651 	unsigned int i, j;
652 	unsigned int api_type, num_elems;
653 
654 	api_type = test_enqdeq_impl[test_idx].api_type;
655 
656 	for (i = 0; i < RTE_DIM(esize); i++) {
657 		test_ring_print_test_string(test_enqdeq_impl[test_idx].desc,
658 			test_enqdeq_impl[test_idx].api_type, esize[i]);
659 
660 		/* Create the ring */
661 		r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
662 				RING_SIZE, SOCKET_ID_ANY,
663 				test_enqdeq_impl[test_idx].create_flags);
664 
665 		/* alloc dummy object pointers */
666 		src = test_ring_calloc(RING_SIZE * 2, esize[i]);
667 		if (src == NULL)
668 			goto fail;
669 		test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
670 		cur_src = src;
671 
672 		/* alloc some room for copied objects */
673 		dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
674 		if (dst == NULL)
675 			goto fail;
676 		cur_dst = dst;
677 
678 		printf("Test enqueue without enough memory space\n");
679 		for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
680 			ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
681 							test_idx);
682 			if (ret != MAX_BULK)
683 				goto fail;
684 			cur_src = test_ring_inc_ptr(cur_src, esize[i],
685 								MAX_BULK);
686 		}
687 
688 		printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
689 		ret = test_ring_enq_impl(r, cur_src, esize[i], 2, test_idx);
690 		if (ret != 2)
691 			goto fail;
692 		cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
693 
694 		printf("Enqueue the remaining entries = MAX_BULK - 3\n");
695 		/* Bulk APIs enqueue exact number of elements */
696 		if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
697 			num_elems = MAX_BULK - 3;
698 		else
699 			num_elems = MAX_BULK;
700 		/* Always one free entry left */
701 		ret = test_ring_enq_impl(r, cur_src, esize[i], num_elems,
702 						test_idx);
703 		if (ret != MAX_BULK - 3)
704 			goto fail;
705 		cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
706 
707 		printf("Test if ring is full\n");
708 		if (rte_ring_full(r) != 1)
709 			goto fail;
710 
711 		printf("Test enqueue for a full entry\n");
712 		ret = test_ring_enq_impl(r, cur_src, esize[i], MAX_BULK,
713 						test_idx);
714 		if (ret != 0)
715 			goto fail;
716 
717 		printf("Test dequeue without enough objects\n");
718 		for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
719 			ret = test_ring_deq_impl(r, cur_dst, esize[i], MAX_BULK,
720 							test_idx);
721 			if (ret != MAX_BULK)
722 				goto fail;
723 			cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
724 								MAX_BULK);
725 		}
726 
727 		/* Available memory space for the exact MAX_BULK entries */
728 		ret = test_ring_deq_impl(r, cur_dst, esize[i], 2, test_idx);
729 		if (ret != 2)
730 			goto fail;
731 		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
732 
733 		/* Bulk APIs enqueue exact number of elements */
734 		if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
735 			num_elems = MAX_BULK - 3;
736 		else
737 			num_elems = MAX_BULK;
738 		ret = test_ring_deq_impl(r, cur_dst, esize[i], num_elems,
739 						test_idx);
740 		if (ret != MAX_BULK - 3)
741 			goto fail;
742 		cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
743 
744 		printf("Test if ring is empty\n");
745 		/* Check if ring is empty */
746 		if (rte_ring_empty(r) != 1)
747 			goto fail;
748 
749 		/* check data */
750 		if (memcmp(src, dst, cur_dst - dst)) {
751 			rte_hexdump(stdout, "src", src, cur_src - src);
752 			rte_hexdump(stdout, "dst", dst, cur_dst - dst);
753 			printf("data after dequeue is not the same\n");
754 			goto fail;
755 		}
756 
757 		/* Free memory before test completed */
758 		rte_ring_free(r);
759 		rte_free(src);
760 		rte_free(dst);
761 		r = NULL;
762 		src = NULL;
763 		dst = NULL;
764 	}
765 
766 	return 0;
767 fail:
768 	rte_ring_free(r);
769 	rte_free(src);
770 	rte_free(dst);
771 	return -1;
772 }
773 
774 /*
775  * Test default, single element, bulk and burst APIs
776  */
777 static int
778 test_ring_basic_ex(void)
779 {
780 	int ret = -1;
781 	unsigned int i, j;
782 	struct rte_ring *rp = NULL;
783 	void *obj = NULL;
784 
785 	for (i = 0; i < RTE_DIM(esize); i++) {
786 		obj = test_ring_calloc(RING_SIZE, esize[i]);
787 		if (obj == NULL) {
788 			printf("%s: failed to alloc memory\n", __func__);
789 			goto fail_test;
790 		}
791 
792 		rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE,
793 					SOCKET_ID_ANY,
794 					RING_F_SP_ENQ | RING_F_SC_DEQ);
795 		if (rp == NULL) {
796 			printf("%s: failed to create ring\n", __func__);
797 			goto fail_test;
798 		}
799 
800 		if (rte_ring_lookup("test_ring_basic_ex") != rp) {
801 			printf("%s: failed to find ring\n", __func__);
802 			goto fail_test;
803 		}
804 
805 		if (rte_ring_empty(rp) != 1) {
806 			printf("%s: ring is not empty but it should be\n",
807 				__func__);
808 			goto fail_test;
809 		}
810 
811 		printf("%u ring entries are now free\n",
812 			rte_ring_free_count(rp));
813 
814 		for (j = 0; j < RING_SIZE; j++) {
815 			test_ring_enqueue(rp, obj, esize[i], 1,
816 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
817 		}
818 
819 		if (rte_ring_full(rp) != 1) {
820 			printf("%s: ring is not full but it should be\n",
821 				__func__);
822 			goto fail_test;
823 		}
824 
825 		for (j = 0; j < RING_SIZE; j++) {
826 			test_ring_dequeue(rp, obj, esize[i], 1,
827 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
828 		}
829 
830 		if (rte_ring_empty(rp) != 1) {
831 			printf("%s: ring is not empty but it should be\n",
832 				__func__);
833 			goto fail_test;
834 		}
835 
836 		/* Following tests use the configured flags to decide
837 		 * SP/SC or MP/MC.
838 		 */
839 		/* Covering the ring burst operation */
840 		ret = test_ring_enqueue(rp, obj, esize[i], 2,
841 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
842 		if (ret != 2) {
843 			printf("%s: rte_ring_enqueue_burst fails\n", __func__);
844 			goto fail_test;
845 		}
846 
847 		ret = test_ring_dequeue(rp, obj, esize[i], 2,
848 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
849 		if (ret != 2) {
850 			printf("%s: rte_ring_dequeue_burst fails\n", __func__);
851 			goto fail_test;
852 		}
853 
854 		/* Covering the ring bulk operation */
855 		ret = test_ring_enqueue(rp, obj, esize[i], 2,
856 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
857 		if (ret != 2) {
858 			printf("%s: rte_ring_enqueue_bulk fails\n", __func__);
859 			goto fail_test;
860 		}
861 
862 		ret = test_ring_dequeue(rp, obj, esize[i], 2,
863 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
864 		if (ret != 2) {
865 			printf("%s: rte_ring_dequeue_bulk fails\n", __func__);
866 			goto fail_test;
867 		}
868 
869 		rte_ring_free(rp);
870 		rte_free(obj);
871 		rp = NULL;
872 		obj = NULL;
873 	}
874 
875 	return 0;
876 
877 fail_test:
878 	rte_ring_free(rp);
879 	if (obj != NULL)
880 		rte_free(obj);
881 
882 	return -1;
883 }
884 
885 /*
886  * Basic test cases with exact size ring.
887  */
888 static int
889 test_ring_with_exact_size(void)
890 {
891 	struct rte_ring *std_r = NULL, *exact_sz_r = NULL;
892 	void *obj_orig;
893 	void *obj;
894 	const unsigned int ring_sz = 16;
895 	unsigned int i, j;
896 	int ret = -1;
897 
898 	for (i = 0; i < RTE_DIM(esize); i++) {
899 		test_ring_print_test_string("Test exact size ring",
900 				TEST_RING_IGNORE_API_TYPE,
901 				esize[i]);
902 
903 		/* alloc object pointers. Allocate one extra object
904 		 * and create an unaligned address.
905 		 */
906 		obj_orig = test_ring_calloc(17, esize[i]);
907 		if (obj_orig == NULL)
908 			goto test_fail;
909 		obj = ((char *)obj_orig) + 1;
910 
911 		std_r = test_ring_create("std", esize[i], ring_sz,
912 					rte_socket_id(),
913 					RING_F_SP_ENQ | RING_F_SC_DEQ);
914 		if (std_r == NULL) {
915 			printf("%s: error, can't create std ring\n", __func__);
916 			goto test_fail;
917 		}
918 		exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz,
919 				rte_socket_id(),
920 				RING_F_SP_ENQ | RING_F_SC_DEQ |
921 				RING_F_EXACT_SZ);
922 		if (exact_sz_r == NULL) {
923 			printf("%s: error, can't create exact size ring\n",
924 					__func__);
925 			goto test_fail;
926 		}
927 
928 		/*
929 		 * Check that the exact size ring is bigger than the
930 		 * standard ring
931 		 */
932 		if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) {
933 			printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
934 					__func__,
935 					rte_ring_get_size(std_r),
936 					rte_ring_get_size(exact_sz_r));
937 			goto test_fail;
938 		}
939 		/*
940 		 * check that the exact_sz_ring can hold one more element
941 		 * than the standard ring. (16 vs 15 elements)
942 		 */
943 		for (j = 0; j < ring_sz - 1; j++) {
944 			test_ring_enqueue(std_r, obj, esize[i], 1,
945 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
946 			test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
947 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
948 		}
949 		ret = test_ring_enqueue(std_r, obj, esize[i], 1,
950 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
951 		if (ret != -ENOBUFS) {
952 			printf("%s: error, unexpected successful enqueue\n",
953 				__func__);
954 			goto test_fail;
955 		}
956 		ret = test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
957 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
958 		if (ret == -ENOBUFS) {
959 			printf("%s: error, enqueue failed\n", __func__);
960 			goto test_fail;
961 		}
962 
963 		/* check that dequeue returns the expected number of elements */
964 		ret = test_ring_dequeue(exact_sz_r, obj, esize[i], ring_sz,
965 				TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
966 		if (ret != (int)ring_sz) {
967 			printf("%s: error, failed to dequeue expected nb of elements\n",
968 				__func__);
969 			goto test_fail;
970 		}
971 
972 		/* check that the capacity function returns expected value */
973 		if (rte_ring_get_capacity(exact_sz_r) != ring_sz) {
974 			printf("%s: error, incorrect ring capacity reported\n",
975 					__func__);
976 			goto test_fail;
977 		}
978 
979 		rte_free(obj_orig);
980 		rte_ring_free(std_r);
981 		rte_ring_free(exact_sz_r);
982 		obj_orig = NULL;
983 		std_r = NULL;
984 		exact_sz_r = NULL;
985 	}
986 
987 	return 0;
988 
989 test_fail:
990 	rte_free(obj_orig);
991 	rte_ring_free(std_r);
992 	rte_ring_free(exact_sz_r);
993 	return -1;
994 }
995 
996 static int
997 test_ring(void)
998 {
999 	int32_t rc;
1000 	unsigned int i;
1001 
1002 	/* Negative test cases */
1003 	if (test_ring_negative_tests() < 0)
1004 		goto test_fail;
1005 
1006 	/* Some basic operations */
1007 	if (test_ring_basic_ex() < 0)
1008 		goto test_fail;
1009 
1010 	if (test_ring_with_exact_size() < 0)
1011 		goto test_fail;
1012 
1013 	/* Burst and bulk operations with sp/sc, mp/mc and default.
1014 	 * The test cases are split into smaller test cases to
1015 	 * help clang compile faster.
1016 	 */
1017 	for (i = 0; i != RTE_DIM(test_enqdeq_impl); i++) {
1018 
1019 
1020 		rc = test_ring_burst_bulk_tests1(i);
1021 		if (rc < 0)
1022 			goto test_fail;
1023 
1024 		rc = test_ring_burst_bulk_tests2(i);
1025 		if (rc < 0)
1026 			goto test_fail;
1027 
1028 		rc = test_ring_burst_bulk_tests3(i);
1029 		if (rc < 0)
1030 			goto test_fail;
1031 
1032 		rc = test_ring_burst_bulk_tests4(i);
1033 		if (rc < 0)
1034 			goto test_fail;
1035 	}
1036 
1037 	/* dump the ring status */
1038 	rte_ring_list_dump(stdout);
1039 
1040 	return 0;
1041 
1042 test_fail:
1043 
1044 	return -1;
1045 }
1046 
1047 REGISTER_TEST_COMMAND(ring_autotest, test_ring);
1048