4 * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
36 #include <sys/queue.h>
37 #include <netinet/in.h>
40 #include <rte_common.h>
41 #include <rte_hexdump.h>
42 #include <rte_malloc.h>
43 #include <cmdline_rdline.h>
44 #include <cmdline_parse.h>
45 #include <cmdline_parse_num.h>
46 #include <cmdline_parse_string.h>
49 #include "pipeline_common_fe.h"
50 #include "pipeline_flow_actions.h"
51 #include "hash_func.h"
55 * Flow actions pipeline
58 #define N_FLOWS_BULK 4096
61 struct app_pipeline_fa_flow
{
62 struct pipeline_fa_flow_params params
;
66 struct app_pipeline_fa_dscp
{
67 uint32_t traffic_class
;
68 enum rte_meter_color color
;
71 struct app_pipeline_fa
{
75 struct pipeline_fa_params params
;
78 struct app_pipeline_fa_dscp dscp
[PIPELINE_FA_N_DSCP
];
79 struct app_pipeline_fa_flow
*flows
;
80 } __rte_cache_aligned
;
83 app_pipeline_fa_init(struct pipeline_params
*params
,
84 __rte_unused
void *arg
)
86 struct app_pipeline_fa
*p
;
89 /* Check input arguments */
90 if ((params
== NULL
) ||
91 (params
->n_ports_in
== 0) ||
92 (params
->n_ports_out
== 0))
95 /* Memory allocation */
96 size
= RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fa
));
97 p
= rte_zmalloc(NULL
, size
, RTE_CACHE_LINE_SIZE
);
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
)) {
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
) {
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
);
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
;
132 app_pipeline_fa_free(void *pipeline
)
134 struct app_pipeline_fa
*p
= pipeline
;
136 /* Check input arguments */
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
)
159 for (i
= 0, mask
= 1; i
< PIPELINE_FA_N_TC_MAX
; i
++, mask
<<= 1) {
160 struct pipeline_fa_policer_params
*p
= ¶ms
->p
[i
];
163 if ((mask
& policer_update_mask
) == 0)
166 for (j
= 0; j
< e_RTE_METER_COLORS
; j
++) {
167 struct pipeline_fa_policer_action
*action
=
170 if ((action
->drop
== 0) &&
171 (action
->color
>= e_RTE_METER_COLORS
))
177 if (port_update
&& (params
->port_id
>= p
->n_ports_out
))
184 app_pipeline_fa_flow_config(struct app_params
*app
,
185 uint32_t pipeline_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
)
192 struct app_pipeline_fa
*p
;
193 struct app_pipeline_fa_flow
*flow
;
195 struct pipeline_fa_flow_config_msg_req
*req
;
196 struct pipeline_fa_flow_config_msg_rsp
*rsp
;
200 /* Check input arguments */
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
)) ||
210 p
= app_pipeline_data_fe(app
, pipeline_id
,
211 &pipeline_flow_actions
);
215 if (flow_params_check(p
,
222 flow_id
%= p
->params
.n_flows
;
223 flow
= &p
->flows
[flow_id
];
225 /* Allocate and write request */
226 req
= app_msg_alloc(app
);
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
));
239 /* Send request and wait for response */
240 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
246 (rsp
->entry_ptr
== NULL
)) {
247 app_msg_free(app
, rsp
);
252 for (i
= 0, mask
= 1; i
< PIPELINE_FA_N_TC_MAX
; i
++, mask
<<= 1) {
253 if ((mask
& meter_update_mask
) == 0)
256 memcpy(&flow
->params
.m
[i
], ¶ms
->m
[i
], sizeof(params
->m
[i
]));
259 for (i
= 0, mask
= 1; i
< PIPELINE_FA_N_TC_MAX
; i
++, mask
<<= 1) {
260 if ((mask
& policer_update_mask
) == 0)
263 memcpy(&flow
->params
.p
[i
], ¶ms
->p
[i
], sizeof(params
->p
[i
]));
267 flow
->params
.port_id
= params
->port_id
;
269 flow
->entry_ptr
= rsp
->entry_ptr
;
272 app_msg_free(app
, rsp
);
278 app_pipeline_fa_flow_config_bulk(struct app_params
*app
,
279 uint32_t pipeline_id
,
282 uint32_t meter_update_mask
,
283 uint32_t policer_update_mask
,
284 uint32_t port_update
,
285 struct pipeline_fa_flow_params
*params
)
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
;
295 /* Check input arguments */
299 ((meter_update_mask
== 0) &&
300 (policer_update_mask
== 0) &&
301 (port_update
== 0)) ||
302 (meter_update_mask
>= (1 << PIPELINE_FA_N_TC_MAX
)) ||
303 (policer_update_mask
>= (1 << PIPELINE_FA_N_TC_MAX
)) ||
307 p
= app_pipeline_data_fe(app
, pipeline_id
,
308 &pipeline_flow_actions
);
312 for (i
= 0; i
< n_flows
; i
++) {
313 struct pipeline_fa_flow_params
*flow_params
= ¶ms
[i
];
315 if (flow_params_check(p
,
323 /* Allocate and write request */
324 req_entry_ptr
= (void **) rte_malloc(NULL
,
325 n_flows
* sizeof(void *),
326 RTE_CACHE_LINE_SIZE
);
327 if (req_entry_ptr
== NULL
)
330 req_flow_id
= (uint32_t *) rte_malloc(NULL
,
331 n_flows
* sizeof(uint32_t),
332 RTE_CACHE_LINE_SIZE
);
333 if (req_flow_id
== NULL
) {
334 rte_free(req_entry_ptr
);
338 for (i
= 0; i
< n_flows
; i
++) {
339 uint32_t fid
= flow_id
[i
] % p
->params
.n_flows
;
340 struct app_pipeline_fa_flow
*flow
= &p
->flows
[fid
];
342 req_flow_id
[i
] = fid
;
343 req_entry_ptr
[i
] = flow
->entry_ptr
;
346 req
= app_msg_alloc(app
);
348 rte_free(req_flow_id
);
349 rte_free(req_entry_ptr
);
353 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
354 req
->subtype
= PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK
;
355 req
->entry_ptr
= req_entry_ptr
;
356 req
->flow_id
= req_flow_id
;
357 req
->n_flows
= n_flows
;
358 req
->meter_update_mask
= meter_update_mask
;
359 req
->policer_update_mask
= policer_update_mask
;
360 req
->port_update
= port_update
;
361 req
->params
= params
;
363 /* Send request and wait for response */
364 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
366 rte_free(req_flow_id
);
367 rte_free(req_entry_ptr
);
372 status
= (rsp
->n_flows
== n_flows
) ? 0 : -1;
375 for (i
= 0; i
< rsp
->n_flows
; i
++) {
376 uint32_t fid
= flow_id
[i
] % p
->params
.n_flows
;
377 struct app_pipeline_fa_flow
*flow
= &p
->flows
[fid
];
378 struct pipeline_fa_flow_params
*flow_params
= ¶ms
[i
];
379 void *entry_ptr
= req_entry_ptr
[i
];
382 for (j
= 0, mask
= 1; j
< PIPELINE_FA_N_TC_MAX
;
384 if ((mask
& meter_update_mask
) == 0)
387 memcpy(&flow
->params
.m
[j
],
389 sizeof(flow_params
->m
[j
]));
392 for (j
= 0, mask
= 1; j
< PIPELINE_FA_N_TC_MAX
;
394 if ((mask
& policer_update_mask
) == 0)
397 memcpy(&flow
->params
.p
[j
],
399 sizeof(flow_params
->p
[j
]));
403 flow
->params
.port_id
= flow_params
->port_id
;
405 flow
->entry_ptr
= entry_ptr
;
409 app_msg_free(app
, rsp
);
410 rte_free(req_flow_id
);
411 rte_free(req_entry_ptr
);
417 app_pipeline_fa_dscp_config(struct app_params
*app
,
418 uint32_t pipeline_id
,
420 uint32_t traffic_class
,
421 enum rte_meter_color color
)
423 struct app_pipeline_fa
*p
;
425 struct pipeline_fa_dscp_config_msg_req
*req
;
426 struct pipeline_fa_dscp_config_msg_rsp
*rsp
;
428 /* Check input arguments */
430 (dscp
>= PIPELINE_FA_N_DSCP
) ||
431 (traffic_class
>= PIPELINE_FA_N_TC_MAX
) ||
432 (color
>= e_RTE_METER_COLORS
))
435 p
= app_pipeline_data_fe(app
, pipeline_id
,
436 &pipeline_flow_actions
);
440 if (p
->params
.dscp_enabled
== 0)
443 /* Allocate and write request */
444 req
= app_msg_alloc(app
);
448 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
449 req
->subtype
= PIPELINE_FA_MSG_REQ_DSCP_CONFIG
;
451 req
->traffic_class
= traffic_class
;
454 /* Send request and wait for response */
455 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
461 app_msg_free(app
, rsp
);
466 p
->dscp
[dscp
].traffic_class
= traffic_class
;
467 p
->dscp
[dscp
].color
= color
;
470 app_msg_free(app
, rsp
);
476 app_pipeline_fa_flow_policer_stats_read(struct app_params
*app
,
477 uint32_t pipeline_id
,
481 struct pipeline_fa_policer_stats
*stats
)
483 struct app_pipeline_fa
*p
;
484 struct app_pipeline_fa_flow
*flow
;
486 struct pipeline_fa_policer_stats_msg_req
*req
;
487 struct pipeline_fa_policer_stats_msg_rsp
*rsp
;
489 /* Check input arguments */
490 if ((app
== NULL
) || (stats
== NULL
))
493 p
= app_pipeline_data_fe(app
, pipeline_id
,
494 &pipeline_flow_actions
);
498 flow_id
%= p
->params
.n_flows
;
499 flow
= &p
->flows
[flow_id
];
501 if ((policer_id
>= p
->params
.n_meters_per_flow
) ||
502 (flow
->entry_ptr
== NULL
))
505 /* Allocate and write request */
506 req
= app_msg_alloc(app
);
510 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
511 req
->subtype
= PIPELINE_FA_MSG_REQ_POLICER_STATS_READ
;
512 req
->entry_ptr
= flow
->entry_ptr
;
513 req
->policer_id
= policer_id
;
516 /* Send request and wait for response */
517 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
523 app_msg_free(app
, rsp
);
527 memcpy(stats
, &rsp
->stats
, sizeof(*stats
));
530 app_msg_free(app
, rsp
);
536 color_to_string(enum rte_meter_color color
)
539 case e_RTE_METER_GREEN
: return "G";
540 case e_RTE_METER_YELLOW
: return "Y";
541 case e_RTE_METER_RED
: return "R";
547 string_to_color(char *s
, enum rte_meter_color
*c
)
549 if (strcmp(s
, "G") == 0) {
550 *c
= e_RTE_METER_GREEN
;
554 if (strcmp(s
, "Y") == 0) {
555 *c
= e_RTE_METER_YELLOW
;
559 if (strcmp(s
, "R") == 0) {
560 *c
= e_RTE_METER_RED
;
568 policer_action_to_string(struct pipeline_fa_policer_action
*a
)
573 return color_to_string(a
->color
);
577 string_to_policer_action(char *s
, struct pipeline_fa_policer_action
*a
)
579 if (strcmp(s
, "G") == 0) {
581 a
->color
= e_RTE_METER_GREEN
;
585 if (strcmp(s
, "Y") == 0) {
587 a
->color
= e_RTE_METER_YELLOW
;
591 if (strcmp(s
, "R") == 0) {
593 a
->color
= e_RTE_METER_RED
;
597 if (strcmp(s
, "D") == 0) {
599 a
->color
= e_RTE_METER_GREEN
;
607 print_flow(struct app_pipeline_fa
*p
,
609 struct app_pipeline_fa_flow
*flow
)
613 printf("Flow ID = %" PRIu32
"\n", flow_id
);
615 for (i
= 0; i
< p
->params
.n_meters_per_flow
; i
++) {
616 struct rte_meter_trtcm_params
*meter
= &flow
->params
.m
[i
];
617 struct pipeline_fa_policer_params
*policer
= &flow
->params
.p
[i
];
619 printf("\ttrTCM [CIR = %" PRIu64
620 ", CBS = %" PRIu64
", PIR = %" PRIu64
621 ", PBS = %" PRIu64
"] Policer [G : %s, Y : %s, R : %s]\n",
626 policer_action_to_string(&policer
->action
[e_RTE_METER_GREEN
]),
627 policer_action_to_string(&policer
->action
[e_RTE_METER_YELLOW
]),
628 policer_action_to_string(&policer
->action
[e_RTE_METER_RED
]));
631 printf("\tPort %u (entry_ptr = %p)\n",
632 flow
->params
.port_id
,
638 app_pipeline_fa_flow_ls(struct app_params
*app
,
639 uint32_t pipeline_id
)
641 struct app_pipeline_fa
*p
;
644 /* Check input arguments */
648 p
= app_pipeline_data_fe(app
, pipeline_id
,
649 &pipeline_flow_actions
);
653 for (i
= 0; i
< p
->params
.n_flows
; i
++) {
654 struct app_pipeline_fa_flow
*flow
= &p
->flows
[i
];
656 print_flow(p
, i
, flow
);
663 app_pipeline_fa_dscp_ls(struct app_params
*app
,
664 uint32_t pipeline_id
)
666 struct app_pipeline_fa
*p
;
669 /* Check input arguments */
673 p
= app_pipeline_data_fe(app
, pipeline_id
,
674 &pipeline_flow_actions
);
678 if (p
->params
.dscp_enabled
== 0)
681 for (i
= 0; i
< RTE_DIM(p
->dscp
); i
++) {
682 struct app_pipeline_fa_dscp
*dscp
= &p
->dscp
[i
];
684 printf("DSCP = %2" PRIu32
": Traffic class = %" PRIu32
688 color_to_string(dscp
->color
));
695 app_pipeline_fa_load_file(char *filename
,
697 struct pipeline_fa_flow_params
*p
,
705 /* Check input arguments */
706 if ((filename
== NULL
) ||
707 (flow_ids
== NULL
) ||
717 /* Open input file */
718 f
= fopen(filename
, "r");
725 for (i
= 0, l
= 1; i
< *n_flows
; l
++) {
727 uint32_t n_tokens
= RTE_DIM(tokens
);
731 if (fgets(file_buf
, sizeof(file_buf
), f
) == NULL
)
734 status
= parse_tokenize_string(file_buf
, tokens
, &n_tokens
);
738 if ((n_tokens
== 0) || (tokens
[0][0] == '#'))
742 if ((n_tokens
!= 64) ||
744 strcmp(tokens
[0], "flow") ||
745 parser_read_uint32(&flow_ids
[i
], tokens
[1]) ||
747 /* meter & policer 0 */
748 strcmp(tokens
[2], "meter") ||
749 strcmp(tokens
[3], "0") ||
750 strcmp(tokens
[4], "trtcm") ||
751 parser_read_uint64(&p
[i
].m
[0].cir
, tokens
[5]) ||
752 parser_read_uint64(&p
[i
].m
[0].pir
, tokens
[6]) ||
753 parser_read_uint64(&p
[i
].m
[0].cbs
, tokens
[7]) ||
754 parser_read_uint64(&p
[i
].m
[0].pbs
, tokens
[8]) ||
755 strcmp(tokens
[9], "policer") ||
756 strcmp(tokens
[10], "0") ||
757 strcmp(tokens
[11], "g") ||
758 string_to_policer_action(tokens
[12],
759 &p
[i
].p
[0].action
[e_RTE_METER_GREEN
]) ||
760 strcmp(tokens
[13], "y") ||
761 string_to_policer_action(tokens
[14],
762 &p
[i
].p
[0].action
[e_RTE_METER_YELLOW
]) ||
763 strcmp(tokens
[15], "r") ||
764 string_to_policer_action(tokens
[16],
765 &p
[i
].p
[0].action
[e_RTE_METER_RED
]) ||
767 /* meter & policer 1 */
768 strcmp(tokens
[17], "meter") ||
769 strcmp(tokens
[18], "1") ||
770 strcmp(tokens
[19], "trtcm") ||
771 parser_read_uint64(&p
[i
].m
[1].cir
, tokens
[20]) ||
772 parser_read_uint64(&p
[i
].m
[1].pir
, tokens
[21]) ||
773 parser_read_uint64(&p
[i
].m
[1].cbs
, tokens
[22]) ||
774 parser_read_uint64(&p
[i
].m
[1].pbs
, tokens
[23]) ||
775 strcmp(tokens
[24], "policer") ||
776 strcmp(tokens
[25], "1") ||
777 strcmp(tokens
[26], "g") ||
778 string_to_policer_action(tokens
[27],
779 &p
[i
].p
[1].action
[e_RTE_METER_GREEN
]) ||
780 strcmp(tokens
[28], "y") ||
781 string_to_policer_action(tokens
[29],
782 &p
[i
].p
[1].action
[e_RTE_METER_YELLOW
]) ||
783 strcmp(tokens
[30], "r") ||
784 string_to_policer_action(tokens
[31],
785 &p
[i
].p
[1].action
[e_RTE_METER_RED
]) ||
787 /* meter & policer 2 */
788 strcmp(tokens
[32], "meter") ||
789 strcmp(tokens
[33], "2") ||
790 strcmp(tokens
[34], "trtcm") ||
791 parser_read_uint64(&p
[i
].m
[2].cir
, tokens
[35]) ||
792 parser_read_uint64(&p
[i
].m
[2].pir
, tokens
[36]) ||
793 parser_read_uint64(&p
[i
].m
[2].cbs
, tokens
[37]) ||
794 parser_read_uint64(&p
[i
].m
[2].pbs
, tokens
[38]) ||
795 strcmp(tokens
[39], "policer") ||
796 strcmp(tokens
[40], "2") ||
797 strcmp(tokens
[41], "g") ||
798 string_to_policer_action(tokens
[42],
799 &p
[i
].p
[2].action
[e_RTE_METER_GREEN
]) ||
800 strcmp(tokens
[43], "y") ||
801 string_to_policer_action(tokens
[44],
802 &p
[i
].p
[2].action
[e_RTE_METER_YELLOW
]) ||
803 strcmp(tokens
[45], "r") ||
804 string_to_policer_action(tokens
[46],
805 &p
[i
].p
[2].action
[e_RTE_METER_RED
]) ||
807 /* meter & policer 3 */
808 strcmp(tokens
[47], "meter") ||
809 strcmp(tokens
[48], "3") ||
810 strcmp(tokens
[49], "trtcm") ||
811 parser_read_uint64(&p
[i
].m
[3].cir
, tokens
[50]) ||
812 parser_read_uint64(&p
[i
].m
[3].pir
, tokens
[51]) ||
813 parser_read_uint64(&p
[i
].m
[3].cbs
, tokens
[52]) ||
814 parser_read_uint64(&p
[i
].m
[3].pbs
, tokens
[53]) ||
815 strcmp(tokens
[54], "policer") ||
816 strcmp(tokens
[55], "3") ||
817 strcmp(tokens
[56], "g") ||
818 string_to_policer_action(tokens
[57],
819 &p
[i
].p
[3].action
[e_RTE_METER_GREEN
]) ||
820 strcmp(tokens
[58], "y") ||
821 string_to_policer_action(tokens
[59],
822 &p
[i
].p
[3].action
[e_RTE_METER_YELLOW
]) ||
823 strcmp(tokens
[60], "r") ||
824 string_to_policer_action(tokens
[61],
825 &p
[i
].p
[3].action
[e_RTE_METER_RED
]) ||
828 strcmp(tokens
[62], "port") ||
829 parser_read_uint32(&p
[i
].port_id
, tokens
[63]))
849 * flow meter, policer and output port configuration:
850 * p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs>
852 * p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction>
853 * <action> is one of the following:
854 * G = recolor to green
855 * Y = recolor as yellow
859 * p <pipelineid> action flow <flowid> port <port ID>
861 * p <pipelineid> action flow bulk <file>
863 * flow policer stats read:
864 * p <pipelineid> action flow <flowid> stats
867 * p <pipelineid> action flow ls
869 * dscp table configuration:
870 * p <pipelineid> action dscp <dscpid> class <class ID> color <color>
873 * p <pipelineid> action dscp ls
876 struct cmd_action_result
{
877 cmdline_fixed_string_t p_string
;
878 uint32_t pipeline_id
;
879 cmdline_fixed_string_t action_string
;
880 cmdline_multi_string_t multi_string
;
886 __rte_unused
struct cmdline
*cl
,
889 struct cmd_action_result
*params
= parsed_result
;
890 struct app_params
*app
= data
;
893 uint32_t n_tokens
= RTE_DIM(tokens
);
896 status
= parse_tokenize_string(params
->multi_string
, tokens
, &n_tokens
);
898 printf(CMD_MSG_TOO_MANY_ARGS
, "action");
902 /* action flow meter */
903 if ((n_tokens
>= 3) &&
904 (strcmp(tokens
[0], "flow") == 0) &&
905 strcmp(tokens
[1], "bulk") &&
906 strcmp(tokens
[1], "ls") &&
907 (strcmp(tokens
[2], "meter") == 0)) {
908 struct pipeline_fa_flow_params flow_params
;
909 uint32_t flow_id
, meter_id
;
912 printf(CMD_MSG_MISMATCH_ARGS
, "action flow meter");
916 memset(&flow_params
, 0, sizeof(flow_params
));
918 if (parser_read_uint32(&flow_id
, tokens
[1])) {
919 printf(CMD_MSG_INVALID_ARG
, "flowid");
923 if (parser_read_uint32(&meter_id
, tokens
[3]) ||
924 (meter_id
>= PIPELINE_FA_N_TC_MAX
)) {
925 printf(CMD_MSG_INVALID_ARG
, "meterid");
929 if (strcmp(tokens
[4], "trtcm")) {
930 printf(CMD_MSG_ARG_NOT_FOUND
, "trtcm");
934 if (parser_read_uint64(&flow_params
.m
[meter_id
].cir
, tokens
[5])) {
935 printf(CMD_MSG_INVALID_ARG
, "cir");
939 if (parser_read_uint64(&flow_params
.m
[meter_id
].pir
, tokens
[6])) {
940 printf(CMD_MSG_INVALID_ARG
, "pir");
944 if (parser_read_uint64(&flow_params
.m
[meter_id
].cbs
, tokens
[7])) {
945 printf(CMD_MSG_INVALID_ARG
, "cbs");
949 if (parser_read_uint64(&flow_params
.m
[meter_id
].pbs
, tokens
[8])) {
950 printf(CMD_MSG_INVALID_ARG
, "pbs");
954 status
= app_pipeline_fa_flow_config(app
,
962 printf(CMD_MSG_FAIL
, "action flow meter");
965 } /* action flow meter */
967 /* action flow policer */
968 if ((n_tokens
>= 3) &&
969 (strcmp(tokens
[0], "flow") == 0) &&
970 strcmp(tokens
[1], "bulk") &&
971 strcmp(tokens
[1], "ls") &&
972 (strcmp(tokens
[2], "policer") == 0)) {
973 struct pipeline_fa_flow_params flow_params
;
974 uint32_t flow_id
, policer_id
;
976 if (n_tokens
!= 10) {
977 printf(CMD_MSG_MISMATCH_ARGS
, "action flow policer");
981 memset(&flow_params
, 0, sizeof(flow_params
));
983 if (parser_read_uint32(&flow_id
, tokens
[1])) {
984 printf(CMD_MSG_INVALID_ARG
, "flowid");
988 if (parser_read_uint32(&policer_id
, tokens
[3]) ||
989 (policer_id
>= PIPELINE_FA_N_TC_MAX
)) {
990 printf(CMD_MSG_INVALID_ARG
, "policerid");
994 if (strcmp(tokens
[4], "g")) {
995 printf(CMD_MSG_ARG_NOT_FOUND
, "g");
999 if (string_to_policer_action(tokens
[5],
1000 &flow_params
.p
[policer_id
].action
[e_RTE_METER_GREEN
])) {
1001 printf(CMD_MSG_INVALID_ARG
, "gaction");
1005 if (strcmp(tokens
[6], "y")) {
1006 printf(CMD_MSG_ARG_NOT_FOUND
, "y");
1010 if (string_to_policer_action(tokens
[7],
1011 &flow_params
.p
[policer_id
].action
[e_RTE_METER_YELLOW
])) {
1012 printf(CMD_MSG_INVALID_ARG
, "yaction");
1016 if (strcmp(tokens
[8], "r")) {
1017 printf(CMD_MSG_ARG_NOT_FOUND
, "r");
1021 if (string_to_policer_action(tokens
[9],
1022 &flow_params
.p
[policer_id
].action
[e_RTE_METER_RED
])) {
1023 printf(CMD_MSG_INVALID_ARG
, "raction");
1027 status
= app_pipeline_fa_flow_config(app
,
1028 params
->pipeline_id
,
1035 printf(CMD_MSG_FAIL
, "action flow policer");
1038 } /* action flow policer */
1040 /* action flow port */
1041 if ((n_tokens
>= 3) &&
1042 (strcmp(tokens
[0], "flow") == 0) &&
1043 strcmp(tokens
[1], "bulk") &&
1044 strcmp(tokens
[1], "ls") &&
1045 (strcmp(tokens
[2], "port") == 0)) {
1046 struct pipeline_fa_flow_params flow_params
;
1047 uint32_t flow_id
, port_id
;
1049 if (n_tokens
!= 4) {
1050 printf(CMD_MSG_MISMATCH_ARGS
, "action flow port");
1054 memset(&flow_params
, 0, sizeof(flow_params
));
1056 if (parser_read_uint32(&flow_id
, tokens
[1])) {
1057 printf(CMD_MSG_INVALID_ARG
, "flowid");
1061 if (parser_read_uint32(&port_id
, tokens
[3])) {
1062 printf(CMD_MSG_INVALID_ARG
, "portid");
1066 flow_params
.port_id
= port_id
;
1068 status
= app_pipeline_fa_flow_config(app
,
1069 params
->pipeline_id
,
1076 printf(CMD_MSG_FAIL
, "action flow port");
1079 } /* action flow port */
1081 /* action flow stats */
1082 if ((n_tokens
>= 3) &&
1083 (strcmp(tokens
[0], "flow") == 0) &&
1084 strcmp(tokens
[1], "bulk") &&
1085 strcmp(tokens
[1], "ls") &&
1086 (strcmp(tokens
[2], "stats") == 0)) {
1087 struct pipeline_fa_policer_stats stats
;
1088 uint32_t flow_id
, policer_id
;
1090 if (n_tokens
!= 3) {
1091 printf(CMD_MSG_MISMATCH_ARGS
, "action flow stats");
1095 if (parser_read_uint32(&flow_id
, tokens
[1])) {
1096 printf(CMD_MSG_INVALID_ARG
, "flowid");
1100 for (policer_id
= 0;
1101 policer_id
< PIPELINE_FA_N_TC_MAX
;
1103 status
= app_pipeline_fa_flow_policer_stats_read(app
,
1104 params
->pipeline_id
,
1110 printf(CMD_MSG_FAIL
, "action flow stats");
1115 printf("\tPolicer: %" PRIu32
1116 "\tPkts G: %" PRIu64
1117 "\tPkts Y: %" PRIu64
1118 "\tPkts R: %" PRIu64
1119 "\tPkts D: %" PRIu64
"\n",
1121 stats
.n_pkts
[e_RTE_METER_GREEN
],
1122 stats
.n_pkts
[e_RTE_METER_YELLOW
],
1123 stats
.n_pkts
[e_RTE_METER_RED
],
1128 } /* action flow stats */
1130 /* action flow bulk */
1131 if ((n_tokens
>= 2) &&
1132 (strcmp(tokens
[0], "flow") == 0) &&
1133 (strcmp(tokens
[1], "bulk") == 0)) {
1134 struct pipeline_fa_flow_params
*flow_params
;
1135 uint32_t *flow_ids
, n_flows
, line
;
1138 if (n_tokens
!= 3) {
1139 printf(CMD_MSG_MISMATCH_ARGS
, "action flow bulk");
1143 filename
= tokens
[2];
1145 n_flows
= APP_PIPELINE_FA_MAX_RECORDS_IN_FILE
;
1146 flow_ids
= malloc(n_flows
* sizeof(uint32_t));
1147 if (flow_ids
== NULL
) {
1148 printf(CMD_MSG_OUT_OF_MEMORY
);
1152 flow_params
= malloc(n_flows
* sizeof(struct pipeline_fa_flow_params
));
1153 if (flow_params
== NULL
) {
1154 printf(CMD_MSG_OUT_OF_MEMORY
);
1159 status
= app_pipeline_fa_load_file(filename
,
1165 printf(CMD_MSG_FILE_ERR
, filename
, line
);
1171 status
= app_pipeline_fa_flow_config_bulk(app
,
1172 params
->pipeline_id
,
1180 printf(CMD_MSG_FAIL
, "action flow bulk");
1185 } /* action flow bulk */
1187 /* action flow ls */
1188 if ((n_tokens
>= 2) &&
1189 (strcmp(tokens
[0], "flow") == 0) &&
1190 (strcmp(tokens
[1], "ls") == 0)) {
1191 if (n_tokens
!= 2) {
1192 printf(CMD_MSG_MISMATCH_ARGS
, "action flow ls");
1196 status
= app_pipeline_fa_flow_ls(app
,
1197 params
->pipeline_id
);
1199 printf(CMD_MSG_FAIL
, "action flow ls");
1202 } /* action flow ls */
1205 if ((n_tokens
>= 2) &&
1206 (strcmp(tokens
[0], "dscp") == 0) &&
1207 strcmp(tokens
[1], "ls")) {
1208 uint32_t dscp_id
, tc_id
;
1209 enum rte_meter_color color
;
1211 if (n_tokens
!= 6) {
1212 printf(CMD_MSG_MISMATCH_ARGS
, "action dscp");
1216 if (parser_read_uint32(&dscp_id
, tokens
[1])) {
1217 printf(CMD_MSG_INVALID_ARG
, "dscpid");
1221 if (strcmp(tokens
[2], "class")) {
1222 printf(CMD_MSG_ARG_NOT_FOUND
, "class");
1226 if (parser_read_uint32(&tc_id
, tokens
[3])) {
1227 printf(CMD_MSG_INVALID_ARG
, "classid");
1231 if (strcmp(tokens
[4], "color")) {
1232 printf(CMD_MSG_ARG_NOT_FOUND
, "color");
1236 if (string_to_color(tokens
[5], &color
)) {
1237 printf(CMD_MSG_INVALID_ARG
, "colorid");
1241 status
= app_pipeline_fa_dscp_config(app
,
1242 params
->pipeline_id
,
1247 printf(CMD_MSG_FAIL
, "action dscp");
1252 /* action dscp ls */
1253 if ((n_tokens
>= 2) &&
1254 (strcmp(tokens
[0], "dscp") == 0) &&
1255 (strcmp(tokens
[1], "ls") == 0)) {
1256 if (n_tokens
!= 2) {
1257 printf(CMD_MSG_MISMATCH_ARGS
, "action dscp ls");
1261 status
= app_pipeline_fa_dscp_ls(app
,
1262 params
->pipeline_id
);
1264 printf(CMD_MSG_FAIL
, "action dscp ls");
1267 } /* action dscp ls */
1269 printf(CMD_MSG_FAIL
, "action");
1272 static cmdline_parse_token_string_t cmd_action_p_string
=
1273 TOKEN_STRING_INITIALIZER(struct cmd_action_result
, p_string
, "p");
1275 static cmdline_parse_token_num_t cmd_action_pipeline_id
=
1276 TOKEN_NUM_INITIALIZER(struct cmd_action_result
, pipeline_id
, UINT32
);
1278 static cmdline_parse_token_string_t cmd_action_action_string
=
1279 TOKEN_STRING_INITIALIZER(struct cmd_action_result
, action_string
, "action");
1281 static cmdline_parse_token_string_t cmd_action_multi_string
=
1282 TOKEN_STRING_INITIALIZER(struct cmd_action_result
, multi_string
,
1283 TOKEN_STRING_MULTI
);
1285 cmdline_parse_inst_t cmd_action
= {
1286 .f
= cmd_action_parsed
,
1288 .help_str
= "flow actions (meter, policer, policer stats, dscp table)",
1290 (void *) &cmd_action_p_string
,
1291 (void *) &cmd_action_pipeline_id
,
1292 (void *) &cmd_action_action_string
,
1293 (void *) &cmd_action_multi_string
,
1298 static cmdline_parse_ctx_t pipeline_cmds
[] = {
1299 (cmdline_parse_inst_t
*) &cmd_action
,
1303 static struct pipeline_fe_ops pipeline_flow_actions_fe_ops
= {
1304 .f_init
= app_pipeline_fa_init
,
1305 .f_post_init
= NULL
,
1306 .f_free
= app_pipeline_fa_free
,
1307 .f_track
= app_pipeline_track_default
,
1308 .cmds
= pipeline_cmds
,
1311 struct pipeline_type pipeline_flow_actions
= {
1312 .name
= "FLOW_ACTIONS",
1313 .be_ops
= &pipeline_flow_actions_be_ops
,
1314 .fe_ops
= &pipeline_flow_actions_fe_ops
,