/*-
* BSD LICENSE
- *
- * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
* All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
* are met:
- *
- * * Redistributions of source code must retain the above copyright
+ *
+ * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
* distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include <string.h>
#include <rte_errno.h>
#include <rte_hexdump.h>
-#include <cmdline_parse.h>
-
#include "test.h"
/*
*
* #. Performance tests.
*
- * This test is done on the following configurations:
- *
- * - One core enqueuing, one core dequeuing
- * - One core enqueuing, other cores dequeuing
- * - One core dequeuing, other cores enqueuing
- * - Half of the cores enqueuing, the other half dequeuing
- *
- * When only one core enqueues/dequeues, the test is done with the
- * SP/SC functions in addition to the MP/MC functions.
- *
- * The test is done with different bulk size.
- *
- * On each core, the test enqueues or dequeues objects during
- * TIME_S seconds. The number of successes and failures are stored on
- * each core, then summed and displayed.
- *
- * The test checks that the number of enqueues is equal to the
- * number of dequeues.
+ * Tests done in test_ring_perf.c
*/
#define RING_SIZE 4096
static struct rte_ring *r;
-struct test_stats {
- unsigned enq_success ;
- unsigned enq_quota;
- unsigned enq_fail;
-
- unsigned deq_success;
- unsigned deq_fail;
-} __rte_cache_aligned;
-
-static struct test_stats test_stats[RTE_MAX_LCORE];
-
-static int
-ring_enqueue_test(int (que_func)(struct rte_ring*, void * const *, unsigned),
- void* arg, unsigned bulk_or_burst)
-{
- unsigned success = 0;
- unsigned quota = 0;
- unsigned fail = 0;
- unsigned i;
- unsigned long dummy_obj;
- void *obj_table[MAX_BULK];
- int ret;
- unsigned lcore_id = rte_lcore_id();
- unsigned count = *((unsigned*)arg);
- uint64_t start_cycles, end_cycles;
- uint64_t time_diff = 0, hz = rte_get_hpet_hz();
-
- /* init dummy object table */
- for (i = 0; i< MAX_BULK; i++) {
- dummy_obj = lcore_id + 0x1000 + i;
- obj_table[i] = (void *)dummy_obj;
- }
-
- /* wait synchro for slaves */
- if (lcore_id != rte_get_master_lcore())
- while (rte_atomic32_read(&synchro) == 0);
-
- start_cycles = rte_get_hpet_cycles();
-
- /* enqueue as many object as possible */
- while (time_diff/hz < TIME_S) {
- for (i = 0; likely(i < N); i++) {
- ret = que_func(r, obj_table, count);
- /*
- * bulk_or_burst
- * 1: for bulk operation
- * 0: for burst operation
- */
- if (bulk_or_burst) {
- /* The *count* objects enqueued, unless fail */
- if (ret == 0)
- success += count;
- else if (ret == -EDQUOT)
- quota += count;
- else
- fail++;
- } else {
- /* The actual objects enqueued */
- if (ret != 0)
- success += (ret & RTE_RING_SZ_MASK);
- else
- fail++;
- }
- }
- end_cycles = rte_get_hpet_cycles();
- time_diff = end_cycles - start_cycles;
- }
-
- /* write statistics in a shared structure */
- test_stats[lcore_id].enq_success = success;
- test_stats[lcore_id].enq_quota = quota;
- test_stats[lcore_id].enq_fail = fail;
-
- return 0;
-}
-
-static int
-ring_dequeue_test(int (que_func)(struct rte_ring*, void **, unsigned),
- void* arg, unsigned bulk_or_burst)
-{
- unsigned success = 0;
- unsigned fail = 0;
- unsigned i;
- void *obj_table[MAX_BULK];
- int ret;
- unsigned lcore_id = rte_lcore_id();
- unsigned count = *((unsigned*)arg);
- uint64_t start_cycles, end_cycles;
- uint64_t time_diff = 0, hz = rte_get_hpet_hz();
-
- /* wait synchro for slaves */
- if (lcore_id != rte_get_master_lcore())
- while (rte_atomic32_read(&synchro) == 0);
-
- start_cycles = rte_get_hpet_cycles();
-
- /* dequeue as many object as possible */
- while (time_diff/hz < TIME_S) {
- for (i = 0; likely(i < N); i++) {
- ret = que_func(r, obj_table, count);
- /*
- * bulk_or_burst
- * 1: for bulk operation
- * 0: for burst operation
- */
- if (bulk_or_burst) {
- if (ret == 0)
- success += count;
- else
- fail++;
- } else {
- if (ret != 0)
- success += ret;
- else
- fail++;
- }
- }
- end_cycles = rte_get_hpet_cycles();
- time_diff = end_cycles - start_cycles;
- }
-
- /* write statistics in a shared structure */
- test_stats[lcore_id].deq_success = success;
- test_stats[lcore_id].deq_fail = fail;
-
- return 0;
-}
-
-static int
-test_ring_per_core_sp_enqueue(void *arg)
-{
- return ring_enqueue_test(&rte_ring_sp_enqueue_bulk, arg, 1);
-}
-
-static int
-test_ring_per_core_mp_enqueue(void *arg)
-{
- return ring_enqueue_test(&rte_ring_mp_enqueue_bulk, arg, 1);
-}
-
-static int
-test_ring_per_core_mc_dequeue(void *arg)
-{
- return ring_dequeue_test(&rte_ring_mc_dequeue_bulk, arg, 1);
-}
-
-static int
-test_ring_per_core_sc_dequeue(void *arg)
-{
- return ring_dequeue_test(&rte_ring_sc_dequeue_bulk, arg, 1);
-}
-
-static int
-test_ring_per_core_sp_enqueue_burst(void *arg)
-{
- return ring_enqueue_test(&rte_ring_sp_enqueue_burst, arg, 0);
-}
-
-static int
-test_ring_per_core_mp_enqueue_burst(void *arg)
-{
- return ring_enqueue_test(&rte_ring_mp_enqueue_burst, arg, 0);
-}
-
-static int
-test_ring_per_core_mc_dequeue_burst(void *arg)
-{
- return ring_dequeue_test(&rte_ring_mc_dequeue_burst, arg, 0);
-}
-
-static int
-test_ring_per_core_sc_dequeue_burst(void *arg)
-{
- return ring_dequeue_test(&rte_ring_sc_dequeue_burst, arg, 0);
-}
-
#define TEST_RING_VERIFY(exp) \
if (!(exp)) { \
printf("error at %s:%d\tcondition " #exp " failed\n", \
__func__, __LINE__); \
- rte_ring_dump(r); \
+ rte_ring_dump(stdout, r); \
return (-1); \
}
#define TEST_RING_FULL_EMTPY_ITER 8
-
-static int
-launch_cores(unsigned enq_core_count, unsigned deq_core_count,
- unsigned n_enq_bulk, unsigned n_deq_bulk,
- int sp, int sc, int bulk_not_burst)
-{
- void *obj;
- unsigned lcore_id;
- unsigned rate, deq_remain = 0;
- unsigned enq_total, deq_total;
- struct test_stats sum;
- int (*enq_f)(void *);
- int (*deq_f)(void *);
- unsigned cores = enq_core_count + deq_core_count;
- int ret;
-
- rte_atomic32_set(&synchro, 0);
-
- printf("ring_autotest e/d_core=%u,%u e/d_bulk=%u,%u ",
- enq_core_count, deq_core_count, n_enq_bulk, n_deq_bulk);
- printf("sp=%d sc=%d ", sp, sc);
-
- if (bulk_not_burst) {
- /* set enqueue function to be used */
- if (sp)
- enq_f = test_ring_per_core_sp_enqueue;
- else
- enq_f = test_ring_per_core_mp_enqueue;
-
- /* set dequeue function to be used */
- if (sc)
- deq_f = test_ring_per_core_sc_dequeue;
- else
- deq_f = test_ring_per_core_mc_dequeue;
-
- } else {
- /* set enqueue function to be used */
- if (sp)
- enq_f = test_ring_per_core_sp_enqueue_burst;
- else
- enq_f = test_ring_per_core_mp_enqueue_burst;
-
- /* set dequeue function to be used */
- if (sc)
- deq_f = test_ring_per_core_sc_dequeue_burst;
- else
- deq_f = test_ring_per_core_mc_dequeue_burst;
- }
-
- RTE_LCORE_FOREACH_SLAVE(lcore_id) {
- if (enq_core_count != 0) {
- enq_core_count--;
- rte_eal_remote_launch(enq_f, &n_enq_bulk, lcore_id);
- }
- if (deq_core_count != 1) {
- deq_core_count--;
- rte_eal_remote_launch(deq_f, &n_deq_bulk, lcore_id);
- }
- }
-
- memset(test_stats, 0, sizeof(test_stats));
-
- /* start synchro and launch test on master */
- rte_atomic32_set(&synchro, 1);
- ret = deq_f(&n_deq_bulk);
-
- /* wait all cores */
- RTE_LCORE_FOREACH_SLAVE(lcore_id) {
- if (cores == 1)
- break;
- cores--;
- if (rte_eal_wait_lcore(lcore_id) < 0)
- ret = -1;
- }
-
- memset(&sum, 0, sizeof(sum));
- for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
- sum.enq_success += test_stats[lcore_id].enq_success;
- sum.enq_quota += test_stats[lcore_id].enq_quota;
- sum.enq_fail += test_stats[lcore_id].enq_fail;
- sum.deq_success += test_stats[lcore_id].deq_success;
- sum.deq_fail += test_stats[lcore_id].deq_fail;
- }
-
- /* empty the ring */
- while (rte_ring_sc_dequeue(r, &obj) == 0)
- deq_remain += 1;
-
- if (ret < 0) {
- printf("per-lcore test returned -1\n");
- return -1;
- }
-
- enq_total = sum.enq_success + sum.enq_quota;
- deq_total = sum.deq_success + deq_remain;
-
- rate = deq_total/TIME_S;
-
- printf("rate_persec=%u\n", rate);
-
- if (enq_total != deq_total) {
- printf("invalid enq/deq_success counter: %u %u\n",
- enq_total, deq_total);
- return -1;
- }
-
- return 0;
-}
-
-static int
-do_one_ring_test2(unsigned enq_core_count, unsigned deq_core_count,
- unsigned n_enq_bulk, unsigned n_deq_bulk, unsigned bulk_or_burst)
-{
- int sp, sc;
- int do_sp, do_sc;
- int ret;
-
- do_sp = (enq_core_count == 1) ? 1 : 0;
- do_sc = (deq_core_count == 1) ? 1 : 0;
-
- for (sp = 0; sp <= do_sp; sp ++) {
- for (sc = 0; sc <= do_sc; sc ++) {
- ret = launch_cores(enq_core_count, deq_core_count,
- n_enq_bulk, n_deq_bulk, sp, sc, bulk_or_burst);
- if (ret < 0)
- return -1;
- }
- }
- return 0;
-}
-
-static int
-do_one_ring_test(unsigned enq_core_count, unsigned deq_core_count,
- unsigned bulk_or_burst)
-{
- unsigned bulk_enqueue_tab[] = { 1, 2, 4, 32, 0 };
- unsigned bulk_dequeue_tab[] = { 1, 2, 4, 32, 0 };
- unsigned *bulk_enqueue_ptr;
- unsigned *bulk_dequeue_ptr;
- int ret;
-
- for (bulk_enqueue_ptr = bulk_enqueue_tab;
- *bulk_enqueue_ptr;
- bulk_enqueue_ptr++) {
-
- for (bulk_dequeue_ptr = bulk_dequeue_tab;
- *bulk_dequeue_ptr;
- bulk_dequeue_ptr++) {
-
- ret = do_one_ring_test2(enq_core_count, deq_core_count,
- *bulk_enqueue_ptr,
- *bulk_dequeue_ptr,
- bulk_or_burst);
- if (ret < 0)
- return -1;
- }
- }
- return 0;
-}
-
static int
check_live_watermark_change(__attribute__((unused)) void *dummy)
{
- uint64_t hz = rte_get_hpet_hz();
+ uint64_t hz = rte_get_timer_hz();
void *obj_table[MAX_BULK];
unsigned watermark, watermark_old = 16;
uint64_t cur_time, end_time;
/* init the object table */
memset(obj_table, 0, sizeof(obj_table));
- end_time = rte_get_hpet_cycles() + (hz * 2);
+ end_time = rte_get_timer_cycles() + (hz * 2);
/* check that bulk and watermark are 4 and 32 (respectively) */
while (diff >= 0) {
}
}
- cur_time = rte_get_hpet_cycles();
+ cur_time = rte_get_timer_cycles();
diff = end_time - cur_time;
}
/* check data */
TEST_RING_VERIFY(0 == memcmp(src, dst, rsz));
- rte_ring_dump(r);
+ rte_ring_dump(stdout, r);
}
return (0);
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
/* check data */
if (memcmp(src, dst, cur_dst - dst)) {
- rte_hexdump("src", src, cur_src - src);
- rte_hexdump("dst", dst, cur_dst - dst);
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
printf("data after dequeue is not the same\n");
goto fail;
}
return ret;
}
-int
+static int
test_ring(void)
{
- unsigned enq_core_count, deq_core_count;
-
/* some more basic operations */
if (test_ring_basic_ex() < 0)
return -1;
else
printf ( "Test detected NULL ring lookup \n");
- printf("start performance tests \n");
-
- /* one lcore for enqueue, one for dequeue */
- enq_core_count = 1;
- deq_core_count = 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 1) < 0)
- return -1;
-
- /* max cores for enqueue, one for dequeue */
- enq_core_count = rte_lcore_count() - 1;
- deq_core_count = 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 1) < 0)
- return -1;
-
- /* max cores for dequeue, one for enqueue */
- enq_core_count = 1;
- deq_core_count = rte_lcore_count() - 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 1) < 0)
- return -1;
-
- /* half for enqueue and half for dequeue */
- enq_core_count = rte_lcore_count() / 2;
- deq_core_count = rte_lcore_count() / 2;
- if (do_one_ring_test(enq_core_count, deq_core_count, 1) < 0)
- return -1;
-
- printf("start performance tests - burst operations \n");
-
- /* one lcore for enqueue, one for dequeue */
- enq_core_count = 1;
- deq_core_count = 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 0) < 0)
- return -1;
-
- /* max cores for enqueue, one for dequeue */
- enq_core_count = rte_lcore_count() - 1;
- deq_core_count = 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 0) < 0)
- return -1;
-
- /* max cores for dequeue, one for enqueue */
- enq_core_count = 1;
- deq_core_count = rte_lcore_count() - 1;
- if (do_one_ring_test(enq_core_count, deq_core_count, 0) < 0)
- return -1;
-
- /* half for enqueue and half for dequeue */
- enq_core_count = rte_lcore_count() / 2;
- deq_core_count = rte_lcore_count() / 2;
- if (do_one_ring_test(enq_core_count, deq_core_count, 0) < 0)
- return -1;
-
/* test of creating ring with wrong size */
if (test_ring_creation_with_wrong_size() < 0)
return -1;
return -1;
/* dump the ring status */
- rte_ring_list_dump();
+ rte_ring_list_dump(stdout);
return 0;
}
+
+static struct test_command ring_cmd = {
+ .command = "ring_autotest",
+ .callback = test_ring,
+};
+REGISTER_TEST_COMMAND(ring_cmd);