-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2010-2013 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
- * are met:
- *
- * * 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
- * distribution.
- * * 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
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
*/
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
-#include <cmdline_parse.h>
#include "test.h"
-#ifdef RTE_LIBRTE_SCHED
-
#include <rte_red.h>
#ifdef __INTEL_COMPILER
#pragma warning(disable:181) /* Arg incompatible with format string */
#endif
-#define DIM(x) (sizeof(x)/sizeof(x[0]))
#define TEST_HZ_PER_KHZ 1000
#define TEST_NSEC_MARGIN 500 /**< nanosecond margin when calculating clk freq */
#define MSEC_PER_SEC 1000 /**< Milli-seconds per second */
#define USEC_PER_MSEC 1000 /**< Micro-seconds per milli-second */
#define USEC_PER_SEC 1000000 /**< Micro-seconds per second */
+#define NSEC_PER_SEC (USEC_PER_SEC * 1000) /**< Nano-seconds per second */
/**< structures for testing rte_red performance and function */
struct test_rte_red_config { /**< Test structure for RTE_RED config */
uint32_t *qconfig; /**< Configuration of RTE_RED queues for test */
uint32_t *q; /**< Queue size */
uint32_t q_ramp_up; /**< Num of enqueues to ramp up the queue */
- uint32_t avg_ramp_up; /**< Average num of enqueues to ramp up the queue */
+ uint32_t avg_ramp_up; /**< Average num of enqueues to ramp up the queue */
uint32_t avg_tolerance; /**< Tolerance in queue average */
double drop_tolerance; /**< Drop tolerance of packets not enqueued */
};
static inline void rdtsc_prof_start(struct rdtsc_prof *p)
{
- asm( "cpuid" : : : "%eax", "%ebx", "%ecx", "%edx" );
- p->clk_start = rte_rdtsc();
+ p->clk_start = rte_rdtsc_precise();
}
static inline void rdtsc_prof_end(struct rdtsc_prof *p)
} else {
drop_prob = 1.0;
}
- return (drop_prob);
+ return drop_prob;
}
/**
ret = 0;
}
}
- return (ret);
+ return ret;
}
/**
ret = 0;
}
}
- return (ret);
-}
-
-/**
- * get the clk frequency in Hz
- */
-static uint64_t get_machclk_freq(void)
-{
- uint64_t start = 0;
- uint64_t end = 0;
- uint64_t diff = 0;
- uint64_t clk_freq_hz = 0;
- struct timespec tv_start = {0, 0}, tv_end = {0, 0};
- struct timespec req = {0, 0};
-
- req.tv_sec = 1;
- req.tv_nsec = 0;
-
- clock_gettime(CLOCK_REALTIME, &tv_start);
- start = rte_rdtsc();
-
- if (nanosleep(&req, NULL) != 0) {
- perror("get_machclk_freq()");
- exit(EXIT_FAILURE);
- }
-
- clock_gettime(CLOCK_REALTIME, &tv_end);
- end = rte_rdtsc();
-
- diff = (uint64_t)(tv_end.tv_sec - tv_start.tv_sec) * USEC_PER_SEC
- + ((tv_end.tv_nsec - tv_start.tv_nsec + TEST_NSEC_MARGIN) /
- USEC_PER_MSEC); /**< diff is in micro secs */
-
- if (diff == 0)
- return(0);
-
- clk_freq_hz = ((end - start) * USEC_PER_SEC / diff);
- return (clk_freq_hz);
+ return ret;
}
/**
{
unsigned i = 0;
- tcfg->tvar->clk_freq = get_machclk_freq();
+ tcfg->tvar->clk_freq = rte_get_timer_hz();
init_port_ts( tcfg->tvar->clk_freq );
for (i = 0; i < tcfg->tconfig->num_cfg; i++) {
(uint16_t)tcfg->tconfig->min_th,
(uint16_t)tcfg->tconfig->max_th,
(uint16_t)tcfg->tconfig->maxp_inv[i]) != 0) {
- return(FAIL);
+ return FAIL;
}
}
*tcfg->tqueue->q = 0;
*tcfg->tvar->dropped = 0;
*tcfg->tvar->enqueued = 0;
- return(PASS);
+ return PASS;
}
/**
* check if target actual queue size has been reached
*/
if (*q != level)
- return (-1);
+ return -1;
/**
* success
*/
- return (0);
+ return 0;
}
/**
*/
avg = rte_red_get_avg_int(red_cfg, red);
if (avg != level)
- return (-1);
+ return -1;
/**
* success
*/
- return (0);
+ return 0;
}
/**
static struct rte_red_config ft_wrconfig[1];
static struct rte_red ft_rtdata[1];
static uint8_t ft_wq_log2[] = {9};
-static uint8_t ft_maxp_inv[] = {10};
+static uint8_t ft_maxp_inv[] = {10};
static uint32_t ft_qconfig[] = {0, 0, 1, 1};
static uint32_t ft_q[] ={0};
static uint32_t ft_dropped[] ={0};
static struct test_rte_red_config ft_tconfig = {
.rconfig = ft_wrconfig,
- .num_cfg = DIM(ft_wrconfig),
+ .num_cfg = RTE_DIM(ft_wrconfig),
.wq_log2 = ft_wq_log2,
.min_th = 32,
.max_th = 128,
static struct test_queue ft_tqueue = {
.rdata = ft_rtdata,
- .num_queues = DIM(ft_rtdata),
+ .num_queues = RTE_DIM(ft_rtdata),
.qconfig = ft_qconfig,
.q = ft_q,
.q_ramp_up = 1000000,
};
static struct test_var ft_tvar = {
- .wait_usec = 250000,
- .num_iterations = 20,
+ .wait_usec = 10000,
+ .num_iterations = 5,
.num_ops = 10000,
.clk_freq = 0,
.dropped = ft_dropped,
goto out;
}
- printf("%s", tcfg->htxt);
+ printf("%s", tcfg->htxt);
- for (i = 0; i < DIM(ft1_tlevels); i++) {
+ for (i = 0; i < RTE_DIM(ft1_tlevels); i++) {
const char *label = NULL;
uint32_t avg = 0;
double drop_rate = 0.0;
(double)tcfg->tqueue->drop_tolerance);
}
out:
- return (result);
+ return result;
}
/**
static struct test_rte_red_config ft2_tconfig = {
.rconfig = ft2_rconfig,
- .num_cfg = DIM(ft2_rconfig),
+ .num_cfg = RTE_DIM(ft2_rconfig),
.wq_log2 = ft2_wq_log2,
.min_th = 32,
.max_th = 128,
(double)tcfg->tqueue->drop_tolerance);
}
out:
- return (result);
+ return result;
}
/**
static struct test_rte_red_config ft3_tconfig = {
.rconfig = ft_wrconfig,
- .num_cfg = DIM(ft_wrconfig),
+ .num_cfg = RTE_DIM(ft_wrconfig),
.wq_log2 = ft_wq_log2,
.min_th = 32,
.max_th = 1023,
result = FAIL;
}
- exp_avg = calc_exp_avg_on_empty(avg_before,
+ exp_avg = calc_exp_avg_on_empty(avg_before,
(1 << *tcfg->tconfig->wq_log2),
tcfg->tvar->wait_usec);
- avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig,
+ avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig,
tcfg->tqueue->rdata);
if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
result = FAIL;
diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail");
}
out:
- return (result);
+ return result;
}
/**
static struct test_rte_red_config ft4_tconfig = {
.rconfig = ft_wrconfig,
- .num_cfg = DIM(ft_wrconfig),
+ .num_cfg = RTE_DIM(ft_wrconfig),
.min_th = 32,
.max_th = 1023,
.wq_log2 = ft4_wq_log2,
static struct test_queue ft4_tqueue = {
.rdata = ft_rtdata,
- .num_queues = DIM(ft_rtdata),
+ .num_queues = RTE_DIM(ft_rtdata),
.qconfig = ft_qconfig,
.q = ft_q,
.q_ramp_up = 1000000,
rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts());
/**
- * record empty time locally
+ * record empty time locally
*/
start = rte_rdtsc();
/**
* enqueue one packet to recalculate average queue size
*/
- if (rte_red_enqueue(tcfg->tconfig->rconfig,
- tcfg->tqueue->rdata,
+ if (rte_red_enqueue(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
*tcfg->tqueue->q,
get_port_ts()) != 0) {
result = FAIL;
diff, (double)tcfg->tqueue->avg_tolerance,
diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail");
out:
- return (result);
+ return result;
}
/**
static struct test_rte_red_config ft5_tconfig = {
.rconfig = ft5_config,
- .num_cfg = DIM(ft5_config),
+ .num_cfg = RTE_DIM(ft5_config),
.min_th = 32,
.max_th = 128,
.wq_log2 = ft5_wq_log2,
static struct test_queue ft5_tqueue = {
.rdata = ft5_data,
- .num_queues = DIM(ft5_data),
+ .num_queues = RTE_DIM(ft5_data),
.qconfig = ft_qconfig,
.q = ft5_q,
.q_ramp_up = 1000000,
drop_rate = calc_drop_rate(tcfg->tvar->enqueued[j],tcfg->tvar->dropped[j]);
drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th,
- tcfg->tconfig->maxp_inv[tcfg->tqueue->qconfig[j]],
+ tcfg->tconfig->maxp_inv[tcfg->tqueue->qconfig[j]],
*tcfg->tlevel);
if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance))
result = FAIL;
diff, (double)tcfg->tqueue->drop_tolerance);
}
out:
- return (result);
+ return result;
}
/**
static struct test_rte_red_config ft6_tconfig = {
.rconfig = ft6_config,
- .num_cfg = DIM(ft6_config),
+ .num_cfg = RTE_DIM(ft6_config),
.min_th = 32,
.max_th = 1023,
.wq_log2 = ft6_wq_log2,
static struct test_queue ft6_tqueue = {
.rdata = ft6_data,
- .num_queues = DIM(ft6_data),
+ .num_queues = RTE_DIM(ft6_data),
.qconfig = ft_qconfig,
.q = ft6_q,
.q_ramp_up = 1000000,
double exp_avg = 0;
double diff = 0.0;
- avg_before = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ avg_before = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
&tcfg->tqueue->rdata[j]);
/**
/**
* enqueue one packet to recalculate average queue size
*/
- if (rte_red_enqueue(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ if (rte_red_enqueue(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
&tcfg->tqueue->rdata[j],
tcfg->tqueue->q[j],
get_port_ts()) == 0) {
result = FAIL;
}
- exp_avg = calc_exp_avg_on_empty(avg_before,
+ exp_avg = calc_exp_avg_on_empty(avg_before,
(1 << tcfg->tconfig->wq_log2[tcfg->tqueue->qconfig[j]]),
tcfg->tvar->wait_usec);
avg_after = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
diff <= tcfg->tqueue->avg_tolerance ? "pass" : "fail");
}
out:
- return (result);
+ return result;
}
/**
static struct rte_red_config pt_wrconfig[1];
static struct rte_red pt_rtdata[1];
static uint8_t pt_wq_log2[] = {9};
-static uint8_t pt_maxp_inv[] = {10};
+static uint8_t pt_maxp_inv[] = {10};
static uint32_t pt_qconfig[] = {0};
static uint32_t pt_q[] = {0};
static uint32_t pt_dropped[] = {0};
static struct test_rte_red_config pt_tconfig = {
.rconfig = pt_wrconfig,
- .num_cfg = DIM(pt_wrconfig),
+ .num_cfg = RTE_DIM(pt_wrconfig),
.wq_log2 = pt_wq_log2,
.min_th = 32,
.max_th = 128,
static struct test_queue pt_tqueue = {
.rdata = pt_rtdata,
- .num_queues = DIM(pt_rtdata),
+ .num_queues = RTE_DIM(pt_rtdata),
.qconfig = pt_qconfig,
.q = pt_q,
.q_ramp_up = 1000000,
}
/**
- * Setup test structures for tests P1, P2, P3
+ * Setup test structures for tests P1, P2, P3
* performance tests 1, 2 and 3
*/
static uint32_t pt1_tlevel[] = {16};
};
/**
- * Performance test function to measure enqueue performance.
- * This runs performance tests 1, 2 and 3
+ * Performance test function to measure enqueue performance.
+ * This runs performance tests 1, 2 and 3
*/
static enum test_result perf1_test(struct test_config *tcfg)
{
* set the queue average
*/
rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel);
- if (rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata)
+ if (rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata)
!= *tcfg->tlevel) {
result = FAIL;
goto out;
rdtsc_prof_print(&prof);
out:
- return (result);
+ return result;
}
/**
- * Setup test structures for tests P4, P5, P6
+ * Setup test structures for tests P4, P5, P6
* performance tests 4, 5 and 6
*/
static uint32_t pt4_tlevel[] = {16};
};
/**
- * Performance test function to measure enqueue performance when the
- * queue is empty. This runs performance tests 4, 5 and 6
+ * Performance test function to measure enqueue performance when the
+ * queue is empty. This runs performance tests 4, 5 and 6
*/
static enum test_result perf2_test(struct test_config *tcfg)
{
goto out;
}
- printf("%s", tcfg->htxt);
+ printf("%s", tcfg->htxt);
for (i = 0; i < tcfg->tvar->num_iterations; i++) {
uint32_t count = 0;
*/
ts = get_port_ts();
rdtsc_prof_start(&prof);
- ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata,
+ ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata,
*tcfg->tqueue->q, ts );
rdtsc_prof_end(&prof);
int ok = 0;
avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
- exp_avg = calc_exp_avg_on_empty(avg_before,
+ exp_avg = calc_exp_avg_on_empty(avg_before,
(1 << *tcfg->tconfig->wq_log2),
tcfg->tvar->wait_usec);
if (check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
rdtsc_prof_print(&prof);
out:
- return (result);
+ return result;
}
/**
static struct rte_red_config ovfl_wrconfig[1];
static struct rte_red ovfl_rtdata[1];
-static uint8_t ovfl_maxp_inv[] = {10};
+static uint8_t ovfl_maxp_inv[] = {10};
static uint32_t ovfl_qconfig[] = {0, 0, 1, 1};
static uint32_t ovfl_q[] ={0};
static uint32_t ovfl_dropped[] ={0};
static struct test_rte_red_config ovfl_tconfig = {
.rconfig = ovfl_wrconfig,
- .num_cfg = DIM(ovfl_wrconfig),
+ .num_cfg = RTE_DIM(ovfl_wrconfig),
.wq_log2 = ovfl_wq_log2,
.min_th = 32,
.max_th = 1023,
static struct test_queue ovfl_tqueue = {
.rdata = ovfl_rtdata,
- .num_queues = DIM(ovfl_rtdata),
+ .num_queues = RTE_DIM(ovfl_rtdata),
.qconfig = ovfl_qconfig,
.q = ovfl_q,
.q_ramp_up = 1000000,
result = FAIL;
printf("%s", tcfg->htxt);
-
+
printf("%-16u%-9u%-15u0x%08x %-10u%-10u%-10u%-13.2lf%-13.2lf\n",
avg, *tcfg->tconfig->wq_log2, RTE_RED_SCALING,
avg_max, avg_max_bits,
*tcfg->tvar->enqueued, *tcfg->tvar->dropped,
drop_prob * 100.0, drop_rate * 100.0);
out:
- return (result);
+ return result;
}
/**
* define the functional and performance tests to be executed
*/
-struct tests func_tests[] = {
+struct tests func_tests[] = {
{ &func_test1_config, func_test1 },
- { &func_test2_config, func_test2 },
+ { &func_test2_config, func_test2 },
{ &func_test3_config, func_test3 },
{ &func_test4_config, func_test4 },
{ &func_test5_config, func_test5 },
{ &func_test6_config, func_test6 },
- { &ovfl_test1_config, ovfl_test1 },
+ { &ovfl_test1_config, ovfl_test1 },
+};
+
+struct tests func_tests_quick[] = {
+ { &func_test1_config, func_test1 },
+ { &func_test2_config, func_test2 },
+ { &func_test3_config, func_test3 },
+ /* no test 4 as it takes a lot of time */
+ { &func_test5_config, func_test5 },
+ { &func_test6_config, func_test6 },
+ { &ovfl_test1_config, ovfl_test1 },
};
-struct tests perf_tests[] = {
+struct tests perf_tests[] = {
{ &perf1_test1_config, perf1_test },
{ &perf1_test2_config, perf1_test },
{ &perf1_test3_config, perf1_test },
return 0;
}
-int test_red(void)
+static void
+show_stats(const uint32_t num_tests, const uint32_t num_pass)
+{
+ if (num_pass == num_tests)
+ printf("[total: %u, pass: %u]\n", num_tests, num_pass);
+ else
+ printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass,
+ num_tests - num_pass);
+}
+
+static int
+tell_the_result(const uint32_t num_tests, const uint32_t num_pass)
+{
+ return (num_pass == num_tests) ? 0 : 1;
+}
+
+static int
+test_red(void)
{
uint32_t num_tests = 0;
uint32_t num_pass = 0;
- int ret = 0;
if (test_invalid_parameters() < 0)
return -1;
+ run_tests(func_tests_quick, RTE_DIM(func_tests_quick),
+ &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
+}
- run_tests(func_tests, DIM(func_tests), &num_tests, &num_pass);
- run_tests(perf_tests, DIM(perf_tests), &num_tests, &num_pass);
+static int
+test_red_perf(void)
+{
+ uint32_t num_tests = 0;
+ uint32_t num_pass = 0;
- if (num_pass == num_tests) {
- printf("[total: %u, pass: %u]\n", num_tests, num_pass);
- ret = 0;
- } else {
- printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass, num_tests - num_pass);
- ret = -1;
- }
- return (ret);
+ run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
}
-#else
-
-int
-test_red(void)
+static int
+test_red_all(void)
{
- printf("The SCHED library is not included in this build\n");
- return 0;
+ uint32_t num_tests = 0;
+ uint32_t num_pass = 0;
+
+ if (test_invalid_parameters() < 0)
+ return -1;
+
+ run_tests(func_tests, RTE_DIM(func_tests), &num_tests, &num_pass);
+ run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
}
-#endif
+REGISTER_TEST_COMMAND(red_autotest, test_red);
+REGISTER_TEST_COMMAND(red_perf, test_red_perf);
+REGISTER_TEST_COMMAND(red_all, test_red_all);