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;
294 /* Check input arguments */
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)) ||
306 p = app_pipeline_data_fe(app, pipeline_id,
307 &pipeline_flow_actions);
311 for (i = 0; i < n_flows; i++) {
312 struct pipeline_fa_flow_params *flow_params = ¶ms[i];
314 if (flow_params_check(p,
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)
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);
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];
341 req_flow_id[i] = fid;
342 req_entry_ptr[i] = flow->entry_ptr;
345 req = app_msg_alloc(app);
347 rte_free(req_flow_id);
348 rte_free(req_entry_ptr);
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;
362 /* Send request and wait for response */
363 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
365 rte_free(req_flow_id);
366 rte_free(req_entry_ptr);
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 = ¶ms[i];
377 void *entry_ptr = req_entry_ptr[i];
380 for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;
382 if ((mask & meter_update_mask) == 0)
385 memcpy(&flow->params.m[j],
387 sizeof(flow_params->m[j]));
390 for (j = 0, mask = 1; j < PIPELINE_FA_N_TC_MAX;
392 if ((mask & policer_update_mask) == 0)
395 memcpy(&flow->params.p[j],
397 sizeof(flow_params->p[j]));
401 flow->params.port_id = flow_params->port_id;
403 flow->entry_ptr = entry_ptr;
407 app_msg_free(app, rsp);
408 rte_free(req_flow_id);
409 rte_free(req_entry_ptr);
411 return (rsp->n_flows == n_flows) ? 0 : -1;
415 app_pipeline_fa_dscp_config(struct app_params *app,
416 uint32_t pipeline_id,
418 uint32_t traffic_class,
419 enum rte_meter_color color)
421 struct app_pipeline_fa *p;
423 struct pipeline_fa_dscp_config_msg_req *req;
424 struct pipeline_fa_dscp_config_msg_rsp *rsp;
426 /* Check input arguments */
428 (dscp >= PIPELINE_FA_N_DSCP) ||
429 (traffic_class >= PIPELINE_FA_N_TC_MAX) ||
430 (color >= e_RTE_METER_COLORS))
433 p = app_pipeline_data_fe(app, pipeline_id,
434 &pipeline_flow_actions);
438 if (p->params.dscp_enabled == 0)
441 /* Allocate and write request */
442 req = app_msg_alloc(app);
446 req->type = PIPELINE_MSG_REQ_CUSTOM;
447 req->subtype = PIPELINE_FA_MSG_REQ_DSCP_CONFIG;
449 req->traffic_class = traffic_class;
452 /* Send request and wait for response */
453 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
459 app_msg_free(app, rsp);
464 p->dscp[dscp].traffic_class = traffic_class;
465 p->dscp[dscp].color = color;
468 app_msg_free(app, rsp);
474 app_pipeline_fa_flow_policer_stats_read(struct app_params *app,
475 uint32_t pipeline_id,
479 struct pipeline_fa_policer_stats *stats)
481 struct app_pipeline_fa *p;
482 struct app_pipeline_fa_flow *flow;
484 struct pipeline_fa_policer_stats_msg_req *req;
485 struct pipeline_fa_policer_stats_msg_rsp *rsp;
487 /* Check input arguments */
488 if ((app == NULL) || (stats == NULL))
491 p = app_pipeline_data_fe(app, pipeline_id,
492 &pipeline_flow_actions);
496 flow_id %= p->params.n_flows;
497 flow = &p->flows[flow_id];
499 if ((policer_id >= p->params.n_meters_per_flow) ||
500 (flow->entry_ptr == NULL))
503 /* Allocate and write request */
504 req = app_msg_alloc(app);
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;
514 /* Send request and wait for response */
515 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
521 app_msg_free(app, rsp);
525 memcpy(stats, &rsp->stats, sizeof(*stats));
528 app_msg_free(app, rsp);
534 color_to_string(enum rte_meter_color 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";
545 string_to_color(char *s, enum rte_meter_color *c)
547 if (strcmp(s, "G") == 0) {
548 *c = e_RTE_METER_GREEN;
552 if (strcmp(s, "Y") == 0) {
553 *c = e_RTE_METER_YELLOW;
557 if (strcmp(s, "R") == 0) {
558 *c = e_RTE_METER_RED;
566 policer_action_to_string(struct pipeline_fa_policer_action *a)
571 return color_to_string(a->color);
575 string_to_policer_action(char *s, struct pipeline_fa_policer_action *a)
577 if (strcmp(s, "G") == 0) {
579 a->color = e_RTE_METER_GREEN;
583 if (strcmp(s, "Y") == 0) {
585 a->color = e_RTE_METER_YELLOW;
589 if (strcmp(s, "R") == 0) {
591 a->color = e_RTE_METER_RED;
595 if (strcmp(s, "D") == 0) {
597 a->color = e_RTE_METER_GREEN;
605 print_flow(struct app_pipeline_fa *p,
607 struct app_pipeline_fa_flow *flow)
611 printf("Flow ID = %" PRIu32 "\n", flow_id);
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];
617 printf("\ttrTCM [CIR = %" PRIu64
618 ", CBS = %" PRIu64 ", PIR = %" PRIu64
619 ", PBS = %" PRIu64 "] Policer [G : %s, Y : %s, R : %s]\n",
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]));
629 printf("\tPort %u (entry_ptr = %p)\n",
630 flow->params.port_id,
636 app_pipeline_fa_flow_ls(struct app_params *app,
637 uint32_t pipeline_id)
639 struct app_pipeline_fa *p;
642 /* Check input arguments */
646 p = app_pipeline_data_fe(app, pipeline_id,
647 &pipeline_flow_actions);
651 for (i = 0; i < p->params.n_flows; i++) {
652 struct app_pipeline_fa_flow *flow = &p->flows[i];
654 print_flow(p, i, flow);
661 app_pipeline_fa_dscp_ls(struct app_params *app,
662 uint32_t pipeline_id)
664 struct app_pipeline_fa *p;
667 /* Check input arguments */
671 p = app_pipeline_data_fe(app, pipeline_id,
672 &pipeline_flow_actions);
676 if (p->params.dscp_enabled == 0)
679 for (i = 0; i < RTE_DIM(p->dscp); i++) {
680 struct app_pipeline_fa_dscp *dscp = &p->dscp[i];
682 printf("DSCP = %2" PRIu32 ": Traffic class = %" PRIu32
686 color_to_string(dscp->color));
693 app_pipeline_fa_load_file(char *filename,
695 struct pipeline_fa_flow_params *p,
703 /* Check input arguments */
704 if ((filename == NULL) ||
705 (flow_ids == NULL) ||
715 /* Open input file */
716 f = fopen(filename, "r");
723 for (i = 0, l = 1; i < *n_flows; l++) {
725 uint32_t n_tokens = RTE_DIM(tokens);
729 if (fgets(file_buf, sizeof(file_buf), f) == NULL)
732 status = parse_tokenize_string(file_buf, tokens, &n_tokens);
736 if ((n_tokens == 0) || (tokens[0][0] == '#'))
740 if ((n_tokens != 64) ||
742 strcmp(tokens[0], "flow") ||
743 parser_read_uint32(&flow_ids[i], tokens[1]) ||
745 /* meter & policer 0 */
746 strcmp(tokens[2], "meter") ||
747 strcmp(tokens[3], "0") ||
748 strcmp(tokens[4], "trtcm") ||
749 parser_read_uint64(&p[i].m[0].cir, tokens[5]) ||
750 parser_read_uint64(&p[i].m[0].pir, tokens[6]) ||
751 parser_read_uint64(&p[i].m[0].cbs, tokens[7]) ||
752 parser_read_uint64(&p[i].m[0].pbs, tokens[8]) ||
753 strcmp(tokens[9], "policer") ||
754 strcmp(tokens[10], "0") ||
755 strcmp(tokens[11], "g") ||
756 string_to_policer_action(tokens[12],
757 &p[i].p[0].action[e_RTE_METER_GREEN]) ||
758 strcmp(tokens[13], "y") ||
759 string_to_policer_action(tokens[14],
760 &p[i].p[0].action[e_RTE_METER_YELLOW]) ||
761 strcmp(tokens[15], "r") ||
762 string_to_policer_action(tokens[16],
763 &p[i].p[0].action[e_RTE_METER_RED]) ||
765 /* meter & policer 1 */
766 strcmp(tokens[17], "meter") ||
767 strcmp(tokens[18], "1") ||
768 strcmp(tokens[19], "trtcm") ||
769 parser_read_uint64(&p[i].m[1].cir, tokens[20]) ||
770 parser_read_uint64(&p[i].m[1].pir, tokens[21]) ||
771 parser_read_uint64(&p[i].m[1].cbs, tokens[22]) ||
772 parser_read_uint64(&p[i].m[1].pbs, tokens[23]) ||
773 strcmp(tokens[24], "policer") ||
774 strcmp(tokens[25], "1") ||
775 strcmp(tokens[26], "g") ||
776 string_to_policer_action(tokens[27],
777 &p[i].p[1].action[e_RTE_METER_GREEN]) ||
778 strcmp(tokens[28], "y") ||
779 string_to_policer_action(tokens[29],
780 &p[i].p[1].action[e_RTE_METER_YELLOW]) ||
781 strcmp(tokens[30], "r") ||
782 string_to_policer_action(tokens[31],
783 &p[i].p[1].action[e_RTE_METER_RED]) ||
785 /* meter & policer 2 */
786 strcmp(tokens[32], "meter") ||
787 strcmp(tokens[33], "2") ||
788 strcmp(tokens[34], "trtcm") ||
789 parser_read_uint64(&p[i].m[2].cir, tokens[35]) ||
790 parser_read_uint64(&p[i].m[2].pir, tokens[36]) ||
791 parser_read_uint64(&p[i].m[2].cbs, tokens[37]) ||
792 parser_read_uint64(&p[i].m[2].pbs, tokens[38]) ||
793 strcmp(tokens[39], "policer") ||
794 strcmp(tokens[40], "2") ||
795 strcmp(tokens[41], "g") ||
796 string_to_policer_action(tokens[42],
797 &p[i].p[2].action[e_RTE_METER_GREEN]) ||
798 strcmp(tokens[43], "y") ||
799 string_to_policer_action(tokens[44],
800 &p[i].p[2].action[e_RTE_METER_YELLOW]) ||
801 strcmp(tokens[45], "r") ||
802 string_to_policer_action(tokens[46],
803 &p[i].p[2].action[e_RTE_METER_RED]) ||
805 /* meter & policer 3 */
806 strcmp(tokens[47], "meter") ||
807 strcmp(tokens[48], "3") ||
808 strcmp(tokens[49], "trtcm") ||
809 parser_read_uint64(&p[i].m[3].cir, tokens[50]) ||
810 parser_read_uint64(&p[i].m[3].pir, tokens[51]) ||
811 parser_read_uint64(&p[i].m[3].cbs, tokens[52]) ||
812 parser_read_uint64(&p[i].m[3].pbs, tokens[53]) ||
813 strcmp(tokens[54], "policer") ||
814 strcmp(tokens[55], "3") ||
815 strcmp(tokens[56], "g") ||
816 string_to_policer_action(tokens[57],
817 &p[i].p[3].action[e_RTE_METER_GREEN]) ||
818 strcmp(tokens[58], "y") ||
819 string_to_policer_action(tokens[59],
820 &p[i].p[3].action[e_RTE_METER_YELLOW]) ||
821 strcmp(tokens[60], "r") ||
822 string_to_policer_action(tokens[61],
823 &p[i].p[3].action[e_RTE_METER_RED]) ||
826 strcmp(tokens[62], "port") ||
827 parser_read_uint32(&p[i].port_id, tokens[63]))
847 * flow meter, policer and output port configuration:
848 * p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs>
850 * p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction>
851 * <action> is one of the following:
852 * G = recolor to green
853 * Y = recolor as yellow
857 * p <pipelineid> action flow <flowid> port <port ID>
859 * p <pipelineid> action flow bulk <file>
861 * flow policer stats read:
862 * p <pipelineid> action flow <flowid> stats
865 * p <pipelineid> action flow ls
867 * dscp table configuration:
868 * p <pipelineid> action dscp <dscpid> class <class ID> color <color>
871 * p <pipelineid> action dscp ls
874 struct cmd_action_result {
875 cmdline_fixed_string_t p_string;
876 uint32_t pipeline_id;
877 cmdline_fixed_string_t action_string;
878 cmdline_multi_string_t multi_string;
884 __rte_unused struct cmdline *cl,
887 struct cmd_action_result *params = parsed_result;
888 struct app_params *app = data;
891 uint32_t n_tokens = RTE_DIM(tokens);
894 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
896 printf(CMD_MSG_TOO_MANY_ARGS, "action");
900 /* action flow meter */
901 if ((n_tokens >= 3) &&
902 (strcmp(tokens[0], "flow") == 0) &&
903 strcmp(tokens[1], "bulk") &&
904 strcmp(tokens[1], "ls") &&
905 (strcmp(tokens[2], "meter") == 0)) {
906 struct pipeline_fa_flow_params flow_params;
907 uint32_t flow_id, meter_id;
910 printf(CMD_MSG_MISMATCH_ARGS, "action flow meter");
914 memset(&flow_params, 0, sizeof(flow_params));
916 if (parser_read_uint32(&flow_id, tokens[1])) {
917 printf(CMD_MSG_INVALID_ARG, "flowid");
921 if (parser_read_uint32(&meter_id, tokens[3]) ||
922 (meter_id >= PIPELINE_FA_N_TC_MAX)) {
923 printf(CMD_MSG_INVALID_ARG, "meterid");
927 if (strcmp(tokens[4], "trtcm")) {
928 printf(CMD_MSG_ARG_NOT_FOUND, "trtcm");
932 if (parser_read_uint64(&flow_params.m[meter_id].cir, tokens[5])) {
933 printf(CMD_MSG_INVALID_ARG, "cir");
937 if (parser_read_uint64(&flow_params.m[meter_id].pir, tokens[6])) {
938 printf(CMD_MSG_INVALID_ARG, "pir");
942 if (parser_read_uint64(&flow_params.m[meter_id].cbs, tokens[7])) {
943 printf(CMD_MSG_INVALID_ARG, "cbs");
947 if (parser_read_uint64(&flow_params.m[meter_id].pbs, tokens[8])) {
948 printf(CMD_MSG_INVALID_ARG, "pbs");
952 status = app_pipeline_fa_flow_config(app,
960 printf(CMD_MSG_FAIL, "action flow meter");
963 } /* action flow meter */
965 /* action flow policer */
966 if ((n_tokens >= 3) &&
967 (strcmp(tokens[0], "flow") == 0) &&
968 strcmp(tokens[1], "bulk") &&
969 strcmp(tokens[1], "ls") &&
970 (strcmp(tokens[2], "policer") == 0)) {
971 struct pipeline_fa_flow_params flow_params;
972 uint32_t flow_id, policer_id;
974 if (n_tokens != 10) {
975 printf(CMD_MSG_MISMATCH_ARGS, "action flow policer");
979 memset(&flow_params, 0, sizeof(flow_params));
981 if (parser_read_uint32(&flow_id, tokens[1])) {
982 printf(CMD_MSG_INVALID_ARG, "flowid");
986 if (parser_read_uint32(&policer_id, tokens[3]) ||
987 (policer_id >= PIPELINE_FA_N_TC_MAX)) {
988 printf(CMD_MSG_INVALID_ARG, "policerid");
992 if (strcmp(tokens[4], "g")) {
993 printf(CMD_MSG_ARG_NOT_FOUND, "g");
997 if (string_to_policer_action(tokens[5],
998 &flow_params.p[policer_id].action[e_RTE_METER_GREEN])) {
999 printf(CMD_MSG_INVALID_ARG, "gaction");
1003 if (strcmp(tokens[6], "y")) {
1004 printf(CMD_MSG_ARG_NOT_FOUND, "y");
1008 if (string_to_policer_action(tokens[7],
1009 &flow_params.p[policer_id].action[e_RTE_METER_YELLOW])) {
1010 printf(CMD_MSG_INVALID_ARG, "yaction");
1014 if (strcmp(tokens[8], "r")) {
1015 printf(CMD_MSG_ARG_NOT_FOUND, "r");
1019 if (string_to_policer_action(tokens[9],
1020 &flow_params.p[policer_id].action[e_RTE_METER_RED])) {
1021 printf(CMD_MSG_INVALID_ARG, "raction");
1025 status = app_pipeline_fa_flow_config(app,
1026 params->pipeline_id,
1033 printf(CMD_MSG_FAIL, "action flow policer");
1036 } /* action flow policer */
1038 /* action flow port */
1039 if ((n_tokens >= 3) &&
1040 (strcmp(tokens[0], "flow") == 0) &&
1041 strcmp(tokens[1], "bulk") &&
1042 strcmp(tokens[1], "ls") &&
1043 (strcmp(tokens[2], "port") == 0)) {
1044 struct pipeline_fa_flow_params flow_params;
1045 uint32_t flow_id, port_id;
1047 if (n_tokens != 4) {
1048 printf(CMD_MSG_MISMATCH_ARGS, "action flow port");
1052 memset(&flow_params, 0, sizeof(flow_params));
1054 if (parser_read_uint32(&flow_id, tokens[1])) {
1055 printf(CMD_MSG_INVALID_ARG, "flowid");
1059 if (parser_read_uint32(&port_id, tokens[3])) {
1060 printf(CMD_MSG_INVALID_ARG, "portid");
1064 flow_params.port_id = port_id;
1066 status = app_pipeline_fa_flow_config(app,
1067 params->pipeline_id,
1074 printf(CMD_MSG_FAIL, "action flow port");
1077 } /* action flow port */
1079 /* action flow stats */
1080 if ((n_tokens >= 3) &&
1081 (strcmp(tokens[0], "flow") == 0) &&
1082 strcmp(tokens[1], "bulk") &&
1083 strcmp(tokens[1], "ls") &&
1084 (strcmp(tokens[2], "stats") == 0)) {
1085 struct pipeline_fa_policer_stats stats;
1086 uint32_t flow_id, policer_id;
1088 if (n_tokens != 3) {
1089 printf(CMD_MSG_MISMATCH_ARGS, "action flow stats");
1093 if (parser_read_uint32(&flow_id, tokens[1])) {
1094 printf(CMD_MSG_INVALID_ARG, "flowid");
1098 for (policer_id = 0;
1099 policer_id < PIPELINE_FA_N_TC_MAX;
1101 status = app_pipeline_fa_flow_policer_stats_read(app,
1102 params->pipeline_id,
1108 printf(CMD_MSG_FAIL, "action flow stats");
1113 printf("\tPolicer: %" PRIu32
1114 "\tPkts G: %" PRIu64
1115 "\tPkts Y: %" PRIu64
1116 "\tPkts R: %" PRIu64
1117 "\tPkts D: %" PRIu64 "\n",
1119 stats.n_pkts[e_RTE_METER_GREEN],
1120 stats.n_pkts[e_RTE_METER_YELLOW],
1121 stats.n_pkts[e_RTE_METER_RED],
1126 } /* action flow stats */
1128 /* action flow bulk */
1129 if ((n_tokens >= 2) &&
1130 (strcmp(tokens[0], "flow") == 0) &&
1131 (strcmp(tokens[1], "bulk") == 0)) {
1132 struct pipeline_fa_flow_params *flow_params;
1133 uint32_t *flow_ids, n_flows, line;
1136 if (n_tokens != 3) {
1137 printf(CMD_MSG_MISMATCH_ARGS, "action flow bulk");
1141 filename = tokens[2];
1143 n_flows = APP_PIPELINE_FA_MAX_RECORDS_IN_FILE;
1144 flow_ids = malloc(n_flows * sizeof(uint32_t));
1145 if (flow_ids == NULL) {
1146 printf(CMD_MSG_OUT_OF_MEMORY);
1150 flow_params = malloc(n_flows * sizeof(struct pipeline_fa_flow_params));
1151 if (flow_params == NULL) {
1152 printf(CMD_MSG_OUT_OF_MEMORY);
1157 status = app_pipeline_fa_load_file(filename,
1163 printf(CMD_MSG_FILE_ERR, filename, line);
1169 status = app_pipeline_fa_flow_config_bulk(app,
1170 params->pipeline_id,
1178 printf(CMD_MSG_FAIL, "action flow bulk");
1183 } /* action flow bulk */
1185 /* action flow ls */
1186 if ((n_tokens >= 2) &&
1187 (strcmp(tokens[0], "flow") == 0) &&
1188 (strcmp(tokens[1], "ls") == 0)) {
1189 if (n_tokens != 2) {
1190 printf(CMD_MSG_MISMATCH_ARGS, "action flow ls");
1194 status = app_pipeline_fa_flow_ls(app,
1195 params->pipeline_id);
1197 printf(CMD_MSG_FAIL, "action flow ls");
1200 } /* action flow ls */
1203 if ((n_tokens >= 2) &&
1204 (strcmp(tokens[0], "dscp") == 0) &&
1205 strcmp(tokens[1], "ls")) {
1206 uint32_t dscp_id, tc_id;
1207 enum rte_meter_color color;
1209 if (n_tokens != 6) {
1210 printf(CMD_MSG_MISMATCH_ARGS, "action dscp");
1214 if (parser_read_uint32(&dscp_id, tokens[1])) {
1215 printf(CMD_MSG_INVALID_ARG, "dscpid");
1219 if (strcmp(tokens[2], "class")) {
1220 printf(CMD_MSG_ARG_NOT_FOUND, "class");
1224 if (parser_read_uint32(&tc_id, tokens[3])) {
1225 printf(CMD_MSG_INVALID_ARG, "classid");
1229 if (strcmp(tokens[4], "color")) {
1230 printf(CMD_MSG_ARG_NOT_FOUND, "color");
1234 if (string_to_color(tokens[5], &color)) {
1235 printf(CMD_MSG_INVALID_ARG, "colorid");
1239 status = app_pipeline_fa_dscp_config(app,
1240 params->pipeline_id,
1245 printf(CMD_MSG_FAIL, "action dscp");
1250 /* action dscp ls */
1251 if ((n_tokens >= 2) &&
1252 (strcmp(tokens[0], "dscp") == 0) &&
1253 (strcmp(tokens[1], "ls") == 0)) {
1254 if (n_tokens != 2) {
1255 printf(CMD_MSG_MISMATCH_ARGS, "action dscp ls");
1259 status = app_pipeline_fa_dscp_ls(app,
1260 params->pipeline_id);
1262 printf(CMD_MSG_FAIL, "action dscp ls");
1265 } /* action dscp ls */
1267 printf(CMD_MSG_FAIL, "action");
1270 static cmdline_parse_token_string_t cmd_action_p_string =
1271 TOKEN_STRING_INITIALIZER(struct cmd_action_result, p_string, "p");
1273 static cmdline_parse_token_num_t cmd_action_pipeline_id =
1274 TOKEN_NUM_INITIALIZER(struct cmd_action_result, pipeline_id, UINT32);
1276 static cmdline_parse_token_string_t cmd_action_action_string =
1277 TOKEN_STRING_INITIALIZER(struct cmd_action_result, action_string, "action");
1279 static cmdline_parse_token_string_t cmd_action_multi_string =
1280 TOKEN_STRING_INITIALIZER(struct cmd_action_result, multi_string,
1281 TOKEN_STRING_MULTI);
1283 cmdline_parse_inst_t cmd_action = {
1284 .f = cmd_action_parsed,
1286 .help_str = "flow actions (meter, policer, policer stats, dscp table)",
1288 (void *) &cmd_action_p_string,
1289 (void *) &cmd_action_pipeline_id,
1290 (void *) &cmd_action_action_string,
1291 (void *) &cmd_action_multi_string,
1296 static cmdline_parse_ctx_t pipeline_cmds[] = {
1297 (cmdline_parse_inst_t *) &cmd_action,
1301 static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = {
1302 .f_init = app_pipeline_fa_init,
1303 .f_free = app_pipeline_fa_free,
1304 .cmds = pipeline_cmds,
1307 struct pipeline_type pipeline_flow_actions = {
1308 .name = "FLOW_ACTIONS",
1309 .be_ops = &pipeline_flow_actions_be_ops,
1310 .fe_ops = &pipeline_flow_actions_fe_ops,