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