Branch data Line data Source code
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 : 11 : double cycles_per_byte = (double)(cpu_clock) / (double)(port_speed_bytes);
115 : 11 : inv_cycles_per_byte = 1.0 / cycles_per_byte;
116 : : }
117 : :
118 : : static uint64_t get_port_ts(void)
119 : : {
120 : 0 : 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 : 0 : p->clk_min = (uint64_t)(-1LL);
126 : : p->clk_max = 0;
127 : : p->clk_avg = 0;
128 : : p->clk_avgc = 0;
129 : 0 : p->name = name;
130 : : }
131 : :
132 : : static inline void rdtsc_prof_start(struct rdtsc_prof *p)
133 : : {
134 : 0 : p->clk_start = rte_rdtsc_precise();
135 : : }
136 : :
137 : : static inline void rdtsc_prof_end(struct rdtsc_prof *p)
138 : : {
139 : 0 : uint64_t clk_start = rte_rdtsc() - p->clk_start;
140 : :
141 : 0 : p->clk_avgc++;
142 : 0 : p->clk_avg += (double) clk_start;
143 : :
144 [ # # # # ]: 0 : if (clk_start > p->clk_max)
145 : 0 : p->clk_max = clk_start;
146 [ # # # # ]: 0 : if (clk_start < p->clk_min)
147 : 0 : p->clk_min = clk_start;
148 : : }
149 : :
150 : 0 : static void rdtsc_prof_print(struct rdtsc_prof *p)
151 : : {
152 [ # # ]: 0 : if (p->clk_avgc > 0) {
153 : 0 : 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 : 0 : (p->clk_avg / ((double) p->clk_avgc)));
160 : : }
161 : 0 : }
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 : 24 : 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 : 11 : 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 : 34 : 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 : 10 : return pie->avg_dq_time;
197 : : }
198 : :
199 : : static double calc_drop_rate(uint32_t enqueued, uint32_t dropped)
200 : : {
201 : 34 : 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 : 10 : abs_diff = fabs(drop_rate - drop_prob);
214 : 10 : if ((int)abs_diff == 0) {
215 : : *diff = 0.0;
216 : : } else {
217 : 0 : *diff = (abs_diff / drop_prob) * 100.0;
218 [ # # ]: 0 : 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 : 11 : test_rte_pie_init(struct test_config *tcfg)
229 : : {
230 : : unsigned int i = 0;
231 : :
232 : 11 : tcfg->tvar->clk_freq = rte_get_timer_hz();
233 : 11 : init_port_ts(tcfg->tvar->clk_freq);
234 : :
235 [ + + ]: 112 : for (i = 0; i < tcfg->tconfig->num_cfg; i++) {
236 [ + - ]: 101 : if (rte_pie_config_init(&tcfg->tconfig->pconfig[i],
237 : 101 : (uint16_t)tcfg->tconfig->qdelay_ref,
238 : 101 : (uint16_t)tcfg->tconfig->dp_update_interval[i],
239 : 101 : (uint16_t)tcfg->tconfig->max_burst[i],
240 : 101 : (uint16_t)tcfg->tconfig->tailq_th) != 0) {
241 : : return FAIL;
242 : : }
243 : : }
244 : :
245 : 11 : *tcfg->tqueue->qlen = 0;
246 : 11 : *tcfg->tvar->dropped = 0;
247 : 11 : *tcfg->tvar->enqueued = 0;
248 : :
249 : 11 : return PASS;
250 : : }
251 : :
252 : : /**
253 : : * enqueue until actual queue size reaches target level
254 : : */
255 : : static int
256 : 11 : 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 [ + - ]: 11 : for (i = 0; i < attempts; i++) {
265 : : int ret = 0;
266 : :
267 : : /**
268 : : * enqueue
269 : : */
270 : 11 : 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 [ - + ]: 11 : 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 : 34 : 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 [ + + ]: 340034 : for (i = 0; i < num_ops; i++) {
297 : : int ret = 0;
298 : :
299 : : /**
300 : : * enqueue
301 : : */
302 : 340000 : ret = rte_pie_enqueue(pie_cfg, pie, *qlen, sizeof(uint32_t),
303 : : get_port_ts());
304 [ + - ]: 340000 : if (ret == 0)
305 : 340000 : (*enqueued)++;
306 : : else
307 : 0 : (*dropped)++;
308 : : }
309 : 34 : }
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 : 1 : static enum test_result func_test1(struct test_config *tcfg)
373 : : {
374 : : enum test_result result = PASS;
375 : : uint32_t i = 0;
376 : :
377 : 1 : printf("%s", tcfg->msg);
378 : :
379 [ - + ]: 1 : if (test_rte_pie_init(tcfg) != PASS) {
380 : : result = FAIL;
381 : 0 : goto out;
382 : : }
383 : :
384 : 1 : printf("%s", tcfg->htxt);
385 : :
386 : : /**
387 : : * reset rte_pie run-time data
388 : : */
389 : 1 : rte_pie_rt_data_init(tcfg->tqueue->pdata_in);
390 : 1 : rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1);
391 : 1 : *tcfg->tvar->enqueued = 0;
392 : 1 : *tcfg->tvar->dropped = 0;
393 : :
394 [ + - ]: 1 : if (increase_qsize(&tcfg->tconfig->pconfig[i],
395 : : tcfg->tqueue->pdata_in,
396 : : tcfg->tqueue->qlen,
397 : 1 : tcfg->tlevel[i],
398 : 1 : tcfg->tqueue->q_ramp_up) != 0) {
399 : 0 : fprintf(stderr, "Fail: increase qsize\n");
400 : : result = FAIL;
401 : 0 : goto out;
402 : : }
403 : :
404 [ + + ]: 25 : 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 : 24 : enqueue_dequeue_func(&tcfg->tconfig->pconfig[i],
413 : : tcfg->tqueue->pdata_in,
414 : 24 : tcfg->tqueue->qlen,
415 : : tcfg->tvar->num_ops,
416 : : tcfg->tvar->enqueued,
417 : 24 : tcfg->tvar->dropped);
418 : :
419 : 24 : drop_rate = calc_drop_rate(*tcfg->tvar->enqueued,
420 : 24 : *tcfg->tvar->dropped);
421 : 24 : drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in);
422 : :
423 [ - + ]: 24 : if (drop_prob != 0) {
424 : 0 : fprintf(stderr, "Fail: check drop prob\n");
425 : : result = FAIL;
426 : : }
427 : :
428 [ - + ]: 24 : if (drop_rate != 0) {
429 : 0 : fprintf(stderr, "Fail: check drop rate\n");
430 : : result = FAIL;
431 : : }
432 : :
433 : : label = "Summary ";
434 : 24 : active = rte_pie_get_active(NULL, tcfg->tqueue->pdata_in);
435 : 24 : printf("%s%-16u%-12u%-12u%-12.4lf%-12.4lf%-12.4lf%-12.4lf%-8i\n",
436 : 24 : 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 : 1 : out:
441 : 1 : 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 : 1 : static enum test_result func_test2(struct test_config *tcfg)
482 : : {
483 : : enum test_result result = PASS;
484 : : uint32_t i = 0;
485 : :
486 : 1 : printf("%s", tcfg->msg);
487 : :
488 : 1 : printf("%s", tcfg->htxt);
489 : :
490 [ + + ]: 11 : 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 [ - + ]: 10 : if (test_rte_pie_init(tcfg) != PASS) {
497 : : result = FAIL;
498 : 0 : goto out;
499 : : }
500 : :
501 : 10 : rte_pie_rt_data_init(tcfg->tqueue->pdata_in);
502 : 10 : rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1);
503 : 10 : *tcfg->tvar->enqueued = 0;
504 : 10 : *tcfg->tvar->dropped = 0;
505 : :
506 [ - + ]: 10 : if (increase_qsize(&tcfg->tconfig->pconfig[i],
507 : : tcfg->tqueue->pdata_in,
508 : : tcfg->tqueue->qlen,
509 : 10 : *tcfg->tlevel,
510 : 10 : tcfg->tqueue->q_ramp_up) != 0) {
511 : : result = FAIL;
512 : 0 : goto out;
513 : : }
514 : :
515 : 10 : enqueue_dequeue_func(&tcfg->tconfig->pconfig[i],
516 : : tcfg->tqueue->pdata_in,
517 : 10 : tcfg->tqueue->qlen,
518 : : tcfg->tvar->num_ops,
519 : : tcfg->tvar->enqueued,
520 : 10 : tcfg->tvar->dropped);
521 : :
522 : 10 : avg = rte_pie_get_avg_dq_time(NULL, tcfg->tqueue->pdata_in);
523 : :
524 : 10 : drop_rate = calc_drop_rate(*tcfg->tvar->enqueued,
525 : 10 : *tcfg->tvar->dropped);
526 : : drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in);
527 : :
528 [ - + ]: 10 : if (!check_drop_rate(&diff, drop_rate, drop_prob,
529 : : (double)tcfg->tqueue->drop_tolerance)) {
530 : 0 : fprintf(stderr, "Fail: drop rate outside tolerance\n");
531 : : result = FAIL;
532 : : }
533 : :
534 : 10 : printf("%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n",
535 : 10 : i, avg, *tcfg->tvar->enqueued, *tcfg->tvar->dropped,
536 : : drop_prob * 100.0, drop_rate * 100.0, diff,
537 : 10 : (double)tcfg->tqueue->drop_tolerance);
538 : : }
539 : 1 : out:
540 : 1 : 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 : 0 : static enum test_result func_test3(struct test_config *tcfg)
596 : : {
597 : : enum test_result result = PASS;
598 : : uint32_t i = 0;
599 : :
600 : 0 : printf("%s", tcfg->msg);
601 : :
602 [ # # ]: 0 : if (test_rte_pie_init(tcfg) != PASS) {
603 : : result = FAIL;
604 : 0 : goto out;
605 : : }
606 : :
607 : 0 : printf("%s", tcfg->htxt);
608 : :
609 : : /**
610 : : * reset rte_pie run-time data
611 : : */
612 : 0 : rte_pie_rt_data_init(tcfg->tqueue->pdata_in);
613 : 0 : rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1);
614 : 0 : *tcfg->tvar->enqueued = 0;
615 : 0 : *tcfg->tvar->dropped = 0;
616 : :
617 [ # # ]: 0 : if (increase_qsize(&tcfg->tconfig->pconfig[i],
618 : : tcfg->tqueue->pdata_in,
619 : : tcfg->tqueue->qlen,
620 : 0 : tcfg->tlevel[i],
621 : 0 : tcfg->tqueue->q_ramp_up) != 0) {
622 : 0 : fprintf(stderr, "Fail: increase qsize\n");
623 : : result = FAIL;
624 : 0 : goto out;
625 : : }
626 : :
627 [ # # ]: 0 : 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 : 0 : enqueue_dequeue_func(&tcfg->tconfig->pconfig[i],
636 : : tcfg->tqueue->pdata_in,
637 : 0 : tcfg->tqueue->qlen,
638 : : tcfg->tvar->num_ops,
639 : : tcfg->tvar->enqueued,
640 : 0 : tcfg->tvar->dropped);
641 : :
642 : 0 : drop_rate = calc_drop_rate(*tcfg->tvar->enqueued,
643 : 0 : *tcfg->tvar->dropped);
644 : 0 : drop_prob = rte_pie_get_drop_prob(NULL, tcfg->tqueue->pdata_in);
645 : :
646 [ # # ]: 0 : if (drop_prob != 0) {
647 : 0 : fprintf(stderr, "Fail: check drop prob\n");
648 : : result = FAIL;
649 : : }
650 : :
651 [ # # ]: 0 : if (drop_rate != 0) {
652 : 0 : fprintf(stderr, "Fail: check drop rate\n");
653 : : result = FAIL;
654 : : }
655 : :
656 : : label = "Summary ";
657 : 0 : active = rte_pie_get_active(NULL, tcfg->tqueue->pdata_in);
658 : 0 : printf("%s%-16u%-12u%-12u%-12.4lf%-12.4lf%-12.4lf%-12.4lf%-8i\n",
659 : 0 : 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 : 0 : out:
664 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (pie_cfg == NULL) {
734 : : printf("%s: Error: PIE configuration cannot be empty.\n", __func__);
735 : 0 : return;
736 : : }
737 : :
738 [ # # ]: 0 : if (pie_in == NULL) {
739 : : printf("%s: Error: PIE enqueue data cannot be empty.\n", __func__);
740 : 0 : return;
741 : : }
742 : :
743 [ # # ]: 0 : 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 : 0 : ret = rte_pie_enqueue(pie_cfg, pie_in, *qlen,
753 : : 1000*sizeof(uint32_t), ts);
754 : : rdtsc_prof_end(prof);
755 : :
756 [ # # ]: 0 : if (ret == 0)
757 : 0 : (*enqueued)++;
758 : : else
759 : 0 : (*dropped)++;
760 : :
761 [ # # ]: 0 : if (pie_out != NULL) {
762 : : ts = get_port_ts();
763 : : rdtsc_prof_start(prof);
764 : 0 : rte_pie_dequeue(pie_out, 1000*sizeof(uint32_t), ts);
765 : : rdtsc_prof_end(prof);
766 : :
767 : 0 : (*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 : 0 : static enum test_result perf_test(struct test_config *tcfg)
801 : : {
802 : : enum test_result result = PASS;
803 : 0 : struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL};
804 : : uint32_t total = 0;
805 : :
806 : 0 : printf("%s", tcfg->msg);
807 : :
808 : : rdtsc_prof_init(&prof, "enqueue");
809 : :
810 [ # # ]: 0 : if (test_rte_pie_init(tcfg) != PASS) {
811 : : result = FAIL;
812 : 0 : goto out;
813 : : }
814 : :
815 : : /**
816 : : * initialize the rte_pie run time data structure
817 : : */
818 : 0 : rte_pie_rt_data_init(tcfg->tqueue->pdata_in);
819 : 0 : rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1);
820 : 0 : *tcfg->tvar->enqueued = 0;
821 : 0 : *tcfg->tvar->dropped = 0;
822 : :
823 : 0 : enqueue_dequeue_perf(tcfg->tconfig->pconfig,
824 : : tcfg->tqueue->pdata_in,
825 : : NULL,
826 : 0 : tcfg->tqueue->qlen,
827 : : tcfg->tvar->num_ops,
828 : : tcfg->tvar->enqueued,
829 : : tcfg->tvar->dropped,
830 : 0 : tcfg->tvar->dequeued,
831 : : &prof);
832 : :
833 : 0 : total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped;
834 : :
835 : 0 : printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n",
836 : : total, *tcfg->tvar->enqueued,
837 : 0 : ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0,
838 : : *tcfg->tvar->dropped,
839 : 0 : ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0);
840 : :
841 : 0 : rdtsc_prof_print(&prof);
842 : 0 : out:
843 : 0 : 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 : 0 : static enum test_result perf_test2(struct test_config *tcfg)
878 : : {
879 : : enum test_result result = PASS;
880 : 0 : struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL};
881 : : uint32_t total = 0;
882 : :
883 : 0 : printf("%s", tcfg->msg);
884 : :
885 : : rdtsc_prof_init(&prof, "enqueue");
886 : :
887 [ # # ]: 0 : if (test_rte_pie_init(tcfg) != PASS) {
888 : : result = FAIL;
889 : 0 : goto out;
890 : : }
891 : :
892 : : /**
893 : : * initialize the rte_pie run time data structure
894 : : */
895 : 0 : rte_pie_rt_data_init(tcfg->tqueue->pdata_in);
896 : 0 : rte_pie_set_active(NULL, tcfg->tqueue->pdata_in, 1);
897 : 0 : *tcfg->tvar->enqueued = 0;
898 : 0 : *tcfg->tvar->dequeued = 0;
899 : 0 : *tcfg->tvar->dropped = 0;
900 : :
901 : 0 : enqueue_dequeue_perf(tcfg->tconfig->pconfig,
902 : : tcfg->tqueue->pdata_in,
903 : : tcfg->tqueue->pdata_out,
904 : 0 : tcfg->tqueue->qlen,
905 : : tcfg->tvar->num_ops,
906 : : tcfg->tvar->enqueued,
907 : : tcfg->tvar->dropped,
908 : 0 : tcfg->tvar->dequeued,
909 : : &prof);
910 : :
911 : 0 : total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped;
912 : :
913 : 0 : printf("\ntotal: %u, dequeued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n",
914 : : total, *tcfg->tvar->dequeued,
915 : 0 : ((double)(*tcfg->tvar->dequeued) / (double)total) * 100.0,
916 : : *tcfg->tvar->dropped,
917 : 0 : ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0);
918 : :
919 : 0 : rdtsc_prof_print(&prof);
920 : 0 : out:
921 : 0 : 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 : 1 : 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 [ + + ]: 3 : for (i = 0; i < test_count; i++) {
962 : 2 : printf("\n%s\n", bar_str);
963 : 2 : result = test_type[i].testfn(test_type[i].testcfg);
964 : 2 : (*num_tests)++;
965 [ + - ]: 2 : if (result == PASS) {
966 : 2 : (*num_pass)++;
967 : 2 : printf("%s\n", bar_pass_str);
968 : : } else {
969 : 0 : printf("%s\n", bar_fail_str);
970 : : }
971 : : }
972 : 1 : }
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 : 1 : 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 [ - + ]: 1 : if (rte_pie_rt_data_init(NULL) == 0) {
992 : 0 : printf("%i: %s\n", __LINE__, shf_rt_str);
993 : 0 : return -1;
994 : : }
995 : :
996 : : /* NULL config */
997 [ - + ]: 1 : if (rte_pie_config_init(NULL, 0, 0, 0, 0) == 0) {
998 : 0 : printf("%i%s\n", __LINE__, shf_str);
999 : 0 : return -1;
1000 : : }
1001 : :
1002 : : /* qdelay_ref <= 0 */
1003 [ - + ]: 1 : if (rte_pie_config_init(&config, 0, 1, 1, 1) == 0) {
1004 : 0 : printf("%i%s\n", __LINE__, shf_str);
1005 : 0 : return -1;
1006 : : }
1007 : :
1008 : : /* dp_update_interval <= 0 */
1009 [ - + ]: 1 : if (rte_pie_config_init(&config, 1, 0, 1, 1) == 0) {
1010 : 0 : printf("%i%s\n", __LINE__, shf_str);
1011 : 0 : return -1;
1012 : : }
1013 : :
1014 : : /* max_burst <= 0 */
1015 [ - + ]: 1 : if (rte_pie_config_init(&config, 1, 1, 0, 1) == 0) {
1016 : 0 : printf("%i%s\n", __LINE__, shf_str);
1017 : 0 : return -1;
1018 : : }
1019 : :
1020 : : /* tailq_th <= 0 */
1021 [ - + ]: 1 : if (rte_pie_config_init(&config, 1, 1, 1, 0) == 0) {
1022 : 0 : printf("%i%s\n", __LINE__, shf_str);
1023 : 0 : return -1;
1024 : : }
1025 : :
1026 : : RTE_SET_USED(config);
1027 : :
1028 : : return 0;
1029 : : }
1030 : :
1031 : : static void
1032 : 1 : show_stats(const uint32_t num_tests, const uint32_t num_pass)
1033 : : {
1034 [ + - ]: 1 : if (num_pass == num_tests)
1035 : : printf("[total: %u, pass: %u]\n", num_tests, num_pass);
1036 : : else
1037 : 0 : printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass,
1038 : : num_tests - num_pass);
1039 : 1 : }
1040 : :
1041 : : static int
1042 : : tell_the_result(const uint32_t num_tests, const uint32_t num_pass)
1043 : : {
1044 : 1 : return (num_pass == num_tests) ? 0 : 1;
1045 : : }
1046 : :
1047 : : static int
1048 : 1 : test_pie(void)
1049 : : {
1050 : 1 : uint32_t num_tests = 0;
1051 : 1 : uint32_t num_pass = 0;
1052 : :
1053 [ + - ]: 1 : if (test_invalid_parameters() < 0)
1054 : : return -1;
1055 : :
1056 : 1 : run_tests(func_pie_tests_quick, RTE_DIM(func_pie_tests_quick),
1057 : : &num_tests, &num_pass);
1058 : 1 : show_stats(num_tests, num_pass);
1059 : 1 : return tell_the_result(num_tests, num_pass);
1060 : : }
1061 : :
1062 : : static int
1063 : 0 : test_pie_perf(void)
1064 : : {
1065 : 0 : uint32_t num_tests = 0;
1066 : 0 : uint32_t num_pass = 0;
1067 : :
1068 : 0 : run_tests(perf_pie_tests, RTE_DIM(perf_pie_tests), &num_tests, &num_pass);
1069 : 0 : show_stats(num_tests, num_pass);
1070 : 0 : return tell_the_result(num_tests, num_pass);
1071 : : }
1072 : :
1073 : : static int
1074 : 0 : test_pie_all(void)
1075 : : {
1076 : 0 : uint32_t num_tests = 0;
1077 : 0 : uint32_t num_pass = 0;
1078 : :
1079 [ # # ]: 0 : if (test_invalid_parameters() < 0)
1080 : : return -1;
1081 : :
1082 : 0 : run_tests(func_pie_tests, RTE_DIM(func_pie_tests), &num_tests, &num_pass);
1083 : 0 : run_tests(perf_pie_tests, RTE_DIM(perf_pie_tests), &num_tests, &num_pass);
1084 : 0 : show_stats(num_tests, num_pass);
1085 : 0 : return tell_the_result(num_tests, num_pass);
1086 : : }
1087 : :
1088 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1089 : :
1090 : 251 : REGISTER_FAST_TEST(pie_autotest, true, true, test_pie);
1091 : 251 : REGISTER_PERF_TEST(pie_perf, test_pie_perf);
1092 : 251 : REGISTER_PERF_TEST(pie_all, test_pie_all);
|