1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include "test.h" 6 7 #ifdef RTE_EXEC_ENV_WINDOWS 8 9 static int 10 test_pie(void) 11 { 12 printf("pie not supported on Windows, skipping test\n"); 13 return TEST_SKIPPED; 14 } 15 16 static int 17 test_pie_perf(void) 18 { 19 printf("pie_perf not supported on Windows, skipping test\n"); 20 return TEST_SKIPPED; 21 } 22 23 static int 24 test_pie_all(void) 25 { 26 printf("pie_all not supported on Windows, skipping test\n"); 27 return TEST_SKIPPED; 28 } 29 30 #else 31 32 #include <stdlib.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <stdint.h> 36 #include <unistd.h> 37 #include <inttypes.h> 38 #include <sys/time.h> 39 #include <time.h> 40 #include <math.h> 41 42 #include <rte_pie.h> 43 44 #ifdef __INTEL_COMPILER 45 #pragma warning(disable:2259) /* conversion may lose significant bits */ 46 #pragma warning(disable:181) /* Arg incompatible with format string */ 47 #endif 48 49 /**< structures for testing rte_pie performance and function */ 50 struct test_rte_pie_config { /**< Test structure for RTE_PIE config */ 51 struct rte_pie_config *pconfig; /**< RTE_PIE configuration parameters */ 52 uint8_t num_cfg; /**< Number of RTE_PIE configs to test */ 53 uint16_t qdelay_ref; /**< Latency Target (milliseconds) */ 54 uint16_t *dp_update_interval; /**< Update interval for drop probability 55 * (milliseconds) 56 */ 57 uint16_t *max_burst; /**< Max Burst Allowance (milliseconds) */ 58 uint16_t tailq_th; /**< Tailq drop threshold (packet counts) */ 59 }; 60 61 struct test_queue { /**< Test structure for RTE_PIE Queues */ 62 struct rte_pie *pdata_in; /**< RTE_PIE runtime data input */ 63 struct rte_pie *pdata_out; /**< RTE_PIE runtime data output*/ 64 uint32_t num_queues; /**< Number of RTE_PIE queues to test */ 65 uint32_t *qlen; /**< Queue size */ 66 uint32_t q_ramp_up; /**< Num of enqueues to ramp up the queue */ 67 double drop_tolerance; /**< Drop tolerance of packets not enqueued */ 68 }; 69 70 struct test_var { /**< Test variables used for testing RTE_PIE */ 71 uint32_t num_iterations; /**< Number of test iterations */ 72 uint32_t num_ops; /**< Number of test operations */ 73 uint64_t clk_freq; /**< CPU clock frequency */ 74 uint32_t *dropped; /**< Test operations dropped */ 75 uint32_t *enqueued; /**< Test operations enqueued */ 76 uint32_t *dequeued; /**< Test operations dequeued */ 77 }; 78 79 struct test_config { /**< Primary test structure for RTE_PIE */ 80 const char *ifname; /**< Interface name */ 81 const char *msg; /**< Test message for display */ 82 const char *htxt; /**< Header txt display for result output */ 83 struct test_rte_pie_config *tconfig; /**< Test structure for RTE_PIE config */ 84 struct test_queue *tqueue; /**< Test structure for RTE_PIE Queues */ 85 struct test_var *tvar; /**< Test variables used for testing RTE_PIE */ 86 uint32_t *tlevel; /**< Queue levels */ 87 }; 88 89 enum test_result { 90 FAIL = 0, 91 PASS 92 }; 93 94 /**< Test structure to define tests to run */ 95 struct tests { 96 struct test_config *testcfg; 97 enum test_result (*testfn)(struct test_config *cfg); 98 }; 99 100 struct rdtsc_prof { 101 uint64_t clk_start; 102 uint64_t clk_min; /**< min clocks */ 103 uint64_t clk_max; /**< max clocks */ 104 uint64_t clk_avgc; /**< count to calc average */ 105 double clk_avg; /**< cumulative sum to calc average */ 106 const char *name; 107 }; 108 109 static const uint64_t port_speed_bytes = (10ULL*1000ULL*1000ULL*1000ULL)/8ULL; 110 static double inv_cycles_per_byte; 111 112 static void init_port_ts(uint64_t cpu_clock) 113 { 114 double cycles_per_byte = (double)(cpu_clock) / (double)(port_speed_bytes); 115 inv_cycles_per_byte = 1.0 / cycles_per_byte; 116 } 117 118 static uint64_t get_port_ts(void) 119 { 120 return (uint64_t)((double)rte_rdtsc() * inv_cycles_per_byte); 121 } 122 123 static void rdtsc_prof_init(struct rdtsc_prof *p, const char *name) 124 { 125 p->clk_min = (uint64_t)(-1LL); 126 p->clk_max = 0; 127 p->clk_avg = 0; 128 p->clk_avgc = 0; 129 p->name = name; 130 } 131 132 static inline void rdtsc_prof_start(struct rdtsc_prof *p) 133 { 134 p->clk_start = rte_rdtsc_precise(); 135 } 136 137 static inline void rdtsc_prof_end(struct rdtsc_prof *p) 138 { 139 uint64_t clk_start = rte_rdtsc() - p->clk_start; 140 141 p->clk_avgc++; 142 p->clk_avg += (double) clk_start; 143 144 if (clk_start > p->clk_max) 145 p->clk_max = clk_start; 146 if (clk_start < p->clk_min) 147 p->clk_min = clk_start; 148 } 149 150 static void rdtsc_prof_print(struct rdtsc_prof *p) 151 { 152 if (p->clk_avgc > 0) { 153 printf("RDTSC stats for %s: n=%" PRIu64 ", min=%" PRIu64 154 ",max=%" PRIu64 ", avg=%.1f\n", 155 p->name, 156 p->clk_avgc, 157 p->clk_min, 158 p->clk_max, 159 (p->clk_avg / ((double) p->clk_avgc))); 160 } 161 } 162 163 static uint16_t rte_pie_get_active(const struct rte_pie_config *pie_cfg, 164 struct rte_pie *pie) 165 { 166 /**< Flag for activating/deactivating pie */ 167 RTE_SET_USED(pie_cfg); 168 return pie->active; 169 } 170 171 static void rte_pie_set_active(const struct rte_pie_config *pie_cfg, 172 struct rte_pie *pie, 173 uint16_t active) 174 { 175 /**< Flag for activating/deactivating pie */ 176 RTE_SET_USED(pie_cfg); 177 pie->active = active; 178 } 179 180 /** 181 * Read the drop probability 182 */ 183 static double rte_pie_get_drop_prob(const struct rte_pie_config *pie_cfg, 184 struct rte_pie *pie) 185 { 186 /**< Current packet drop probability */ 187 RTE_SET_USED(pie_cfg); 188 return pie->drop_prob; 189 } 190 191 static double rte_pie_get_avg_dq_time(const struct rte_pie_config *pie_cfg, 192 struct rte_pie *pie) 193 { 194 /**< Current packet drop probability */ 195 RTE_SET_USED(pie_cfg); 196 return pie->avg_dq_time; 197 } 198 199 static double calc_drop_rate(uint32_t enqueued, uint32_t dropped) 200 { 201 return (double)dropped / ((double)enqueued + (double)dropped); 202 } 203 204 /** 205 * check if drop rate matches drop probability within tolerance 206 */ 207 static int check_drop_rate(double *diff, double drop_rate, double drop_prob, 208 double tolerance) 209 { 210 double abs_diff = 0.0; 211 int ret = 1; 212 213 abs_diff = fabs(drop_rate - drop_prob); 214 if ((int)abs_diff == 0) { 215 *diff = 0.0; 216 } else { 217 *diff = (abs_diff / drop_prob) * 100.0; 218 if (*diff > tolerance) 219 ret = 0; 220 } 221 return ret; 222 } 223 224 /** 225 * initialize the test rte_pie config 226 */ 227 static enum test_result 228 test_rte_pie_init(struct test_config *tcfg) 229 { 230 unsigned int i = 0; 231 232 tcfg->tvar->clk_freq = rte_get_timer_hz(); 233 init_port_ts(tcfg->tvar->clk_freq); 234 235 for (i = 0; i < tcfg->tconfig->num_cfg; i++) { 236 if (rte_pie_config_init(&tcfg->tconfig->pconfig[i], 237 (uint16_t)tcfg->tconfig->qdelay_ref, 238 (uint16_t)tcfg->tconfig->dp_update_interval[i], 239 (uint16_t)tcfg->tconfig->max_burst[i], 240 (uint16_t)tcfg->tconfig->tailq_th) != 0) { 241 return FAIL; 242 } 243 } 244 245 *tcfg->tqueue->qlen = 0; 246 *tcfg->tvar->dropped = 0; 247 *tcfg->tvar->enqueued = 0; 248 249 return PASS; 250 } 251 252 /** 253 * enqueue until actual queue size reaches target level 254 */ 255 static int 256 increase_qsize(struct rte_pie_config *pie_cfg, 257 struct rte_pie *pie, 258 uint32_t *qlen, 259 uint32_t pkt_len, 260 uint32_t attempts) 261 { 262 uint32_t i = 0; 263 264 for (i = 0; i < attempts; i++) { 265 int ret = 0; 266 267 /** 268 * enqueue 269 */ 270 ret = rte_pie_enqueue(pie_cfg, pie, *qlen, pkt_len, get_port_ts()); 271 /** 272 * check if target actual queue size has been reached 273 */ 274 if (ret == 0) 275 return 0; 276 } 277 /** 278 * no success 279 */ 280 return -1; 281 } 282 283 /** 284 * functional test enqueue/dequeue packets 285 */ 286 static void 287 enqueue_dequeue_func(struct rte_pie_config *pie_cfg, 288 struct rte_pie *pie, 289 uint32_t *qlen, 290 uint32_t num_ops, 291 uint32_t *enqueued, 292 uint32_t *dropped) 293 { 294 uint32_t i = 0; 295 296 for (i = 0; i < num_ops; i++) { 297 int ret = 0; 298 299 /** 300 * enqueue 301 */ 302 ret = rte_pie_enqueue(pie_cfg, pie, *qlen, sizeof(uint32_t), 303 get_port_ts()); 304 if (ret == 0) 305 (*enqueued)++; 306 else 307 (*dropped)++; 308 } 309 } 310 311 /** 312 * setup default values for the Functional test structures 313 */ 314 static struct rte_pie_config ft_wpconfig[1]; 315 static struct rte_pie ft_rtdata[1]; 316 static uint32_t ft_q[] = {0}; 317 static uint32_t ft_dropped[] = {0}; 318 static uint32_t ft_enqueued[] = {0}; 319 static uint16_t ft_max_burst[] = {64}; 320 static uint16_t ft_dp_update_interval[] = {150}; 321 322 static struct test_rte_pie_config ft_tconfig = { 323 .pconfig = ft_wpconfig, 324 .num_cfg = RTE_DIM(ft_wpconfig), 325 .qdelay_ref = 15, 326 .dp_update_interval = ft_dp_update_interval, 327 .max_burst = ft_max_burst, 328 .tailq_th = 15, 329 }; 330 331 static struct test_queue ft_tqueue = { 332 .pdata_in = ft_rtdata, 333 .num_queues = RTE_DIM(ft_rtdata), 334 .qlen = ft_q, 335 .q_ramp_up = 10, 336 .drop_tolerance = 0, 337 }; 338 339 static struct test_var ft_tvar = { 340 .num_iterations = 0, 341 .num_ops = 10000, 342 .clk_freq = 0, 343 .dropped = ft_dropped, 344 .enqueued = ft_enqueued, 345 }; 346 347 /** 348 * Test F1: functional test 1 349 */ 350 static uint32_t ft_tlevels[] = {6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 351 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144}; 352 353 static struct test_config func_test_config1 = { 354 .ifname = "functional test interface", 355 .msg = "functional test : use one pie configuration\n\n", 356 .htxt = " " 357 "drop probability " 358 "enqueued " 359 "dropped " 360 "drop prob % " 361 "drop rate % " 362 "diff % " 363 "tolerance % " 364 "active " 365 "\n", 366 .tconfig = &ft_tconfig, 367 .tqueue = &ft_tqueue, 368 .tvar = &ft_tvar, 369 .tlevel = ft_tlevels, 370 }; 371 372 static enum test_result func_test1(struct test_config *tcfg) 373 { 374 enum test_result result = PASS; 375 uint32_t i = 0; 376 377 printf("%s", tcfg->msg); 378 379 if (test_rte_pie_init(tcfg) != PASS) { 380 result = FAIL; 381 goto out; 382 } 383 384 printf("%s", tcfg->htxt); 385 386 /** 387 * reset rte_pie run-time data 388 */ 389 rte_pie_rt_data_init(tcfg->tqueue->pdata_in); 390 rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1); 391 *tcfg->tvar->enqueued = 0; 392 *tcfg->tvar->dropped = 0; 393 394 if (increase_qsize(&tcfg->tconfig->pconfig[i], 395 tcfg->tqueue->pdata_in, 396 tcfg->tqueue->qlen, 397 tcfg->tlevel[i], 398 tcfg->tqueue->q_ramp_up) != 0) { 399 fprintf(stderr, "Fail: increase qsize\n"); 400 result = FAIL; 401 goto out; 402 } 403 404 for (i = 0; i < RTE_DIM(ft_tlevels); i++) { 405 const char *label = NULL; 406 uint16_t prob = 0; 407 uint16_t active = 0; 408 double drop_rate = 1.0; 409 double drop_prob = 0.0; 410 double diff = 0.0; 411 412 enqueue_dequeue_func(&tcfg->tconfig->pconfig[i], 413 tcfg->tqueue->pdata_in, 414 tcfg->tqueue->qlen, 415 tcfg->tvar->num_ops, 416 tcfg->tvar->enqueued, 417 tcfg->tvar->dropped); 418 419 drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, 420 *tcfg->tvar->dropped); 421 drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in); 422 423 if (drop_prob != 0) { 424 fprintf(stderr, "Fail: check drop prob\n"); 425 result = FAIL; 426 } 427 428 if (drop_rate != 0) { 429 fprintf(stderr, "Fail: check drop rate\n"); 430 result = FAIL; 431 } 432 433 label = "Summary "; 434 active = rte_pie_get_active(NULL, tcfg->tqueue->pdata_in); 435 printf("%s%-16u%-12u%-12u%-12.4lf%-12.4lf%-12.4lf%-12.4lf%-8i\n", 436 label, prob, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, 437 drop_prob * 100.0, drop_rate * 100.0, diff, 438 (double)tcfg->tqueue->drop_tolerance, active); 439 } 440 out: 441 return result; 442 } 443 444 /** 445 * Test F2: functional test 2 446 */ 447 static uint32_t ft2_tlevel[] = {127}; 448 static uint16_t ft2_max_burst[] = {1, 2, 8, 16, 32, 64, 128, 256, 512, 1024}; 449 static uint16_t ft2_dp_update_interval[] = { 450 10, 20, 50, 150, 300, 600, 900, 1200, 1500, 3000}; 451 static struct rte_pie_config ft2_pconfig[10]; 452 453 static struct test_rte_pie_config ft2_tconfig = { 454 .pconfig = ft2_pconfig, 455 .num_cfg = RTE_DIM(ft2_pconfig), 456 .qdelay_ref = 15, 457 .dp_update_interval = ft2_dp_update_interval, 458 .max_burst = ft2_max_burst, 459 .tailq_th = 15, 460 }; 461 462 static struct test_config func_test_config2 = { 463 .ifname = "functional test 2 interface", 464 .msg = "functional test 2 : use several PIE configurations,\n" 465 " compare drop rate to drop probability\n\n", 466 .htxt = "PIE config " 467 "avg queue size " 468 "enqueued " 469 "dropped " 470 "drop prob % " 471 "drop rate % " 472 "diff % " 473 "tolerance % " 474 "\n", 475 .tconfig = &ft2_tconfig, 476 .tqueue = &ft_tqueue, 477 .tvar = &ft_tvar, 478 .tlevel = ft2_tlevel, 479 }; 480 481 static enum test_result func_test2(struct test_config *tcfg) 482 { 483 enum test_result result = PASS; 484 uint32_t i = 0; 485 486 printf("%s", tcfg->msg); 487 488 printf("%s", tcfg->htxt); 489 490 for (i = 0; i < tcfg->tconfig->num_cfg; i++) { 491 uint32_t avg = 0; 492 double drop_rate = 0.0; 493 double drop_prob = 0.0; 494 double diff = 0.0; 495 496 if (test_rte_pie_init(tcfg) != PASS) { 497 result = FAIL; 498 goto out; 499 } 500 501 rte_pie_rt_data_init(tcfg->tqueue->pdata_in); 502 rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1); 503 *tcfg->tvar->enqueued = 0; 504 *tcfg->tvar->dropped = 0; 505 506 if (increase_qsize(&tcfg->tconfig->pconfig[i], 507 tcfg->tqueue->pdata_in, 508 tcfg->tqueue->qlen, 509 *tcfg->tlevel, 510 tcfg->tqueue->q_ramp_up) != 0) { 511 result = FAIL; 512 goto out; 513 } 514 515 enqueue_dequeue_func(&tcfg->tconfig->pconfig[i], 516 tcfg->tqueue->pdata_in, 517 tcfg->tqueue->qlen, 518 tcfg->tvar->num_ops, 519 tcfg->tvar->enqueued, 520 tcfg->tvar->dropped); 521 522 avg = rte_pie_get_avg_dq_time(NULL, tcfg->tqueue->pdata_in); 523 524 drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, 525 *tcfg->tvar->dropped); 526 drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in); 527 528 if (!check_drop_rate(&diff, drop_rate, drop_prob, 529 (double)tcfg->tqueue->drop_tolerance)) { 530 fprintf(stderr, "Fail: drop rate outside tolerance\n"); 531 result = FAIL; 532 } 533 534 printf("%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", 535 i, avg, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, 536 drop_prob * 100.0, drop_rate * 100.0, diff, 537 (double)tcfg->tqueue->drop_tolerance); 538 } 539 out: 540 return result; 541 } 542 543 static uint32_t ft3_qlen[] = {100}; 544 545 static struct test_rte_pie_config ft3_tconfig = { 546 .pconfig = ft_wpconfig, 547 .num_cfg = RTE_DIM(ft_wpconfig), 548 .qdelay_ref = 15, 549 .dp_update_interval = ft_dp_update_interval, 550 .max_burst = ft_max_burst, 551 .tailq_th = 15, 552 }; 553 554 static struct test_queue ft3_tqueue = { 555 .pdata_in = ft_rtdata, 556 .num_queues = RTE_DIM(ft_rtdata), 557 .qlen = ft3_qlen, 558 .q_ramp_up = 10, 559 .drop_tolerance = 0, 560 }; 561 562 static struct test_var ft3_tvar = { 563 .num_iterations = 0, 564 .num_ops = 10000, 565 .clk_freq = 0, 566 .dropped = ft_dropped, 567 .enqueued = ft_enqueued, 568 }; 569 570 /** 571 * Test F3: functional test 3 572 */ 573 static uint32_t ft3_tlevels[] = {64, 127, 222}; 574 575 static struct test_config func_test_config3 = { 576 .ifname = "functional test interface", 577 .msg = "functional test 2 : use one pie configuration\n" 578 "using non zero qlen\n\n", 579 .htxt = " " 580 "drop probability " 581 "enqueued " 582 "dropped " 583 "drop prob % " 584 "drop rate % " 585 "diff % " 586 "tolerance % " 587 "active " 588 "\n", 589 .tconfig = &ft3_tconfig, 590 .tqueue = &ft3_tqueue, 591 .tvar = &ft3_tvar, 592 .tlevel = ft3_tlevels, 593 }; 594 595 static enum test_result func_test3(struct test_config *tcfg) 596 { 597 enum test_result result = PASS; 598 uint32_t i = 0; 599 600 printf("%s", tcfg->msg); 601 602 if (test_rte_pie_init(tcfg) != PASS) { 603 result = FAIL; 604 goto out; 605 } 606 607 printf("%s", tcfg->htxt); 608 609 /** 610 * reset rte_pie run-time data 611 */ 612 rte_pie_rt_data_init(tcfg->tqueue->pdata_in); 613 rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1); 614 *tcfg->tvar->enqueued = 0; 615 *tcfg->tvar->dropped = 0; 616 617 if (increase_qsize(&tcfg->tconfig->pconfig[i], 618 tcfg->tqueue->pdata_in, 619 tcfg->tqueue->qlen, 620 tcfg->tlevel[i], 621 tcfg->tqueue->q_ramp_up) != 0) { 622 fprintf(stderr, "Fail: increase qsize\n"); 623 result = FAIL; 624 goto out; 625 } 626 627 for (i = 0; i < RTE_DIM(ft_tlevels); i++) { 628 const char *label = NULL; 629 uint16_t prob = 0; 630 uint16_t active = 0; 631 double drop_rate = 1.0; 632 double drop_prob = 0.0; 633 double diff = 0.0; 634 635 enqueue_dequeue_func(&tcfg->tconfig->pconfig[i], 636 tcfg->tqueue->pdata_in, 637 tcfg->tqueue->qlen, 638 tcfg->tvar->num_ops, 639 tcfg->tvar->enqueued, 640 tcfg->tvar->dropped); 641 642 drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, 643 *tcfg->tvar->dropped); 644 drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in); 645 646 if (drop_prob != 0) { 647 fprintf(stderr, "Fail: check drop prob\n"); 648 result = FAIL; 649 } 650 651 if (drop_rate != 0) { 652 fprintf(stderr, "Fail: check drop rate\n"); 653 result = FAIL; 654 } 655 656 label = "Summary "; 657 active = rte_pie_get_active(NULL, tcfg->tqueue->pdata_in); 658 printf("%s%-16u%-12u%-12u%-12.4lf%-12.4lf%-12.4lf%-12.4lf%-8i\n", 659 label, prob, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, 660 drop_prob * 100.0, drop_rate * 100.0, diff, 661 (double)tcfg->tqueue->drop_tolerance, active); 662 } 663 out: 664 return result; 665 } 666 667 /** 668 * setup default values for the Performance test structures 669 */ 670 static struct rte_pie_config pt_wrconfig[1]; 671 static struct rte_pie pt_rtdata[1]; 672 static struct rte_pie pt_wtdata[1]; 673 static uint32_t pt_q[] = {0}; 674 static uint32_t pt_dropped[] = {0}; 675 static uint32_t pt_enqueued[] = {0}; 676 static uint32_t pt_dequeued[] = {0}; 677 static uint16_t pt_max_burst[] = {64}; 678 static uint16_t pt_dp_update_interval[] = {150}; 679 680 static struct test_rte_pie_config pt_tconfig = { 681 .pconfig = pt_wrconfig, 682 .num_cfg = RTE_DIM(pt_wrconfig), 683 .qdelay_ref = 15, 684 .dp_update_interval = pt_dp_update_interval, 685 .max_burst = pt_max_burst, 686 .tailq_th = 150, 687 }; 688 689 static struct test_queue pt_tqueue = { 690 .pdata_in = pt_rtdata, 691 .num_queues = RTE_DIM(pt_rtdata), 692 .qlen = pt_q, 693 .q_ramp_up = 1000000, 694 .drop_tolerance = 0, /* 0 percent */ 695 }; 696 697 static struct test_rte_pie_config pt_tconfig2 = { 698 .pconfig = pt_wrconfig, 699 .num_cfg = RTE_DIM(pt_wrconfig), 700 .qdelay_ref = 15, 701 .dp_update_interval = pt_dp_update_interval, 702 .max_burst = pt_max_burst, 703 .tailq_th = 150, 704 }; 705 706 static struct test_queue pt_tqueue2 = { 707 .pdata_in = pt_rtdata, 708 .pdata_out = pt_wtdata, 709 .num_queues = RTE_DIM(pt_rtdata), 710 .qlen = pt_q, 711 .q_ramp_up = 1000000, 712 .drop_tolerance = 0, /* 0 percent */ 713 }; 714 715 /** 716 * enqueue/dequeue packets 717 * aka 718 * rte_sched_port_enqueue(port, in_mbufs, 10); 719 * rte_sched_port_dequeue(port, out_mbufs, 10); 720 */ 721 static void enqueue_dequeue_perf(struct rte_pie_config *pie_cfg, 722 struct rte_pie *pie_in, 723 struct rte_pie *pie_out, 724 uint32_t *qlen, 725 uint32_t num_ops, 726 uint32_t *enqueued, 727 uint32_t *dropped, 728 uint32_t *dequeued, 729 struct rdtsc_prof *prof) 730 { 731 uint32_t i = 0; 732 733 if (pie_cfg == NULL) { 734 printf("%s: Error: PIE configuration cannot be empty.\n", __func__); 735 return; 736 } 737 738 if (pie_in == NULL) { 739 printf("%s: Error: PIE enqueue data cannot be empty.\n", __func__); 740 return; 741 } 742 743 for (i = 0; i < num_ops; i++) { 744 uint64_t ts = 0; 745 int ret = 0; 746 747 /** 748 * enqueue 749 */ 750 ts = get_port_ts(); 751 rdtsc_prof_start(prof); 752 ret = rte_pie_enqueue(pie_cfg, pie_in, *qlen, 753 1000*sizeof(uint32_t), ts); 754 rdtsc_prof_end(prof); 755 756 if (ret == 0) 757 (*enqueued)++; 758 else 759 (*dropped)++; 760 761 if (pie_out != NULL) { 762 ts = get_port_ts(); 763 rdtsc_prof_start(prof); 764 rte_pie_dequeue(pie_out, 1000*sizeof(uint32_t), ts); 765 rdtsc_prof_end(prof); 766 767 (*dequeued)++; 768 } 769 } 770 } 771 772 /** 773 * Setup test structures for tests P1 774 * performance tests 1 775 */ 776 static uint32_t pt1_tlevel[] = {80}; 777 778 static struct test_var perf1_tvar = { 779 .num_iterations = 0, 780 .num_ops = 30000, 781 .clk_freq = 0, 782 .dropped = pt_dropped, 783 .enqueued = pt_enqueued 784 }; 785 786 static struct test_config perf_test_config = { 787 .ifname = "performance test 1 interface", 788 .msg = "performance test 1 : use one PIE configuration,\n" 789 " measure enqueue performance\n\n", 790 .tconfig = &pt_tconfig, 791 .tqueue = &pt_tqueue, 792 .tvar = &perf1_tvar, 793 .tlevel = pt1_tlevel, 794 }; 795 796 /** 797 * Performance test function to measure enqueue performance. 798 * 799 */ 800 static enum test_result perf_test(struct test_config *tcfg) 801 { 802 enum test_result result = PASS; 803 struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; 804 uint32_t total = 0; 805 806 printf("%s", tcfg->msg); 807 808 rdtsc_prof_init(&prof, "enqueue"); 809 810 if (test_rte_pie_init(tcfg) != PASS) { 811 result = FAIL; 812 goto out; 813 } 814 815 /** 816 * initialize the rte_pie run time data structure 817 */ 818 rte_pie_rt_data_init(tcfg->tqueue->pdata_in); 819 rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1); 820 *tcfg->tvar->enqueued = 0; 821 *tcfg->tvar->dropped = 0; 822 823 enqueue_dequeue_perf(tcfg->tconfig->pconfig, 824 tcfg->tqueue->pdata_in, 825 NULL, 826 tcfg->tqueue->qlen, 827 tcfg->tvar->num_ops, 828 tcfg->tvar->enqueued, 829 tcfg->tvar->dropped, 830 tcfg->tvar->dequeued, 831 &prof); 832 833 total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; 834 835 printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", 836 total, *tcfg->tvar->enqueued, 837 ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0, 838 *tcfg->tvar->dropped, 839 ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); 840 841 rdtsc_prof_print(&prof); 842 out: 843 return result; 844 } 845 846 847 848 /** 849 * Setup test structures for tests P2 850 * performance tests 2 851 */ 852 static uint32_t pt2_tlevel[] = {80}; 853 854 static struct test_var perf2_tvar = { 855 .num_iterations = 0, 856 .num_ops = 30000, 857 .clk_freq = 0, 858 .dropped = pt_dropped, 859 .enqueued = pt_enqueued, 860 .dequeued = pt_dequeued 861 }; 862 863 static struct test_config perf_test_config2 = { 864 .ifname = "performance test 2 interface", 865 .msg = "performance test 2 : use one PIE configuration,\n" 866 " measure enqueue & dequeue performance\n\n", 867 .tconfig = &pt_tconfig2, 868 .tqueue = &pt_tqueue2, 869 .tvar = &perf2_tvar, 870 .tlevel = pt2_tlevel, 871 }; 872 873 /** 874 * Performance test function to measure enqueue & dequeue performance. 875 * 876 */ 877 static enum test_result perf_test2(struct test_config *tcfg) 878 { 879 enum test_result result = PASS; 880 struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; 881 uint32_t total = 0; 882 883 printf("%s", tcfg->msg); 884 885 rdtsc_prof_init(&prof, "enqueue"); 886 887 if (test_rte_pie_init(tcfg) != PASS) { 888 result = FAIL; 889 goto out; 890 } 891 892 /** 893 * initialize the rte_pie run time data structure 894 */ 895 rte_pie_rt_data_init(tcfg->tqueue->pdata_in); 896 rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1); 897 *tcfg->tvar->enqueued = 0; 898 *tcfg->tvar->dequeued = 0; 899 *tcfg->tvar->dropped = 0; 900 901 enqueue_dequeue_perf(tcfg->tconfig->pconfig, 902 tcfg->tqueue->pdata_in, 903 tcfg->tqueue->pdata_out, 904 tcfg->tqueue->qlen, 905 tcfg->tvar->num_ops, 906 tcfg->tvar->enqueued, 907 tcfg->tvar->dropped, 908 tcfg->tvar->dequeued, 909 &prof); 910 911 total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; 912 913 printf("\ntotal: %u, dequeued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", 914 total, *tcfg->tvar->dequeued, 915 ((double)(*tcfg->tvar->dequeued) / (double)total) * 100.0, 916 *tcfg->tvar->dropped, 917 ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); 918 919 rdtsc_prof_print(&prof); 920 out: 921 return result; 922 } 923 924 /** 925 * define the functional tests to be executed fast 926 */ 927 struct tests func_pie_tests_quick[] = { 928 { &func_test_config1, func_test1 }, 929 { &func_test_config2, func_test2 }, 930 }; 931 932 /** 933 * define the functional and performance tests to be executed 934 */ 935 struct tests func_pie_tests[] = { 936 { &func_test_config1, func_test1 }, 937 { &func_test_config2, func_test2 }, 938 { &func_test_config3, func_test3 }, 939 }; 940 941 struct tests perf_pie_tests[] = { 942 { &perf_test_config, perf_test }, 943 { &perf_test_config2, perf_test2 }, 944 }; 945 946 /** 947 * function to execute the required pie tests 948 */ 949 static void run_tests(struct tests *test_type, uint32_t test_count, 950 uint32_t *num_tests, uint32_t *num_pass) 951 { 952 enum test_result result = PASS; 953 uint32_t i = 0; 954 static const char *bar_str = "-------------------------------------" 955 "-------------------------------------------"; 956 static const char *bar_pass_str = "-------------------------------------" 957 "<pass>-------------------------------------"; 958 static const char *bar_fail_str = "-------------------------------------" 959 "<fail>-------------------------------------"; 960 961 for (i = 0; i < test_count; i++) { 962 printf("\n%s\n", bar_str); 963 result = test_type[i].testfn(test_type[i].testcfg); 964 (*num_tests)++; 965 if (result == PASS) { 966 (*num_pass)++; 967 printf("%s\n", bar_pass_str); 968 } else { 969 printf("%s\n", bar_fail_str); 970 } 971 } 972 } 973 974 /** 975 * check if functions accept invalid parameters 976 * 977 * First, all functions will be called without initialized PIE 978 * Then, all of them will be called with NULL/invalid parameters 979 * 980 * Some functions are not tested as they are performance-critical and thus 981 * don't do any parameter checking. 982 */ 983 static int 984 test_invalid_parameters(void) 985 { 986 struct rte_pie_config config; 987 static const char *shf_str = "rte_pie_config_init should have failed!"; 988 static const char *shf_rt_str = "rte_pie_rt_data_init should have failed!"; 989 990 /* NULL config */ 991 if (rte_pie_rt_data_init(NULL) == 0) { 992 printf("%i: %s\n", __LINE__, shf_rt_str); 993 return -1; 994 } 995 996 /* NULL config */ 997 if (rte_pie_config_init(NULL, 0, 0, 0, 0) == 0) { 998 printf("%i%s\n", __LINE__, shf_str); 999 return -1; 1000 } 1001 1002 /* qdelay_ref <= 0 */ 1003 if (rte_pie_config_init(&config, 0, 1, 1, 1) == 0) { 1004 printf("%i%s\n", __LINE__, shf_str); 1005 return -1; 1006 } 1007 1008 /* dp_update_interval <= 0 */ 1009 if (rte_pie_config_init(&config, 1, 0, 1, 1) == 0) { 1010 printf("%i%s\n", __LINE__, shf_str); 1011 return -1; 1012 } 1013 1014 /* max_burst <= 0 */ 1015 if (rte_pie_config_init(&config, 1, 1, 0, 1) == 0) { 1016 printf("%i%s\n", __LINE__, shf_str); 1017 return -1; 1018 } 1019 1020 /* tailq_th <= 0 */ 1021 if (rte_pie_config_init(&config, 1, 1, 1, 0) == 0) { 1022 printf("%i%s\n", __LINE__, shf_str); 1023 return -1; 1024 } 1025 1026 RTE_SET_USED(config); 1027 1028 return 0; 1029 } 1030 1031 static void 1032 show_stats(const uint32_t num_tests, const uint32_t num_pass) 1033 { 1034 if (num_pass == num_tests) 1035 printf("[total: %u, pass: %u]\n", num_tests, num_pass); 1036 else 1037 printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass, 1038 num_tests - num_pass); 1039 } 1040 1041 static int 1042 tell_the_result(const uint32_t num_tests, const uint32_t num_pass) 1043 { 1044 return (num_pass == num_tests) ? 0 : 1; 1045 } 1046 1047 static int 1048 test_pie(void) 1049 { 1050 uint32_t num_tests = 0; 1051 uint32_t num_pass = 0; 1052 1053 if (test_invalid_parameters() < 0) 1054 return -1; 1055 1056 run_tests(func_pie_tests_quick, RTE_DIM(func_pie_tests_quick), 1057 &num_tests, &num_pass); 1058 show_stats(num_tests, num_pass); 1059 return tell_the_result(num_tests, num_pass); 1060 } 1061 1062 static int 1063 test_pie_perf(void) 1064 { 1065 uint32_t num_tests = 0; 1066 uint32_t num_pass = 0; 1067 1068 run_tests(perf_pie_tests, RTE_DIM(perf_pie_tests), &num_tests, &num_pass); 1069 show_stats(num_tests, num_pass); 1070 return tell_the_result(num_tests, num_pass); 1071 } 1072 1073 static int 1074 test_pie_all(void) 1075 { 1076 uint32_t num_tests = 0; 1077 uint32_t num_pass = 0; 1078 1079 if (test_invalid_parameters() < 0) 1080 return -1; 1081 1082 run_tests(func_pie_tests, RTE_DIM(func_pie_tests), &num_tests, &num_pass); 1083 run_tests(perf_pie_tests, RTE_DIM(perf_pie_tests), &num_tests, &num_pass); 1084 show_stats(num_tests, num_pass); 1085 return tell_the_result(num_tests, num_pass); 1086 } 1087 1088 #endif /* !RTE_EXEC_ENV_WINDOWS */ 1089 1090 REGISTER_TEST_COMMAND(pie_autotest, test_pie); 1091 REGISTER_TEST_COMMAND(pie_perf, test_pie_perf); 1092 REGISTER_TEST_COMMAND(pie_all, test_pie_all); 1093