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