1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 3a9de470cSBruce Richardson */ 4a9de470cSBruce Richardson 53c60274cSJie Zhou #include "test.h" 63c60274cSJie Zhou 7a9de470cSBruce Richardson #include <stdlib.h> 8a9de470cSBruce Richardson #include <stdio.h> 9a9de470cSBruce Richardson #include <string.h> 10a9de470cSBruce Richardson #include <stdint.h> 11a9de470cSBruce Richardson #include <unistd.h> 12a9de470cSBruce Richardson #include <inttypes.h> 133c60274cSJie Zhou 143c60274cSJie Zhou #ifdef RTE_EXEC_ENV_WINDOWS 153c60274cSJie Zhou static int 163c60274cSJie Zhou test_red(void) 173c60274cSJie Zhou { 183c60274cSJie Zhou printf("red not supported on Windows, skipping test\n"); 193c60274cSJie Zhou return TEST_SKIPPED; 203c60274cSJie Zhou } 213c60274cSJie Zhou 223c60274cSJie Zhou static int 233c60274cSJie Zhou test_red_perf(void) 243c60274cSJie Zhou { 253c60274cSJie Zhou printf("red_perf not supported on Windows, skipping test\n"); 263c60274cSJie Zhou return TEST_SKIPPED; 273c60274cSJie Zhou } 283c60274cSJie Zhou 293c60274cSJie Zhou static int 303c60274cSJie Zhou test_red_all(void) 313c60274cSJie Zhou { 323c60274cSJie Zhou printf("red_all not supported on Windows, skipping test\n"); 333c60274cSJie Zhou return TEST_SKIPPED; 343c60274cSJie Zhou } 353c60274cSJie Zhou #else 363c60274cSJie Zhou 37a9de470cSBruce Richardson #include <sys/time.h> 38a9de470cSBruce Richardson #include <time.h> 39a9de470cSBruce Richardson #include <math.h> 40a9de470cSBruce Richardson 41a9de470cSBruce Richardson #include <rte_red.h> 42a9de470cSBruce Richardson 43a9de470cSBruce Richardson #ifdef __INTEL_COMPILER 44a9de470cSBruce Richardson #pragma warning(disable:2259) /* conversion may lose significant bits */ 45a9de470cSBruce Richardson #pragma warning(disable:181) /* Arg incompatible with format string */ 46a9de470cSBruce Richardson #endif 47a9de470cSBruce Richardson 48a9de470cSBruce Richardson #define TEST_HZ_PER_KHZ 1000 49a9de470cSBruce Richardson #define TEST_NSEC_MARGIN 500 /**< nanosecond margin when calculating clk freq */ 50a9de470cSBruce Richardson 51a9de470cSBruce Richardson #define MAX_QEMPTY_TIME_MSEC 50000 52a9de470cSBruce Richardson #define MSEC_PER_SEC 1000 /**< Milli-seconds per second */ 53a9de470cSBruce Richardson #define USEC_PER_MSEC 1000 /**< Micro-seconds per milli-second */ 54a9de470cSBruce Richardson #define USEC_PER_SEC 1000000 /**< Micro-seconds per second */ 55a9de470cSBruce Richardson #define NSEC_PER_SEC (USEC_PER_SEC * 1000) /**< Nano-seconds per second */ 56a9de470cSBruce Richardson 57a9de470cSBruce Richardson /**< structures for testing rte_red performance and function */ 58a9de470cSBruce Richardson struct test_rte_red_config { /**< Test structure for RTE_RED config */ 59a9de470cSBruce Richardson struct rte_red_config *rconfig; /**< RTE_RED configuration parameters */ 60a9de470cSBruce Richardson uint8_t num_cfg; /**< Number of RTE_RED configs to test */ 61a9de470cSBruce Richardson uint8_t *wq_log2; /**< Test wq_log2 value to use */ 62a9de470cSBruce Richardson uint32_t min_th; /**< Queue minimum threshold */ 63a9de470cSBruce Richardson uint32_t max_th; /**< Queue maximum threshold */ 64a9de470cSBruce Richardson uint8_t *maxp_inv; /**< Inverse mark probability */ 65a9de470cSBruce Richardson }; 66a9de470cSBruce Richardson 67a9de470cSBruce Richardson struct test_queue { /**< Test structure for RTE_RED Queues */ 68a9de470cSBruce Richardson struct rte_red *rdata; /**< RTE_RED runtime data */ 69a9de470cSBruce Richardson uint32_t num_queues; /**< Number of RTE_RED queues to test */ 70a9de470cSBruce Richardson uint32_t *qconfig; /**< Configuration of RTE_RED queues for test */ 71a9de470cSBruce Richardson uint32_t *q; /**< Queue size */ 72a9de470cSBruce Richardson uint32_t q_ramp_up; /**< Num of enqueues to ramp up the queue */ 73a9de470cSBruce Richardson uint32_t avg_ramp_up; /**< Average num of enqueues to ramp up the queue */ 74a9de470cSBruce Richardson uint32_t avg_tolerance; /**< Tolerance in queue average */ 75a9de470cSBruce Richardson double drop_tolerance; /**< Drop tolerance of packets not enqueued */ 76a9de470cSBruce Richardson }; 77a9de470cSBruce Richardson 78a9de470cSBruce Richardson struct test_var { /**< Test variables used for testing RTE_RED */ 79a9de470cSBruce Richardson uint32_t wait_usec; /**< Micro second wait interval */ 80a9de470cSBruce Richardson uint32_t num_iterations; /**< Number of test iterations */ 81a9de470cSBruce Richardson uint32_t num_ops; /**< Number of test operations */ 82a9de470cSBruce Richardson uint64_t clk_freq; /**< CPU clock frequency */ 83a9de470cSBruce Richardson uint32_t sleep_sec; /**< Seconds to sleep */ 84a9de470cSBruce Richardson uint32_t *dropped; /**< Test operations dropped */ 85a9de470cSBruce Richardson uint32_t *enqueued; /**< Test operations enqueued */ 86a9de470cSBruce Richardson }; 87a9de470cSBruce Richardson 88*bccabd15SStephen Hemminger struct test_config { /**< Test structure for RTE_RED */ 89a9de470cSBruce Richardson const char *ifname; /**< Interface name */ 90a9de470cSBruce Richardson const char *msg; /**< Test message for display */ 91a9de470cSBruce Richardson const char *htxt; /**< Header txt display for result output */ 92a9de470cSBruce Richardson struct test_rte_red_config *tconfig; /**< Test structure for RTE_RED config */ 93a9de470cSBruce Richardson struct test_queue *tqueue; /**< Test structure for RTE_RED Queues */ 94a9de470cSBruce Richardson struct test_var *tvar; /**< Test variables used for testing RTE_RED */ 95a9de470cSBruce Richardson uint32_t *tlevel; /**< Queue levels */ 96a9de470cSBruce Richardson }; 97a9de470cSBruce Richardson 98a9de470cSBruce Richardson enum test_result { 99a9de470cSBruce Richardson FAIL = 0, 100a9de470cSBruce Richardson PASS 101a9de470cSBruce Richardson }; 102a9de470cSBruce Richardson 103a9de470cSBruce Richardson /**< Test structure to define tests to run */ 104a9de470cSBruce Richardson struct tests { 105a9de470cSBruce Richardson struct test_config *testcfg; 106a9de470cSBruce Richardson enum test_result (*testfn)(struct test_config *); 107a9de470cSBruce Richardson }; 108a9de470cSBruce Richardson 109a9de470cSBruce Richardson struct rdtsc_prof { 110a9de470cSBruce Richardson uint64_t clk_start; 111a9de470cSBruce Richardson uint64_t clk_min; /**< min clocks */ 112a9de470cSBruce Richardson uint64_t clk_max; /**< max clocks */ 113a9de470cSBruce Richardson uint64_t clk_avgc; /**< count to calc average */ 114a9de470cSBruce Richardson double clk_avg; /**< cumulative sum to calc average */ 115a9de470cSBruce Richardson const char *name; 116a9de470cSBruce Richardson }; 117a9de470cSBruce Richardson 118a9de470cSBruce Richardson static const uint64_t port_speed_bytes = (10ULL*1000ULL*1000ULL*1000ULL)/8ULL; 119a9de470cSBruce Richardson static double inv_cycles_per_byte = 0; 120a9de470cSBruce Richardson static double pkt_time_usec = 0; 121a9de470cSBruce Richardson 122a9de470cSBruce Richardson static void init_port_ts(uint64_t cpu_clock) 123a9de470cSBruce Richardson { 124a9de470cSBruce Richardson double cycles_per_byte = (double)(cpu_clock) / (double)(port_speed_bytes); 125a9de470cSBruce Richardson inv_cycles_per_byte = 1.0 / cycles_per_byte; 126a9de470cSBruce Richardson pkt_time_usec = 1000000.0 / ((double)port_speed_bytes / (double)RTE_RED_S); 127a9de470cSBruce Richardson } 128a9de470cSBruce Richardson 129a9de470cSBruce Richardson static uint64_t get_port_ts(void) 130a9de470cSBruce Richardson { 131a9de470cSBruce Richardson return (uint64_t)((double)rte_rdtsc() * inv_cycles_per_byte); 132a9de470cSBruce Richardson } 133a9de470cSBruce Richardson 134a9de470cSBruce Richardson static void rdtsc_prof_init(struct rdtsc_prof *p, const char *name) 135a9de470cSBruce Richardson { 136a9de470cSBruce Richardson p->clk_min = (uint64_t)(-1LL); 137a9de470cSBruce Richardson p->clk_max = 0; 138a9de470cSBruce Richardson p->clk_avg = 0; 139a9de470cSBruce Richardson p->clk_avgc = 0; 140a9de470cSBruce Richardson p->name = name; 141a9de470cSBruce Richardson } 142a9de470cSBruce Richardson 143a9de470cSBruce Richardson static inline void rdtsc_prof_start(struct rdtsc_prof *p) 144a9de470cSBruce Richardson { 145a9de470cSBruce Richardson p->clk_start = rte_rdtsc_precise(); 146a9de470cSBruce Richardson } 147a9de470cSBruce Richardson 148a9de470cSBruce Richardson static inline void rdtsc_prof_end(struct rdtsc_prof *p) 149a9de470cSBruce Richardson { 150a9de470cSBruce Richardson uint64_t clk_start = rte_rdtsc() - p->clk_start; 151a9de470cSBruce Richardson 152a9de470cSBruce Richardson p->clk_avgc++; 153a9de470cSBruce Richardson p->clk_avg += (double) clk_start; 154a9de470cSBruce Richardson 155a9de470cSBruce Richardson if (clk_start > p->clk_max) 156a9de470cSBruce Richardson p->clk_max = clk_start; 157a9de470cSBruce Richardson if (clk_start < p->clk_min) 158a9de470cSBruce Richardson p->clk_min = clk_start; 159a9de470cSBruce Richardson } 160a9de470cSBruce Richardson 161a9de470cSBruce Richardson static void rdtsc_prof_print(struct rdtsc_prof *p) 162a9de470cSBruce Richardson { 163a9de470cSBruce Richardson if (p->clk_avgc>0) { 164a9de470cSBruce Richardson printf("RDTSC stats for %s: n=%" PRIu64 ", min=%" PRIu64 ", max=%" PRIu64 ", avg=%.1f\n", 165a9de470cSBruce Richardson p->name, 166a9de470cSBruce Richardson p->clk_avgc, 167a9de470cSBruce Richardson p->clk_min, 168a9de470cSBruce Richardson p->clk_max, 169a9de470cSBruce Richardson (p->clk_avg / ((double) p->clk_avgc))); 170a9de470cSBruce Richardson } 171a9de470cSBruce Richardson } 172a9de470cSBruce Richardson 173a9de470cSBruce Richardson static uint32_t rte_red_get_avg_int(const struct rte_red_config *red_cfg, 174a9de470cSBruce Richardson struct rte_red *red) 175a9de470cSBruce Richardson { 176a9de470cSBruce Richardson /** 177a9de470cSBruce Richardson * scale by 1/n and convert from fixed-point to integer 178a9de470cSBruce Richardson */ 179a9de470cSBruce Richardson return red->avg >> (RTE_RED_SCALING + red_cfg->wq_log2); 180a9de470cSBruce Richardson } 181a9de470cSBruce Richardson 182a9de470cSBruce Richardson static double rte_red_get_avg_float(const struct rte_red_config *red_cfg, 183a9de470cSBruce Richardson struct rte_red *red) 184a9de470cSBruce Richardson { 185a9de470cSBruce Richardson /** 186a9de470cSBruce Richardson * scale by 1/n and convert from fixed-point to floating-point 187a9de470cSBruce Richardson */ 188a9de470cSBruce Richardson return ldexp((double)red->avg, -(RTE_RED_SCALING + red_cfg->wq_log2)); 189a9de470cSBruce Richardson } 190a9de470cSBruce Richardson 191a9de470cSBruce Richardson static void rte_red_set_avg_int(const struct rte_red_config *red_cfg, 192a9de470cSBruce Richardson struct rte_red *red, 193a9de470cSBruce Richardson uint32_t avg) 194a9de470cSBruce Richardson { 195a9de470cSBruce Richardson /** 196a9de470cSBruce Richardson * scale by n and convert from integer to fixed-point 197a9de470cSBruce Richardson */ 198a9de470cSBruce Richardson red->avg = avg << (RTE_RED_SCALING + red_cfg->wq_log2); 199a9de470cSBruce Richardson } 200a9de470cSBruce Richardson 201a9de470cSBruce Richardson static double calc_exp_avg_on_empty(double avg, uint32_t n, uint32_t time_diff) 202a9de470cSBruce Richardson { 203a9de470cSBruce Richardson return avg * pow((1.0 - 1.0 / (double)n), (double)time_diff / pkt_time_usec); 204a9de470cSBruce Richardson } 205a9de470cSBruce Richardson 206a9de470cSBruce Richardson static double calc_drop_rate(uint32_t enqueued, uint32_t dropped) 207a9de470cSBruce Richardson { 208a9de470cSBruce Richardson return (double)dropped / ((double)enqueued + (double)dropped); 209a9de470cSBruce Richardson } 210a9de470cSBruce Richardson 211a9de470cSBruce Richardson /** 212a9de470cSBruce Richardson * calculate the drop probability 213a9de470cSBruce Richardson */ 214a9de470cSBruce Richardson static double calc_drop_prob(uint32_t min_th, uint32_t max_th, 215a9de470cSBruce Richardson uint32_t maxp_inv, uint32_t avg) 216a9de470cSBruce Richardson { 217a9de470cSBruce Richardson double drop_prob = 0.0; 218a9de470cSBruce Richardson 219a9de470cSBruce Richardson if (avg < min_th) { 220a9de470cSBruce Richardson drop_prob = 0.0; 221a9de470cSBruce Richardson } else if (avg < max_th) { 222a9de470cSBruce Richardson drop_prob = (1.0 / (double)maxp_inv) 223a9de470cSBruce Richardson * ((double)(avg - min_th) 224a9de470cSBruce Richardson / (double)(max_th - min_th)); 225a9de470cSBruce Richardson } else { 226a9de470cSBruce Richardson drop_prob = 1.0; 227a9de470cSBruce Richardson } 228a9de470cSBruce Richardson return drop_prob; 229a9de470cSBruce Richardson } 230a9de470cSBruce Richardson 231a9de470cSBruce Richardson /** 232a9de470cSBruce Richardson * check if drop rate matches drop probability within tolerance 233a9de470cSBruce Richardson */ 234a9de470cSBruce Richardson static int check_drop_rate(double *diff, double drop_rate, double drop_prob, double tolerance) 235a9de470cSBruce Richardson { 236a9de470cSBruce Richardson double abs_diff = 0.0; 237a9de470cSBruce Richardson int ret = 1; 238a9de470cSBruce Richardson 239a9de470cSBruce Richardson abs_diff = fabs(drop_rate - drop_prob); 240a9de470cSBruce Richardson if ((int)abs_diff == 0) { 241a9de470cSBruce Richardson *diff = 0.0; 242a9de470cSBruce Richardson } else { 243a9de470cSBruce Richardson *diff = (abs_diff / drop_prob) * 100.0; 244a9de470cSBruce Richardson if (*diff > tolerance) { 245a9de470cSBruce Richardson ret = 0; 246a9de470cSBruce Richardson } 247a9de470cSBruce Richardson } 248a9de470cSBruce Richardson return ret; 249a9de470cSBruce Richardson } 250a9de470cSBruce Richardson 251a9de470cSBruce Richardson /** 252a9de470cSBruce Richardson * check if average queue size is within tolerance 253a9de470cSBruce Richardson */ 254a9de470cSBruce Richardson static int check_avg(double *diff, double avg, double exp_avg, double tolerance) 255a9de470cSBruce Richardson { 256a9de470cSBruce Richardson double abs_diff = 0.0; 257a9de470cSBruce Richardson int ret = 1; 258a9de470cSBruce Richardson 259a9de470cSBruce Richardson abs_diff = fabs(avg - exp_avg); 260a9de470cSBruce Richardson if ((int)abs_diff == 0) { 261a9de470cSBruce Richardson *diff = 0.0; 262a9de470cSBruce Richardson } else { 263a9de470cSBruce Richardson *diff = (abs_diff / exp_avg) * 100.0; 264a9de470cSBruce Richardson if (*diff > tolerance) { 265a9de470cSBruce Richardson ret = 0; 266a9de470cSBruce Richardson } 267a9de470cSBruce Richardson } 268a9de470cSBruce Richardson return ret; 269a9de470cSBruce Richardson } 270a9de470cSBruce Richardson 271a9de470cSBruce Richardson /** 272a9de470cSBruce Richardson * initialize the test rte_red config 273a9de470cSBruce Richardson */ 274a9de470cSBruce Richardson static enum test_result 275a9de470cSBruce Richardson test_rte_red_init(struct test_config *tcfg) 276a9de470cSBruce Richardson { 277a9de470cSBruce Richardson unsigned i = 0; 278a9de470cSBruce Richardson 279a9de470cSBruce Richardson tcfg->tvar->clk_freq = rte_get_timer_hz(); 280a9de470cSBruce Richardson init_port_ts( tcfg->tvar->clk_freq ); 281a9de470cSBruce Richardson 282a9de470cSBruce Richardson for (i = 0; i < tcfg->tconfig->num_cfg; i++) { 283a9de470cSBruce Richardson if (rte_red_config_init(&tcfg->tconfig->rconfig[i], 284a9de470cSBruce Richardson (uint16_t)tcfg->tconfig->wq_log2[i], 285a9de470cSBruce Richardson (uint16_t)tcfg->tconfig->min_th, 286a9de470cSBruce Richardson (uint16_t)tcfg->tconfig->max_th, 287a9de470cSBruce Richardson (uint16_t)tcfg->tconfig->maxp_inv[i]) != 0) { 288a9de470cSBruce Richardson return FAIL; 289a9de470cSBruce Richardson } 290a9de470cSBruce Richardson } 291a9de470cSBruce Richardson 292a9de470cSBruce Richardson *tcfg->tqueue->q = 0; 293a9de470cSBruce Richardson *tcfg->tvar->dropped = 0; 294a9de470cSBruce Richardson *tcfg->tvar->enqueued = 0; 295a9de470cSBruce Richardson return PASS; 296a9de470cSBruce Richardson } 297a9de470cSBruce Richardson 298a9de470cSBruce Richardson /** 299a9de470cSBruce Richardson * enqueue until actual queue size reaches target level 300a9de470cSBruce Richardson */ 301a9de470cSBruce Richardson static int 302a9de470cSBruce Richardson increase_actual_qsize(struct rte_red_config *red_cfg, 303a9de470cSBruce Richardson struct rte_red *red, 304a9de470cSBruce Richardson uint32_t *q, 305a9de470cSBruce Richardson uint32_t level, 306a9de470cSBruce Richardson uint32_t attempts) 307a9de470cSBruce Richardson { 308a9de470cSBruce Richardson uint32_t i = 0; 309a9de470cSBruce Richardson 310a9de470cSBruce Richardson for (i = 0; i < attempts; i++) { 311a9de470cSBruce Richardson int ret = 0; 312a9de470cSBruce Richardson 313a9de470cSBruce Richardson /** 314a9de470cSBruce Richardson * enqueue 315a9de470cSBruce Richardson */ 316a9de470cSBruce Richardson ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts() ); 317a9de470cSBruce Richardson if (ret == 0) { 318a9de470cSBruce Richardson if (++(*q) >= level) 319a9de470cSBruce Richardson break; 320a9de470cSBruce Richardson } 321a9de470cSBruce Richardson } 322a9de470cSBruce Richardson /** 323a9de470cSBruce Richardson * check if target actual queue size has been reached 324a9de470cSBruce Richardson */ 325a9de470cSBruce Richardson if (*q != level) 326a9de470cSBruce Richardson return -1; 327a9de470cSBruce Richardson /** 328a9de470cSBruce Richardson * success 329a9de470cSBruce Richardson */ 330a9de470cSBruce Richardson return 0; 331a9de470cSBruce Richardson } 332a9de470cSBruce Richardson 333a9de470cSBruce Richardson /** 334a9de470cSBruce Richardson * enqueue until average queue size reaches target level 335a9de470cSBruce Richardson */ 336a9de470cSBruce Richardson static int 337a9de470cSBruce Richardson increase_average_qsize(struct rte_red_config *red_cfg, 338a9de470cSBruce Richardson struct rte_red *red, 339a9de470cSBruce Richardson uint32_t *q, 340a9de470cSBruce Richardson uint32_t level, 341a9de470cSBruce Richardson uint32_t num_ops) 342a9de470cSBruce Richardson { 343a9de470cSBruce Richardson uint32_t avg = 0; 344a9de470cSBruce Richardson uint32_t i = 0; 345a9de470cSBruce Richardson 346a9de470cSBruce Richardson for (i = 0; i < num_ops; i++) { 347a9de470cSBruce Richardson /** 348a9de470cSBruce Richardson * enqueue 349a9de470cSBruce Richardson */ 350a9de470cSBruce Richardson rte_red_enqueue(red_cfg, red, *q, get_port_ts()); 351a9de470cSBruce Richardson } 352a9de470cSBruce Richardson /** 353a9de470cSBruce Richardson * check if target average queue size has been reached 354a9de470cSBruce Richardson */ 355a9de470cSBruce Richardson avg = rte_red_get_avg_int(red_cfg, red); 356a9de470cSBruce Richardson if (avg != level) 357a9de470cSBruce Richardson return -1; 358a9de470cSBruce Richardson /** 359a9de470cSBruce Richardson * success 360a9de470cSBruce Richardson */ 361a9de470cSBruce Richardson return 0; 362a9de470cSBruce Richardson } 363a9de470cSBruce Richardson 364a9de470cSBruce Richardson /** 365a9de470cSBruce Richardson * setup default values for the functional test structures 366a9de470cSBruce Richardson */ 367a9de470cSBruce Richardson static struct rte_red_config ft_wrconfig[1]; 368a9de470cSBruce Richardson static struct rte_red ft_rtdata[1]; 369a9de470cSBruce Richardson static uint8_t ft_wq_log2[] = {9}; 370a9de470cSBruce Richardson static uint8_t ft_maxp_inv[] = {10}; 371a9de470cSBruce Richardson static uint32_t ft_qconfig[] = {0, 0, 1, 1}; 372a9de470cSBruce Richardson static uint32_t ft_q[] ={0}; 373a9de470cSBruce Richardson static uint32_t ft_dropped[] ={0}; 374a9de470cSBruce Richardson static uint32_t ft_enqueued[] ={0}; 375a9de470cSBruce Richardson 376a9de470cSBruce Richardson static struct test_rte_red_config ft_tconfig = { 377a9de470cSBruce Richardson .rconfig = ft_wrconfig, 378a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft_wrconfig), 379a9de470cSBruce Richardson .wq_log2 = ft_wq_log2, 380a9de470cSBruce Richardson .min_th = 32, 381a9de470cSBruce Richardson .max_th = 128, 382a9de470cSBruce Richardson .maxp_inv = ft_maxp_inv, 383a9de470cSBruce Richardson }; 384a9de470cSBruce Richardson 385a9de470cSBruce Richardson static struct test_queue ft_tqueue = { 386a9de470cSBruce Richardson .rdata = ft_rtdata, 387a9de470cSBruce Richardson .num_queues = RTE_DIM(ft_rtdata), 388a9de470cSBruce Richardson .qconfig = ft_qconfig, 389a9de470cSBruce Richardson .q = ft_q, 390a9de470cSBruce Richardson .q_ramp_up = 1000000, 391a9de470cSBruce Richardson .avg_ramp_up = 1000000, 392a9de470cSBruce Richardson .avg_tolerance = 5, /* 5 percent */ 393a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 394a9de470cSBruce Richardson }; 395a9de470cSBruce Richardson 396a9de470cSBruce Richardson static struct test_var ft_tvar = { 397a9de470cSBruce Richardson .wait_usec = 10000, 398a9de470cSBruce Richardson .num_iterations = 5, 399a9de470cSBruce Richardson .num_ops = 10000, 400a9de470cSBruce Richardson .clk_freq = 0, 401a9de470cSBruce Richardson .dropped = ft_dropped, 402a9de470cSBruce Richardson .enqueued = ft_enqueued, 403a9de470cSBruce Richardson .sleep_sec = (MAX_QEMPTY_TIME_MSEC / MSEC_PER_SEC) + 2, 404a9de470cSBruce Richardson }; 405a9de470cSBruce Richardson 406a9de470cSBruce Richardson /** 407a9de470cSBruce Richardson * functional test enqueue/dequeue packets 408a9de470cSBruce Richardson */ 409a9de470cSBruce Richardson static void enqueue_dequeue_func(struct rte_red_config *red_cfg, 410a9de470cSBruce Richardson struct rte_red *red, 411a9de470cSBruce Richardson uint32_t *q, 412a9de470cSBruce Richardson uint32_t num_ops, 413a9de470cSBruce Richardson uint32_t *enqueued, 414a9de470cSBruce Richardson uint32_t *dropped) 415a9de470cSBruce Richardson { 416a9de470cSBruce Richardson uint32_t i = 0; 417a9de470cSBruce Richardson 418a9de470cSBruce Richardson for (i = 0; i < num_ops; i++) { 419a9de470cSBruce Richardson int ret = 0; 420a9de470cSBruce Richardson 421a9de470cSBruce Richardson /** 422a9de470cSBruce Richardson * enqueue 423a9de470cSBruce Richardson */ 424a9de470cSBruce Richardson ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts()); 425a9de470cSBruce Richardson if (ret == 0) 426a9de470cSBruce Richardson (*enqueued)++; 427a9de470cSBruce Richardson else 428a9de470cSBruce Richardson (*dropped)++; 429a9de470cSBruce Richardson } 430a9de470cSBruce Richardson } 431a9de470cSBruce Richardson 432a9de470cSBruce Richardson /** 433a9de470cSBruce Richardson * Test F1: functional test 1 434a9de470cSBruce Richardson */ 435a9de470cSBruce Richardson static uint32_t ft1_tlevels[] = {6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144}; 436a9de470cSBruce Richardson 437a9de470cSBruce Richardson static struct test_config func_test1_config = { 438a9de470cSBruce Richardson .ifname = "functional test 1 interface", 439a9de470cSBruce Richardson .msg = "functional test 1 : use one rte_red configuration,\n" 440a9de470cSBruce Richardson " increase average queue size to various levels,\n" 441a9de470cSBruce Richardson " compare drop rate to drop probability\n\n", 442a9de470cSBruce Richardson .htxt = " " 443a9de470cSBruce Richardson "avg queue size " 444a9de470cSBruce Richardson "enqueued " 445a9de470cSBruce Richardson "dropped " 446a9de470cSBruce Richardson "drop prob % " 447a9de470cSBruce Richardson "drop rate % " 448a9de470cSBruce Richardson "diff % " 449a9de470cSBruce Richardson "tolerance % " 450a9de470cSBruce Richardson "\n", 451a9de470cSBruce Richardson .tconfig = &ft_tconfig, 452a9de470cSBruce Richardson .tqueue = &ft_tqueue, 453a9de470cSBruce Richardson .tvar = &ft_tvar, 454a9de470cSBruce Richardson .tlevel = ft1_tlevels, 455a9de470cSBruce Richardson }; 456a9de470cSBruce Richardson 457a9de470cSBruce Richardson static enum test_result func_test1(struct test_config *tcfg) 458a9de470cSBruce Richardson { 459a9de470cSBruce Richardson enum test_result result = PASS; 460a9de470cSBruce Richardson uint32_t i = 0; 461a9de470cSBruce Richardson 462a9de470cSBruce Richardson printf("%s", tcfg->msg); 463a9de470cSBruce Richardson 464a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 465a9de470cSBruce Richardson result = FAIL; 466a9de470cSBruce Richardson goto out; 467a9de470cSBruce Richardson } 468a9de470cSBruce Richardson 469a9de470cSBruce Richardson printf("%s", tcfg->htxt); 470a9de470cSBruce Richardson 471a9de470cSBruce Richardson for (i = 0; i < RTE_DIM(ft1_tlevels); i++) { 472a9de470cSBruce Richardson const char *label = NULL; 473a9de470cSBruce Richardson uint32_t avg = 0; 474a9de470cSBruce Richardson double drop_rate = 0.0; 475a9de470cSBruce Richardson double drop_prob = 0.0; 476a9de470cSBruce Richardson double diff = 0.0; 477a9de470cSBruce Richardson 478a9de470cSBruce Richardson /** 479a9de470cSBruce Richardson * reset rte_red run-time data 480a9de470cSBruce Richardson */ 481a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 482a9de470cSBruce Richardson *tcfg->tvar->enqueued = 0; 483a9de470cSBruce Richardson *tcfg->tvar->dropped = 0; 484a9de470cSBruce Richardson 485a9de470cSBruce Richardson if (increase_actual_qsize(tcfg->tconfig->rconfig, 486a9de470cSBruce Richardson tcfg->tqueue->rdata, 487a9de470cSBruce Richardson tcfg->tqueue->q, 488a9de470cSBruce Richardson tcfg->tlevel[i], 489a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 490a9de470cSBruce Richardson result = FAIL; 491a9de470cSBruce Richardson goto out; 492a9de470cSBruce Richardson } 493a9de470cSBruce Richardson 494a9de470cSBruce Richardson if (increase_average_qsize(tcfg->tconfig->rconfig, 495a9de470cSBruce Richardson tcfg->tqueue->rdata, 496a9de470cSBruce Richardson tcfg->tqueue->q, 497a9de470cSBruce Richardson tcfg->tlevel[i], 498a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 499a9de470cSBruce Richardson result = FAIL; 500a9de470cSBruce Richardson goto out; 501a9de470cSBruce Richardson } 502a9de470cSBruce Richardson 503a9de470cSBruce Richardson enqueue_dequeue_func(tcfg->tconfig->rconfig, 504a9de470cSBruce Richardson tcfg->tqueue->rdata, 505a9de470cSBruce Richardson tcfg->tqueue->q, 506a9de470cSBruce Richardson tcfg->tvar->num_ops, 507a9de470cSBruce Richardson tcfg->tvar->enqueued, 508a9de470cSBruce Richardson tcfg->tvar->dropped); 509a9de470cSBruce Richardson 510a9de470cSBruce Richardson avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 511a9de470cSBruce Richardson if (avg != tcfg->tlevel[i]) { 512a9de470cSBruce Richardson fprintf(stderr, "Fail: avg != level\n"); 513a9de470cSBruce Richardson result = FAIL; 514a9de470cSBruce Richardson } 515a9de470cSBruce Richardson 516a9de470cSBruce Richardson drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); 517a9de470cSBruce Richardson drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, 518a9de470cSBruce Richardson *tcfg->tconfig->maxp_inv, tcfg->tlevel[i]); 519a9de470cSBruce Richardson if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) 520a9de470cSBruce Richardson result = FAIL; 521a9de470cSBruce Richardson 522a9de470cSBruce Richardson if (tcfg->tlevel[i] == tcfg->tconfig->min_th) 523a9de470cSBruce Richardson label = "min thresh: "; 524a9de470cSBruce Richardson else if (tcfg->tlevel[i] == tcfg->tconfig->max_th) 525a9de470cSBruce Richardson label = "max thresh: "; 526a9de470cSBruce Richardson else 527a9de470cSBruce Richardson label = " "; 528a9de470cSBruce Richardson printf("%s%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", 529a9de470cSBruce Richardson label, avg, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, 530a9de470cSBruce Richardson drop_prob * 100.0, drop_rate * 100.0, diff, 531a9de470cSBruce Richardson (double)tcfg->tqueue->drop_tolerance); 532a9de470cSBruce Richardson } 533a9de470cSBruce Richardson out: 534a9de470cSBruce Richardson return result; 535a9de470cSBruce Richardson } 536a9de470cSBruce Richardson 537a9de470cSBruce Richardson /** 538a9de470cSBruce Richardson * Test F2: functional test 2 539a9de470cSBruce Richardson */ 540a9de470cSBruce Richardson static uint32_t ft2_tlevel[] = {127}; 541a9de470cSBruce Richardson static uint8_t ft2_wq_log2[] = {9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; 542a9de470cSBruce Richardson static uint8_t ft2_maxp_inv[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; 543a9de470cSBruce Richardson static struct rte_red_config ft2_rconfig[10]; 544a9de470cSBruce Richardson 545a9de470cSBruce Richardson static struct test_rte_red_config ft2_tconfig = { 546a9de470cSBruce Richardson .rconfig = ft2_rconfig, 547a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft2_rconfig), 548a9de470cSBruce Richardson .wq_log2 = ft2_wq_log2, 549a9de470cSBruce Richardson .min_th = 32, 550a9de470cSBruce Richardson .max_th = 128, 551a9de470cSBruce Richardson .maxp_inv = ft2_maxp_inv, 552a9de470cSBruce Richardson }; 553a9de470cSBruce Richardson 554a9de470cSBruce Richardson static struct test_config func_test2_config = { 555a9de470cSBruce Richardson .ifname = "functional test 2 interface", 556a9de470cSBruce Richardson .msg = "functional test 2 : use several RED configurations,\n" 557a9de470cSBruce Richardson " increase average queue size to just below maximum threshold,\n" 558a9de470cSBruce Richardson " compare drop rate to drop probability\n\n", 559a9de470cSBruce Richardson .htxt = "RED config " 560a9de470cSBruce Richardson "avg queue size " 561a9de470cSBruce Richardson "min threshold " 562a9de470cSBruce Richardson "max threshold " 563a9de470cSBruce Richardson "drop prob % " 564a9de470cSBruce Richardson "drop rate % " 565a9de470cSBruce Richardson "diff % " 566a9de470cSBruce Richardson "tolerance % " 567a9de470cSBruce Richardson "\n", 568a9de470cSBruce Richardson .tconfig = &ft2_tconfig, 569a9de470cSBruce Richardson .tqueue = &ft_tqueue, 570a9de470cSBruce Richardson .tvar = &ft_tvar, 571a9de470cSBruce Richardson .tlevel = ft2_tlevel, 572a9de470cSBruce Richardson }; 573a9de470cSBruce Richardson 574a9de470cSBruce Richardson static enum test_result func_test2(struct test_config *tcfg) 575a9de470cSBruce Richardson { 576a9de470cSBruce Richardson enum test_result result = PASS; 577a9de470cSBruce Richardson double prev_drop_rate = 1.0; 578a9de470cSBruce Richardson uint32_t i = 0; 579a9de470cSBruce Richardson 580a9de470cSBruce Richardson printf("%s", tcfg->msg); 581a9de470cSBruce Richardson 582a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 583a9de470cSBruce Richardson result = FAIL; 584a9de470cSBruce Richardson goto out; 585a9de470cSBruce Richardson } 586a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 587a9de470cSBruce Richardson 588a9de470cSBruce Richardson if (increase_actual_qsize(tcfg->tconfig->rconfig, 589a9de470cSBruce Richardson tcfg->tqueue->rdata, 590a9de470cSBruce Richardson tcfg->tqueue->q, 591a9de470cSBruce Richardson *tcfg->tlevel, 592a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 593a9de470cSBruce Richardson result = FAIL; 594a9de470cSBruce Richardson goto out; 595a9de470cSBruce Richardson } 596a9de470cSBruce Richardson 597a9de470cSBruce Richardson if (increase_average_qsize(tcfg->tconfig->rconfig, 598a9de470cSBruce Richardson tcfg->tqueue->rdata, 599a9de470cSBruce Richardson tcfg->tqueue->q, 600a9de470cSBruce Richardson *tcfg->tlevel, 601a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 602a9de470cSBruce Richardson result = FAIL; 603a9de470cSBruce Richardson goto out; 604a9de470cSBruce Richardson } 605a9de470cSBruce Richardson printf("%s", tcfg->htxt); 606a9de470cSBruce Richardson 607a9de470cSBruce Richardson for (i = 0; i < tcfg->tconfig->num_cfg; i++) { 608a9de470cSBruce Richardson uint32_t avg = 0; 609a9de470cSBruce Richardson double drop_rate = 0.0; 610a9de470cSBruce Richardson double drop_prob = 0.0; 611a9de470cSBruce Richardson double diff = 0.0; 612a9de470cSBruce Richardson 613a9de470cSBruce Richardson *tcfg->tvar->dropped = 0; 614a9de470cSBruce Richardson *tcfg->tvar->enqueued = 0; 615a9de470cSBruce Richardson 616a9de470cSBruce Richardson enqueue_dequeue_func(&tcfg->tconfig->rconfig[i], 617a9de470cSBruce Richardson tcfg->tqueue->rdata, 618a9de470cSBruce Richardson tcfg->tqueue->q, 619a9de470cSBruce Richardson tcfg->tvar->num_ops, 620a9de470cSBruce Richardson tcfg->tvar->enqueued, 621a9de470cSBruce Richardson tcfg->tvar->dropped); 622a9de470cSBruce Richardson 623a9de470cSBruce Richardson avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[i], tcfg->tqueue->rdata); 624a9de470cSBruce Richardson if (avg != *tcfg->tlevel) 625a9de470cSBruce Richardson result = FAIL; 626a9de470cSBruce Richardson 627a9de470cSBruce Richardson drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); 628a9de470cSBruce Richardson drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, 629a9de470cSBruce Richardson tcfg->tconfig->maxp_inv[i], *tcfg->tlevel); 630a9de470cSBruce Richardson if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) 631a9de470cSBruce Richardson result = FAIL; 632a9de470cSBruce Richardson /** 633a9de470cSBruce Richardson * drop rate should decrease as maxp_inv increases 634a9de470cSBruce Richardson */ 635a9de470cSBruce Richardson if (drop_rate > prev_drop_rate) 636a9de470cSBruce Richardson result = FAIL; 637a9de470cSBruce Richardson prev_drop_rate = drop_rate; 638a9de470cSBruce Richardson 639a9de470cSBruce Richardson printf("%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", 640a9de470cSBruce Richardson i, avg, tcfg->tconfig->min_th, tcfg->tconfig->max_th, 641a9de470cSBruce Richardson drop_prob * 100.0, drop_rate * 100.0, diff, 642a9de470cSBruce Richardson (double)tcfg->tqueue->drop_tolerance); 643a9de470cSBruce Richardson } 644a9de470cSBruce Richardson out: 645a9de470cSBruce Richardson return result; 646a9de470cSBruce Richardson } 647a9de470cSBruce Richardson 648a9de470cSBruce Richardson /** 649a9de470cSBruce Richardson * Test F3: functional test 3 650a9de470cSBruce Richardson */ 651a9de470cSBruce Richardson static uint32_t ft3_tlevel[] = {1022}; 652a9de470cSBruce Richardson 653a9de470cSBruce Richardson static struct test_rte_red_config ft3_tconfig = { 654a9de470cSBruce Richardson .rconfig = ft_wrconfig, 655a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft_wrconfig), 656a9de470cSBruce Richardson .wq_log2 = ft_wq_log2, 657a9de470cSBruce Richardson .min_th = 32, 658a9de470cSBruce Richardson .max_th = 1023, 659a9de470cSBruce Richardson .maxp_inv = ft_maxp_inv, 660a9de470cSBruce Richardson }; 661a9de470cSBruce Richardson 662a9de470cSBruce Richardson static struct test_config func_test3_config = { 663a9de470cSBruce Richardson .ifname = "functional test 3 interface", 664a9de470cSBruce Richardson .msg = "functional test 3 : use one RED configuration,\n" 665a9de470cSBruce Richardson " increase average queue size to target level,\n" 666a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 667a9de470cSBruce Richardson " confirm that average queue size is computed correctly while queue is empty\n\n", 668a9de470cSBruce Richardson .htxt = "q avg before " 669a9de470cSBruce Richardson "q avg after " 670a9de470cSBruce Richardson "expected " 671a9de470cSBruce Richardson "difference % " 672a9de470cSBruce Richardson "tolerance % " 673a9de470cSBruce Richardson "result " 674a9de470cSBruce Richardson "\n", 675a9de470cSBruce Richardson .tconfig = &ft3_tconfig, 676a9de470cSBruce Richardson .tqueue = &ft_tqueue, 677a9de470cSBruce Richardson .tvar = &ft_tvar, 678a9de470cSBruce Richardson .tlevel = ft3_tlevel, 679a9de470cSBruce Richardson }; 680a9de470cSBruce Richardson 681a9de470cSBruce Richardson static enum test_result func_test3(struct test_config *tcfg) 682a9de470cSBruce Richardson { 683a9de470cSBruce Richardson enum test_result result = PASS; 684a9de470cSBruce Richardson uint32_t i = 0; 685a9de470cSBruce Richardson 686a9de470cSBruce Richardson printf("%s", tcfg->msg); 687a9de470cSBruce Richardson 688a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 689a9de470cSBruce Richardson result = FAIL; 690a9de470cSBruce Richardson goto out; 691a9de470cSBruce Richardson } 692a9de470cSBruce Richardson 693a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 694a9de470cSBruce Richardson 695a9de470cSBruce Richardson if (increase_actual_qsize(tcfg->tconfig->rconfig, 696a9de470cSBruce Richardson tcfg->tqueue->rdata, 697a9de470cSBruce Richardson tcfg->tqueue->q, 698a9de470cSBruce Richardson *tcfg->tlevel, 699a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 700a9de470cSBruce Richardson result = FAIL; 701a9de470cSBruce Richardson goto out; 702a9de470cSBruce Richardson } 703a9de470cSBruce Richardson 704a9de470cSBruce Richardson if (increase_average_qsize(tcfg->tconfig->rconfig, 705a9de470cSBruce Richardson tcfg->tqueue->rdata, 706a9de470cSBruce Richardson tcfg->tqueue->q, 707a9de470cSBruce Richardson *tcfg->tlevel, 708a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 709a9de470cSBruce Richardson result = FAIL; 710a9de470cSBruce Richardson goto out; 711a9de470cSBruce Richardson } 712a9de470cSBruce Richardson 713a9de470cSBruce Richardson printf("%s", tcfg->htxt); 714a9de470cSBruce Richardson 715a9de470cSBruce Richardson for (i = 0; i < tcfg->tvar->num_iterations; i++) { 716a9de470cSBruce Richardson double avg_before = 0; 717a9de470cSBruce Richardson double avg_after = 0; 718a9de470cSBruce Richardson double exp_avg = 0; 719a9de470cSBruce Richardson double diff = 0.0; 720a9de470cSBruce Richardson 721a9de470cSBruce Richardson avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 722a9de470cSBruce Richardson 723a9de470cSBruce Richardson /** 724a9de470cSBruce Richardson * empty the queue 725a9de470cSBruce Richardson */ 726a9de470cSBruce Richardson *tcfg->tqueue->q = 0; 727a9de470cSBruce Richardson rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); 728a9de470cSBruce Richardson 729a9de470cSBruce Richardson rte_delay_us(tcfg->tvar->wait_usec); 730a9de470cSBruce Richardson 731a9de470cSBruce Richardson /** 732a9de470cSBruce Richardson * enqueue one packet to recalculate average queue size 733a9de470cSBruce Richardson */ 734a9de470cSBruce Richardson if (rte_red_enqueue(tcfg->tconfig->rconfig, 735a9de470cSBruce Richardson tcfg->tqueue->rdata, 736a9de470cSBruce Richardson *tcfg->tqueue->q, 737a9de470cSBruce Richardson get_port_ts()) == 0) { 738a9de470cSBruce Richardson (*tcfg->tqueue->q)++; 739a9de470cSBruce Richardson } else { 740a9de470cSBruce Richardson printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__); 741a9de470cSBruce Richardson result = FAIL; 742a9de470cSBruce Richardson } 743a9de470cSBruce Richardson 744a9de470cSBruce Richardson exp_avg = calc_exp_avg_on_empty(avg_before, 745a9de470cSBruce Richardson (1 << *tcfg->tconfig->wq_log2), 746a9de470cSBruce Richardson tcfg->tvar->wait_usec); 747a9de470cSBruce Richardson avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, 748a9de470cSBruce Richardson tcfg->tqueue->rdata); 749a9de470cSBruce Richardson if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) 750a9de470cSBruce Richardson result = FAIL; 751a9de470cSBruce Richardson 752a9de470cSBruce Richardson printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", 753a9de470cSBruce Richardson avg_before, avg_after, exp_avg, diff, 754a9de470cSBruce Richardson (double)tcfg->tqueue->avg_tolerance, 755a9de470cSBruce Richardson diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail"); 756a9de470cSBruce Richardson } 757a9de470cSBruce Richardson out: 758a9de470cSBruce Richardson return result; 759a9de470cSBruce Richardson } 760a9de470cSBruce Richardson 761a9de470cSBruce Richardson /** 762a9de470cSBruce Richardson * Test F4: functional test 4 763a9de470cSBruce Richardson */ 764a9de470cSBruce Richardson static uint32_t ft4_tlevel[] = {1022}; 765a9de470cSBruce Richardson static uint8_t ft4_wq_log2[] = {11}; 766a9de470cSBruce Richardson 767a9de470cSBruce Richardson static struct test_rte_red_config ft4_tconfig = { 768a9de470cSBruce Richardson .rconfig = ft_wrconfig, 769a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft_wrconfig), 770a9de470cSBruce Richardson .min_th = 32, 771a9de470cSBruce Richardson .max_th = 1023, 772a9de470cSBruce Richardson .wq_log2 = ft4_wq_log2, 773a9de470cSBruce Richardson .maxp_inv = ft_maxp_inv, 774a9de470cSBruce Richardson }; 775a9de470cSBruce Richardson 776a9de470cSBruce Richardson static struct test_queue ft4_tqueue = { 777a9de470cSBruce Richardson .rdata = ft_rtdata, 778a9de470cSBruce Richardson .num_queues = RTE_DIM(ft_rtdata), 779a9de470cSBruce Richardson .qconfig = ft_qconfig, 780a9de470cSBruce Richardson .q = ft_q, 781a9de470cSBruce Richardson .q_ramp_up = 1000000, 782a9de470cSBruce Richardson .avg_ramp_up = 1000000, 783a9de470cSBruce Richardson .avg_tolerance = 0, /* 0 percent */ 784a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 785a9de470cSBruce Richardson }; 786a9de470cSBruce Richardson 787a9de470cSBruce Richardson static struct test_config func_test4_config = { 788a9de470cSBruce Richardson .ifname = "functional test 4 interface", 789a9de470cSBruce Richardson .msg = "functional test 4 : use one RED configuration,\n" 790a9de470cSBruce Richardson " increase average queue size to target level,\n" 791a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 792a9de470cSBruce Richardson " confirm that average queue size is computed correctly while\n" 793a9de470cSBruce Richardson " queue is empty for more than 50 sec,\n" 794a9de470cSBruce Richardson " (this test takes 52 sec to run)\n\n", 795a9de470cSBruce Richardson .htxt = "q avg before " 796a9de470cSBruce Richardson "q avg after " 797a9de470cSBruce Richardson "expected " 798a9de470cSBruce Richardson "difference % " 799a9de470cSBruce Richardson "tolerance % " 800a9de470cSBruce Richardson "result " 801a9de470cSBruce Richardson "\n", 802a9de470cSBruce Richardson .tconfig = &ft4_tconfig, 803a9de470cSBruce Richardson .tqueue = &ft4_tqueue, 804a9de470cSBruce Richardson .tvar = &ft_tvar, 805a9de470cSBruce Richardson .tlevel = ft4_tlevel, 806a9de470cSBruce Richardson }; 807a9de470cSBruce Richardson 808a9de470cSBruce Richardson static enum test_result func_test4(struct test_config *tcfg) 809a9de470cSBruce Richardson { 810a9de470cSBruce Richardson enum test_result result = PASS; 811a9de470cSBruce Richardson uint64_t time_diff = 0; 812a9de470cSBruce Richardson uint64_t start = 0; 813a9de470cSBruce Richardson double avg_before = 0.0; 814a9de470cSBruce Richardson double avg_after = 0.0; 815a9de470cSBruce Richardson double exp_avg = 0.0; 816a9de470cSBruce Richardson double diff = 0.0; 817a9de470cSBruce Richardson 818a9de470cSBruce Richardson printf("%s", tcfg->msg); 819a9de470cSBruce Richardson 820a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 821a9de470cSBruce Richardson result = FAIL; 822a9de470cSBruce Richardson goto out; 823a9de470cSBruce Richardson } 824a9de470cSBruce Richardson 825a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 826a9de470cSBruce Richardson 827a9de470cSBruce Richardson if (increase_actual_qsize(tcfg->tconfig->rconfig, 828a9de470cSBruce Richardson tcfg->tqueue->rdata, 829a9de470cSBruce Richardson tcfg->tqueue->q, 830a9de470cSBruce Richardson *tcfg->tlevel, 831a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 832a9de470cSBruce Richardson result = FAIL; 833a9de470cSBruce Richardson goto out; 834a9de470cSBruce Richardson } 835a9de470cSBruce Richardson 836a9de470cSBruce Richardson if (increase_average_qsize(tcfg->tconfig->rconfig, 837a9de470cSBruce Richardson tcfg->tqueue->rdata, 838a9de470cSBruce Richardson tcfg->tqueue->q, 839a9de470cSBruce Richardson *tcfg->tlevel, 840a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 841a9de470cSBruce Richardson result = FAIL; 842a9de470cSBruce Richardson goto out; 843a9de470cSBruce Richardson } 844a9de470cSBruce Richardson 845a9de470cSBruce Richardson printf("%s", tcfg->htxt); 846a9de470cSBruce Richardson 847a9de470cSBruce Richardson avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 848a9de470cSBruce Richardson 849a9de470cSBruce Richardson /** 850a9de470cSBruce Richardson * empty the queue 851a9de470cSBruce Richardson */ 852a9de470cSBruce Richardson *tcfg->tqueue->q = 0; 853a9de470cSBruce Richardson rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); 854a9de470cSBruce Richardson 855a9de470cSBruce Richardson /** 856a9de470cSBruce Richardson * record empty time locally 857a9de470cSBruce Richardson */ 858a9de470cSBruce Richardson start = rte_rdtsc(); 859a9de470cSBruce Richardson 860a9de470cSBruce Richardson sleep(tcfg->tvar->sleep_sec); 861a9de470cSBruce Richardson 862a9de470cSBruce Richardson /** 863a9de470cSBruce Richardson * enqueue one packet to recalculate average queue size 864a9de470cSBruce Richardson */ 865a9de470cSBruce Richardson if (rte_red_enqueue(tcfg->tconfig->rconfig, 866a9de470cSBruce Richardson tcfg->tqueue->rdata, 867a9de470cSBruce Richardson *tcfg->tqueue->q, 868a9de470cSBruce Richardson get_port_ts()) != 0) { 869a9de470cSBruce Richardson result = FAIL; 870a9de470cSBruce Richardson goto out; 871a9de470cSBruce Richardson } 872a9de470cSBruce Richardson (*tcfg->tqueue->q)++; 873a9de470cSBruce Richardson 874a9de470cSBruce Richardson /** 875a9de470cSBruce Richardson * calculate how long queue has been empty 876a9de470cSBruce Richardson */ 877a9de470cSBruce Richardson time_diff = ((rte_rdtsc() - start) / tcfg->tvar->clk_freq) 878a9de470cSBruce Richardson * MSEC_PER_SEC; 879a9de470cSBruce Richardson if (time_diff < MAX_QEMPTY_TIME_MSEC) { 880a9de470cSBruce Richardson /** 881a9de470cSBruce Richardson * this could happen if sleep was interrupted for some reason 882a9de470cSBruce Richardson */ 883a9de470cSBruce Richardson result = FAIL; 884a9de470cSBruce Richardson goto out; 885a9de470cSBruce Richardson } 886a9de470cSBruce Richardson 887a9de470cSBruce Richardson /** 888a9de470cSBruce Richardson * confirm that average queue size is now at expected level 889a9de470cSBruce Richardson */ 890a9de470cSBruce Richardson exp_avg = 0.0; 891a9de470cSBruce Richardson avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 892a9de470cSBruce Richardson if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) 893a9de470cSBruce Richardson result = FAIL; 894a9de470cSBruce Richardson 895a9de470cSBruce Richardson printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", 896a9de470cSBruce Richardson avg_before, avg_after, exp_avg, 897a9de470cSBruce Richardson diff, (double)tcfg->tqueue->avg_tolerance, 898a9de470cSBruce Richardson diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail"); 899a9de470cSBruce Richardson out: 900a9de470cSBruce Richardson return result; 901a9de470cSBruce Richardson } 902a9de470cSBruce Richardson 903a9de470cSBruce Richardson /** 904a9de470cSBruce Richardson * Test F5: functional test 5 905a9de470cSBruce Richardson */ 906a9de470cSBruce Richardson static uint32_t ft5_tlevel[] = {127}; 907a9de470cSBruce Richardson static uint8_t ft5_wq_log2[] = {9, 8}; 908a9de470cSBruce Richardson static uint8_t ft5_maxp_inv[] = {10, 20}; 909a9de470cSBruce Richardson static struct rte_red_config ft5_config[2]; 910a9de470cSBruce Richardson static struct rte_red ft5_data[4]; 911a9de470cSBruce Richardson static uint32_t ft5_q[4]; 912a9de470cSBruce Richardson static uint32_t ft5_dropped[] = {0, 0, 0, 0}; 913a9de470cSBruce Richardson static uint32_t ft5_enqueued[] = {0, 0, 0, 0}; 914a9de470cSBruce Richardson 915a9de470cSBruce Richardson static struct test_rte_red_config ft5_tconfig = { 916a9de470cSBruce Richardson .rconfig = ft5_config, 917a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft5_config), 918a9de470cSBruce Richardson .min_th = 32, 919a9de470cSBruce Richardson .max_th = 128, 920a9de470cSBruce Richardson .wq_log2 = ft5_wq_log2, 921a9de470cSBruce Richardson .maxp_inv = ft5_maxp_inv, 922a9de470cSBruce Richardson }; 923a9de470cSBruce Richardson 924a9de470cSBruce Richardson static struct test_queue ft5_tqueue = { 925a9de470cSBruce Richardson .rdata = ft5_data, 926a9de470cSBruce Richardson .num_queues = RTE_DIM(ft5_data), 927a9de470cSBruce Richardson .qconfig = ft_qconfig, 928a9de470cSBruce Richardson .q = ft5_q, 929a9de470cSBruce Richardson .q_ramp_up = 1000000, 930a9de470cSBruce Richardson .avg_ramp_up = 1000000, 931a9de470cSBruce Richardson .avg_tolerance = 5, /* 10 percent */ 932a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 933a9de470cSBruce Richardson }; 934a9de470cSBruce Richardson 935a9de470cSBruce Richardson struct test_var ft5_tvar = { 936a9de470cSBruce Richardson .wait_usec = 0, 937a9de470cSBruce Richardson .num_iterations = 15, 938a9de470cSBruce Richardson .num_ops = 10000, 939a9de470cSBruce Richardson .clk_freq = 0, 940a9de470cSBruce Richardson .dropped = ft5_dropped, 941a9de470cSBruce Richardson .enqueued = ft5_enqueued, 942a9de470cSBruce Richardson .sleep_sec = 0, 943a9de470cSBruce Richardson }; 944a9de470cSBruce Richardson 945a9de470cSBruce Richardson static struct test_config func_test5_config = { 946a9de470cSBruce Richardson .ifname = "functional test 5 interface", 947a9de470cSBruce Richardson .msg = "functional test 5 : use several queues (each with its own run-time data),\n" 948a9de470cSBruce Richardson " use several RED configurations (such that each configuration is shared by multiple queues),\n" 949a9de470cSBruce Richardson " increase average queue size to just below maximum threshold,\n" 950a9de470cSBruce Richardson " compare drop rate to drop probability,\n" 951a9de470cSBruce Richardson " (this is a larger scale version of functional test 2)\n\n", 952a9de470cSBruce Richardson .htxt = "queue " 953a9de470cSBruce Richardson "config " 954a9de470cSBruce Richardson "avg queue size " 955a9de470cSBruce Richardson "min threshold " 956a9de470cSBruce Richardson "max threshold " 957a9de470cSBruce Richardson "drop prob % " 958a9de470cSBruce Richardson "drop rate % " 959a9de470cSBruce Richardson "diff % " 960a9de470cSBruce Richardson "tolerance % " 961a9de470cSBruce Richardson "\n", 962a9de470cSBruce Richardson .tconfig = &ft5_tconfig, 963a9de470cSBruce Richardson .tqueue = &ft5_tqueue, 964a9de470cSBruce Richardson .tvar = &ft5_tvar, 965a9de470cSBruce Richardson .tlevel = ft5_tlevel, 966a9de470cSBruce Richardson }; 967a9de470cSBruce Richardson 968a9de470cSBruce Richardson static enum test_result func_test5(struct test_config *tcfg) 969a9de470cSBruce Richardson { 970a9de470cSBruce Richardson enum test_result result = PASS; 971a9de470cSBruce Richardson uint32_t j = 0; 972a9de470cSBruce Richardson 973a9de470cSBruce Richardson printf("%s", tcfg->msg); 974a9de470cSBruce Richardson 975a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 976a9de470cSBruce Richardson result = FAIL; 977a9de470cSBruce Richardson goto out; 978a9de470cSBruce Richardson } 979a9de470cSBruce Richardson 980a9de470cSBruce Richardson printf("%s", tcfg->htxt); 981a9de470cSBruce Richardson 982a9de470cSBruce Richardson for (j = 0; j < tcfg->tqueue->num_queues; j++) { 983a9de470cSBruce Richardson rte_red_rt_data_init(&tcfg->tqueue->rdata[j]); 984a9de470cSBruce Richardson tcfg->tqueue->q[j] = 0; 985a9de470cSBruce Richardson 986a9de470cSBruce Richardson if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 987a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 988a9de470cSBruce Richardson &tcfg->tqueue->q[j], 989a9de470cSBruce Richardson *tcfg->tlevel, 990a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 991a9de470cSBruce Richardson result = FAIL; 992a9de470cSBruce Richardson goto out; 993a9de470cSBruce Richardson } 994a9de470cSBruce Richardson 995a9de470cSBruce Richardson if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 996a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 997a9de470cSBruce Richardson &tcfg->tqueue->q[j], 998a9de470cSBruce Richardson *tcfg->tlevel, 999a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 1000a9de470cSBruce Richardson result = FAIL; 1001a9de470cSBruce Richardson goto out; 1002a9de470cSBruce Richardson } 1003a9de470cSBruce Richardson } 1004a9de470cSBruce Richardson 1005a9de470cSBruce Richardson for (j = 0; j < tcfg->tqueue->num_queues; j++) { 1006a9de470cSBruce Richardson uint32_t avg = 0; 1007a9de470cSBruce Richardson double drop_rate = 0.0; 1008a9de470cSBruce Richardson double drop_prob = 0.0; 1009a9de470cSBruce Richardson double diff = 0.0; 1010a9de470cSBruce Richardson 1011a9de470cSBruce Richardson tcfg->tvar->dropped[j] = 0; 1012a9de470cSBruce Richardson tcfg->tvar->enqueued[j] = 0; 1013a9de470cSBruce Richardson 1014a9de470cSBruce Richardson enqueue_dequeue_func(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1015a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 1016a9de470cSBruce Richardson &tcfg->tqueue->q[j], 1017a9de470cSBruce Richardson tcfg->tvar->num_ops, 1018a9de470cSBruce Richardson &tcfg->tvar->enqueued[j], 1019a9de470cSBruce Richardson &tcfg->tvar->dropped[j]); 1020a9de470cSBruce Richardson 1021a9de470cSBruce Richardson avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1022a9de470cSBruce Richardson &tcfg->tqueue->rdata[j]); 1023a9de470cSBruce Richardson if (avg != *tcfg->tlevel) 1024a9de470cSBruce Richardson result = FAIL; 1025a9de470cSBruce Richardson 1026a9de470cSBruce Richardson drop_rate = calc_drop_rate(tcfg->tvar->enqueued[j],tcfg->tvar->dropped[j]); 1027a9de470cSBruce Richardson drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, 1028a9de470cSBruce Richardson tcfg->tconfig->maxp_inv[tcfg->tqueue->qconfig[j]], 1029a9de470cSBruce Richardson *tcfg->tlevel); 1030a9de470cSBruce Richardson if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) 1031a9de470cSBruce Richardson result = FAIL; 1032a9de470cSBruce Richardson 1033a9de470cSBruce Richardson printf("%-15u%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", 1034a9de470cSBruce Richardson j, tcfg->tqueue->qconfig[j], avg, 1035a9de470cSBruce Richardson tcfg->tconfig->min_th, tcfg->tconfig->max_th, 1036a9de470cSBruce Richardson drop_prob * 100.0, drop_rate * 100.0, 1037a9de470cSBruce Richardson diff, (double)tcfg->tqueue->drop_tolerance); 1038a9de470cSBruce Richardson } 1039a9de470cSBruce Richardson out: 1040a9de470cSBruce Richardson return result; 1041a9de470cSBruce Richardson } 1042a9de470cSBruce Richardson 1043a9de470cSBruce Richardson /** 1044a9de470cSBruce Richardson * Test F6: functional test 6 1045a9de470cSBruce Richardson */ 1046a9de470cSBruce Richardson static uint32_t ft6_tlevel[] = {1022}; 1047a9de470cSBruce Richardson static uint8_t ft6_wq_log2[] = {9, 8}; 1048a9de470cSBruce Richardson static uint8_t ft6_maxp_inv[] = {10, 20}; 1049a9de470cSBruce Richardson static struct rte_red_config ft6_config[2]; 1050a9de470cSBruce Richardson static struct rte_red ft6_data[4]; 1051a9de470cSBruce Richardson static uint32_t ft6_q[4]; 1052a9de470cSBruce Richardson 1053a9de470cSBruce Richardson static struct test_rte_red_config ft6_tconfig = { 1054a9de470cSBruce Richardson .rconfig = ft6_config, 1055a9de470cSBruce Richardson .num_cfg = RTE_DIM(ft6_config), 1056a9de470cSBruce Richardson .min_th = 32, 1057a9de470cSBruce Richardson .max_th = 1023, 1058a9de470cSBruce Richardson .wq_log2 = ft6_wq_log2, 1059a9de470cSBruce Richardson .maxp_inv = ft6_maxp_inv, 1060a9de470cSBruce Richardson }; 1061a9de470cSBruce Richardson 1062a9de470cSBruce Richardson static struct test_queue ft6_tqueue = { 1063a9de470cSBruce Richardson .rdata = ft6_data, 1064a9de470cSBruce Richardson .num_queues = RTE_DIM(ft6_data), 1065a9de470cSBruce Richardson .qconfig = ft_qconfig, 1066a9de470cSBruce Richardson .q = ft6_q, 1067a9de470cSBruce Richardson .q_ramp_up = 1000000, 1068a9de470cSBruce Richardson .avg_ramp_up = 1000000, 1069a9de470cSBruce Richardson .avg_tolerance = 5, /* 10 percent */ 1070a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 1071a9de470cSBruce Richardson }; 1072a9de470cSBruce Richardson 1073a9de470cSBruce Richardson static struct test_config func_test6_config = { 1074a9de470cSBruce Richardson .ifname = "functional test 6 interface", 1075a9de470cSBruce Richardson .msg = "functional test 6 : use several queues (each with its own run-time data),\n" 1076fc812a21SDavid Marchand " use several RED configurations (such that each configuration is shared by multiple queues),\n" 1077a9de470cSBruce Richardson " increase average queue size to target level,\n" 1078a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 1079a9de470cSBruce Richardson " confirm that average queue size is computed correctly while queue is empty\n" 1080a9de470cSBruce Richardson " (this is a larger scale version of functional test 3)\n\n", 1081a9de470cSBruce Richardson .htxt = "queue " 1082a9de470cSBruce Richardson "config " 1083a9de470cSBruce Richardson "q avg before " 1084a9de470cSBruce Richardson "q avg after " 1085a9de470cSBruce Richardson "expected " 1086a9de470cSBruce Richardson "difference % " 1087a9de470cSBruce Richardson "tolerance % " 1088a9de470cSBruce Richardson "result ""\n", 1089a9de470cSBruce Richardson .tconfig = &ft6_tconfig, 1090a9de470cSBruce Richardson .tqueue = &ft6_tqueue, 1091a9de470cSBruce Richardson .tvar = &ft_tvar, 1092a9de470cSBruce Richardson .tlevel = ft6_tlevel, 1093a9de470cSBruce Richardson }; 1094a9de470cSBruce Richardson 1095a9de470cSBruce Richardson static enum test_result func_test6(struct test_config *tcfg) 1096a9de470cSBruce Richardson { 1097a9de470cSBruce Richardson enum test_result result = PASS; 1098a9de470cSBruce Richardson uint32_t j = 0; 1099a9de470cSBruce Richardson 1100a9de470cSBruce Richardson printf("%s", tcfg->msg); 1101a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 1102a9de470cSBruce Richardson result = FAIL; 1103a9de470cSBruce Richardson goto out; 1104a9de470cSBruce Richardson } 1105a9de470cSBruce Richardson printf("%s", tcfg->htxt); 1106a9de470cSBruce Richardson 1107a9de470cSBruce Richardson for (j = 0; j < tcfg->tqueue->num_queues; j++) { 1108a9de470cSBruce Richardson rte_red_rt_data_init(&tcfg->tqueue->rdata[j]); 1109a9de470cSBruce Richardson tcfg->tqueue->q[j] = 0; 1110a9de470cSBruce Richardson 1111a9de470cSBruce Richardson if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1112a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 1113a9de470cSBruce Richardson &tcfg->tqueue->q[j], 1114a9de470cSBruce Richardson *tcfg->tlevel, 1115a9de470cSBruce Richardson tcfg->tqueue->q_ramp_up) != 0) { 1116a9de470cSBruce Richardson result = FAIL; 1117a9de470cSBruce Richardson goto out; 1118a9de470cSBruce Richardson } 1119a9de470cSBruce Richardson if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1120a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 1121a9de470cSBruce Richardson &tcfg->tqueue->q[j], 1122a9de470cSBruce Richardson *tcfg->tlevel, 1123a9de470cSBruce Richardson tcfg->tqueue->avg_ramp_up) != 0) { 1124a9de470cSBruce Richardson result = FAIL; 1125a9de470cSBruce Richardson goto out; 1126a9de470cSBruce Richardson } 1127a9de470cSBruce Richardson } 1128a9de470cSBruce Richardson for (j = 0; j < tcfg->tqueue->num_queues; j++) { 1129a9de470cSBruce Richardson double avg_before = 0; 1130a9de470cSBruce Richardson double avg_after = 0; 1131a9de470cSBruce Richardson double exp_avg = 0; 1132a9de470cSBruce Richardson double diff = 0.0; 1133a9de470cSBruce Richardson 1134a9de470cSBruce Richardson avg_before = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1135a9de470cSBruce Richardson &tcfg->tqueue->rdata[j]); 1136a9de470cSBruce Richardson 1137a9de470cSBruce Richardson /** 1138a9de470cSBruce Richardson * empty the queue 1139a9de470cSBruce Richardson */ 1140a9de470cSBruce Richardson tcfg->tqueue->q[j] = 0; 1141a9de470cSBruce Richardson rte_red_mark_queue_empty(&tcfg->tqueue->rdata[j], get_port_ts()); 1142a9de470cSBruce Richardson rte_delay_us(tcfg->tvar->wait_usec); 1143a9de470cSBruce Richardson 1144a9de470cSBruce Richardson /** 1145a9de470cSBruce Richardson * enqueue one packet to recalculate average queue size 1146a9de470cSBruce Richardson */ 1147a9de470cSBruce Richardson if (rte_red_enqueue(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1148a9de470cSBruce Richardson &tcfg->tqueue->rdata[j], 1149a9de470cSBruce Richardson tcfg->tqueue->q[j], 1150a9de470cSBruce Richardson get_port_ts()) == 0) { 1151a9de470cSBruce Richardson tcfg->tqueue->q[j]++; 1152a9de470cSBruce Richardson } else { 1153a9de470cSBruce Richardson printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__); 1154a9de470cSBruce Richardson result = FAIL; 1155a9de470cSBruce Richardson } 1156a9de470cSBruce Richardson 1157a9de470cSBruce Richardson exp_avg = calc_exp_avg_on_empty(avg_before, 1158a9de470cSBruce Richardson (1 << tcfg->tconfig->wq_log2[tcfg->tqueue->qconfig[j]]), 1159a9de470cSBruce Richardson tcfg->tvar->wait_usec); 1160a9de470cSBruce Richardson avg_after = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], 1161a9de470cSBruce Richardson &tcfg->tqueue->rdata[j]); 1162a9de470cSBruce Richardson if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) 1163a9de470cSBruce Richardson result = FAIL; 1164a9de470cSBruce Richardson 1165a9de470cSBruce Richardson printf("%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", 1166a9de470cSBruce Richardson j, tcfg->tqueue->qconfig[j], avg_before, avg_after, 1167a9de470cSBruce Richardson exp_avg, diff, (double)tcfg->tqueue->avg_tolerance, 1168a9de470cSBruce Richardson diff <= tcfg->tqueue->avg_tolerance ? "pass" : "fail"); 1169a9de470cSBruce Richardson } 1170a9de470cSBruce Richardson out: 1171a9de470cSBruce Richardson return result; 1172a9de470cSBruce Richardson } 1173a9de470cSBruce Richardson 1174a9de470cSBruce Richardson /** 1175a9de470cSBruce Richardson * setup default values for the performance test structures 1176a9de470cSBruce Richardson */ 1177a9de470cSBruce Richardson static struct rte_red_config pt_wrconfig[1]; 1178a9de470cSBruce Richardson static struct rte_red pt_rtdata[1]; 1179a9de470cSBruce Richardson static uint8_t pt_wq_log2[] = {9}; 1180a9de470cSBruce Richardson static uint8_t pt_maxp_inv[] = {10}; 1181a9de470cSBruce Richardson static uint32_t pt_qconfig[] = {0}; 1182a9de470cSBruce Richardson static uint32_t pt_q[] = {0}; 1183a9de470cSBruce Richardson static uint32_t pt_dropped[] = {0}; 1184a9de470cSBruce Richardson static uint32_t pt_enqueued[] = {0}; 1185a9de470cSBruce Richardson 1186a9de470cSBruce Richardson static struct test_rte_red_config pt_tconfig = { 1187a9de470cSBruce Richardson .rconfig = pt_wrconfig, 1188a9de470cSBruce Richardson .num_cfg = RTE_DIM(pt_wrconfig), 1189a9de470cSBruce Richardson .wq_log2 = pt_wq_log2, 1190a9de470cSBruce Richardson .min_th = 32, 1191a9de470cSBruce Richardson .max_th = 128, 1192a9de470cSBruce Richardson .maxp_inv = pt_maxp_inv, 1193a9de470cSBruce Richardson }; 1194a9de470cSBruce Richardson 1195a9de470cSBruce Richardson static struct test_queue pt_tqueue = { 1196a9de470cSBruce Richardson .rdata = pt_rtdata, 1197a9de470cSBruce Richardson .num_queues = RTE_DIM(pt_rtdata), 1198a9de470cSBruce Richardson .qconfig = pt_qconfig, 1199a9de470cSBruce Richardson .q = pt_q, 1200a9de470cSBruce Richardson .q_ramp_up = 1000000, 1201a9de470cSBruce Richardson .avg_ramp_up = 1000000, 1202a9de470cSBruce Richardson .avg_tolerance = 5, /* 10 percent */ 1203a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 1204a9de470cSBruce Richardson }; 1205a9de470cSBruce Richardson 1206a9de470cSBruce Richardson /** 1207a9de470cSBruce Richardson * enqueue/dequeue packets 1208a9de470cSBruce Richardson */ 1209a9de470cSBruce Richardson static void enqueue_dequeue_perf(struct rte_red_config *red_cfg, 1210a9de470cSBruce Richardson struct rte_red *red, 1211a9de470cSBruce Richardson uint32_t *q, 1212a9de470cSBruce Richardson uint32_t num_ops, 1213a9de470cSBruce Richardson uint32_t *enqueued, 1214a9de470cSBruce Richardson uint32_t *dropped, 1215a9de470cSBruce Richardson struct rdtsc_prof *prof) 1216a9de470cSBruce Richardson { 1217a9de470cSBruce Richardson uint32_t i = 0; 1218a9de470cSBruce Richardson 1219a9de470cSBruce Richardson for (i = 0; i < num_ops; i++) { 1220a9de470cSBruce Richardson uint64_t ts = 0; 1221a9de470cSBruce Richardson int ret = 0; 1222a9de470cSBruce Richardson /** 1223a9de470cSBruce Richardson * enqueue 1224a9de470cSBruce Richardson */ 1225a9de470cSBruce Richardson ts = get_port_ts(); 1226a9de470cSBruce Richardson rdtsc_prof_start(prof); 1227a9de470cSBruce Richardson ret = rte_red_enqueue(red_cfg, red, *q, ts ); 1228a9de470cSBruce Richardson rdtsc_prof_end(prof); 1229a9de470cSBruce Richardson if (ret == 0) 1230a9de470cSBruce Richardson (*enqueued)++; 1231a9de470cSBruce Richardson else 1232a9de470cSBruce Richardson (*dropped)++; 1233a9de470cSBruce Richardson } 1234a9de470cSBruce Richardson } 1235a9de470cSBruce Richardson 1236a9de470cSBruce Richardson /** 1237a9de470cSBruce Richardson * Setup test structures for tests P1, P2, P3 1238a9de470cSBruce Richardson * performance tests 1, 2 and 3 1239a9de470cSBruce Richardson */ 1240a9de470cSBruce Richardson static uint32_t pt1_tlevel[] = {16}; 1241a9de470cSBruce Richardson static uint32_t pt2_tlevel[] = {80}; 1242a9de470cSBruce Richardson static uint32_t pt3_tlevel[] = {144}; 1243a9de470cSBruce Richardson 1244a9de470cSBruce Richardson static struct test_var perf1_tvar = { 1245a9de470cSBruce Richardson .wait_usec = 0, 1246a9de470cSBruce Richardson .num_iterations = 15, 1247a9de470cSBruce Richardson .num_ops = 50000000, 1248a9de470cSBruce Richardson .clk_freq = 0, 1249a9de470cSBruce Richardson .dropped = pt_dropped, 1250a9de470cSBruce Richardson .enqueued = pt_enqueued, 1251a9de470cSBruce Richardson .sleep_sec = 0 1252a9de470cSBruce Richardson }; 1253a9de470cSBruce Richardson 1254a9de470cSBruce Richardson static struct test_config perf1_test1_config = { 1255a9de470cSBruce Richardson .ifname = "performance test 1 interface", 1256a9de470cSBruce Richardson .msg = "performance test 1 : use one RED configuration,\n" 1257a9de470cSBruce Richardson " set actual and average queue sizes to level below min threshold,\n" 1258a9de470cSBruce Richardson " measure enqueue performance\n\n", 1259a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1260a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1261a9de470cSBruce Richardson .tvar = &perf1_tvar, 1262a9de470cSBruce Richardson .tlevel = pt1_tlevel, 1263a9de470cSBruce Richardson }; 1264a9de470cSBruce Richardson 1265a9de470cSBruce Richardson static struct test_config perf1_test2_config = { 1266a9de470cSBruce Richardson .ifname = "performance test 2 interface", 1267a9de470cSBruce Richardson .msg = "performance test 2 : use one RED configuration,\n" 1268a9de470cSBruce Richardson " set actual and average queue sizes to level in between min and max thresholds,\n" 1269a9de470cSBruce Richardson " measure enqueue performance\n\n", 1270a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1271a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1272a9de470cSBruce Richardson .tvar = &perf1_tvar, 1273a9de470cSBruce Richardson .tlevel = pt2_tlevel, 1274a9de470cSBruce Richardson }; 1275a9de470cSBruce Richardson 1276a9de470cSBruce Richardson static struct test_config perf1_test3_config = { 1277a9de470cSBruce Richardson .ifname = "performance test 3 interface", 1278a9de470cSBruce Richardson .msg = "performance test 3 : use one RED configuration,\n" 1279a9de470cSBruce Richardson " set actual and average queue sizes to level above max threshold,\n" 1280a9de470cSBruce Richardson " measure enqueue performance\n\n", 1281a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1282a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1283a9de470cSBruce Richardson .tvar = &perf1_tvar, 1284a9de470cSBruce Richardson .tlevel = pt3_tlevel, 1285a9de470cSBruce Richardson }; 1286a9de470cSBruce Richardson 1287a9de470cSBruce Richardson /** 1288a9de470cSBruce Richardson * Performance test function to measure enqueue performance. 1289a9de470cSBruce Richardson * This runs performance tests 1, 2 and 3 1290a9de470cSBruce Richardson */ 1291a9de470cSBruce Richardson static enum test_result perf1_test(struct test_config *tcfg) 1292a9de470cSBruce Richardson { 1293a9de470cSBruce Richardson enum test_result result = PASS; 1294a9de470cSBruce Richardson struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; 1295a9de470cSBruce Richardson uint32_t total = 0; 1296a9de470cSBruce Richardson 1297a9de470cSBruce Richardson printf("%s", tcfg->msg); 1298a9de470cSBruce Richardson 1299a9de470cSBruce Richardson rdtsc_prof_init(&prof, "enqueue"); 1300a9de470cSBruce Richardson 1301a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 1302a9de470cSBruce Richardson result = FAIL; 1303a9de470cSBruce Richardson goto out; 1304a9de470cSBruce Richardson } 1305a9de470cSBruce Richardson 1306a9de470cSBruce Richardson /** 1307a9de470cSBruce Richardson * set average queue size to target level 1308a9de470cSBruce Richardson */ 1309a9de470cSBruce Richardson *tcfg->tqueue->q = *tcfg->tlevel; 1310a9de470cSBruce Richardson 1311a9de470cSBruce Richardson /** 1312a9de470cSBruce Richardson * initialize the rte_red run time data structure 1313a9de470cSBruce Richardson */ 1314a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 1315a9de470cSBruce Richardson 1316a9de470cSBruce Richardson /** 1317a9de470cSBruce Richardson * set the queue average 1318a9de470cSBruce Richardson */ 1319a9de470cSBruce Richardson rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel); 1320a9de470cSBruce Richardson if (rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata) 1321a9de470cSBruce Richardson != *tcfg->tlevel) { 1322a9de470cSBruce Richardson result = FAIL; 1323a9de470cSBruce Richardson goto out; 1324a9de470cSBruce Richardson } 1325a9de470cSBruce Richardson 1326a9de470cSBruce Richardson enqueue_dequeue_perf(tcfg->tconfig->rconfig, 1327a9de470cSBruce Richardson tcfg->tqueue->rdata, 1328a9de470cSBruce Richardson tcfg->tqueue->q, 1329a9de470cSBruce Richardson tcfg->tvar->num_ops, 1330a9de470cSBruce Richardson tcfg->tvar->enqueued, 1331a9de470cSBruce Richardson tcfg->tvar->dropped, 1332a9de470cSBruce Richardson &prof); 1333a9de470cSBruce Richardson 1334a9de470cSBruce Richardson total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; 1335a9de470cSBruce Richardson 1336a9de470cSBruce Richardson printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total, 1337a9de470cSBruce Richardson *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0, 1338a9de470cSBruce Richardson *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); 1339a9de470cSBruce Richardson 1340a9de470cSBruce Richardson rdtsc_prof_print(&prof); 1341a9de470cSBruce Richardson out: 1342a9de470cSBruce Richardson return result; 1343a9de470cSBruce Richardson } 1344a9de470cSBruce Richardson 1345a9de470cSBruce Richardson /** 1346a9de470cSBruce Richardson * Setup test structures for tests P4, P5, P6 1347a9de470cSBruce Richardson * performance tests 4, 5 and 6 1348a9de470cSBruce Richardson */ 1349a9de470cSBruce Richardson static uint32_t pt4_tlevel[] = {16}; 1350a9de470cSBruce Richardson static uint32_t pt5_tlevel[] = {80}; 1351a9de470cSBruce Richardson static uint32_t pt6_tlevel[] = {144}; 1352a9de470cSBruce Richardson 1353a9de470cSBruce Richardson static struct test_var perf2_tvar = { 1354a9de470cSBruce Richardson .wait_usec = 500, 1355a9de470cSBruce Richardson .num_iterations = 10000, 1356a9de470cSBruce Richardson .num_ops = 10000, 1357a9de470cSBruce Richardson .dropped = pt_dropped, 1358a9de470cSBruce Richardson .enqueued = pt_enqueued, 1359a9de470cSBruce Richardson .sleep_sec = 0 1360a9de470cSBruce Richardson }; 1361a9de470cSBruce Richardson 1362a9de470cSBruce Richardson static struct test_config perf2_test4_config = { 1363a9de470cSBruce Richardson .ifname = "performance test 4 interface", 1364a9de470cSBruce Richardson .msg = "performance test 4 : use one RED configuration,\n" 1365a9de470cSBruce Richardson " set actual and average queue sizes to level below min threshold,\n" 1366a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 1367a9de470cSBruce Richardson " measure enqueue performance when queue is empty\n\n", 1368a9de470cSBruce Richardson .htxt = "iteration " 1369a9de470cSBruce Richardson "q avg before " 1370a9de470cSBruce Richardson "q avg after " 1371a9de470cSBruce Richardson "expected " 1372a9de470cSBruce Richardson "difference % " 1373a9de470cSBruce Richardson "tolerance % " 1374a9de470cSBruce Richardson "result ""\n", 1375a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1376a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1377a9de470cSBruce Richardson .tvar = &perf2_tvar, 1378a9de470cSBruce Richardson .tlevel = pt4_tlevel, 1379a9de470cSBruce Richardson }; 1380a9de470cSBruce Richardson 1381a9de470cSBruce Richardson static struct test_config perf2_test5_config = { 1382a9de470cSBruce Richardson .ifname = "performance test 5 interface", 1383a9de470cSBruce Richardson .msg = "performance test 5 : use one RED configuration,\n" 1384a9de470cSBruce Richardson " set actual and average queue sizes to level in between min and max thresholds,\n" 1385a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 1386a9de470cSBruce Richardson " measure enqueue performance when queue is empty\n\n", 1387a9de470cSBruce Richardson .htxt = "iteration " 1388a9de470cSBruce Richardson "q avg before " 1389a9de470cSBruce Richardson "q avg after " 1390a9de470cSBruce Richardson "expected " 1391a9de470cSBruce Richardson "difference " 1392a9de470cSBruce Richardson "tolerance " 1393a9de470cSBruce Richardson "result ""\n", 1394a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1395a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1396a9de470cSBruce Richardson .tvar = &perf2_tvar, 1397a9de470cSBruce Richardson .tlevel = pt5_tlevel, 1398a9de470cSBruce Richardson }; 1399a9de470cSBruce Richardson 1400a9de470cSBruce Richardson static struct test_config perf2_test6_config = { 1401a9de470cSBruce Richardson .ifname = "performance test 6 interface", 1402a9de470cSBruce Richardson .msg = "performance test 6 : use one RED configuration,\n" 1403a9de470cSBruce Richardson " set actual and average queue sizes to level above max threshold,\n" 1404a9de470cSBruce Richardson " dequeue all packets until queue is empty,\n" 1405a9de470cSBruce Richardson " measure enqueue performance when queue is empty\n\n", 1406a9de470cSBruce Richardson .htxt = "iteration " 1407a9de470cSBruce Richardson "q avg before " 1408a9de470cSBruce Richardson "q avg after " 1409a9de470cSBruce Richardson "expected " 1410a9de470cSBruce Richardson "difference % " 1411a9de470cSBruce Richardson "tolerance % " 1412a9de470cSBruce Richardson "result ""\n", 1413a9de470cSBruce Richardson .tconfig = &pt_tconfig, 1414a9de470cSBruce Richardson .tqueue = &pt_tqueue, 1415a9de470cSBruce Richardson .tvar = &perf2_tvar, 1416a9de470cSBruce Richardson .tlevel = pt6_tlevel, 1417a9de470cSBruce Richardson }; 1418a9de470cSBruce Richardson 1419a9de470cSBruce Richardson /** 1420a9de470cSBruce Richardson * Performance test function to measure enqueue performance when the 1421a9de470cSBruce Richardson * queue is empty. This runs performance tests 4, 5 and 6 1422a9de470cSBruce Richardson */ 1423a9de470cSBruce Richardson static enum test_result perf2_test(struct test_config *tcfg) 1424a9de470cSBruce Richardson { 1425a9de470cSBruce Richardson enum test_result result = PASS; 1426a9de470cSBruce Richardson struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; 1427a9de470cSBruce Richardson uint32_t total = 0; 1428a9de470cSBruce Richardson uint32_t i = 0; 1429a9de470cSBruce Richardson 1430a9de470cSBruce Richardson printf("%s", tcfg->msg); 1431a9de470cSBruce Richardson 1432a9de470cSBruce Richardson rdtsc_prof_init(&prof, "enqueue"); 1433a9de470cSBruce Richardson 1434a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 1435a9de470cSBruce Richardson result = FAIL; 1436a9de470cSBruce Richardson goto out; 1437a9de470cSBruce Richardson } 1438a9de470cSBruce Richardson 1439a9de470cSBruce Richardson printf("%s", tcfg->htxt); 1440a9de470cSBruce Richardson 1441a9de470cSBruce Richardson for (i = 0; i < tcfg->tvar->num_iterations; i++) { 1442a9de470cSBruce Richardson uint32_t count = 0; 1443a9de470cSBruce Richardson uint64_t ts = 0; 1444a9de470cSBruce Richardson double avg_before = 0; 1445a9de470cSBruce Richardson int ret = 0; 1446a9de470cSBruce Richardson 1447a9de470cSBruce Richardson /** 1448a9de470cSBruce Richardson * set average queue size to target level 1449a9de470cSBruce Richardson */ 1450a9de470cSBruce Richardson *tcfg->tqueue->q = *tcfg->tlevel; 1451a9de470cSBruce Richardson count = (*tcfg->tqueue->rdata).count; 1452a9de470cSBruce Richardson 1453a9de470cSBruce Richardson /** 1454a9de470cSBruce Richardson * initialize the rte_red run time data structure 1455a9de470cSBruce Richardson */ 1456a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 1457a9de470cSBruce Richardson (*tcfg->tqueue->rdata).count = count; 1458a9de470cSBruce Richardson 1459a9de470cSBruce Richardson /** 1460a9de470cSBruce Richardson * set the queue average 1461a9de470cSBruce Richardson */ 1462a9de470cSBruce Richardson rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel); 1463a9de470cSBruce Richardson avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 1464a9de470cSBruce Richardson if ((avg_before < *tcfg->tlevel) || (avg_before > *tcfg->tlevel)) { 1465a9de470cSBruce Richardson result = FAIL; 1466a9de470cSBruce Richardson goto out; 1467a9de470cSBruce Richardson } 1468a9de470cSBruce Richardson 1469a9de470cSBruce Richardson /** 1470a9de470cSBruce Richardson * empty the queue 1471a9de470cSBruce Richardson */ 1472a9de470cSBruce Richardson *tcfg->tqueue->q = 0; 1473a9de470cSBruce Richardson rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); 1474a9de470cSBruce Richardson 1475a9de470cSBruce Richardson /** 1476a9de470cSBruce Richardson * wait for specified period of time 1477a9de470cSBruce Richardson */ 1478a9de470cSBruce Richardson rte_delay_us(tcfg->tvar->wait_usec); 1479a9de470cSBruce Richardson 1480a9de470cSBruce Richardson /** 1481a9de470cSBruce Richardson * measure performance of enqueue operation while queue is empty 1482a9de470cSBruce Richardson */ 1483a9de470cSBruce Richardson ts = get_port_ts(); 1484a9de470cSBruce Richardson rdtsc_prof_start(&prof); 1485a9de470cSBruce Richardson ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, 1486a9de470cSBruce Richardson *tcfg->tqueue->q, ts ); 1487a9de470cSBruce Richardson rdtsc_prof_end(&prof); 1488a9de470cSBruce Richardson 1489a9de470cSBruce Richardson /** 1490a9de470cSBruce Richardson * gather enqueued/dropped statistics 1491a9de470cSBruce Richardson */ 1492a9de470cSBruce Richardson if (ret == 0) 1493a9de470cSBruce Richardson (*tcfg->tvar->enqueued)++; 1494a9de470cSBruce Richardson else 1495a9de470cSBruce Richardson (*tcfg->tvar->dropped)++; 1496a9de470cSBruce Richardson 1497a9de470cSBruce Richardson /** 1498a9de470cSBruce Richardson * on first and last iteration, confirm that 1499a9de470cSBruce Richardson * average queue size was computed correctly 1500a9de470cSBruce Richardson */ 1501a9de470cSBruce Richardson if ((i == 0) || (i == tcfg->tvar->num_iterations - 1)) { 1502a9de470cSBruce Richardson double avg_after = 0; 1503a9de470cSBruce Richardson double exp_avg = 0; 1504a9de470cSBruce Richardson double diff = 0.0; 1505a9de470cSBruce Richardson int ok = 0; 1506a9de470cSBruce Richardson 1507a9de470cSBruce Richardson avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 1508a9de470cSBruce Richardson exp_avg = calc_exp_avg_on_empty(avg_before, 1509a9de470cSBruce Richardson (1 << *tcfg->tconfig->wq_log2), 1510a9de470cSBruce Richardson tcfg->tvar->wait_usec); 1511a9de470cSBruce Richardson if (check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) 1512a9de470cSBruce Richardson ok = 1; 1513a9de470cSBruce Richardson printf("%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", 1514a9de470cSBruce Richardson i, avg_before, avg_after, exp_avg, diff, 1515a9de470cSBruce Richardson (double)tcfg->tqueue->avg_tolerance, ok ? "pass" : "fail"); 1516a9de470cSBruce Richardson if (!ok) { 1517a9de470cSBruce Richardson result = FAIL; 1518a9de470cSBruce Richardson goto out; 1519a9de470cSBruce Richardson } 1520a9de470cSBruce Richardson } 1521a9de470cSBruce Richardson } 1522a9de470cSBruce Richardson total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; 1523a9de470cSBruce Richardson printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total, 1524a9de470cSBruce Richardson *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0, 1525a9de470cSBruce Richardson *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); 1526a9de470cSBruce Richardson 1527a9de470cSBruce Richardson rdtsc_prof_print(&prof); 1528a9de470cSBruce Richardson out: 1529a9de470cSBruce Richardson return result; 1530a9de470cSBruce Richardson } 1531a9de470cSBruce Richardson 1532a9de470cSBruce Richardson /** 1533a9de470cSBruce Richardson * setup default values for overflow test structures 1534a9de470cSBruce Richardson */ 1535a9de470cSBruce Richardson static uint32_t avg_max = 0; 1536a9de470cSBruce Richardson static uint32_t avg_max_bits = 0; 1537a9de470cSBruce Richardson 1538a9de470cSBruce Richardson static struct rte_red_config ovfl_wrconfig[1]; 1539a9de470cSBruce Richardson static struct rte_red ovfl_rtdata[1]; 1540a9de470cSBruce Richardson static uint8_t ovfl_maxp_inv[] = {10}; 1541a9de470cSBruce Richardson static uint32_t ovfl_qconfig[] = {0, 0, 1, 1}; 1542a9de470cSBruce Richardson static uint32_t ovfl_q[] ={0}; 1543a9de470cSBruce Richardson static uint32_t ovfl_dropped[] ={0}; 1544a9de470cSBruce Richardson static uint32_t ovfl_enqueued[] ={0}; 1545a9de470cSBruce Richardson static uint32_t ovfl_tlevel[] = {1023}; 1546a9de470cSBruce Richardson static uint8_t ovfl_wq_log2[] = {12}; 1547a9de470cSBruce Richardson 1548a9de470cSBruce Richardson static struct test_rte_red_config ovfl_tconfig = { 1549a9de470cSBruce Richardson .rconfig = ovfl_wrconfig, 1550a9de470cSBruce Richardson .num_cfg = RTE_DIM(ovfl_wrconfig), 1551a9de470cSBruce Richardson .wq_log2 = ovfl_wq_log2, 1552a9de470cSBruce Richardson .min_th = 32, 1553a9de470cSBruce Richardson .max_th = 1023, 1554a9de470cSBruce Richardson .maxp_inv = ovfl_maxp_inv, 1555a9de470cSBruce Richardson }; 1556a9de470cSBruce Richardson 1557a9de470cSBruce Richardson static struct test_queue ovfl_tqueue = { 1558a9de470cSBruce Richardson .rdata = ovfl_rtdata, 1559a9de470cSBruce Richardson .num_queues = RTE_DIM(ovfl_rtdata), 1560a9de470cSBruce Richardson .qconfig = ovfl_qconfig, 1561a9de470cSBruce Richardson .q = ovfl_q, 1562a9de470cSBruce Richardson .q_ramp_up = 1000000, 1563a9de470cSBruce Richardson .avg_ramp_up = 1000000, 1564a9de470cSBruce Richardson .avg_tolerance = 5, /* 10 percent */ 1565a9de470cSBruce Richardson .drop_tolerance = 50, /* 50 percent */ 1566a9de470cSBruce Richardson }; 1567a9de470cSBruce Richardson 1568a9de470cSBruce Richardson static struct test_var ovfl_tvar = { 1569a9de470cSBruce Richardson .wait_usec = 10000, 1570a9de470cSBruce Richardson .num_iterations = 1, 1571a9de470cSBruce Richardson .num_ops = 10000, 1572a9de470cSBruce Richardson .clk_freq = 0, 1573a9de470cSBruce Richardson .dropped = ovfl_dropped, 1574a9de470cSBruce Richardson .enqueued = ovfl_enqueued, 1575a9de470cSBruce Richardson .sleep_sec = 0 1576a9de470cSBruce Richardson }; 1577a9de470cSBruce Richardson 1578a9de470cSBruce Richardson static void ovfl_check_avg(uint32_t avg) 1579a9de470cSBruce Richardson { 1580a9de470cSBruce Richardson if (avg > avg_max) { 1581a9de470cSBruce Richardson double avg_log = 0; 1582a9de470cSBruce Richardson uint32_t bits = 0; 1583a9de470cSBruce Richardson avg_max = avg; 1584a9de470cSBruce Richardson avg_log = log(((double)avg_max)); 1585a9de470cSBruce Richardson avg_log = avg_log / log(2.0); 1586a9de470cSBruce Richardson bits = (uint32_t)ceil(avg_log); 1587a9de470cSBruce Richardson if (bits > avg_max_bits) 1588a9de470cSBruce Richardson avg_max_bits = bits; 1589a9de470cSBruce Richardson } 1590a9de470cSBruce Richardson } 1591a9de470cSBruce Richardson 1592a9de470cSBruce Richardson static struct test_config ovfl_test1_config = { 15937be78d02SJosh Soref .ifname = "queue average overflow test interface", 1594a9de470cSBruce Richardson .msg = "overflow test 1 : use one RED configuration,\n" 1595a9de470cSBruce Richardson " increase average queue size to target level,\n" 15967be78d02SJosh Soref " check maximum number of bits required to represent avg_s\n\n", 1597a9de470cSBruce Richardson .htxt = "avg queue size " 1598a9de470cSBruce Richardson "wq_log2 " 1599a9de470cSBruce Richardson "fraction bits " 1600a9de470cSBruce Richardson "max queue avg " 1601a9de470cSBruce Richardson "num bits " 1602a9de470cSBruce Richardson "enqueued " 1603a9de470cSBruce Richardson "dropped " 1604a9de470cSBruce Richardson "drop prob % " 1605a9de470cSBruce Richardson "drop rate % " 1606a9de470cSBruce Richardson "\n", 1607a9de470cSBruce Richardson .tconfig = &ovfl_tconfig, 1608a9de470cSBruce Richardson .tqueue = &ovfl_tqueue, 1609a9de470cSBruce Richardson .tvar = &ovfl_tvar, 1610a9de470cSBruce Richardson .tlevel = ovfl_tlevel, 1611a9de470cSBruce Richardson }; 1612a9de470cSBruce Richardson 1613a9de470cSBruce Richardson static enum test_result ovfl_test1(struct test_config *tcfg) 1614a9de470cSBruce Richardson { 1615a9de470cSBruce Richardson enum test_result result = PASS; 1616a9de470cSBruce Richardson uint32_t avg = 0; 1617a9de470cSBruce Richardson uint32_t i = 0; 1618a9de470cSBruce Richardson double drop_rate = 0.0; 1619a9de470cSBruce Richardson double drop_prob = 0.0; 1620a9de470cSBruce Richardson double diff = 0.0; 1621a9de470cSBruce Richardson int ret = 0; 1622a9de470cSBruce Richardson 1623a9de470cSBruce Richardson printf("%s", tcfg->msg); 1624a9de470cSBruce Richardson 1625a9de470cSBruce Richardson if (test_rte_red_init(tcfg) != PASS) { 1626a9de470cSBruce Richardson 1627a9de470cSBruce Richardson result = FAIL; 1628a9de470cSBruce Richardson goto out; 1629a9de470cSBruce Richardson } 1630a9de470cSBruce Richardson 1631a9de470cSBruce Richardson /** 1632a9de470cSBruce Richardson * reset rte_red run-time data 1633a9de470cSBruce Richardson */ 1634a9de470cSBruce Richardson rte_red_rt_data_init(tcfg->tqueue->rdata); 1635a9de470cSBruce Richardson 1636a9de470cSBruce Richardson /** 1637a9de470cSBruce Richardson * increase actual queue size 1638a9de470cSBruce Richardson */ 1639a9de470cSBruce Richardson for (i = 0; i < tcfg->tqueue->q_ramp_up; i++) { 1640a9de470cSBruce Richardson ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, 1641a9de470cSBruce Richardson *tcfg->tqueue->q, get_port_ts()); 1642a9de470cSBruce Richardson 1643a9de470cSBruce Richardson if (ret == 0) { 1644a9de470cSBruce Richardson if (++(*tcfg->tqueue->q) >= *tcfg->tlevel) 1645a9de470cSBruce Richardson break; 1646a9de470cSBruce Richardson } 1647a9de470cSBruce Richardson } 1648a9de470cSBruce Richardson 1649a9de470cSBruce Richardson /** 1650a9de470cSBruce Richardson * enqueue 1651a9de470cSBruce Richardson */ 1652a9de470cSBruce Richardson for (i = 0; i < tcfg->tqueue->avg_ramp_up; i++) { 1653a9de470cSBruce Richardson ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, 1654a9de470cSBruce Richardson *tcfg->tqueue->q, get_port_ts()); 1655a9de470cSBruce Richardson ovfl_check_avg((*tcfg->tqueue->rdata).avg); 1656a9de470cSBruce Richardson avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 1657a9de470cSBruce Richardson if (avg == *tcfg->tlevel) { 1658a9de470cSBruce Richardson if (ret == 0) 1659a9de470cSBruce Richardson (*tcfg->tvar->enqueued)++; 1660a9de470cSBruce Richardson else 1661a9de470cSBruce Richardson (*tcfg->tvar->dropped)++; 1662a9de470cSBruce Richardson } 1663a9de470cSBruce Richardson } 1664a9de470cSBruce Richardson 1665a9de470cSBruce Richardson /** 1666a9de470cSBruce Richardson * check if target average queue size has been reached 1667a9de470cSBruce Richardson */ 1668a9de470cSBruce Richardson avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); 1669a9de470cSBruce Richardson if (avg != *tcfg->tlevel) { 1670a9de470cSBruce Richardson result = FAIL; 1671a9de470cSBruce Richardson goto out; 1672a9de470cSBruce Richardson } 1673a9de470cSBruce Richardson 1674a9de470cSBruce Richardson /** 1675a9de470cSBruce Richardson * check drop rate against drop probability 1676a9de470cSBruce Richardson */ 1677a9de470cSBruce Richardson drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); 1678a9de470cSBruce Richardson drop_prob = calc_drop_prob(tcfg->tconfig->min_th, 1679a9de470cSBruce Richardson tcfg->tconfig->max_th, 1680a9de470cSBruce Richardson *tcfg->tconfig->maxp_inv, 1681a9de470cSBruce Richardson *tcfg->tlevel); 1682a9de470cSBruce Richardson if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) 1683a9de470cSBruce Richardson result = FAIL; 1684a9de470cSBruce Richardson 1685a9de470cSBruce Richardson printf("%s", tcfg->htxt); 1686a9de470cSBruce Richardson 1687a9de470cSBruce Richardson printf("%-16u%-9u%-15u0x%08x %-10u%-10u%-10u%-13.2lf%-13.2lf\n", 1688a9de470cSBruce Richardson avg, *tcfg->tconfig->wq_log2, RTE_RED_SCALING, 1689a9de470cSBruce Richardson avg_max, avg_max_bits, 1690a9de470cSBruce Richardson *tcfg->tvar->enqueued, *tcfg->tvar->dropped, 1691a9de470cSBruce Richardson drop_prob * 100.0, drop_rate * 100.0); 1692a9de470cSBruce Richardson out: 1693a9de470cSBruce Richardson return result; 1694a9de470cSBruce Richardson } 1695a9de470cSBruce Richardson 1696a9de470cSBruce Richardson /** 1697a9de470cSBruce Richardson * define the functional and performance tests to be executed 1698a9de470cSBruce Richardson */ 1699a9de470cSBruce Richardson struct tests func_tests[] = { 1700a9de470cSBruce Richardson { &func_test1_config, func_test1 }, 1701a9de470cSBruce Richardson { &func_test2_config, func_test2 }, 1702a9de470cSBruce Richardson { &func_test3_config, func_test3 }, 1703a9de470cSBruce Richardson { &func_test4_config, func_test4 }, 1704a9de470cSBruce Richardson { &func_test5_config, func_test5 }, 1705a9de470cSBruce Richardson { &func_test6_config, func_test6 }, 1706a9de470cSBruce Richardson { &ovfl_test1_config, ovfl_test1 }, 1707a9de470cSBruce Richardson }; 1708a9de470cSBruce Richardson 1709a9de470cSBruce Richardson struct tests func_tests_quick[] = { 1710a9de470cSBruce Richardson { &func_test1_config, func_test1 }, 1711a9de470cSBruce Richardson { &func_test2_config, func_test2 }, 1712a9de470cSBruce Richardson { &func_test3_config, func_test3 }, 1713a9de470cSBruce Richardson /* no test 4 as it takes a lot of time */ 1714a9de470cSBruce Richardson { &func_test5_config, func_test5 }, 1715a9de470cSBruce Richardson { &func_test6_config, func_test6 }, 1716a9de470cSBruce Richardson { &ovfl_test1_config, ovfl_test1 }, 1717a9de470cSBruce Richardson }; 1718a9de470cSBruce Richardson 1719a9de470cSBruce Richardson struct tests perf_tests[] = { 1720a9de470cSBruce Richardson { &perf1_test1_config, perf1_test }, 1721a9de470cSBruce Richardson { &perf1_test2_config, perf1_test }, 1722a9de470cSBruce Richardson { &perf1_test3_config, perf1_test }, 1723a9de470cSBruce Richardson { &perf2_test4_config, perf2_test }, 1724a9de470cSBruce Richardson { &perf2_test5_config, perf2_test }, 1725a9de470cSBruce Richardson { &perf2_test6_config, perf2_test }, 1726a9de470cSBruce Richardson }; 1727a9de470cSBruce Richardson 1728a9de470cSBruce Richardson /** 1729a9de470cSBruce Richardson * function to execute the required_red tests 1730a9de470cSBruce Richardson */ 1731a9de470cSBruce Richardson static void run_tests(struct tests *test_type, uint32_t test_count, uint32_t *num_tests, uint32_t *num_pass) 1732a9de470cSBruce Richardson { 1733a9de470cSBruce Richardson enum test_result result = PASS; 1734a9de470cSBruce Richardson uint32_t i = 0; 1735a9de470cSBruce Richardson 1736a9de470cSBruce Richardson for (i = 0; i < test_count; i++) { 1737a9de470cSBruce Richardson printf("\n--------------------------------------------------------------------------------\n"); 1738a9de470cSBruce Richardson result = test_type[i].testfn(test_type[i].testcfg); 1739a9de470cSBruce Richardson (*num_tests)++; 1740a9de470cSBruce Richardson if (result == PASS) { 1741a9de470cSBruce Richardson (*num_pass)++; 1742a9de470cSBruce Richardson printf("-------------------------------------<pass>-------------------------------------\n"); 1743a9de470cSBruce Richardson } else { 1744a9de470cSBruce Richardson printf("-------------------------------------<fail>-------------------------------------\n"); 1745a9de470cSBruce Richardson } 1746a9de470cSBruce Richardson } 1747a9de470cSBruce Richardson return; 1748a9de470cSBruce Richardson } 1749a9de470cSBruce Richardson 1750a9de470cSBruce Richardson /** 1751a9de470cSBruce Richardson * check if functions accept invalid parameters 1752a9de470cSBruce Richardson * 1753a9de470cSBruce Richardson * First, all functions will be called without initialized RED 1754a9de470cSBruce Richardson * Then, all of them will be called with NULL/invalid parameters 1755a9de470cSBruce Richardson * 1756a9de470cSBruce Richardson * Some functions are not tested as they are performance-critical and thus 1757a9de470cSBruce Richardson * don't do any parameter checking. 1758a9de470cSBruce Richardson */ 1759a9de470cSBruce Richardson static int 1760a9de470cSBruce Richardson test_invalid_parameters(void) 1761a9de470cSBruce Richardson { 1762a9de470cSBruce Richardson struct rte_red_config config; 1763a9de470cSBruce Richardson 1764a9de470cSBruce Richardson if (rte_red_rt_data_init(NULL) == 0) { 1765a9de470cSBruce Richardson printf("rte_red_rt_data_init should have failed!\n"); 1766a9de470cSBruce Richardson return -1; 1767a9de470cSBruce Richardson } 1768a9de470cSBruce Richardson 1769a9de470cSBruce Richardson if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) { 1770a9de470cSBruce Richardson printf("rte_red_config_init should have failed!\n"); 1771a9de470cSBruce Richardson return -1; 1772a9de470cSBruce Richardson } 1773a9de470cSBruce Richardson 1774a9de470cSBruce Richardson if (rte_red_rt_data_init(NULL) == 0) { 1775a9de470cSBruce Richardson printf("rte_red_rt_data_init should have failed!\n"); 1776a9de470cSBruce Richardson return -1; 1777a9de470cSBruce Richardson } 1778a9de470cSBruce Richardson 1779a9de470cSBruce Richardson /* NULL config */ 1780a9de470cSBruce Richardson if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) { 1781a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1782a9de470cSBruce Richardson return -1; 1783a9de470cSBruce Richardson } 17847be78d02SJosh Soref /* min_threshold == max_threshold */ 1785a9de470cSBruce Richardson if (rte_red_config_init(&config, 0, 1, 1, 0) == 0) { 1786a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1787a9de470cSBruce Richardson return -1; 1788a9de470cSBruce Richardson } 17897be78d02SJosh Soref /* min_threshold > max_threshold */ 1790a9de470cSBruce Richardson if (rte_red_config_init(&config, 0, 2, 1, 0) == 0) { 1791a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1792a9de470cSBruce Richardson return -1; 1793a9de470cSBruce Richardson } 1794a9de470cSBruce Richardson /* wq_log2 > RTE_RED_WQ_LOG2_MAX */ 1795a9de470cSBruce Richardson if (rte_red_config_init(&config, 1796a9de470cSBruce Richardson RTE_RED_WQ_LOG2_MAX + 1, 1, 2, 0) == 0) { 1797a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1798a9de470cSBruce Richardson return -1; 1799a9de470cSBruce Richardson } 1800a9de470cSBruce Richardson /* wq_log2 < RTE_RED_WQ_LOG2_MIN */ 1801a9de470cSBruce Richardson if (rte_red_config_init(&config, 1802a9de470cSBruce Richardson RTE_RED_WQ_LOG2_MIN - 1, 1, 2, 0) == 0) { 1803a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1804a9de470cSBruce Richardson return -1; 1805a9de470cSBruce Richardson } 1806a9de470cSBruce Richardson /* maxp_inv > RTE_RED_MAXP_INV_MAX */ 1807a9de470cSBruce Richardson if (rte_red_config_init(&config, 1808a9de470cSBruce Richardson RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MAX + 1) == 0) { 1809a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1810a9de470cSBruce Richardson return -1; 1811a9de470cSBruce Richardson } 1812a9de470cSBruce Richardson /* maxp_inv < RTE_RED_MAXP_INV_MIN */ 1813a9de470cSBruce Richardson if (rte_red_config_init(&config, 1814a9de470cSBruce Richardson RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MIN - 1) == 0) { 1815a9de470cSBruce Richardson printf("%i: rte_red_config_init should have failed!\n", __LINE__); 1816a9de470cSBruce Richardson return -1; 1817a9de470cSBruce Richardson } 1818a9de470cSBruce Richardson 1819a9de470cSBruce Richardson return 0; 1820a9de470cSBruce Richardson } 1821a9de470cSBruce Richardson 1822a9de470cSBruce Richardson static void 1823a9de470cSBruce Richardson show_stats(const uint32_t num_tests, const uint32_t num_pass) 1824a9de470cSBruce Richardson { 1825a9de470cSBruce Richardson if (num_pass == num_tests) 1826a9de470cSBruce Richardson printf("[total: %u, pass: %u]\n", num_tests, num_pass); 1827a9de470cSBruce Richardson else 1828a9de470cSBruce Richardson printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass, 1829a9de470cSBruce Richardson num_tests - num_pass); 1830a9de470cSBruce Richardson } 1831a9de470cSBruce Richardson 1832a9de470cSBruce Richardson static int 1833a9de470cSBruce Richardson tell_the_result(const uint32_t num_tests, const uint32_t num_pass) 1834a9de470cSBruce Richardson { 1835a9de470cSBruce Richardson return (num_pass == num_tests) ? 0 : 1; 1836a9de470cSBruce Richardson } 1837a9de470cSBruce Richardson 1838a9de470cSBruce Richardson static int 1839a9de470cSBruce Richardson test_red(void) 1840a9de470cSBruce Richardson { 1841a9de470cSBruce Richardson uint32_t num_tests = 0; 1842a9de470cSBruce Richardson uint32_t num_pass = 0; 1843a9de470cSBruce Richardson 1844a9de470cSBruce Richardson if (test_invalid_parameters() < 0) 1845a9de470cSBruce Richardson return -1; 1846a9de470cSBruce Richardson run_tests(func_tests_quick, RTE_DIM(func_tests_quick), 1847a9de470cSBruce Richardson &num_tests, &num_pass); 1848a9de470cSBruce Richardson show_stats(num_tests, num_pass); 1849a9de470cSBruce Richardson return tell_the_result(num_tests, num_pass); 1850a9de470cSBruce Richardson } 1851a9de470cSBruce Richardson 1852a9de470cSBruce Richardson static int 1853a9de470cSBruce Richardson test_red_perf(void) 1854a9de470cSBruce Richardson { 1855a9de470cSBruce Richardson uint32_t num_tests = 0; 1856a9de470cSBruce Richardson uint32_t num_pass = 0; 1857a9de470cSBruce Richardson 1858a9de470cSBruce Richardson run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass); 1859a9de470cSBruce Richardson show_stats(num_tests, num_pass); 1860a9de470cSBruce Richardson return tell_the_result(num_tests, num_pass); 1861a9de470cSBruce Richardson } 1862a9de470cSBruce Richardson 1863a9de470cSBruce Richardson static int 1864a9de470cSBruce Richardson test_red_all(void) 1865a9de470cSBruce Richardson { 1866a9de470cSBruce Richardson uint32_t num_tests = 0; 1867a9de470cSBruce Richardson uint32_t num_pass = 0; 1868a9de470cSBruce Richardson 1869a9de470cSBruce Richardson if (test_invalid_parameters() < 0) 1870a9de470cSBruce Richardson return -1; 1871a9de470cSBruce Richardson 1872a9de470cSBruce Richardson run_tests(func_tests, RTE_DIM(func_tests), &num_tests, &num_pass); 1873a9de470cSBruce Richardson run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass); 1874a9de470cSBruce Richardson show_stats(num_tests, num_pass); 1875a9de470cSBruce Richardson return tell_the_result(num_tests, num_pass); 1876a9de470cSBruce Richardson } 1877a9de470cSBruce Richardson 18783c60274cSJie Zhou #endif /* !RTE_EXEC_ENV_WINDOWS */ 18793c60274cSJie Zhou 1880a9de470cSBruce Richardson REGISTER_TEST_COMMAND(red_autotest, test_red); 1881e0a8442cSBruce Richardson REGISTER_PERF_TEST(red_perf, test_red_perf); 1882e0a8442cSBruce Richardson REGISTER_PERF_TEST(red_all, test_red_all); 1883