15129044dSC.J. Collier/*-
25129044dSC.J. Collier *   BSD LICENSE
35129044dSC.J. Collier *
45129044dSC.J. Collier *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
55129044dSC.J. Collier *   All rights reserved.
65129044dSC.J. Collier *
75129044dSC.J. Collier *   Redistribution and use in source and binary forms, with or without
85129044dSC.J. Collier *   modification, are permitted provided that the following conditions
95129044dSC.J. Collier *   are met:
105129044dSC.J. Collier *
115129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
125129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
135129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
145129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in
155129044dSC.J. Collier *       the documentation and/or other materials provided with the
165129044dSC.J. Collier *       distribution.
175129044dSC.J. Collier *     * Neither the name of Intel Corporation nor the names of its
185129044dSC.J. Collier *       contributors may be used to endorse or promote products derived
195129044dSC.J. Collier *       from this software without specific prior written permission.
205129044dSC.J. Collier *
215129044dSC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225129044dSC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235129044dSC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245129044dSC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255129044dSC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265129044dSC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275129044dSC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285129044dSC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295129044dSC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305129044dSC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315129044dSC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier#include <string.h>
355129044dSC.J. Collier#include <stdarg.h>
365129044dSC.J. Collier#include <stdio.h>
375129044dSC.J. Collier#include <stdlib.h>
385129044dSC.J. Collier#include <stdint.h>
395129044dSC.J. Collier#include <inttypes.h>
405129044dSC.J. Collier#include <errno.h>
415129044dSC.J. Collier#include <sys/queue.h>
425129044dSC.J. Collier
435129044dSC.J. Collier#include <rte_common.h>
445129044dSC.J. Collier#include <rte_log.h>
455129044dSC.J. Collier#include <rte_memory.h>
465129044dSC.J. Collier#include <rte_memzone.h>
475129044dSC.J. Collier#include <rte_launch.h>
485129044dSC.J. Collier#include <rte_cycles.h>
495129044dSC.J. Collier#include <rte_eal.h>
505129044dSC.J. Collier#include <rte_per_lcore.h>
515129044dSC.J. Collier#include <rte_lcore.h>
525129044dSC.J. Collier#include <rte_atomic.h>
535129044dSC.J. Collier#include <rte_branch_prediction.h>
545129044dSC.J. Collier#include <rte_malloc.h>
555129044dSC.J. Collier#include <rte_ring.h>
565129044dSC.J. Collier#include <rte_random.h>
575129044dSC.J. Collier#include <rte_common.h>
585129044dSC.J. Collier#include <rte_errno.h>
595129044dSC.J. Collier#include <rte_hexdump.h>
605129044dSC.J. Collier
615129044dSC.J. Collier#include "test.h"
625129044dSC.J. Collier
635129044dSC.J. Collier/*
645129044dSC.J. Collier * Ring
655129044dSC.J. Collier * ====
665129044dSC.J. Collier *
675129044dSC.J. Collier * #. Basic tests: done on one core:
685129044dSC.J. Collier *
695129044dSC.J. Collier *    - Using single producer/single consumer functions:
705129044dSC.J. Collier *
715129044dSC.J. Collier *      - Enqueue one object, two objects, MAX_BULK objects
725129044dSC.J. Collier *      - Dequeue one object, two objects, MAX_BULK objects
735129044dSC.J. Collier *      - Check that dequeued pointers are correct
745129044dSC.J. Collier *
755129044dSC.J. Collier *    - Using multi producers/multi consumers functions:
765129044dSC.J. Collier *
775129044dSC.J. Collier *      - Enqueue one object, two objects, MAX_BULK objects
785129044dSC.J. Collier *      - Dequeue one object, two objects, MAX_BULK objects
795129044dSC.J. Collier *      - Check that dequeued pointers are correct
805129044dSC.J. Collier *
815129044dSC.J. Collier *    - Test watermark and default bulk enqueue/dequeue:
825129044dSC.J. Collier *
835129044dSC.J. Collier *      - Set watermark
845129044dSC.J. Collier *      - Set default bulk value
855129044dSC.J. Collier *      - Enqueue objects, check that -EDQUOT is returned when
865129044dSC.J. Collier *        watermark is exceeded
875129044dSC.J. Collier *      - Check that dequeued pointers are correct
885129044dSC.J. Collier *
895129044dSC.J. Collier * #. Check live watermark change
905129044dSC.J. Collier *
915129044dSC.J. Collier *    - Start a loop on another lcore that will enqueue and dequeue
925129044dSC.J. Collier *      objects in a ring. It will monitor the value of watermark.
935129044dSC.J. Collier *    - At the same time, change the watermark on the master lcore.
945129044dSC.J. Collier *    - The slave lcore will check that watermark changes from 16 to 32.
955129044dSC.J. Collier *
965129044dSC.J. Collier * #. Performance tests.
975129044dSC.J. Collier *
985129044dSC.J. Collier * Tests done in test_ring_perf.c
995129044dSC.J. Collier */
1005129044dSC.J. Collier
1015129044dSC.J. Collier#define RING_SIZE 4096
1025129044dSC.J. Collier#define MAX_BULK 32
1035129044dSC.J. Collier
1045129044dSC.J. Collierstatic rte_atomic32_t synchro;
1055129044dSC.J. Collier
1065129044dSC.J. Collierstatic struct rte_ring *r;
1075129044dSC.J. Collier
1085129044dSC.J. Collier#define	TEST_RING_VERIFY(exp)						\
1095129044dSC.J. Collier	if (!(exp)) {							\
1105129044dSC.J. Collier		printf("error at %s:%d\tcondition " #exp " failed\n",	\
1115129044dSC.J. Collier		    __func__, __LINE__);				\
1125129044dSC.J. Collier		rte_ring_dump(stdout, r);				\
1135129044dSC.J. Collier		return -1;						\
1145129044dSC.J. Collier	}
1155129044dSC.J. Collier
1165129044dSC.J. Collier#define	TEST_RING_FULL_EMTPY_ITER	8
1175129044dSC.J. Collier
1185129044dSC.J. Collierstatic int
1195129044dSC.J. Colliercheck_live_watermark_change(__attribute__((unused)) void *dummy)
1205129044dSC.J. Collier{
1215129044dSC.J. Collier	uint64_t hz = rte_get_timer_hz();
1225129044dSC.J. Collier	void *obj_table[MAX_BULK];
1235129044dSC.J. Collier	unsigned watermark, watermark_old = 16;
1245129044dSC.J. Collier	uint64_t cur_time, end_time;
1255129044dSC.J. Collier	int64_t diff = 0;
1265129044dSC.J. Collier	int i, ret;
1275129044dSC.J. Collier	unsigned count = 4;
1285129044dSC.J. Collier
1295129044dSC.J. Collier	/* init the object table */
1305129044dSC.J. Collier	memset(obj_table, 0, sizeof(obj_table));
131809f0800SChristian Ehrhardt	end_time = rte_get_timer_cycles() + (hz / 4);
1325129044dSC.J. Collier
1335129044dSC.J. Collier	/* check that bulk and watermark are 4 and 32 (respectively) */
1345129044dSC.J. Collier	while (diff >= 0) {
1355129044dSC.J. Collier
1365129044dSC.J. Collier		/* add in ring until we reach watermark */
1375129044dSC.J. Collier		ret = 0;
1385129044dSC.J. Collier		for (i = 0; i < 16; i ++) {
1395129044dSC.J. Collier			if (ret != 0)
1405129044dSC.J. Collier				break;
1415129044dSC.J. Collier			ret = rte_ring_enqueue_bulk(r, obj_table, count);
1425129044dSC.J. Collier		}
1435129044dSC.J. Collier
1445129044dSC.J. Collier		if (ret != -EDQUOT) {
1455129044dSC.J. Collier			printf("Cannot enqueue objects, or watermark not "
1465129044dSC.J. Collier			       "reached (ret=%d)\n", ret);
1475129044dSC.J. Collier			return -1;
1485129044dSC.J. Collier		}
1495129044dSC.J. Collier
1505129044dSC.J. Collier		/* read watermark, the only change allowed is from 16 to 32 */
1515129044dSC.J. Collier		watermark = r->prod.watermark;
1525129044dSC.J. Collier		if (watermark != watermark_old &&
1535129044dSC.J. Collier		    (watermark_old != 16 || watermark != 32)) {
1545129044dSC.J. Collier			printf("Bad watermark change %u -> %u\n", watermark_old,
1555129044dSC.J. Collier			       watermark);
1565129044dSC.J. Collier			return -1;
1575129044dSC.J. Collier		}
1585129044dSC.J. Collier		watermark_old = watermark;
1595129044dSC.J. Collier
1605129044dSC.J. Collier		/* dequeue objects from ring */
1615129044dSC.J. Collier		while (i--) {
1625129044dSC.J. Collier			ret = rte_ring_dequeue_bulk(r, obj_table, count);
1635129044dSC.J. Collier			if (ret != 0) {
1645129044dSC.J. Collier				printf("Cannot dequeue (ret=%d)\n", ret);
1655129044dSC.J. Collier				return -1;
1665129044dSC.J. Collier			}
1675129044dSC.J. Collier		}
1685129044dSC.J. Collier
1695129044dSC.J. Collier		cur_time = rte_get_timer_cycles();
1705129044dSC.J. Collier		diff = end_time - cur_time;
1715129044dSC.J. Collier	}
1725129044dSC.J. Collier
1735129044dSC.J. Collier	if (watermark_old != 32 ) {
1745129044dSC.J. Collier		printf(" watermark was not updated (wm=%u)\n",
1755129044dSC.J. Collier		       watermark_old);
1765129044dSC.J. Collier		return -1;
1775129044dSC.J. Collier	}
1785129044dSC.J. Collier
1795129044dSC.J. Collier	return 0;
1805129044dSC.J. Collier}
1815129044dSC.J. Collier
1825129044dSC.J. Collierstatic int
1835129044dSC.J. Colliertest_live_watermark_change(void)
1845129044dSC.J. Collier{
1855129044dSC.J. Collier	unsigned lcore_id = rte_lcore_id();
1865129044dSC.J. Collier	unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1);
1875129044dSC.J. Collier
1885129044dSC.J. Collier	printf("Test watermark live modification\n");
1895129044dSC.J. Collier	rte_ring_set_water_mark(r, 16);
1905129044dSC.J. Collier
1915129044dSC.J. Collier	/* launch a thread that will enqueue and dequeue, checking
1925129044dSC.J. Collier	 * watermark and quota */
1935129044dSC.J. Collier	rte_eal_remote_launch(check_live_watermark_change, NULL, lcore_id2);
1945129044dSC.J. Collier
195809f0800SChristian Ehrhardt	rte_delay_ms(100);
1965129044dSC.J. Collier	rte_ring_set_water_mark(r, 32);
197809f0800SChristian Ehrhardt	rte_delay_ms(100);
1985129044dSC.J. Collier
1995129044dSC.J. Collier	if (rte_eal_wait_lcore(lcore_id2) < 0)
2005129044dSC.J. Collier		return -1;
2015129044dSC.J. Collier
2025129044dSC.J. Collier	return 0;
2035129044dSC.J. Collier}
2045129044dSC.J. Collier
2055129044dSC.J. Collier/* Test for catch on invalid watermark values */
2065129044dSC.J. Collierstatic int
2075129044dSC.J. Colliertest_set_watermark( void ){
2085129044dSC.J. Collier	unsigned count;
2095129044dSC.J. Collier	int setwm;
2105129044dSC.J. Collier
2115129044dSC.J. Collier	struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex");
2125129044dSC.J. Collier	if(r == NULL){
2135129044dSC.J. Collier		printf( " ring lookup failed\n" );
2145129044dSC.J. Collier		goto error;
2155129044dSC.J. Collier	}
2165129044dSC.J. Collier	count = r->prod.size*2;
2175129044dSC.J. Collier	setwm = rte_ring_set_water_mark(r, count);
2185129044dSC.J. Collier	if (setwm != -EINVAL){
2195129044dSC.J. Collier		printf("Test failed to detect invalid watermark count value\n");
2205129044dSC.J. Collier		goto error;
2215129044dSC.J. Collier	}
2225129044dSC.J. Collier
2235129044dSC.J. Collier	count = 0;
2245129044dSC.J. Collier	rte_ring_set_water_mark(r, count);
2255129044dSC.J. Collier	if (r->prod.watermark != r->prod.size) {
2265129044dSC.J. Collier		printf("Test failed to detect invalid watermark count value\n");
2275129044dSC.J. Collier		goto error;
2285129044dSC.J. Collier	}
2295129044dSC.J. Collier	return 0;
2305129044dSC.J. Collier
2315129044dSC.J. Colliererror:
2325129044dSC.J. Collier	return -1;
2335129044dSC.J. Collier}
2345129044dSC.J. Collier
2355129044dSC.J. Collier/*
2365129044dSC.J. Collier * helper routine for test_ring_basic
2375129044dSC.J. Collier */
2385129044dSC.J. Collierstatic int
2395129044dSC.J. Colliertest_ring_basic_full_empty(void * const src[], void *dst[])
2405129044dSC.J. Collier{
2415129044dSC.J. Collier	unsigned i, rand;
2425129044dSC.J. Collier	const unsigned rsz = RING_SIZE - 1;
2435129044dSC.J. Collier
2445129044dSC.J. Collier	printf("Basic full/empty test\n");
2455129044dSC.J. Collier
2465129044dSC.J. Collier	for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) {
2475129044dSC.J. Collier
2485129044dSC.J. Collier		/* random shift in the ring */
2495129044dSC.J. Collier		rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
2505129044dSC.J. Collier		printf("%s: iteration %u, random shift: %u;\n",
2515129044dSC.J. Collier		    __func__, i, rand);
2525129044dSC.J. Collier		TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src,
2535129044dSC.J. Collier		    rand));
2545129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rand));
2555129044dSC.J. Collier
2565129044dSC.J. Collier		/* fill the ring */
2575129044dSC.J. Collier		TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src,
2585129044dSC.J. Collier		    rsz));
2595129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_free_count(r));
2605129044dSC.J. Collier		TEST_RING_VERIFY(rsz == rte_ring_count(r));
2615129044dSC.J. Collier		TEST_RING_VERIFY(rte_ring_full(r));
2625129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_empty(r));
2635129044dSC.J. Collier
2645129044dSC.J. Collier		/* empty the ring */
2655129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rsz));
2665129044dSC.J. Collier		TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
2675129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_count(r));
2685129044dSC.J. Collier		TEST_RING_VERIFY(0 == rte_ring_full(r));
2695129044dSC.J. Collier		TEST_RING_VERIFY(rte_ring_empty(r));
2705129044dSC.J. Collier
2715129044dSC.J. Collier		/* check data */
2725129044dSC.J. Collier		TEST_RING_VERIFY(0 == memcmp(src, dst, rsz));
2735129044dSC.J. Collier		rte_ring_dump(stdout, r);
2745129044dSC.J. Collier	}
2755129044dSC.J. Collier	return 0;
2765129044dSC.J. Collier}
2775129044dSC.J. Collier
2785129044dSC.J. Collierstatic int
2795129044dSC.J. Colliertest_ring_basic(void)
2805129044dSC.J. Collier{
2815129044dSC.J. Collier	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
2825129044dSC.J. Collier	int ret;
2835129044dSC.J. Collier	unsigned i, num_elems;
2845129044dSC.J. Collier
2855129044dSC.J. Collier	/* alloc dummy object pointers */
2865129044dSC.J. Collier	src = malloc(RING_SIZE*2*sizeof(void *));
2875129044dSC.J. Collier	if (src == NULL)
2885129044dSC.J. Collier		goto fail;
2895129044dSC.J. Collier
2905129044dSC.J. Collier	for (i = 0; i < RING_SIZE*2 ; i++) {
2915129044dSC.J. Collier		src[i] = (void *)(unsigned long)i;
2925129044dSC.J. Collier	}
2935129044dSC.J. Collier	cur_src = src;
2945129044dSC.J. Collier
2955129044dSC.J. Collier	/* alloc some room for copied objects */
2965129044dSC.J. Collier	dst = malloc(RING_SIZE*2*sizeof(void *));
2975129044dSC.J. Collier	if (dst == NULL)
2985129044dSC.J. Collier		goto fail;
2995129044dSC.J. Collier
3005129044dSC.J. Collier	memset(dst, 0, RING_SIZE*2*sizeof(void *));
3015129044dSC.J. Collier	cur_dst = dst;
3025129044dSC.J. Collier
3035129044dSC.J. Collier	printf("enqueue 1 obj\n");
3045129044dSC.J. Collier	ret = rte_ring_sp_enqueue_bulk(r, cur_src, 1);
3055129044dSC.J. Collier	cur_src += 1;
3065129044dSC.J. Collier	if (ret != 0)
3075129044dSC.J. Collier		goto fail;
3085129044dSC.J. Collier
3095129044dSC.J. Collier	printf("enqueue 2 objs\n");
3105129044dSC.J. Collier	ret = rte_ring_sp_enqueue_bulk(r, cur_src, 2);
3115129044dSC.J. Collier	cur_src += 2;
3125129044dSC.J. Collier	if (ret != 0)
3135129044dSC.J. Collier		goto fail;
3145129044dSC.J. Collier
3155129044dSC.J. Collier	printf("enqueue MAX_BULK objs\n");
3165129044dSC.J. Collier	ret = rte_ring_sp_enqueue_bulk(r, cur_src, MAX_BULK);
3175129044dSC.J. Collier	cur_src += MAX_BULK;
3185129044dSC.J. Collier	if (ret != 0)
3195129044dSC.J. Collier		goto fail;
3205129044dSC.J. Collier
3215129044dSC.J. Collier	printf("dequeue 1 obj\n");
3225129044dSC.J. Collier	ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 1);
3235129044dSC.J. Collier	cur_dst += 1;
3245129044dSC.J. Collier	if (ret != 0)
3255129044dSC.J. Collier		goto fail;
3265129044dSC.J. Collier
3275129044dSC.J. Collier	printf("dequeue 2 objs\n");
3285129044dSC.J. Collier	ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 2);
3295129044dSC.J. Collier	cur_dst += 2;
3305129044dSC.J. Collier	if (ret != 0)
3315129044dSC.J. Collier		goto fail;
3325129044dSC.J. Collier
3335129044dSC.J. Collier	printf("dequeue MAX_BULK objs\n");
3345129044dSC.J. Collier	ret = rte_ring_sc_dequeue_bulk(r, cur_dst, MAX_BULK);
3355129044dSC.J. Collier	cur_dst += MAX_BULK;
3365129044dSC.J. Collier	if (ret != 0)
3375129044dSC.J. Collier		goto fail;
3385129044dSC.J. Collier
3395129044dSC.J. Collier	/* check data */
3405129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
3415129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
3425129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
3435129044dSC.J. Collier		printf("data after dequeue is not the same\n");
3445129044dSC.J. Collier		goto fail;
3455129044dSC.J. Collier	}
3465129044dSC.J. Collier	cur_src = src;
3475129044dSC.J. Collier	cur_dst = dst;
3485129044dSC.J. Collier
3495129044dSC.J. Collier	printf("enqueue 1 obj\n");
3505129044dSC.J. Collier	ret = rte_ring_mp_enqueue_bulk(r, cur_src, 1);
3515129044dSC.J. Collier	cur_src += 1;
3525129044dSC.J. Collier	if (ret != 0)
3535129044dSC.J. Collier		goto fail;
3545129044dSC.J. Collier
3555129044dSC.J. Collier	printf("enqueue 2 objs\n");
3565129044dSC.J. Collier	ret = rte_ring_mp_enqueue_bulk(r, cur_src, 2);
3575129044dSC.J. Collier	cur_src += 2;
3585129044dSC.J. Collier	if (ret != 0)
3595129044dSC.J. Collier		goto fail;
3605129044dSC.J. Collier
3615129044dSC.J. Collier	printf("enqueue MAX_BULK objs\n");
3625129044dSC.J. Collier	ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK);
3635129044dSC.J. Collier	cur_src += MAX_BULK;
3645129044dSC.J. Collier	if (ret != 0)
3655129044dSC.J. Collier		goto fail;
3665129044dSC.J. Collier
3675129044dSC.J. Collier	printf("dequeue 1 obj\n");
3685129044dSC.J. Collier	ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 1);
3695129044dSC.J. Collier	cur_dst += 1;
3705129044dSC.J. Collier	if (ret != 0)
3715129044dSC.J. Collier		goto fail;
3725129044dSC.J. Collier
3735129044dSC.J. Collier	printf("dequeue 2 objs\n");
3745129044dSC.J. Collier	ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 2);
3755129044dSC.J. Collier	cur_dst += 2;
3765129044dSC.J. Collier	if (ret != 0)
3775129044dSC.J. Collier		goto fail;
3785129044dSC.J. Collier
3795129044dSC.J. Collier	printf("dequeue MAX_BULK objs\n");
3805129044dSC.J. Collier	ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK);
3815129044dSC.J. Collier	cur_dst += MAX_BULK;
3825129044dSC.J. Collier	if (ret != 0)
3835129044dSC.J. Collier		goto fail;
3845129044dSC.J. Collier
3855129044dSC.J. Collier	/* check data */
3865129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
3875129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
3885129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
3895129044dSC.J. Collier		printf("data after dequeue is not the same\n");
3905129044dSC.J. Collier		goto fail;
3915129044dSC.J. Collier	}
3925129044dSC.J. Collier	cur_src = src;
3935129044dSC.J. Collier	cur_dst = dst;
3945129044dSC.J. Collier
3955129044dSC.J. Collier	printf("fill and empty the ring\n");
3965129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK; i++) {
3975129044dSC.J. Collier		ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK);
3985129044dSC.J. Collier		cur_src += MAX_BULK;
3995129044dSC.J. Collier		if (ret != 0)
4005129044dSC.J. Collier			goto fail;
4015129044dSC.J. Collier		ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK);
4025129044dSC.J. Collier		cur_dst += MAX_BULK;
4035129044dSC.J. Collier		if (ret != 0)
4045129044dSC.J. Collier			goto fail;
4055129044dSC.J. Collier	}
4065129044dSC.J. Collier
4075129044dSC.J. Collier	/* check data */
4085129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
4095129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
4105129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
4115129044dSC.J. Collier		printf("data after dequeue is not the same\n");
4125129044dSC.J. Collier		goto fail;
4135129044dSC.J. Collier	}
4145129044dSC.J. Collier
4155129044dSC.J. Collier	if (test_ring_basic_full_empty(src, dst) != 0)
4165129044dSC.J. Collier		goto fail;
4175129044dSC.J. Collier
4185129044dSC.J. Collier	cur_src = src;
4195129044dSC.J. Collier	cur_dst = dst;
4205129044dSC.J. Collier
4215129044dSC.J. Collier	printf("test watermark and default bulk enqueue / dequeue\n");
4225129044dSC.J. Collier	rte_ring_set_water_mark(r, 20);
4235129044dSC.J. Collier	num_elems = 16;
4245129044dSC.J. Collier
4255129044dSC.J. Collier	cur_src = src;
4265129044dSC.J. Collier	cur_dst = dst;
4275129044dSC.J. Collier
4285129044dSC.J. Collier	ret = rte_ring_enqueue_bulk(r, cur_src, num_elems);
4295129044dSC.J. Collier	cur_src += num_elems;
4305129044dSC.J. Collier	if (ret != 0) {
4315129044dSC.J. Collier		printf("Cannot enqueue\n");
4325129044dSC.J. Collier		goto fail;
4335129044dSC.J. Collier	}
4345129044dSC.J. Collier	ret = rte_ring_enqueue_bulk(r, cur_src, num_elems);
4355129044dSC.J. Collier	cur_src += num_elems;
4365129044dSC.J. Collier	if (ret != -EDQUOT) {
4375129044dSC.J. Collier		printf("Watermark not exceeded\n");
4385129044dSC.J. Collier		goto fail;
4395129044dSC.J. Collier	}
4405129044dSC.J. Collier	ret = rte_ring_dequeue_bulk(r, cur_dst, num_elems);
4415129044dSC.J. Collier	cur_dst += num_elems;
4425129044dSC.J. Collier	if (ret != 0) {
4435129044dSC.J. Collier		printf("Cannot dequeue\n");
4445129044dSC.J. Collier		goto fail;
4455129044dSC.J. Collier	}
4465129044dSC.J. Collier	ret = rte_ring_dequeue_bulk(r, cur_dst, num_elems);
4475129044dSC.J. Collier	cur_dst += num_elems;
4485129044dSC.J. Collier	if (ret != 0) {
4495129044dSC.J. Collier		printf("Cannot dequeue2\n");
4505129044dSC.J. Collier		goto fail;
4515129044dSC.J. Collier	}
4525129044dSC.J. Collier
4535129044dSC.J. Collier	/* check data */
4545129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
4555129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
4565129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
4575129044dSC.J. Collier		printf("data after dequeue is not the same\n");
4585129044dSC.J. Collier		goto fail;
4595129044dSC.J. Collier	}
4605129044dSC.J. Collier
4615129044dSC.J. Collier	cur_src = src;
4625129044dSC.J. Collier	cur_dst = dst;
4635129044dSC.J. Collier
4645129044dSC.J. Collier	ret = rte_ring_mp_enqueue(r, cur_src);
4655129044dSC.J. Collier	if (ret != 0)
4665129044dSC.J. Collier		goto fail;
4675129044dSC.J. Collier
4685129044dSC.J. Collier	ret = rte_ring_mc_dequeue(r, cur_dst);
4695129044dSC.J. Collier	if (ret != 0)
4705129044dSC.J. Collier		goto fail;
4715129044dSC.J. Collier
4725129044dSC.J. Collier	free(src);
4735129044dSC.J. Collier	free(dst);
4745129044dSC.J. Collier	return 0;
4755129044dSC.J. Collier
4765129044dSC.J. Collier fail:
4775129044dSC.J. Collier	free(src);
4785129044dSC.J. Collier	free(dst);
4795129044dSC.J. Collier	return -1;
4805129044dSC.J. Collier}
4815129044dSC.J. Collier
4825129044dSC.J. Collierstatic int
4835129044dSC.J. Colliertest_ring_burst_basic(void)
4845129044dSC.J. Collier{
4855129044dSC.J. Collier	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
4865129044dSC.J. Collier	int ret;
4875129044dSC.J. Collier	unsigned i;
4885129044dSC.J. Collier
4895129044dSC.J. Collier	/* alloc dummy object pointers */
4905129044dSC.J. Collier	src = malloc(RING_SIZE*2*sizeof(void *));
4915129044dSC.J. Collier	if (src == NULL)
4925129044dSC.J. Collier		goto fail;
4935129044dSC.J. Collier
4945129044dSC.J. Collier	for (i = 0; i < RING_SIZE*2 ; i++) {
4955129044dSC.J. Collier		src[i] = (void *)(unsigned long)i;
4965129044dSC.J. Collier	}
4975129044dSC.J. Collier	cur_src = src;
4985129044dSC.J. Collier
4995129044dSC.J. Collier	/* alloc some room for copied objects */
5005129044dSC.J. Collier	dst = malloc(RING_SIZE*2*sizeof(void *));
5015129044dSC.J. Collier	if (dst == NULL)
5025129044dSC.J. Collier		goto fail;
5035129044dSC.J. Collier
5045129044dSC.J. Collier	memset(dst, 0, RING_SIZE*2*sizeof(void *));
5055129044dSC.J. Collier	cur_dst = dst;
5065129044dSC.J. Collier
5075129044dSC.J. Collier	printf("Test SP & SC basic functions \n");
5085129044dSC.J. Collier	printf("enqueue 1 obj\n");
5095129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, 1);
5105129044dSC.J. Collier	cur_src += 1;
5115129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 1)
5125129044dSC.J. Collier		goto fail;
5135129044dSC.J. Collier
5145129044dSC.J. Collier	printf("enqueue 2 objs\n");
5155129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, 2);
5165129044dSC.J. Collier	cur_src += 2;
5175129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
5185129044dSC.J. Collier		goto fail;
5195129044dSC.J. Collier
5205129044dSC.J. Collier	printf("enqueue MAX_BULK objs\n");
5215129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK) ;
5225129044dSC.J. Collier	cur_src += MAX_BULK;
5235129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
5245129044dSC.J. Collier		goto fail;
5255129044dSC.J. Collier
5265129044dSC.J. Collier	printf("dequeue 1 obj\n");
5275129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, 1) ;
5285129044dSC.J. Collier	cur_dst += 1;
5295129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 1)
5305129044dSC.J. Collier		goto fail;
5315129044dSC.J. Collier
5325129044dSC.J. Collier	printf("dequeue 2 objs\n");
5335129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, 2);
5345129044dSC.J. Collier	cur_dst += 2;
5355129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
5365129044dSC.J. Collier		goto fail;
5375129044dSC.J. Collier
5385129044dSC.J. Collier	printf("dequeue MAX_BULK objs\n");
5395129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK);
5405129044dSC.J. Collier	cur_dst += MAX_BULK;
5415129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
5425129044dSC.J. Collier		goto fail;
5435129044dSC.J. Collier
5445129044dSC.J. Collier	/* check data */
5455129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
5465129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
5475129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
5485129044dSC.J. Collier		printf("data after dequeue is not the same\n");
5495129044dSC.J. Collier		goto fail;
5505129044dSC.J. Collier	}
5515129044dSC.J. Collier
5525129044dSC.J. Collier	cur_src = src;
5535129044dSC.J. Collier	cur_dst = dst;
5545129044dSC.J. Collier
5555129044dSC.J. Collier	printf("Test enqueue without enough memory space \n");
5565129044dSC.J. Collier	for (i = 0; i< (RING_SIZE/MAX_BULK - 1); i++) {
5575129044dSC.J. Collier		ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK);
5585129044dSC.J. Collier		cur_src += MAX_BULK;
5595129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) {
5605129044dSC.J. Collier			goto fail;
5615129044dSC.J. Collier		}
5625129044dSC.J. Collier	}
5635129044dSC.J. Collier
5645129044dSC.J. Collier	printf("Enqueue 2 objects, free entries = MAX_BULK - 2  \n");
5655129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, 2);
5665129044dSC.J. Collier	cur_src += 2;
5675129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
5685129044dSC.J. Collier		goto fail;
5695129044dSC.J. Collier
5705129044dSC.J. Collier	printf("Enqueue the remaining entries = MAX_BULK - 2  \n");
5715129044dSC.J. Collier	/* Always one free entry left */
5725129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK);
5735129044dSC.J. Collier	cur_src += MAX_BULK - 3;
5745129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3)
5755129044dSC.J. Collier		goto fail;
5765129044dSC.J. Collier
5775129044dSC.J. Collier	printf("Test if ring is full  \n");
5785129044dSC.J. Collier	if (rte_ring_full(r) != 1)
5795129044dSC.J. Collier		goto fail;
5805129044dSC.J. Collier
5815129044dSC.J. Collier	printf("Test enqueue for a full entry  \n");
5825129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK);
5835129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 0)
5845129044dSC.J. Collier		goto fail;
5855129044dSC.J. Collier
5865129044dSC.J. Collier	printf("Test dequeue without enough objects \n");
5875129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) {
5885129044dSC.J. Collier		ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK);
5895129044dSC.J. Collier		cur_dst += MAX_BULK;
5905129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
5915129044dSC.J. Collier			goto fail;
5925129044dSC.J. Collier	}
5935129044dSC.J. Collier
5945129044dSC.J. Collier	/* Available memory space for the exact MAX_BULK entries */
5955129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, 2);
5965129044dSC.J. Collier	cur_dst += 2;
5975129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
5985129044dSC.J. Collier		goto fail;
5995129044dSC.J. Collier
6005129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK);
6015129044dSC.J. Collier	cur_dst += MAX_BULK - 3;
6025129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3)
6035129044dSC.J. Collier		goto fail;
6045129044dSC.J. Collier
6055129044dSC.J. Collier	printf("Test if ring is empty \n");
6065129044dSC.J. Collier	/* Check if ring is empty */
6075129044dSC.J. Collier	if (1 != rte_ring_empty(r))
6085129044dSC.J. Collier		goto fail;
6095129044dSC.J. Collier
6105129044dSC.J. Collier	/* check data */
6115129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
6125129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
6135129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
6145129044dSC.J. Collier		printf("data after dequeue is not the same\n");
6155129044dSC.J. Collier		goto fail;
6165129044dSC.J. Collier	}
6175129044dSC.J. Collier
6185129044dSC.J. Collier	cur_src = src;
6195129044dSC.J. Collier	cur_dst = dst;
6205129044dSC.J. Collier
6215129044dSC.J. Collier	printf("Test MP & MC basic functions \n");
6225129044dSC.J. Collier
6235129044dSC.J. Collier	printf("enqueue 1 obj\n");
6245129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, 1);
6255129044dSC.J. Collier	cur_src += 1;
6265129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 1)
6275129044dSC.J. Collier		goto fail;
6285129044dSC.J. Collier
6295129044dSC.J. Collier	printf("enqueue 2 objs\n");
6305129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, 2);
6315129044dSC.J. Collier	cur_src += 2;
6325129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
6335129044dSC.J. Collier		goto fail;
6345129044dSC.J. Collier
6355129044dSC.J. Collier	printf("enqueue MAX_BULK objs\n");
6365129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK);
6375129044dSC.J. Collier	cur_src += MAX_BULK;
6385129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
6395129044dSC.J. Collier		goto fail;
6405129044dSC.J. Collier
6415129044dSC.J. Collier	printf("dequeue 1 obj\n");
6425129044dSC.J. Collier	ret = rte_ring_mc_dequeue_burst(r, cur_dst, 1);
6435129044dSC.J. Collier	cur_dst += 1;
6445129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 1)
6455129044dSC.J. Collier		goto fail;
6465129044dSC.J. Collier
6475129044dSC.J. Collier	printf("dequeue 2 objs\n");
6485129044dSC.J. Collier	ret = rte_ring_mc_dequeue_burst(r, cur_dst, 2);
6495129044dSC.J. Collier	cur_dst += 2;
6505129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
6515129044dSC.J. Collier		goto fail;
6525129044dSC.J. Collier
6535129044dSC.J. Collier	printf("dequeue MAX_BULK objs\n");
6545129044dSC.J. Collier	ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK);
6555129044dSC.J. Collier	cur_dst += MAX_BULK;
6565129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
6575129044dSC.J. Collier		goto fail;
6585129044dSC.J. Collier
6595129044dSC.J. Collier	/* check data */
6605129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
6615129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
6625129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
6635129044dSC.J. Collier		printf("data after dequeue is not the same\n");
6645129044dSC.J. Collier		goto fail;
6655129044dSC.J. Collier	}
6665129044dSC.J. Collier
6675129044dSC.J. Collier	cur_src = src;
6685129044dSC.J. Collier	cur_dst = dst;
6695129044dSC.J. Collier
6705129044dSC.J. Collier	printf("fill and empty the ring\n");
6715129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK; i++) {
6725129044dSC.J. Collier		ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK);
6735129044dSC.J. Collier		cur_src += MAX_BULK;
6745129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
6755129044dSC.J. Collier			goto fail;
6765129044dSC.J. Collier		ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK);
6775129044dSC.J. Collier		cur_dst += MAX_BULK;
6785129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
6795129044dSC.J. Collier			goto fail;
6805129044dSC.J. Collier	}
6815129044dSC.J. Collier
6825129044dSC.J. Collier	/* check data */
6835129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
6845129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
6855129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
6865129044dSC.J. Collier		printf("data after dequeue is not the same\n");
6875129044dSC.J. Collier		goto fail;
6885129044dSC.J. Collier	}
6895129044dSC.J. Collier
6905129044dSC.J. Collier	cur_src = src;
6915129044dSC.J. Collier	cur_dst = dst;
6925129044dSC.J. Collier
6935129044dSC.J. Collier	printf("Test enqueue without enough memory space \n");
6945129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) {
6955129044dSC.J. Collier		ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK);
6965129044dSC.J. Collier		cur_src += MAX_BULK;
6975129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
6985129044dSC.J. Collier			goto fail;
6995129044dSC.J. Collier	}
7005129044dSC.J. Collier
7015129044dSC.J. Collier	/* Available memory space for the exact MAX_BULK objects */
7025129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, 2);
7035129044dSC.J. Collier	cur_src += 2;
7045129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
7055129044dSC.J. Collier		goto fail;
7065129044dSC.J. Collier
7075129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK);
7085129044dSC.J. Collier	cur_src += MAX_BULK - 3;
7095129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3)
7105129044dSC.J. Collier		goto fail;
7115129044dSC.J. Collier
7125129044dSC.J. Collier
7135129044dSC.J. Collier	printf("Test dequeue without enough objects \n");
7145129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) {
7155129044dSC.J. Collier		ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK);
7165129044dSC.J. Collier		cur_dst += MAX_BULK;
7175129044dSC.J. Collier		if ((ret & RTE_RING_SZ_MASK) != MAX_BULK)
7185129044dSC.J. Collier			goto fail;
7195129044dSC.J. Collier	}
7205129044dSC.J. Collier
7215129044dSC.J. Collier	/* Available objects - the exact MAX_BULK */
7225129044dSC.J. Collier	ret = rte_ring_mc_dequeue_burst(r, cur_dst, 2);
7235129044dSC.J. Collier	cur_dst += 2;
7245129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
7255129044dSC.J. Collier		goto fail;
7265129044dSC.J. Collier
7275129044dSC.J. Collier	ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK);
7285129044dSC.J. Collier	cur_dst += MAX_BULK - 3;
7295129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3)
7305129044dSC.J. Collier		goto fail;
7315129044dSC.J. Collier
7325129044dSC.J. Collier	/* check data */
7335129044dSC.J. Collier	if (memcmp(src, dst, cur_dst - dst)) {
7345129044dSC.J. Collier		rte_hexdump(stdout, "src", src, cur_src - src);
7355129044dSC.J. Collier		rte_hexdump(stdout, "dst", dst, cur_dst - dst);
7365129044dSC.J. Collier		printf("data after dequeue is not the same\n");
7375129044dSC.J. Collier		goto fail;
7385129044dSC.J. Collier	}
7395129044dSC.J. Collier
7405129044dSC.J. Collier	cur_src = src;
7415129044dSC.J. Collier	cur_dst = dst;
7425129044dSC.J. Collier
7435129044dSC.J. Collier	printf("Covering rte_ring_enqueue_burst functions \n");
7445129044dSC.J. Collier
7455129044dSC.J. Collier	ret = rte_ring_enqueue_burst(r, cur_src, 2);
7465129044dSC.J. Collier	cur_src += 2;
7475129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 2)
7485129044dSC.J. Collier		goto fail;
7495129044dSC.J. Collier
7505129044dSC.J. Collier	ret = rte_ring_dequeue_burst(r, cur_dst, 2);
7515129044dSC.J. Collier	cur_dst += 2;
7525129044dSC.J. Collier	if (ret != 2)
7535129044dSC.J. Collier		goto fail;
7545129044dSC.J. Collier
7555129044dSC.J. Collier	/* Free memory before test completed */
7565129044dSC.J. Collier	free(src);
7575129044dSC.J. Collier	free(dst);
7585129044dSC.J. Collier	return 0;
7595129044dSC.J. Collier
7605129044dSC.J. Collier fail:
7615129044dSC.J. Collier	free(src);
7625129044dSC.J. Collier	free(dst);
7635129044dSC.J. Collier	return -1;
7645129044dSC.J. Collier}
7655129044dSC.J. Collier
7665129044dSC.J. Collierstatic int
7675129044dSC.J. Colliertest_ring_stats(void)
7685129044dSC.J. Collier{
7695129044dSC.J. Collier
7705129044dSC.J. Collier#ifndef RTE_LIBRTE_RING_DEBUG
7715129044dSC.J. Collier	printf("Enable RTE_LIBRTE_RING_DEBUG to test ring stats.\n");
7725129044dSC.J. Collier	return 0;
7735129044dSC.J. Collier#else
7745129044dSC.J. Collier	void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
7755129044dSC.J. Collier	int ret;
7765129044dSC.J. Collier	unsigned i;
7775129044dSC.J. Collier	unsigned num_items            = 0;
7785129044dSC.J. Collier	unsigned failed_enqueue_ops   = 0;
7795129044dSC.J. Collier	unsigned failed_enqueue_items = 0;
7805129044dSC.J. Collier	unsigned failed_dequeue_ops   = 0;
7815129044dSC.J. Collier	unsigned failed_dequeue_items = 0;
7825129044dSC.J. Collier	unsigned last_enqueue_ops     = 0;
7835129044dSC.J. Collier	unsigned last_enqueue_items   = 0;
7845129044dSC.J. Collier	unsigned last_quota_ops       = 0;
7855129044dSC.J. Collier	unsigned last_quota_items     = 0;
7865129044dSC.J. Collier	unsigned lcore_id = rte_lcore_id();
7875129044dSC.J. Collier	struct rte_ring_debug_stats *ring_stats = &r->stats[lcore_id];
7885129044dSC.J. Collier
7895129044dSC.J. Collier	printf("Test the ring stats.\n");
7905129044dSC.J. Collier
7915129044dSC.J. Collier	/* Reset the watermark in case it was set in another test. */
7925129044dSC.J. Collier	rte_ring_set_water_mark(r, 0);
7935129044dSC.J. Collier
7945129044dSC.J. Collier	/* Reset the ring stats. */
7955129044dSC.J. Collier	memset(&r->stats[lcore_id], 0, sizeof(r->stats[lcore_id]));
7965129044dSC.J. Collier
7975129044dSC.J. Collier	/* Allocate some dummy object pointers. */
7985129044dSC.J. Collier	src = malloc(RING_SIZE*2*sizeof(void *));
7995129044dSC.J. Collier	if (src == NULL)
8005129044dSC.J. Collier		goto fail;
8015129044dSC.J. Collier
8025129044dSC.J. Collier	for (i = 0; i < RING_SIZE*2 ; i++) {
8035129044dSC.J. Collier		src[i] = (void *)(unsigned long)i;
8045129044dSC.J. Collier	}
8055129044dSC.J. Collier
8065129044dSC.J. Collier	/* Allocate some memory for copied objects. */
8075129044dSC.J. Collier	dst = malloc(RING_SIZE*2*sizeof(void *));
8085129044dSC.J. Collier	if (dst == NULL)
8095129044dSC.J. Collier		goto fail;
8105129044dSC.J. Collier
8115129044dSC.J. Collier	memset(dst, 0, RING_SIZE*2*sizeof(void *));
8125129044dSC.J. Collier
8135129044dSC.J. Collier	/* Set the head and tail pointers. */
8145129044dSC.J. Collier	cur_src = src;
8155129044dSC.J. Collier	cur_dst = dst;
8165129044dSC.J. Collier
8175129044dSC.J. Collier	/* Do Enqueue tests. */
8185129044dSC.J. Collier	printf("Test the dequeue stats.\n");
8195129044dSC.J. Collier
8205129044dSC.J. Collier	/* Fill the ring up to RING_SIZE -1. */
8215129044dSC.J. Collier	printf("Fill the ring.\n");
8225129044dSC.J. Collier	for (i = 0; i< (RING_SIZE/MAX_BULK); i++) {
8235129044dSC.J. Collier		rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK);
8245129044dSC.J. Collier		cur_src += MAX_BULK;
8255129044dSC.J. Collier	}
8265129044dSC.J. Collier
8275129044dSC.J. Collier	/* Adjust for final enqueue = MAX_BULK -1. */
8285129044dSC.J. Collier	cur_src--;
8295129044dSC.J. Collier
8305129044dSC.J. Collier	printf("Verify that the ring is full.\n");
8315129044dSC.J. Collier	if (rte_ring_full(r) != 1)
8325129044dSC.J. Collier		goto fail;
8335129044dSC.J. Collier
8345129044dSC.J. Collier
8355129044dSC.J. Collier	printf("Verify the enqueue success stats.\n");
8365129044dSC.J. Collier	/* Stats should match above enqueue operations to fill the ring. */
8375129044dSC.J. Collier	if (ring_stats->enq_success_bulk != (RING_SIZE/MAX_BULK))
8385129044dSC.J. Collier		goto fail;
8395129044dSC.J. Collier
8405129044dSC.J. Collier	/* Current max objects is RING_SIZE -1. */
8415129044dSC.J. Collier	if (ring_stats->enq_success_objs != RING_SIZE -1)
8425129044dSC.J. Collier		goto fail;
8435129044dSC.J. Collier
8445129044dSC.J. Collier	/* Shouldn't have any failures yet. */
8455129044dSC.J. Collier	if (ring_stats->enq_fail_bulk != 0)
8465129044dSC.J. Collier		goto fail;
8475129044dSC.J. Collier	if (ring_stats->enq_fail_objs != 0)
8485129044dSC.J. Collier		goto fail;
8495129044dSC.J. Collier
8505129044dSC.J. Collier
8515129044dSC.J. Collier	printf("Test stats for SP burst enqueue to a full ring.\n");
8525129044dSC.J. Collier	num_items = 2;
8535129044dSC.J. Collier	ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items);
8545129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 0)
8555129044dSC.J. Collier		goto fail;
8565129044dSC.J. Collier
8575129044dSC.J. Collier	failed_enqueue_ops   += 1;
8585129044dSC.J. Collier	failed_enqueue_items += num_items;
8595129044dSC.J. Collier
8605129044dSC.J. Collier	/* The enqueue should have failed. */
8615129044dSC.J. Collier	if (ring_stats->enq_fail_bulk != failed_enqueue_ops)
8625129044dSC.J. Collier		goto fail;
8635129044dSC.J. Collier	if (ring_stats->enq_fail_objs != failed_enqueue_items)
8645129044dSC.J. Collier		goto fail;
8655129044dSC.J. Collier
8665129044dSC.J. Collier
8675129044dSC.J. Collier	printf("Test stats for SP bulk enqueue to a full ring.\n");
8685129044dSC.J. Collier	num_items = 4;
8695129044dSC.J. Collier	ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items);
8705129044dSC.J. Collier	if (ret != -ENOBUFS)
8715129044dSC.J. Collier		goto fail;
8725129044dSC.J. Collier
8735129044dSC.J. Collier	failed_enqueue_ops   += 1;
8745129044dSC.J. Collier	failed_enqueue_items += num_items;
8755129044dSC.J. Collier
8765129044dSC.J. Collier	/* The enqueue should have failed. */
8775129044dSC.J. Collier	if (ring_stats->enq_fail_bulk != failed_enqueue_ops)
8785129044dSC.J. Collier		goto fail;
8795129044dSC.J. Collier	if (ring_stats->enq_fail_objs != failed_enqueue_items)
8805129044dSC.J. Collier		goto fail;
8815129044dSC.J. Collier
8825129044dSC.J. Collier
8835129044dSC.J. Collier	printf("Test stats for MP burst enqueue to a full ring.\n");
8845129044dSC.J. Collier	num_items = 8;
8855129044dSC.J. Collier	ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items);
8865129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 0)
8875129044dSC.J. Collier		goto fail;
8885129044dSC.J. Collier
8895129044dSC.J. Collier	failed_enqueue_ops   += 1;
8905129044dSC.J. Collier	failed_enqueue_items += num_items;
8915129044dSC.J. Collier
8925129044dSC.J. Collier	/* The enqueue should have failed. */
8935129044dSC.J. Collier	if (ring_stats->enq_fail_bulk != failed_enqueue_ops)
8945129044dSC.J. Collier		goto fail;
8955129044dSC.J. Collier	if (ring_stats->enq_fail_objs != failed_enqueue_items)
8965129044dSC.J. Collier		goto fail;
8975129044dSC.J. Collier
8985129044dSC.J. Collier
8995129044dSC.J. Collier	printf("Test stats for MP bulk enqueue to a full ring.\n");
9005129044dSC.J. Collier	num_items = 16;
9015129044dSC.J. Collier	ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items);
9025129044dSC.J. Collier	if (ret != -ENOBUFS)
9035129044dSC.J. Collier		goto fail;
9045129044dSC.J. Collier
9055129044dSC.J. Collier	failed_enqueue_ops   += 1;
9065129044dSC.J. Collier	failed_enqueue_items += num_items;
9075129044dSC.J. Collier
9085129044dSC.J. Collier	/* The enqueue should have failed. */
9095129044dSC.J. Collier	if (ring_stats->enq_fail_bulk != failed_enqueue_ops)
9105129044dSC.J. Collier		goto fail;
9115129044dSC.J. Collier	if (ring_stats->enq_fail_objs != failed_enqueue_items)
9125129044dSC.J. Collier		goto fail;
9135129044dSC.J. Collier
9145129044dSC.J. Collier
9155129044dSC.J. Collier	/* Do Dequeue tests. */
9165129044dSC.J. Collier	printf("Test the dequeue stats.\n");
9175129044dSC.J. Collier
9185129044dSC.J. Collier	printf("Empty the ring.\n");
9195129044dSC.J. Collier	for (i = 0; i<RING_SIZE/MAX_BULK; i++) {
9205129044dSC.J. Collier		rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK);
9215129044dSC.J. Collier		cur_dst += MAX_BULK;
9225129044dSC.J. Collier	}
9235129044dSC.J. Collier
9245129044dSC.J. Collier	/* There was only RING_SIZE -1 objects to dequeue. */
9255129044dSC.J. Collier	cur_dst++;
9265129044dSC.J. Collier
9275129044dSC.J. Collier	printf("Verify ring is empty.\n");
9285129044dSC.J. Collier	if (1 != rte_ring_empty(r))
9295129044dSC.J. Collier		goto fail;
9305129044dSC.J. Collier
9315129044dSC.J. Collier	printf("Verify the dequeue success stats.\n");
9325129044dSC.J. Collier	/* Stats should match above dequeue operations. */
9335129044dSC.J. Collier	if (ring_stats->deq_success_bulk != (RING_SIZE/MAX_BULK))
9345129044dSC.J. Collier		goto fail;
9355129044dSC.J. Collier
9365129044dSC.J. Collier	/* Objects dequeued is RING_SIZE -1. */
9375129044dSC.J. Collier	if (ring_stats->deq_success_objs != RING_SIZE -1)
9385129044dSC.J. Collier		goto fail;
9395129044dSC.J. Collier
9405129044dSC.J. Collier	/* Shouldn't have any dequeue failure stats yet. */
9415129044dSC.J. Collier	if (ring_stats->deq_fail_bulk != 0)
9425129044dSC.J. Collier		goto fail;
9435129044dSC.J. Collier
9445129044dSC.J. Collier	printf("Test stats for SC burst dequeue with an empty ring.\n");
9455129044dSC.J. Collier	num_items = 2;
9465129044dSC.J. Collier	ret = rte_ring_sc_dequeue_burst(r, cur_dst, num_items);
9475129044dSC.J. Collier	if ((ret & RTE_RING_SZ_MASK) != 0)
9485129044dSC.J. Collier		goto fail;
9495129044d