4012121fdec4dc090e77cc7c71a1e0ef6958227b
[deb_dpdk.git] / examples / ip_pipeline / pipeline / pipeline_flow_actions.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/queue.h>
37 #include <netinet/in.h>
38
39 #include <rte_common.h>
40 #include <rte_hexdump.h>
41 #include <rte_malloc.h>
42 #include <cmdline_rdline.h>
43 #include <cmdline_parse.h>
44 #include <cmdline_parse_num.h>
45 #include <cmdline_parse_string.h>
46 #include <cmdline_parse_ipaddr.h>
47 #include <cmdline_parse_etheraddr.h>
48
49 #include "app.h"
50 #include "pipeline_common_fe.h"
51 #include "pipeline_flow_actions.h"
52 #include "hash_func.h"
53
54 /*
55  * Flow actions pipeline
56  */
57 #ifndef N_FLOWS_BULK
58 #define N_FLOWS_BULK                                    4096
59 #endif
60
61 struct app_pipeline_fa_flow {
62         struct pipeline_fa_flow_params params;
63         void *entry_ptr;
64 };
65
66 struct app_pipeline_fa_dscp {
67         uint32_t traffic_class;
68         enum rte_meter_color color;
69 };
70
71 struct app_pipeline_fa {
72         /* Parameters */
73         uint32_t n_ports_in;
74         uint32_t n_ports_out;
75         struct pipeline_fa_params params;
76
77         /* Flows */
78         struct app_pipeline_fa_dscp dscp[PIPELINE_FA_N_DSCP];
79         struct app_pipeline_fa_flow *flows;
80 } __rte_cache_aligned;
81
82 static void*
83 app_pipeline_fa_init(struct pipeline_params *params,
84         __rte_unused void *arg)
85 {
86         struct app_pipeline_fa *p;
87         uint32_t size, i;
88
89         /* Check input arguments */
90         if ((params == NULL) ||
91                 (params->n_ports_in == 0) ||
92                 (params->n_ports_out == 0))
93                 return NULL;
94
95         /* Memory allocation */
96         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fa));
97         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
98         if (p == NULL)
99                 return NULL;
100
101         /* Initialization */
102         p->n_ports_in = params->n_ports_in;
103         p->n_ports_out = params->n_ports_out;
104         if (pipeline_fa_parse_args(&p->params, params)) {
105                 rte_free(p);
106                 return NULL;
107         }
108
109         /* Memory allocation */
110         size = RTE_CACHE_LINE_ROUNDUP(
111                 p->params.n_flows * sizeof(struct app_pipeline_fa_flow));
112         p->flows = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
113         if (p->flows == NULL) {
114                 rte_free(p);
115                 return NULL;
116         }
117
118         /* Initialization of flow table */
119         for (i = 0; i < p->params.n_flows; i++)
120                 pipeline_fa_flow_params_set_default(&p->flows[i].params);
121
122         /* Initialization of DSCP table */
123         for (i = 0; i < RTE_DIM(p->dscp); i++) {
124                 p->dscp[i].traffic_class = 0;
125                 p->dscp[i].color = e_RTE_METER_GREEN;
126         }
127
128         return (void *) p;
129 }
130
131 static int
132 app_pipeline_fa_free(void *pipeline)
133 {
134         struct app_pipeline_fa *p = pipeline;
135
136         /* Check input arguments */
137         if (p == NULL)
138                 return -1;
139
140         /* Free resources */
141         rte_free(p->flows);
142         rte_free(p);
143
144         return 0;
145 }
146
147 static int
148 flow_params_check(struct app_pipeline_fa *p,
149         __rte_unused uint32_t meter_update_mask,
150         uint32_t policer_update_mask,
151         uint32_t port_update,
152         struct pipeline_fa_flow_params *params)
153 {
154         uint32_t mask, i;
155
156         /* Meter */
157
158         /* Policer */
159         for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {
160                 struct pipeline_fa_policer_params *p = &params->p[i];
161                 uint32_t j;
162
163                 if ((mask & policer_update_mask) == 0)
164                         continue;
165
166                 for (j = 0; j < e_RTE_METER_COLORS; j++) {
167                         struct pipeline_fa_policer_action *action =
168                                 &p->action[j];
169
170                         if ((action->drop == 0) &&
171                                 (action->color >= e_RTE_METER_COLORS))
172                                 return -1;
173                 }
174         }
175
176         /* Port */
177         if (port_update && (params->port_id >= p->n_ports_out))
178                 return -1;
179
180         return 0;
181 }
182
183 int
184 app_pipeline_fa_flow_config(struct app_params *app,
185         uint32_t pipeline_id,
186         uint32_t flow_id,
187         uint32_t meter_update_mask,
188         uint32_t policer_update_mask,
189         uint32_t port_update,
190         struct pipeline_fa_flow_params *params)
191 {
192         struct app_pipeline_fa *p;
193         struct app_pipeline_fa_flow *flow;
194
195         struct pipeline_fa_flow_config_msg_req *req;
196         struct pipeline_fa_flow_config_msg_rsp *rsp;
197
198         uint32_t i, mask;
199
200         /* Check input arguments */
201         if ((app == NULL) ||
202                 ((meter_update_mask == 0) &&
203                 (policer_update_mask == 0) &&
204                 (port_update == 0)) ||
205                 (meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||
206                 (policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||
207                 (params == NULL))
208                 return -1;
209
210         p = app_pipeline_data_fe(app, pipeline_id,
211                 &pipeline_flow_actions);
212         if (p == NULL)
213                 return -1;
214
215         if (flow_params_check(p,
216                 meter_update_mask,
217                 policer_update_mask,
218                 port_update,
219                 params) != 0)
220                 return -1;
221
222         flow_id %= p->params.n_flows;
223         flow = &p->flows[flow_id];
224
225         /* Allocate and write request */
226         req = app_msg_alloc(app);
227         if (req == NULL)
228                 return -1;
229
230         req->type = PIPELINE_MSG_REQ_CUSTOM;
231         req->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG;
232         req->entry_ptr = flow->entry_ptr;
233         req->flow_id = flow_id;
234         req->meter_update_mask = meter_update_mask;
235         req->policer_update_mask = policer_update_mask;
236         req->port_update = port_update;
237         memcpy(&req->params, params, sizeof(*params));
238
239         /* Send request and wait for response */
240         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
241         if (rsp == NULL)
242                 return -1;
243
244         /* Read response */
245         if (rsp->status ||
246                 (rsp->entry_ptr == NULL)) {
247                 app_msg_free(app, rsp);
248                 return -1;
249         }
250
251         /* Commit flow */
252         for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {
253                 if ((mask & meter_update_mask) == 0)
254                         continue;
255
256                 memcpy(&flow->params.m[i], &params->m[i], sizeof(params->m[i]));
257         }
258
259         for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {
260                 if ((mask & policer_update_mask) == 0)
261                         continue;
262
263                 memcpy(&flow->params.p[i], &params->p[i], sizeof(params->p[i]));
264         }
265
266         if (port_update)
267                 flow->params.port_id = params->port_id;
268
269         flow->entry_ptr = rsp->entry_ptr;
270
271         /* Free response */
272         app_msg_free(app, rsp);
273
274         return 0;
275 }
276
277 int
278 app_pipeline_fa_flow_config_bulk(struct app_params *app,
279         uint32_t pipeline_id,
280         uint32_t *flow_id,
281         uint32_t n_flows,
282         uint32_t meter_update_mask,
283         uint32_t policer_update_mask,
284         uint32_t port_update,
285         struct pipeline_fa_flow_params *params)
286 {
287         struct app_pipeline_fa *p;
288         struct pipeline_fa_flow_config_bulk_msg_req *req;
289         struct pipeline_fa_flow_config_bulk_msg_rsp *rsp;
290         void **req_entry_ptr;
291         uint32_t *req_flow_id;
292         uint32_t i;
293
294         /* Check input arguments */
295         if ((app == NULL) ||
296                 (flow_id == NULL) ||
297                 (n_flows == 0) ||
298                 ((meter_update_mask == 0) &&
299                 (policer_update_mask == 0) &&
300                 (port_update == 0)) ||
301                 (meter_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||
302                 (policer_update_mask >= (1 << PIPELINE_FA_N_TC_MAX)) ||
303                 (params == NULL))
304                 return -1;
305
306         p = app_pipeline_data_fe(app, pipeline_id,
307                 &pipeline_flow_actions);
308         if (p == NULL)
309                 return -1;
310
311         for (i = 0; i < n_flows; i++) {
312                 struct pipeline_fa_flow_params *flow_params = &params[i];
313
314                 if (flow_params_check(p,
315                         meter_update_mask,
316                         policer_update_mask,
317                         port_update,
318                         flow_params) != 0)
319                         return -1;
320         }
321
322         /* Allocate and write request */
323         req_entry_ptr = (void **) rte_malloc(NULL,
324                 n_flows * sizeof(void *),
325                 RTE_CACHE_LINE_SIZE);
326         if (req_entry_ptr == NULL)
327                 return -1;
328
329         req_flow_id = (uint32_t *) rte_malloc(NULL,
330                 n_flows * sizeof(uint32_t),
331                 RTE_CACHE_LINE_SIZE);
332         if (req_flow_id == NULL) {
333                 rte_free(req_entry_ptr);
334                 return -1;
335         }
336
337         for (i = 0; i < n_flows; i++) {
338                 uint32_t fid = flow_id[i] % p->params.n_flows;
339                 struct app_pipeline_fa_flow *flow = &p->flows[fid];
340
341                 req_flow_id[i] = fid;
342                 req_entry_ptr[i] = flow->entry_ptr;
343         }
344
345         req = app_msg_alloc(app);
346         if (req == NULL) {
347                 rte_free(req_flow_id);
348                 rte_free(req_entry_ptr);
349                 return -1;
350         }
351
352         req->type = PIPELINE_MSG_REQ_CUSTOM;
353         req->subtype = PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK;
354         req->entry_ptr = req_entry_ptr;
355         req->flow_id = req_flow_id;
356         req->n_flows = n_flows;
357         req->meter_update_mask = meter_update_mask;
358         req->policer_update_mask = policer_update_mask;
359         req->port_update = port_update;
360         req->params = params;
361
362         /* Send request and wait for response */
363         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
364         if (rsp == NULL) {
365                 rte_free(req_flow_id);
366                 rte_free(req_entry_ptr);
367                 return -1;
368         }
369
370         /* Read response */
371
372         /* Commit flows */
373         for (i = 0; i < rsp->n_flows; i++) {
374                 uint32_t fid = flow_id[i] % p->params.n_flows;
375                 struct app_pipeline_fa_flow *flow = &p->flows[fid];
376                 struct pipeline_fa_flow_params *flow_params = &params[i];
377                 void *entry_ptr = req_entry_ptr[i];
378                 uint32_t j, mask;
379
380                 for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;
381                         j++, mask <<= 1) {
382                         if ((mask & meter_update_mask) == 0)
383                                 continue;
384
385                         memcpy(&flow->params.m[j],
386                                 &flow_params->m[j],
387                                 sizeof(flow_params->m[j]));
388                 }
389
390                 for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;
391                         j++, mask <<= 1) {
392                         if ((mask & policer_update_mask) == 0)
393                                 continue;
394
395                         memcpy(&flow->params.p[j],
396                                 &flow_params->p[j],
397                                 sizeof(flow_params->p[j]));
398                 }
399
400                 if (port_update)
401                         flow->params.port_id = flow_params->port_id;
402
403                 flow->entry_ptr = entry_ptr;
404         }
405
406         /* Free response */
407         app_msg_free(app, rsp);
408         rte_free(req_flow_id);
409         rte_free(req_entry_ptr);
410
411         return (rsp->n_flows == n_flows) ? 0 : -1;
412 }
413
414 int
415 app_pipeline_fa_dscp_config(struct app_params *app,
416         uint32_t pipeline_id,
417         uint32_t dscp,
418         uint32_t traffic_class,
419         enum rte_meter_color color)
420 {
421         struct app_pipeline_fa *p;
422
423         struct pipeline_fa_dscp_config_msg_req *req;
424         struct pipeline_fa_dscp_config_msg_rsp *rsp;
425
426         /* Check input arguments */
427         if ((app == NULL) ||
428                 (dscp >= PIPELINE_FA_N_DSCP) ||
429                 (traffic_class >= PIPELINE_FA_N_TC_MAX) ||
430                 (color >= e_RTE_METER_COLORS))
431                 return -1;
432
433         p = app_pipeline_data_fe(app, pipeline_id,
434                 &pipeline_flow_actions);
435         if (p == NULL)
436                 return -1;
437
438         if (p->params.dscp_enabled == 0)
439                 return -1;
440
441         /* Allocate and write request */
442         req = app_msg_alloc(app);
443         if (req == NULL)
444                 return -1;
445
446         req->type = PIPELINE_MSG_REQ_CUSTOM;
447         req->subtype = PIPELINE_FA_MSG_REQ_DSCP_CONFIG;
448         req->dscp = dscp;
449         req->traffic_class = traffic_class;
450         req->color = color;
451
452         /* Send request and wait for response */
453         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
454         if (rsp == NULL)
455                 return -1;
456
457         /* Read response */
458         if (rsp->status) {
459                 app_msg_free(app, rsp);
460                 return -1;
461         }
462
463         /* Commit DSCP */
464         p->dscp[dscp].traffic_class = traffic_class;
465         p->dscp[dscp].color = color;
466
467         /* Free response */
468         app_msg_free(app, rsp);
469
470         return 0;
471 }
472
473 int
474 app_pipeline_fa_flow_policer_stats_read(struct app_params *app,
475         uint32_t pipeline_id,
476         uint32_t flow_id,
477         uint32_t policer_id,
478         int clear,
479         struct pipeline_fa_policer_stats *stats)
480 {
481         struct app_pipeline_fa *p;
482         struct app_pipeline_fa_flow *flow;
483
484         struct pipeline_fa_policer_stats_msg_req *req;
485         struct pipeline_fa_policer_stats_msg_rsp *rsp;
486
487         /* Check input arguments */
488         if ((app == NULL) || (stats == NULL))
489                 return -1;
490
491         p = app_pipeline_data_fe(app, pipeline_id,
492                 &pipeline_flow_actions);
493         if (p == NULL)
494                 return -1;
495
496         flow_id %= p->params.n_flows;
497         flow = &p->flows[flow_id];
498
499         if ((policer_id >= p->params.n_meters_per_flow) ||
500                 (flow->entry_ptr == NULL))
501                 return -1;
502
503         /* Allocate and write request */
504         req = app_msg_alloc(app);
505         if (req == NULL)
506                 return -1;
507
508         req->type = PIPELINE_MSG_REQ_CUSTOM;
509         req->subtype = PIPELINE_FA_MSG_REQ_POLICER_STATS_READ;
510         req->entry_ptr = flow->entry_ptr;
511         req->policer_id = policer_id;
512         req->clear = clear;
513
514         /* Send request and wait for response */
515         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
516         if (rsp == NULL)
517                 return -1;
518
519         /* Read response */
520         if (rsp->status) {
521                 app_msg_free(app, rsp);
522                 return -1;
523         }
524
525         memcpy(stats, &rsp->stats, sizeof(*stats));
526
527         /* Free response */
528         app_msg_free(app, rsp);
529
530         return 0;
531 }
532
533 static const char *
534 color_to_string(enum rte_meter_color color)
535 {
536         switch (color) {
537         case e_RTE_METER_GREEN: return "G";
538         case e_RTE_METER_YELLOW: return "Y";
539         case e_RTE_METER_RED: return "R";
540         default: return "?";
541         }
542 }
543
544 static int
545 string_to_color(char *s, enum rte_meter_color *c)
546 {
547         if (strcmp(s, "G") == 0) {
548                 *c = e_RTE_METER_GREEN;
549                 return 0;
550         }
551
552         if (strcmp(s, "Y") == 0) {
553                 *c = e_RTE_METER_YELLOW;
554                 return 0;
555         }
556
557         if (strcmp(s, "R") == 0) {
558                 *c = e_RTE_METER_RED;
559                 return 0;
560         }
561
562         return -1;
563 }
564
565 static const char *
566 policer_action_to_string(struct pipeline_fa_policer_action *a)
567 {
568         if (a->drop)
569                 return "D";
570
571         return color_to_string(a->color);
572 }
573
574 static int
575 string_to_policer_action(char *s, struct pipeline_fa_policer_action *a)
576 {
577         if (strcmp(s, "G") == 0) {
578                 a->drop = 0;
579                 a->color = e_RTE_METER_GREEN;
580                 return 0;
581         }
582
583         if (strcmp(s, "Y") == 0) {
584                 a->drop = 0;
585                 a->color = e_RTE_METER_YELLOW;
586                 return 0;
587         }
588
589         if (strcmp(s, "R") == 0) {
590                 a->drop = 0;
591                 a->color = e_RTE_METER_RED;
592                 return 0;
593         }
594
595         if (strcmp(s, "D") == 0) {
596                 a->drop = 1;
597                 a->color = e_RTE_METER_GREEN;
598                 return 0;
599         }
600
601         return -1;
602 }
603
604 static void
605 print_flow(struct app_pipeline_fa *p,
606         uint32_t flow_id,
607         struct app_pipeline_fa_flow *flow)
608 {
609         uint32_t i;
610
611         printf("Flow ID = %" PRIu32 "\n", flow_id);
612
613         for (i = 0; i < p->params.n_meters_per_flow; i++) {
614                 struct rte_meter_trtcm_params *meter = &flow->params.m[i];
615                 struct pipeline_fa_policer_params *policer = &flow->params.p[i];
616
617         printf("\ttrTCM [CIR = %" PRIu64
618                 ", CBS = %" PRIu64 ", PIR = %" PRIu64
619                 ", PBS = %" PRIu64      "] Policer [G : %s, Y : %s, R : %s]\n",
620                 meter->cir,
621                 meter->cbs,
622                 meter->pir,
623                 meter->pbs,
624                 policer_action_to_string(&policer->action[e_RTE_METER_GREEN]),
625                 policer_action_to_string(&policer->action[e_RTE_METER_YELLOW]),
626                 policer_action_to_string(&policer->action[e_RTE_METER_RED]));
627         }
628
629         printf("\tPort %u (entry_ptr = %p)\n",
630                 flow->params.port_id,
631                 flow->entry_ptr);
632 }
633
634
635 static int
636 app_pipeline_fa_flow_ls(struct app_params *app,
637                 uint32_t pipeline_id)
638 {
639         struct app_pipeline_fa *p;
640         uint32_t i;
641
642         /* Check input arguments */
643         if (app == NULL)
644                 return -1;
645
646         p = app_pipeline_data_fe(app, pipeline_id,
647                 &pipeline_flow_actions);
648         if (p == NULL)
649                 return -1;
650
651         for (i = 0; i < p->params.n_flows; i++) {
652                 struct app_pipeline_fa_flow *flow = &p->flows[i];
653
654                 print_flow(p, i, flow);
655         }
656
657         return 0;
658 }
659
660 static int
661 app_pipeline_fa_dscp_ls(struct app_params *app,
662                 uint32_t pipeline_id)
663 {
664         struct app_pipeline_fa *p;
665         uint32_t i;
666
667         /* Check input arguments */
668         if (app == NULL)
669                 return -1;
670
671         p = app_pipeline_data_fe(app, pipeline_id,
672                 &pipeline_flow_actions);
673         if (p == NULL)
674                 return -1;
675
676         if (p->params.dscp_enabled == 0)
677                 return -1;
678
679         for (i = 0; i < RTE_DIM(p->dscp); i++) {
680                 struct app_pipeline_fa_dscp *dscp =     &p->dscp[i];
681
682                 printf("DSCP = %2" PRIu32 ": Traffic class = %" PRIu32
683                         ", Color = %s\n",
684                         i,
685                         dscp->traffic_class,
686                         color_to_string(dscp->color));
687         }
688
689         return 0;
690 }
691
692 /*
693  * Flow meter configuration (single flow)
694  *
695  * p <pipeline ID> flow <flow ID> meter <meter ID> trtcm <trtcm params>
696  */
697
698 struct cmd_fa_meter_config_result {
699         cmdline_fixed_string_t p_string;
700         uint32_t pipeline_id;
701         cmdline_fixed_string_t flow_string;
702         uint32_t flow_id;
703         cmdline_fixed_string_t meter_string;
704         uint32_t meter_id;
705         cmdline_fixed_string_t trtcm_string;
706         uint64_t cir;
707         uint64_t pir;
708         uint64_t cbs;
709         uint64_t pbs;
710 };
711
712 static void
713 cmd_fa_meter_config_parsed(
714         void *parsed_result,
715         __rte_unused struct cmdline *cl,
716         void *data)
717 {
718         struct cmd_fa_meter_config_result *params = parsed_result;
719         struct app_params *app = data;
720         struct pipeline_fa_flow_params flow_params;
721         int status;
722
723         if (params->meter_id >= PIPELINE_FA_N_TC_MAX) {
724                 printf("Command failed\n");
725                 return;
726         }
727
728         flow_params.m[params->meter_id].cir = params->cir;
729         flow_params.m[params->meter_id].pir = params->pir;
730         flow_params.m[params->meter_id].cbs = params->cbs;
731         flow_params.m[params->meter_id].pbs = params->pbs;
732
733         status = app_pipeline_fa_flow_config(app,
734                 params->pipeline_id,
735                 params->flow_id,
736                 1 << params->meter_id,
737                 0,
738                 0,
739                 &flow_params);
740
741         if (status != 0)
742                 printf("Command failed\n");
743 }
744
745 cmdline_parse_token_string_t cmd_fa_meter_config_p_string =
746         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
747         p_string, "p");
748
749 cmdline_parse_token_num_t cmd_fa_meter_config_pipeline_id =
750         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
751         pipeline_id, UINT32);
752
753 cmdline_parse_token_string_t cmd_fa_meter_config_flow_string =
754         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
755         flow_string, "flow");
756
757 cmdline_parse_token_num_t cmd_fa_meter_config_flow_id =
758         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
759         flow_id, UINT32);
760
761 cmdline_parse_token_string_t cmd_fa_meter_config_meter_string =
762         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
763         meter_string, "meter");
764
765 cmdline_parse_token_num_t cmd_fa_meter_config_meter_id =
766         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
767         meter_id, UINT32);
768
769 cmdline_parse_token_string_t cmd_fa_meter_config_trtcm_string =
770         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
771         trtcm_string, "trtcm");
772
773 cmdline_parse_token_num_t cmd_fa_meter_config_cir =
774         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cir, UINT64);
775
776 cmdline_parse_token_num_t cmd_fa_meter_config_pir =
777         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pir, UINT64);
778
779 cmdline_parse_token_num_t cmd_fa_meter_config_cbs =
780         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cbs, UINT64);
781
782 cmdline_parse_token_num_t cmd_fa_meter_config_pbs =
783         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pbs, UINT64);
784
785 cmdline_parse_inst_t cmd_fa_meter_config = {
786         .f = cmd_fa_meter_config_parsed,
787         .data = NULL,
788         .help_str = "Flow meter configuration (single flow) ",
789         .tokens = {
790                 (void *) &cmd_fa_meter_config_p_string,
791                 (void *) &cmd_fa_meter_config_pipeline_id,
792                 (void *) &cmd_fa_meter_config_flow_string,
793                 (void *) &cmd_fa_meter_config_flow_id,
794                 (void *) &cmd_fa_meter_config_meter_string,
795                 (void *) &cmd_fa_meter_config_meter_id,
796                 (void *) &cmd_fa_meter_config_trtcm_string,
797                 (void *) &cmd_fa_meter_config_cir,
798                 (void *) &cmd_fa_meter_config_pir,
799                 (void *) &cmd_fa_meter_config_cbs,
800                 (void *) &cmd_fa_meter_config_pbs,
801                 NULL,
802         },
803 };
804
805 /*
806  * Flow meter configuration (multiple flows)
807  *
808  * p <pipeline ID> flows <n_flows> meter <meter ID> trtcm <trtcm params>
809  */
810
811 struct cmd_fa_meter_config_bulk_result {
812         cmdline_fixed_string_t p_string;
813         uint32_t pipeline_id;
814         cmdline_fixed_string_t flows_string;
815         uint32_t n_flows;
816         cmdline_fixed_string_t meter_string;
817         uint32_t meter_id;
818         cmdline_fixed_string_t trtcm_string;
819         uint64_t cir;
820         uint64_t pir;
821         uint64_t cbs;
822         uint64_t pbs;
823 };
824
825 static void
826 cmd_fa_meter_config_bulk_parsed(
827         void *parsed_result,
828         __rte_unused struct cmdline *cl,
829         void *data)
830 {
831         struct cmd_fa_meter_config_bulk_result *params = parsed_result;
832         struct app_params *app = data;
833         struct pipeline_fa_flow_params flow_template, *flow_params;
834         uint32_t *flow_id;
835         uint32_t i;
836
837         if ((params->n_flows == 0) ||
838                 (params->meter_id >= PIPELINE_FA_N_TC_MAX)) {
839                 printf("Invalid arguments\n");
840                 return;
841         }
842
843         flow_id = (uint32_t *) rte_malloc(NULL,
844                 N_FLOWS_BULK * sizeof(uint32_t),
845                 RTE_CACHE_LINE_SIZE);
846         if (flow_id == NULL) {
847                 printf("Memory allocation failed\n");
848                 return;
849         }
850
851         flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
852                 N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
853                 RTE_CACHE_LINE_SIZE);
854         if (flow_params == NULL) {
855                 rte_free(flow_id);
856                 printf("Memory allocation failed\n");
857                 return;
858         }
859
860         memset(&flow_template, 0, sizeof(flow_template));
861         flow_template.m[params->meter_id].cir = params->cir;
862         flow_template.m[params->meter_id].pir = params->pir;
863         flow_template.m[params->meter_id].cbs = params->cbs;
864         flow_template.m[params->meter_id].pbs = params->pbs;
865
866         for (i = 0; i < params->n_flows; i++) {
867                 uint32_t pos = i % N_FLOWS_BULK;
868
869                 flow_id[pos] = i;
870                 memcpy(&flow_params[pos],
871                         &flow_template,
872                         sizeof(flow_template));
873
874                 if ((pos == N_FLOWS_BULK - 1) ||
875                         (i == params->n_flows - 1)) {
876                         int status;
877
878                         status = app_pipeline_fa_flow_config_bulk(app,
879                                 params->pipeline_id,
880                                 flow_id,
881                                 pos + 1,
882                                 1 << params->meter_id,
883                                 0,
884                                 0,
885                                 flow_params);
886
887                         if (status != 0) {
888                                 printf("Command failed\n");
889
890                                 break;
891                         }
892                 }
893         }
894
895         rte_free(flow_params);
896         rte_free(flow_id);
897
898 }
899
900 cmdline_parse_token_string_t cmd_fa_meter_config_bulk_p_string =
901         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
902         p_string, "p");
903
904 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pipeline_id =
905         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
906         pipeline_id, UINT32);
907
908 cmdline_parse_token_string_t cmd_fa_meter_config_bulk_flows_string =
909         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
910         flows_string, "flows");
911
912 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_n_flows =
913         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
914         n_flows, UINT32);
915
916 cmdline_parse_token_string_t cmd_fa_meter_config_bulk_meter_string =
917         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
918         meter_string, "meter");
919
920 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_meter_id =
921         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
922         meter_id, UINT32);
923
924 cmdline_parse_token_string_t cmd_fa_meter_config_bulk_trtcm_string =
925         TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
926         trtcm_string, "trtcm");
927
928 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cir =
929         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
930         cir, UINT64);
931
932 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pir =
933         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
934         pir, UINT64);
935
936 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cbs =
937         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
938         cbs, UINT64);
939
940 cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pbs =
941         TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
942         pbs, UINT64);
943
944 cmdline_parse_inst_t cmd_fa_meter_config_bulk = {
945         .f = cmd_fa_meter_config_bulk_parsed,
946         .data = NULL,
947         .help_str = "Flow meter configuration (multiple flows)",
948         .tokens = {
949                 (void *) &cmd_fa_meter_config_bulk_p_string,
950                 (void *) &cmd_fa_meter_config_bulk_pipeline_id,
951                 (void *) &cmd_fa_meter_config_bulk_flows_string,
952                 (void *) &cmd_fa_meter_config_bulk_n_flows,
953                 (void *) &cmd_fa_meter_config_bulk_meter_string,
954                 (void *) &cmd_fa_meter_config_bulk_meter_id,
955                 (void *) &cmd_fa_meter_config_bulk_trtcm_string,
956                 (void *) &cmd_fa_meter_config_cir,
957                 (void *) &cmd_fa_meter_config_pir,
958                 (void *) &cmd_fa_meter_config_cbs,
959                 (void *) &cmd_fa_meter_config_pbs,
960                 NULL,
961         },
962 };
963
964 /*
965  * Flow policer configuration (single flow)
966  *
967  * p <pipeline ID> flow <flow ID> policer <policer ID>
968  *    G <action> Y <action> R <action>
969  *
970  * <action> = G (green) | Y (yellow) | R (red) | D (drop)
971  */
972
973 struct cmd_fa_policer_config_result {
974         cmdline_fixed_string_t p_string;
975         uint32_t pipeline_id;
976         cmdline_fixed_string_t flow_string;
977         uint32_t flow_id;
978         cmdline_fixed_string_t policer_string;
979         uint32_t policer_id;
980         cmdline_fixed_string_t green_string;
981         cmdline_fixed_string_t g_action;
982         cmdline_fixed_string_t yellow_string;
983         cmdline_fixed_string_t y_action;
984         cmdline_fixed_string_t red_string;
985         cmdline_fixed_string_t r_action;
986 };
987
988 static void
989 cmd_fa_policer_config_parsed(
990         void *parsed_result,
991         __rte_unused struct cmdline *cl,
992         void *data)
993 {
994         struct cmd_fa_policer_config_result *params = parsed_result;
995         struct app_params *app = data;
996         struct pipeline_fa_flow_params flow_params;
997         int status;
998
999         if (params->policer_id >= PIPELINE_FA_N_TC_MAX) {
1000                 printf("Command failed\n");
1001                 return;
1002         }
1003
1004         status = string_to_policer_action(params->g_action,
1005                 &flow_params.p[params->policer_id].action[e_RTE_METER_GREEN]);
1006         if (status)
1007                 printf("Invalid policer green action\n");
1008
1009         status = string_to_policer_action(params->y_action,
1010                 &flow_params.p[params->policer_id].action[e_RTE_METER_YELLOW]);
1011         if (status)
1012                 printf("Invalid policer yellow action\n");
1013
1014         status = string_to_policer_action(params->r_action,
1015                 &flow_params.p[params->policer_id].action[e_RTE_METER_RED]);
1016         if (status)
1017                 printf("Invalid policer red action\n");
1018
1019         status = app_pipeline_fa_flow_config(app,
1020                 params->pipeline_id,
1021                 params->flow_id,
1022                 0,
1023                 1 << params->policer_id,
1024                 0,
1025                 &flow_params);
1026
1027         if (status != 0)
1028                 printf("Command failed\n");
1029
1030 }
1031
1032 cmdline_parse_token_string_t cmd_fa_policer_config_p_string =
1033         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1034         p_string, "p");
1035
1036 cmdline_parse_token_num_t cmd_fa_policer_config_pipeline_id =
1037         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
1038         pipeline_id, UINT32);
1039
1040 cmdline_parse_token_string_t cmd_fa_policer_config_flow_string =
1041         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1042         flow_string, "flow");
1043
1044 cmdline_parse_token_num_t cmd_fa_policer_config_flow_id =
1045         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
1046         flow_id, UINT32);
1047
1048 cmdline_parse_token_string_t cmd_fa_policer_config_policer_string =
1049         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1050         policer_string, "policer");
1051
1052 cmdline_parse_token_num_t cmd_fa_policer_config_policer_id =
1053         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
1054         policer_id, UINT32);
1055
1056 cmdline_parse_token_string_t cmd_fa_policer_config_green_string =
1057         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1058         green_string, "G");
1059
1060 cmdline_parse_token_string_t cmd_fa_policer_config_g_action =
1061         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1062         g_action, "R#Y#G#D");
1063
1064 cmdline_parse_token_string_t cmd_fa_policer_config_yellow_string =
1065         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1066         yellow_string, "Y");
1067
1068 cmdline_parse_token_string_t cmd_fa_policer_config_y_action =
1069         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1070         y_action, "R#Y#G#D");
1071
1072 cmdline_parse_token_string_t cmd_fa_policer_config_red_string =
1073         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1074         red_string, "R");
1075
1076 cmdline_parse_token_string_t cmd_fa_policer_config_r_action =
1077         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
1078         r_action, "R#Y#G#D");
1079
1080 cmdline_parse_inst_t cmd_fa_policer_config = {
1081         .f = cmd_fa_policer_config_parsed,
1082         .data = NULL,
1083         .help_str = "Flow policer configuration (single flow)",
1084         .tokens = {
1085                 (void *) &cmd_fa_policer_config_p_string,
1086                 (void *) &cmd_fa_policer_config_pipeline_id,
1087                 (void *) &cmd_fa_policer_config_flow_string,
1088                 (void *) &cmd_fa_policer_config_flow_id,
1089                 (void *) &cmd_fa_policer_config_policer_string,
1090                 (void *) &cmd_fa_policer_config_policer_id,
1091                 (void *) &cmd_fa_policer_config_green_string,
1092                 (void *) &cmd_fa_policer_config_g_action,
1093                 (void *) &cmd_fa_policer_config_yellow_string,
1094                 (void *) &cmd_fa_policer_config_y_action,
1095                 (void *) &cmd_fa_policer_config_red_string,
1096                 (void *) &cmd_fa_policer_config_r_action,
1097                 NULL,
1098         },
1099 };
1100
1101 /*
1102  * Flow policer configuration (multiple flows)
1103  *
1104  * p <pipeline ID> flows <n_flows> policer <policer ID>
1105  *    G <action> Y <action> R <action>
1106  *
1107  * <action> = G (green) | Y (yellow) | R (red) | D (drop)
1108  */
1109
1110 struct cmd_fa_policer_config_bulk_result {
1111         cmdline_fixed_string_t p_string;
1112         uint32_t pipeline_id;
1113         cmdline_fixed_string_t flows_string;
1114         uint32_t n_flows;
1115         cmdline_fixed_string_t policer_string;
1116         uint32_t policer_id;
1117         cmdline_fixed_string_t green_string;
1118         cmdline_fixed_string_t g_action;
1119         cmdline_fixed_string_t yellow_string;
1120         cmdline_fixed_string_t y_action;
1121         cmdline_fixed_string_t red_string;
1122         cmdline_fixed_string_t r_action;
1123 };
1124
1125 static void
1126 cmd_fa_policer_config_bulk_parsed(
1127         void *parsed_result,
1128         __rte_unused struct cmdline *cl,
1129         void *data)
1130 {
1131         struct cmd_fa_policer_config_bulk_result *params = parsed_result;
1132         struct app_params *app = data;
1133         struct pipeline_fa_flow_params flow_template, *flow_params;
1134         uint32_t *flow_id, i;
1135         int status;
1136
1137         if ((params->n_flows == 0) ||
1138                 (params->policer_id >= PIPELINE_FA_N_TC_MAX)) {
1139                 printf("Invalid arguments\n");
1140                 return;
1141         }
1142
1143         flow_id = (uint32_t *) rte_malloc(NULL,
1144                 N_FLOWS_BULK * sizeof(uint32_t),
1145                 RTE_CACHE_LINE_SIZE);
1146         if (flow_id == NULL) {
1147                 printf("Memory allocation failed\n");
1148                 return;
1149         }
1150
1151         flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
1152                 N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
1153                 RTE_CACHE_LINE_SIZE);
1154         if (flow_params == NULL) {
1155                 rte_free(flow_id);
1156                 printf("Memory allocation failed\n");
1157                 return;
1158         }
1159
1160         memset(&flow_template, 0, sizeof(flow_template));
1161
1162         status = string_to_policer_action(params->g_action,
1163                 &flow_template.p[params->policer_id].action[e_RTE_METER_GREEN]);
1164         if (status)
1165                 printf("Invalid policer green action\n");
1166
1167         status = string_to_policer_action(params->y_action,
1168          &flow_template.p[params->policer_id].action[e_RTE_METER_YELLOW]);
1169         if (status)
1170                 printf("Invalid policer yellow action\n");
1171
1172         status = string_to_policer_action(params->r_action,
1173                 &flow_template.p[params->policer_id].action[e_RTE_METER_RED]);
1174         if (status)
1175                 printf("Invalid policer red action\n");
1176
1177         for (i = 0; i < params->n_flows; i++) {
1178                 uint32_t pos = i % N_FLOWS_BULK;
1179
1180                 flow_id[pos] = i;
1181                 memcpy(&flow_params[pos], &flow_template,
1182                         sizeof(flow_template));
1183
1184                 if ((pos == N_FLOWS_BULK - 1) ||
1185                         (i == params->n_flows - 1)) {
1186                         int status;
1187
1188                         status = app_pipeline_fa_flow_config_bulk(app,
1189                                 params->pipeline_id,
1190                                 flow_id,
1191                                 pos + 1,
1192                                 0,
1193                                 1 << params->policer_id,
1194                                 0,
1195                                 flow_params);
1196
1197                         if (status != 0) {
1198                                 printf("Command failed\n");
1199
1200                                 break;
1201                         }
1202                 }
1203         }
1204
1205         rte_free(flow_params);
1206         rte_free(flow_id);
1207
1208 }
1209
1210 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_p_string =
1211         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1212         p_string, "p");
1213
1214 cmdline_parse_token_num_t cmd_fa_policer_config_bulk_pipeline_id =
1215         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1216         pipeline_id, UINT32);
1217
1218 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_flows_string =
1219         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1220         flows_string, "flows");
1221
1222 cmdline_parse_token_num_t cmd_fa_policer_config_bulk_n_flows =
1223         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1224         n_flows, UINT32);
1225
1226 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_policer_string =
1227         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1228         policer_string, "policer");
1229
1230 cmdline_parse_token_num_t cmd_fa_policer_config_bulk_policer_id =
1231         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1232         policer_id, UINT32);
1233
1234 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_green_string =
1235         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1236         green_string, "G");
1237
1238 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_g_action =
1239         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1240         g_action, "R#Y#G#D");
1241
1242 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_yellow_string =
1243         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1244         yellow_string, "Y");
1245
1246 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_y_action =
1247         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1248         y_action, "R#Y#G#D");
1249
1250 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_red_string =
1251         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1252         red_string, "R");
1253
1254 cmdline_parse_token_string_t cmd_fa_policer_config_bulk_r_action =
1255         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
1256         r_action, "R#Y#G#D");
1257
1258 cmdline_parse_inst_t cmd_fa_policer_config_bulk = {
1259         .f = cmd_fa_policer_config_bulk_parsed,
1260         .data = NULL,
1261         .help_str = "Flow policer configuration (multiple flows)",
1262         .tokens = {
1263                 (void *) &cmd_fa_policer_config_bulk_p_string,
1264                 (void *) &cmd_fa_policer_config_bulk_pipeline_id,
1265                 (void *) &cmd_fa_policer_config_bulk_flows_string,
1266                 (void *) &cmd_fa_policer_config_bulk_n_flows,
1267                 (void *) &cmd_fa_policer_config_bulk_policer_string,
1268                 (void *) &cmd_fa_policer_config_bulk_policer_id,
1269                 (void *) &cmd_fa_policer_config_bulk_green_string,
1270                 (void *) &cmd_fa_policer_config_bulk_g_action,
1271                 (void *) &cmd_fa_policer_config_bulk_yellow_string,
1272                 (void *) &cmd_fa_policer_config_bulk_y_action,
1273                 (void *) &cmd_fa_policer_config_bulk_red_string,
1274                 (void *) &cmd_fa_policer_config_bulk_r_action,
1275                 NULL,
1276         },
1277 };
1278
1279 /*
1280  * Flow output port configuration (single flow)
1281  *
1282  * p <pipeline ID> flow <flow ID> port <port ID>
1283  */
1284
1285 struct cmd_fa_output_port_config_result {
1286         cmdline_fixed_string_t p_string;
1287         uint32_t pipeline_id;
1288         cmdline_fixed_string_t flow_string;
1289         uint32_t flow_id;
1290         cmdline_fixed_string_t port_string;
1291         uint32_t port_id;
1292 };
1293
1294 static void
1295 cmd_fa_output_port_config_parsed(
1296         void *parsed_result,
1297         __rte_unused struct cmdline *cl,
1298         void *data)
1299 {
1300         struct cmd_fa_output_port_config_result *params = parsed_result;
1301         struct app_params *app = data;
1302         struct pipeline_fa_flow_params flow_params;
1303         int status;
1304
1305         flow_params.port_id = params->port_id;
1306
1307         status = app_pipeline_fa_flow_config(app,
1308                 params->pipeline_id,
1309                 params->flow_id,
1310                 0,
1311                 0,
1312                 1,
1313                 &flow_params);
1314
1315         if (status != 0)
1316                 printf("Command failed\n");
1317 }
1318
1319 cmdline_parse_token_string_t cmd_fa_output_port_config_p_string =
1320         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
1321         p_string, "p");
1322
1323 cmdline_parse_token_num_t cmd_fa_output_port_config_pipeline_id =
1324         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
1325         pipeline_id, UINT32);
1326
1327 cmdline_parse_token_string_t cmd_fa_output_port_config_flow_string =
1328         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
1329         flow_string, "flow");
1330
1331 cmdline_parse_token_num_t cmd_fa_output_port_config_flow_id =
1332         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
1333         flow_id, UINT32);
1334
1335 cmdline_parse_token_string_t cmd_fa_output_port_config_port_string =
1336         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
1337         port_string, "port");
1338
1339 cmdline_parse_token_num_t cmd_fa_output_port_config_port_id =
1340         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
1341         port_id, UINT32);
1342
1343 cmdline_parse_inst_t cmd_fa_output_port_config = {
1344         .f = cmd_fa_output_port_config_parsed,
1345         .data = NULL,
1346         .help_str = "Flow output port configuration (single flow)",
1347         .tokens = {
1348                 (void *) &cmd_fa_output_port_config_p_string,
1349                 (void *) &cmd_fa_output_port_config_pipeline_id,
1350                 (void *) &cmd_fa_output_port_config_flow_string,
1351                 (void *) &cmd_fa_output_port_config_flow_id,
1352                 (void *) &cmd_fa_output_port_config_port_string,
1353                 (void *) &cmd_fa_output_port_config_port_id,
1354                 NULL,
1355         },
1356 };
1357
1358 /*
1359  * Flow output port configuration (multiple flows)
1360  *
1361  * p <pipeline ID> flows <n_flows> ports <n_ports>
1362  */
1363
1364 struct cmd_fa_output_port_config_bulk_result {
1365         cmdline_fixed_string_t p_string;
1366         uint32_t pipeline_id;
1367         cmdline_fixed_string_t flows_string;
1368         uint32_t n_flows;
1369         cmdline_fixed_string_t ports_string;
1370         uint32_t n_ports;
1371 };
1372
1373 static void
1374 cmd_fa_output_port_config_bulk_parsed(
1375         void *parsed_result,
1376         __rte_unused struct cmdline *cl,
1377         void *data)
1378 {
1379         struct cmd_fa_output_port_config_bulk_result *params = parsed_result;
1380         struct app_params *app = data;
1381         struct pipeline_fa_flow_params *flow_params;
1382         uint32_t *flow_id;
1383         uint32_t i;
1384
1385         if (params->n_flows == 0) {
1386                 printf("Invalid arguments\n");
1387                 return;
1388         }
1389
1390         flow_id = (uint32_t *) rte_malloc(NULL,
1391                 N_FLOWS_BULK * sizeof(uint32_t),
1392                 RTE_CACHE_LINE_SIZE);
1393         if (flow_id == NULL) {
1394                 printf("Memory allocation failed\n");
1395                 return;
1396         }
1397
1398         flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
1399                 N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
1400                 RTE_CACHE_LINE_SIZE);
1401         if (flow_params == NULL) {
1402                 rte_free(flow_id);
1403                 printf("Memory allocation failed\n");
1404                 return;
1405         }
1406
1407         for (i = 0; i < params->n_flows; i++) {
1408                 uint32_t pos = i % N_FLOWS_BULK;
1409                 uint32_t port_id = i % params->n_ports;
1410
1411                 flow_id[pos] = i;
1412
1413                 memset(&flow_params[pos], 0, sizeof(flow_params[pos]));
1414                 flow_params[pos].port_id = port_id;
1415
1416                 if ((pos == N_FLOWS_BULK - 1) ||
1417                         (i == params->n_flows - 1)) {
1418                         int status;
1419
1420                         status = app_pipeline_fa_flow_config_bulk(app,
1421                                 params->pipeline_id,
1422                                 flow_id,
1423                                 pos + 1,
1424                                 0,
1425                                 0,
1426                                 1,
1427                                 flow_params);
1428
1429                         if (status != 0) {
1430                                 printf("Command failed\n");
1431
1432                                 break;
1433                         }
1434                 }
1435         }
1436
1437         rte_free(flow_params);
1438         rte_free(flow_id);
1439
1440 }
1441
1442 cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_p_string =
1443         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1444         p_string, "p");
1445
1446 cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_pipeline_id =
1447         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1448         pipeline_id, UINT32);
1449
1450 cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_flows_string =
1451         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1452         flows_string, "flows");
1453
1454 cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_flows =
1455         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1456         n_flows, UINT32);
1457
1458 cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_ports_string =
1459         TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1460         ports_string, "ports");
1461
1462 cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_ports =
1463         TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
1464         n_ports, UINT32);
1465
1466 cmdline_parse_inst_t cmd_fa_output_port_config_bulk = {
1467         .f = cmd_fa_output_port_config_bulk_parsed,
1468         .data = NULL,
1469         .help_str = "Flow output port configuration (multiple flows)",
1470         .tokens = {
1471                 (void *) &cmd_fa_output_port_config_bulk_p_string,
1472                 (void *) &cmd_fa_output_port_config_bulk_pipeline_id,
1473                 (void *) &cmd_fa_output_port_config_bulk_flows_string,
1474                 (void *) &cmd_fa_output_port_config_bulk_n_flows,
1475                 (void *) &cmd_fa_output_port_config_bulk_ports_string,
1476                 (void *) &cmd_fa_output_port_config_bulk_n_ports,
1477                 NULL,
1478         },
1479 };
1480
1481 /*
1482  * Flow DiffServ Code Point (DSCP) translation table configuration
1483  *
1484  * p <pipeline ID> dscp <DSCP ID> class <traffic class ID> color <color>
1485  *
1486  * <color> = G (green) | Y (yellow) | R (red)
1487 */
1488
1489 struct cmd_fa_dscp_config_result {
1490         cmdline_fixed_string_t p_string;
1491         uint32_t pipeline_id;
1492         cmdline_fixed_string_t dscp_string;
1493         uint32_t dscp_id;
1494         cmdline_fixed_string_t class_string;
1495         uint32_t traffic_class_id;
1496         cmdline_fixed_string_t color_string;
1497         cmdline_fixed_string_t color;
1498
1499 };
1500
1501 static void
1502 cmd_fa_dscp_config_parsed(
1503         void *parsed_result,
1504         __rte_unused struct cmdline *cl,
1505         void *data)
1506 {
1507         struct cmd_fa_dscp_config_result *params = parsed_result;
1508         struct app_params *app = data;
1509         enum rte_meter_color color;
1510         int status;
1511
1512         status = string_to_color(params->color, &color);
1513         if (status) {
1514                 printf("Invalid color\n");
1515                 return;
1516         }
1517
1518         status = app_pipeline_fa_dscp_config(app,
1519                 params->pipeline_id,
1520                 params->dscp_id,
1521                 params->traffic_class_id,
1522                 color);
1523
1524         if (status != 0)
1525                 printf("Command failed\n");
1526 }
1527
1528 cmdline_parse_token_string_t cmd_fa_dscp_config_p_string =
1529         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
1530         p_string, "p");
1531
1532 cmdline_parse_token_num_t cmd_fa_dscp_config_pipeline_id =
1533         TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
1534         pipeline_id, UINT32);
1535
1536 cmdline_parse_token_string_t cmd_fa_dscp_config_dscp_string =
1537         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
1538         dscp_string, "dscp");
1539
1540 cmdline_parse_token_num_t cmd_fa_dscp_config_dscp_id =
1541         TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
1542         dscp_id, UINT32);
1543
1544 cmdline_parse_token_string_t cmd_fa_dscp_config_class_string =
1545         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
1546         class_string, "class");
1547
1548 cmdline_parse_token_num_t cmd_fa_dscp_config_traffic_class_id =
1549         TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
1550         traffic_class_id, UINT32);
1551
1552 cmdline_parse_token_string_t cmd_fa_dscp_config_color_string =
1553         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
1554         color_string, "color");
1555
1556 cmdline_parse_token_string_t cmd_fa_dscp_config_color =
1557         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
1558         color, "G#Y#R");
1559
1560 cmdline_parse_inst_t cmd_fa_dscp_config = {
1561         .f = cmd_fa_dscp_config_parsed,
1562         .data = NULL,
1563         .help_str = "Flow DSCP translation table configuration",
1564         .tokens = {
1565                 (void *) &cmd_fa_dscp_config_p_string,
1566                 (void *) &cmd_fa_dscp_config_pipeline_id,
1567                 (void *) &cmd_fa_dscp_config_dscp_string,
1568                 (void *) &cmd_fa_dscp_config_dscp_id,
1569                 (void *) &cmd_fa_dscp_config_class_string,
1570                 (void *) &cmd_fa_dscp_config_traffic_class_id,
1571                 (void *) &cmd_fa_dscp_config_color_string,
1572                 (void *) &cmd_fa_dscp_config_color,
1573                 NULL,
1574         },
1575 };
1576
1577 /*
1578  * Flow policer stats read
1579  *
1580  * p <pipeline ID> flow <flow ID> policer <policer ID> stats
1581  */
1582
1583 struct cmd_fa_policer_stats_result {
1584         cmdline_fixed_string_t p_string;
1585         uint32_t pipeline_id;
1586         cmdline_fixed_string_t flow_string;
1587         uint32_t flow_id;
1588         cmdline_fixed_string_t policer_string;
1589         uint32_t policer_id;
1590         cmdline_fixed_string_t stats_string;
1591 };
1592
1593 static void
1594 cmd_fa_policer_stats_parsed(
1595         void *parsed_result,
1596         __rte_unused struct cmdline *cl,
1597         void *data)
1598 {
1599         struct cmd_fa_policer_stats_result *params = parsed_result;
1600         struct app_params *app = data;
1601         struct pipeline_fa_policer_stats stats;
1602         int status;
1603
1604         status = app_pipeline_fa_flow_policer_stats_read(app,
1605                 params->pipeline_id,
1606                 params->flow_id,
1607                 params->policer_id,
1608                 1,
1609                 &stats);
1610         if (status != 0) {
1611                 printf("Command failed\n");
1612                 return;
1613         }
1614
1615         /* Display stats */
1616         printf("\tPkts G: %" PRIu64
1617                 "\tPkts Y: %" PRIu64
1618                 "\tPkts R: %" PRIu64
1619                 "\tPkts D: %" PRIu64 "\n",
1620                 stats.n_pkts[e_RTE_METER_GREEN],
1621                 stats.n_pkts[e_RTE_METER_YELLOW],
1622                 stats.n_pkts[e_RTE_METER_RED],
1623                 stats.n_pkts_drop);
1624 }
1625
1626 cmdline_parse_token_string_t cmd_fa_policer_stats_p_string =
1627         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
1628         p_string, "p");
1629
1630 cmdline_parse_token_num_t cmd_fa_policer_stats_pipeline_id =
1631         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
1632         pipeline_id, UINT32);
1633
1634 cmdline_parse_token_string_t cmd_fa_policer_stats_flow_string =
1635         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
1636         flow_string, "flow");
1637
1638 cmdline_parse_token_num_t cmd_fa_policer_stats_flow_id =
1639         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
1640         flow_id, UINT32);
1641
1642 cmdline_parse_token_string_t cmd_fa_policer_stats_policer_string =
1643         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
1644         policer_string, "policer");
1645
1646 cmdline_parse_token_num_t cmd_fa_policer_stats_policer_id =
1647         TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
1648         policer_id, UINT32);
1649
1650 cmdline_parse_token_string_t cmd_fa_policer_stats_string =
1651         TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
1652         stats_string, "stats");
1653
1654 cmdline_parse_inst_t cmd_fa_policer_stats = {
1655         .f = cmd_fa_policer_stats_parsed,
1656         .data = NULL,
1657         .help_str = "Flow policer stats read",
1658         .tokens = {
1659                 (void *) &cmd_fa_policer_stats_p_string,
1660                 (void *) &cmd_fa_policer_stats_pipeline_id,
1661                 (void *) &cmd_fa_policer_stats_flow_string,
1662                 (void *) &cmd_fa_policer_stats_flow_id,
1663                 (void *) &cmd_fa_policer_stats_policer_string,
1664                 (void *) &cmd_fa_policer_stats_policer_id,
1665                 (void *) &cmd_fa_policer_stats_string,
1666                 NULL,
1667         },
1668 };
1669
1670 /*
1671  * Flow list
1672  *
1673  * p <pipeline ID> flow ls
1674  */
1675
1676 struct cmd_fa_flow_ls_result {
1677         cmdline_fixed_string_t p_string;
1678         uint32_t pipeline_id;
1679         cmdline_fixed_string_t flow_string;
1680         cmdline_fixed_string_t actions_string;
1681         cmdline_fixed_string_t ls_string;
1682 };
1683
1684 static void
1685 cmd_fa_flow_ls_parsed(
1686         void *parsed_result,
1687         __rte_unused struct cmdline *cl,
1688         void *data)
1689 {
1690         struct cmd_fa_flow_ls_result *params = parsed_result;
1691         struct app_params *app = data;
1692         int status;
1693
1694         status = app_pipeline_fa_flow_ls(app, params->pipeline_id);
1695         if (status != 0)
1696                 printf("Command failed\n");
1697 }
1698
1699 cmdline_parse_token_string_t cmd_fa_flow_ls_p_string =
1700         TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
1701         p_string, "p");
1702
1703 cmdline_parse_token_num_t cmd_fa_flow_ls_pipeline_id =
1704         TOKEN_NUM_INITIALIZER(struct cmd_fa_flow_ls_result,
1705         pipeline_id, UINT32);
1706
1707 cmdline_parse_token_string_t cmd_fa_flow_ls_flow_string =
1708         TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
1709         flow_string, "flow");
1710
1711 cmdline_parse_token_string_t cmd_fa_flow_ls_actions_string =
1712         TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
1713         actions_string, "actions");
1714
1715 cmdline_parse_token_string_t cmd_fa_flow_ls_ls_string =
1716         TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
1717         ls_string, "ls");
1718
1719 cmdline_parse_inst_t cmd_fa_flow_ls = {
1720         .f = cmd_fa_flow_ls_parsed,
1721         .data = NULL,
1722         .help_str = "Flow actions list",
1723         .tokens = {
1724                 (void *) &cmd_fa_flow_ls_p_string,
1725                 (void *) &cmd_fa_flow_ls_pipeline_id,
1726                 (void *) &cmd_fa_flow_ls_flow_string,
1727                 (void *) &cmd_fa_flow_ls_actions_string,
1728                 (void *) &cmd_fa_flow_ls_ls_string,
1729                 NULL,
1730         },
1731 };
1732
1733 /*
1734  * Flow DiffServ Code Point (DSCP) translation table list
1735  *
1736  * p <pipeline ID> dscp ls
1737  */
1738
1739 struct cmd_fa_dscp_ls_result {
1740         cmdline_fixed_string_t p_string;
1741         uint32_t pipeline_id;
1742         cmdline_fixed_string_t dscp_string;
1743         cmdline_fixed_string_t ls_string;
1744 };
1745
1746 static void
1747 cmd_fa_dscp_ls_parsed(
1748         void *parsed_result,
1749         __rte_unused struct cmdline *cl,
1750         void *data)
1751 {
1752         struct cmd_fa_dscp_ls_result *params = parsed_result;
1753         struct app_params *app = data;
1754         int status;
1755
1756         status = app_pipeline_fa_dscp_ls(app, params->pipeline_id);
1757         if (status != 0)
1758                 printf("Command failed\n");
1759 }
1760
1761 cmdline_parse_token_string_t cmd_fa_dscp_ls_p_string =
1762         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
1763         p_string, "p");
1764
1765 cmdline_parse_token_num_t cmd_fa_dscp_ls_pipeline_id =
1766         TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_ls_result,
1767         pipeline_id, UINT32);
1768
1769 cmdline_parse_token_string_t cmd_fa_dscp_ls_dscp_string =
1770         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
1771         dscp_string, "dscp");
1772
1773 cmdline_parse_token_string_t cmd_fa_dscp_ls_string =
1774         TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, ls_string,
1775         "ls");
1776
1777 cmdline_parse_inst_t cmd_fa_dscp_ls = {
1778         .f = cmd_fa_dscp_ls_parsed,
1779         .data = NULL,
1780         .help_str = "Flow DSCP translaton table list",
1781         .tokens = {
1782                 (void *) &cmd_fa_dscp_ls_p_string,
1783                 (void *) &cmd_fa_dscp_ls_pipeline_id,
1784                 (void *) &cmd_fa_dscp_ls_dscp_string,
1785                 (void *) &cmd_fa_dscp_ls_string,
1786                 NULL,
1787         },
1788 };
1789
1790 static cmdline_parse_ctx_t pipeline_cmds[] = {
1791         (cmdline_parse_inst_t *) &cmd_fa_meter_config,
1792         (cmdline_parse_inst_t *) &cmd_fa_meter_config_bulk,
1793         (cmdline_parse_inst_t *) &cmd_fa_policer_config,
1794         (cmdline_parse_inst_t *) &cmd_fa_policer_config_bulk,
1795         (cmdline_parse_inst_t *) &cmd_fa_output_port_config,
1796         (cmdline_parse_inst_t *) &cmd_fa_output_port_config_bulk,
1797         (cmdline_parse_inst_t *) &cmd_fa_dscp_config,
1798         (cmdline_parse_inst_t *) &cmd_fa_policer_stats,
1799         (cmdline_parse_inst_t *) &cmd_fa_flow_ls,
1800         (cmdline_parse_inst_t *) &cmd_fa_dscp_ls,
1801         NULL,
1802 };
1803
1804 static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = {
1805         .f_init = app_pipeline_fa_init,
1806         .f_free = app_pipeline_fa_free,
1807         .cmds = pipeline_cmds,
1808 };
1809
1810 struct pipeline_type pipeline_flow_actions = {
1811         .name = "FLOW_ACTIONS",
1812         .be_ops = &pipeline_flow_actions_be_ops,
1813         .fe_ops = &pipeline_flow_actions_fe_ops,
1814 };