All of lore.kernel.org
 help / color / mirror / Atom feed
From: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
To: dev@dpdk.org
Cc: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>,
	Marcin Kerlin <marcinx.kerlin@intel.com>
Subject: [PATCH v3 5/7] examples/ip_pipeline: modifies flow action pipeline CLI
Date: Wed,  8 Jun 2016 12:35:23 +0200	[thread overview]
Message-ID: <1465382125-2747-6-git-send-email-piotrx.t.azarewicz@intel.com> (raw)
In-Reply-To: <1465382125-2747-1-git-send-email-piotrx.t.azarewicz@intel.com>

All commands merged into one: cmd_action_parsed.

modified bulk command:
action flow bulk
File line format:
flow <flow ID>
meter 0 <cir> <pir> <cbs> <pbs> meter 1 <cir> <pir> <cbs> <pbs> meter 2
<cir> <pir> <cbs> <pbs> meter 3 <cir> <pir> <cbs> <pbs>
policer 0 <action> <action> <action> policer 1 <action> <action>
<action> policer 2 <action> <action> <action> policer 3 <action>
<action> <action>
port <port ID>

Signed-off-by: Marcin Kerlin <marcinx.kerlin@intel.com>
Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 examples/ip_pipeline/config/action.cfg             |   68 +
 examples/ip_pipeline/config/action.sh              |  119 ++
 examples/ip_pipeline/config/action.txt             |    8 +
 .../ip_pipeline/pipeline/pipeline_flow_actions.c   | 1505 +++++++-------------
 .../ip_pipeline/pipeline/pipeline_flow_actions.h   |   11 +
 5 files changed, 707 insertions(+), 1004 deletions(-)
 create mode 100644 examples/ip_pipeline/config/action.cfg
 create mode 100644 examples/ip_pipeline/config/action.sh
 create mode 100644 examples/ip_pipeline/config/action.txt

diff --git a/examples/ip_pipeline/config/action.cfg b/examples/ip_pipeline/config/action.cfg
new file mode 100644
index 0000000..994ae94
--- /dev/null
+++ b/examples/ip_pipeline/config/action.cfg
@@ -0,0 +1,68 @@
+;   BSD LICENSE
+;
+;   Copyright(c) 2016 Intel Corporation. All rights reserved.
+;   All rights reserved.
+;
+;   Redistribution and use in source and binary forms, with or without
+;   modification, are permitted provided that the following conditions
+;   are met:
+;
+;     * Redistributions of source code must retain the above copyright
+;       notice, this list of conditions and the following disclaimer.
+;     * Redistributions in binary form must reproduce the above copyright
+;       notice, this list of conditions and the following disclaimer in
+;       the documentation and/or other materials provided with the
+;       distribution.
+;     * Neither the name of Intel Corporation nor the names of its
+;       contributors may be used to endorse or promote products derived
+;       from this software without specific prior written permission.
+;
+;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+;   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+;   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+;   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+;   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+;   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+;   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+;   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+;   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+;             ________________
+; RXQ0.0 --->|                |---> TXQ0.0
+;            |                |
+; RXQ1.0 --->|                |---> TXQ1.0
+;            |      Flow      |
+; RXQ2.0 --->|     Actions    |---> TXQ2.0
+;            |                |
+; RXQ3.0 --->|                |---> TXQ3.0
+;            |________________|
+;
+;
+; Input packet: Ethernet/IPv4
+;
+; Packet buffer layout:
+; #	Field Name		Offset (Bytes)	Size (Bytes)
+; 0	Mbuf			0 		128
+; 1	Headroom		128 		128
+; 2	Ethernet header		256 		14
+; 3	IPv4 header		270 		20
+
+[EAL]
+log_level = 0
+
+[PIPELINE0]
+type = MASTER
+core = 0
+
+[PIPELINE1]
+type = FLOW_ACTIONS
+core = 1
+pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0
+pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0
+n_flows = 65536
+n_meters_per_flow = 4
+flow_id_offset = 286; ipdaddr
+ip_hdr_offset = 270
+color_offset = 128
diff --git a/examples/ip_pipeline/config/action.sh b/examples/ip_pipeline/config/action.sh
new file mode 100644
index 0000000..2986ae6
--- /dev/null
+++ b/examples/ip_pipeline/config/action.sh
@@ -0,0 +1,119 @@
+#
+# run ./config/action.sh
+#
+
+p 1 action flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 0 g G y Y r R
+p 1 action flow 0 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 1 g G y Y r R
+p 1 action flow 0 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 2 g G y Y r R
+p 1 action flow 0 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 0 policer 3 g G y Y r R
+p 1 action flow 0 port 0
+
+p 1 action flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 0 g G y Y r R
+p 1 action flow 1 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 1 g G y Y r R
+p 1 action flow 1 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 2 g G y Y r R
+p 1 action flow 1 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 1 policer 3 g G y Y r R
+p 1 action flow 1 port 1
+
+p 1 action flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 0 g G y Y r R
+p 1 action flow 2 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 1 g G y Y r R
+p 1 action flow 2 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 2 g G y Y r R
+p 1 action flow 2 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 2 policer 3 g G y Y r R
+p 1 action flow 2 port 2
+
+p 1 action flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 0 g G y Y r R
+p 1 action flow 3 meter 1 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 1 g G y Y r R
+p 1 action flow 3 meter 2 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 2 g G y Y r R
+p 1 action flow 3 meter 3 trtcm 1250000000 1250000000 1000000 1000000
+p 1 action flow 3 policer 3 g G y Y r R
+p 1 action flow 3 port 3
+
+#p 1 action flow bulk ./config/action.txt
+
+#p 1 action flow ls
+
+p 1 action flow 0 stats
+p 1 action flow 1 stats
+p 1 action flow 2 stats
+p 1 action flow 3 stats
+
+p 1 action dscp 0 class 0 color G
+p 1 action dscp 1 class 1 color G
+p 1 action dscp 2 class 2 color G
+p 1 action dscp 3 class 3 color G
+p 1 action dscp 4 class 0 color G
+p 1 action dscp 5 class 1 color G
+p 1 action dscp 6 class 2 color G
+p 1 action dscp 7 class 3 color G
+p 1 action dscp 8 class 0 color G
+p 1 action dscp 9 class 1 color G
+p 1 action dscp 10 class 2 color G
+p 1 action dscp 11 class 3 color G
+p 1 action dscp 12 class 0 color G
+p 1 action dscp 13 class 1 color G
+p 1 action dscp 14 class 2 color G
+p 1 action dscp 15 class 3 color G
+p 1 action dscp 16 class 0 color G
+p 1 action dscp 17 class 1 color G
+p 1 action dscp 18 class 2 color G
+p 1 action dscp 19 class 3 color G
+p 1 action dscp 20 class 0 color G
+p 1 action dscp 21 class 1 color G
+p 1 action dscp 22 class 2 color G
+p 1 action dscp 23 class 3 color G
+p 1 action dscp 24 class 0 color G
+p 1 action dscp 25 class 1 color G
+p 1 action dscp 26 class 2 color G
+p 1 action dscp 27 class 3 color G
+p 1 action dscp 27 class 0 color G
+p 1 action dscp 29 class 1 color G
+p 1 action dscp 30 class 2 color G
+p 1 action dscp 31 class 3 color G
+p 1 action dscp 32 class 0 color G
+p 1 action dscp 33 class 1 color G
+p 1 action dscp 34 class 2 color G
+p 1 action dscp 35 class 3 color G
+p 1 action dscp 36 class 0 color G
+p 1 action dscp 37 class 1 color G
+p 1 action dscp 38 class 2 color G
+p 1 action dscp 39 class 3 color G
+p 1 action dscp 40 class 0 color G
+p 1 action dscp 41 class 1 color G
+p 1 action dscp 42 class 2 color G
+p 1 action dscp 43 class 3 color G
+p 1 action dscp 44 class 0 color G
+p 1 action dscp 45 class 1 color G
+p 1 action dscp 46 class 2 color G
+p 1 action dscp 47 class 3 color G
+p 1 action dscp 48 class 0 color G
+p 1 action dscp 49 class 1 color G
+p 1 action dscp 50 class 2 color G
+p 1 action dscp 51 class 3 color G
+p 1 action dscp 52 class 0 color G
+p 1 action dscp 53 class 1 color G
+p 1 action dscp 54 class 2 color G
+p 1 action dscp 55 class 3 color G
+p 1 action dscp 56 class 0 color G
+p 1 action dscp 57 class 1 color G
+p 1 action dscp 58 class 2 color G
+p 1 action dscp 59 class 3 color G
+p 1 action dscp 60 class 0 color G
+p 1 action dscp 61 class 1 color G
+p 1 action dscp 62 class 2 color G
+p 1 action dscp 63 class 3 color G
+
+p 1 action dscp ls
diff --git a/examples/ip_pipeline/config/action.txt b/examples/ip_pipeline/config/action.txt
new file mode 100644
index 0000000..f14207b
--- /dev/null
+++ b/examples/ip_pipeline/config/action.txt
@@ -0,0 +1,8 @@
+#
+# p <pipelineid> action flow bulk ./config/action.txt
+#
+
+flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 0
+flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 1
+flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 2
+flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 3
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
index 4012121..7560051 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c
@@ -35,6 +35,7 @@
 #include <string.h>
 #include <sys/queue.h>
 #include <netinet/in.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_hexdump.h>
@@ -43,13 +44,12 @@
 #include <cmdline_parse.h>
 #include <cmdline_parse_num.h>
 #include <cmdline_parse_string.h>
-#include <cmdline_parse_ipaddr.h>
-#include <cmdline_parse_etheraddr.h>
 
 #include "app.h"
 #include "pipeline_common_fe.h"
 #include "pipeline_flow_actions.h"
 #include "hash_func.h"
+#include "parser.h"
 
 /*
  * Flow actions pipeline
@@ -689,1115 +689,612 @@ app_pipeline_fa_dscp_ls(struct app_params *app,
 	return 0;
 }
 
-/*
- * Flow meter configuration (single flow)
- *
- * p <pipeline ID> flow <flow ID> meter <meter ID> trtcm <trtcm params>
- */
-
-struct cmd_fa_meter_config_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flow_string;
-	uint32_t flow_id;
-	cmdline_fixed_string_t meter_string;
-	uint32_t meter_id;
-	cmdline_fixed_string_t trtcm_string;
-	uint64_t cir;
-	uint64_t pir;
-	uint64_t cbs;
-	uint64_t pbs;
-};
-
-static void
-cmd_fa_meter_config_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_meter_config_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_flow_params flow_params;
-	int status;
-
-	if (params->meter_id >= PIPELINE_FA_N_TC_MAX) {
-		printf("Command failed\n");
-		return;
-	}
-
-	flow_params.m[params->meter_id].cir = params->cir;
-	flow_params.m[params->meter_id].pir = params->pir;
-	flow_params.m[params->meter_id].cbs = params->cbs;
-	flow_params.m[params->meter_id].pbs = params->pbs;
-
-	status = app_pipeline_fa_flow_config(app,
-		params->pipeline_id,
-		params->flow_id,
-		1 << params->meter_id,
-		0,
-		0,
-		&flow_params);
-
-	if (status != 0)
-		printf("Command failed\n");
-}
-
-cmdline_parse_token_string_t cmd_fa_meter_config_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
-	flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_flow_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
-	flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_meter_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
-	meter_string, "meter");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_meter_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result,
-	meter_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_trtcm_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result,
-	trtcm_string, "trtcm");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_cir =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pir =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_cbs =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cbs, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_pbs =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pbs, UINT64);
-
-cmdline_parse_inst_t cmd_fa_meter_config = {
-	.f = cmd_fa_meter_config_parsed,
-	.data = NULL,
-	.help_str = "Flow meter configuration (single flow) ",
-	.tokens = {
-		(void *) &cmd_fa_meter_config_p_string,
-		(void *) &cmd_fa_meter_config_pipeline_id,
-		(void *) &cmd_fa_meter_config_flow_string,
-		(void *) &cmd_fa_meter_config_flow_id,
-		(void *) &cmd_fa_meter_config_meter_string,
-		(void *) &cmd_fa_meter_config_meter_id,
-		(void *) &cmd_fa_meter_config_trtcm_string,
-		(void *) &cmd_fa_meter_config_cir,
-		(void *) &cmd_fa_meter_config_pir,
-		(void *) &cmd_fa_meter_config_cbs,
-		(void *) &cmd_fa_meter_config_pbs,
-		NULL,
-	},
-};
-
-/*
- * Flow meter configuration (multiple flows)
- *
- * p <pipeline ID> flows <n_flows> meter <meter ID> trtcm <trtcm params>
- */
-
-struct cmd_fa_meter_config_bulk_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flows_string;
-	uint32_t n_flows;
-	cmdline_fixed_string_t meter_string;
-	uint32_t meter_id;
-	cmdline_fixed_string_t trtcm_string;
-	uint64_t cir;
-	uint64_t pir;
-	uint64_t cbs;
-	uint64_t pbs;
-};
-
-static void
-cmd_fa_meter_config_bulk_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
+int
+app_pipeline_fa_load_file(char *filename,
+	uint32_t *flow_ids,
+	struct pipeline_fa_flow_params *p,
+	uint32_t *n_flows,
+	uint32_t *line)
 {
-	struct cmd_fa_meter_config_bulk_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_flow_params flow_template, *flow_params;
-	uint32_t *flow_id;
-	uint32_t i;
+	FILE *f = NULL;
+	char file_buf[1024];
+	uint32_t i, l;
 
-	if ((params->n_flows == 0) ||
-		(params->meter_id >= PIPELINE_FA_N_TC_MAX)) {
-		printf("Invalid arguments\n");
-		return;
-	}
-
-	flow_id = (uint32_t *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(uint32_t),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_id == NULL) {
-		printf("Memory allocation failed\n");
-		return;
-	}
+	/* Check input arguments */
+	if ((filename == NULL) ||
+		(flow_ids == NULL) ||
+		(p == NULL) ||
+		(n_flows == NULL) ||
+		(*n_flows == 0) ||
+		(line == NULL)) {
+		if (line)
+			*line = 0;
+		return -1;
+		}
 
-	flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_params == NULL) {
-		rte_free(flow_id);
-		printf("Memory allocation failed\n");
-		return;
+	/* Open input file */
+	f = fopen(filename, "r");
+	if (f == NULL) {
+		*line = 0;
+		return -1;
 	}
 
-	memset(&flow_template, 0, sizeof(flow_template));
-	flow_template.m[params->meter_id].cir = params->cir;
-	flow_template.m[params->meter_id].pir = params->pir;
-	flow_template.m[params->meter_id].cbs = params->cbs;
-	flow_template.m[params->meter_id].pbs = params->pbs;
+	/* Read file */
+	for (i = 0, l = 1; i < *n_flows; l++) {
+		char *tokens[64];
+		uint32_t n_tokens = RTE_DIM(tokens);
 
-	for (i = 0; i < params->n_flows; i++) {
-		uint32_t pos = i % N_FLOWS_BULK;
+		int status;
 
-		flow_id[pos] = i;
-		memcpy(&flow_params[pos],
-			&flow_template,
-			sizeof(flow_template));
+		if (fgets(file_buf, sizeof(file_buf), f) == NULL)
+			break;
 
-		if ((pos == N_FLOWS_BULK - 1) ||
-			(i == params->n_flows - 1)) {
-			int status;
+		status = parse_tokenize_string(file_buf, tokens, &n_tokens);
+		if (status)
+			goto error1;
 
-			status = app_pipeline_fa_flow_config_bulk(app,
-				params->pipeline_id,
-				flow_id,
-				pos + 1,
-				1 << params->meter_id,
-				0,
-				0,
-				flow_params);
+		if ((n_tokens == 0) || (tokens[0][0] == '#'))
+			continue;
 
-			if (status != 0) {
-				printf("Command failed\n");
 
-				break;
-			}
-		}
+		if ((n_tokens != 64) ||
+			/* flow */
+			strcmp(tokens[0], "flow") ||
+			parser_read_uint32(&flow_ids[i], tokens[1]) ||
+
+			/* meter & policer 0 */
+			strcmp(tokens[2], "meter") ||
+			strcmp(tokens[3], "0") ||
+			strcmp(tokens[4], "trtcm") ||
+			parser_read_uint64(&p[i].m[0].cir, tokens[5]) ||
+			parser_read_uint64(&p[i].m[0].pir, tokens[6]) ||
+			parser_read_uint64(&p[i].m[0].cbs, tokens[7]) ||
+			parser_read_uint64(&p[i].m[0].pbs, tokens[8]) ||
+			strcmp(tokens[9], "policer") ||
+			strcmp(tokens[10], "0") ||
+			strcmp(tokens[11], "g") ||
+			string_to_policer_action(tokens[12],
+				&p[i].p[0].action[e_RTE_METER_GREEN]) ||
+			strcmp(tokens[13], "y") ||
+			string_to_policer_action(tokens[14],
+				&p[i].p[0].action[e_RTE_METER_YELLOW]) ||
+			strcmp(tokens[15], "r") ||
+			string_to_policer_action(tokens[16],
+				&p[i].p[0].action[e_RTE_METER_RED]) ||
+
+			/* meter & policer 1 */
+			strcmp(tokens[17], "meter") ||
+			strcmp(tokens[18], "1") ||
+			strcmp(tokens[19], "trtcm") ||
+			parser_read_uint64(&p[i].m[1].cir, tokens[20]) ||
+			parser_read_uint64(&p[i].m[1].pir, tokens[21]) ||
+			parser_read_uint64(&p[i].m[1].cbs, tokens[22]) ||
+			parser_read_uint64(&p[i].m[1].pbs, tokens[23]) ||
+			strcmp(tokens[24], "policer") ||
+			strcmp(tokens[25], "1") ||
+			strcmp(tokens[26], "g") ||
+			string_to_policer_action(tokens[27],
+				&p[i].p[1].action[e_RTE_METER_GREEN]) ||
+			strcmp(tokens[28], "y") ||
+			string_to_policer_action(tokens[29],
+				&p[i].p[1].action[e_RTE_METER_YELLOW]) ||
+			strcmp(tokens[30], "r") ||
+			string_to_policer_action(tokens[31],
+				&p[i].p[1].action[e_RTE_METER_RED]) ||
+
+			/* meter & policer 2 */
+			strcmp(tokens[32], "meter") ||
+			strcmp(tokens[33], "2") ||
+			strcmp(tokens[34], "trtcm") ||
+			parser_read_uint64(&p[i].m[2].cir, tokens[35]) ||
+			parser_read_uint64(&p[i].m[2].pir, tokens[36]) ||
+			parser_read_uint64(&p[i].m[2].cbs, tokens[37]) ||
+			parser_read_uint64(&p[i].m[2].pbs, tokens[38]) ||
+			strcmp(tokens[39], "policer") ||
+			strcmp(tokens[40], "2") ||
+			strcmp(tokens[41], "g") ||
+			string_to_policer_action(tokens[42],
+				&p[i].p[2].action[e_RTE_METER_GREEN]) ||
+			strcmp(tokens[43], "y") ||
+			string_to_policer_action(tokens[44],
+				&p[i].p[2].action[e_RTE_METER_YELLOW]) ||
+			strcmp(tokens[45], "r") ||
+			string_to_policer_action(tokens[46],
+				&p[i].p[2].action[e_RTE_METER_RED]) ||
+
+			/* meter & policer 3 */
+			strcmp(tokens[47], "meter") ||
+			strcmp(tokens[48], "3") ||
+			strcmp(tokens[49], "trtcm") ||
+			parser_read_uint64(&p[i].m[3].cir, tokens[50]) ||
+			parser_read_uint64(&p[i].m[3].pir, tokens[51]) ||
+			parser_read_uint64(&p[i].m[3].cbs, tokens[52]) ||
+			parser_read_uint64(&p[i].m[3].pbs, tokens[53]) ||
+			strcmp(tokens[54], "policer") ||
+			strcmp(tokens[55], "3") ||
+			strcmp(tokens[56], "g") ||
+			string_to_policer_action(tokens[57],
+				&p[i].p[3].action[e_RTE_METER_GREEN]) ||
+			strcmp(tokens[58], "y") ||
+			string_to_policer_action(tokens[59],
+				&p[i].p[3].action[e_RTE_METER_YELLOW]) ||
+			strcmp(tokens[60], "r") ||
+			string_to_policer_action(tokens[61],
+				&p[i].p[3].action[e_RTE_METER_RED]) ||
+
+			/* port */
+			strcmp(tokens[62], "port") ||
+			parser_read_uint32(&p[i].port_id, tokens[63]))
+			goto error1;
+
+		i++;
 	}
 
-	rte_free(flow_params);
-	rte_free(flow_id);
+	/* Close file */
+	*n_flows = i;
+	fclose(f);
+	return 0;
 
+error1:
+	*line = l;
+	fclose(f);
+	return -1;
 }
 
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_flows_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_n_flows =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_meter_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	meter_string, "meter");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_meter_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	meter_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_meter_config_bulk_trtcm_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	trtcm_string, "trtcm");
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cir =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	cir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pir =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	pir, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cbs =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	cbs, UINT64);
-
-cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pbs =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result,
-	pbs, UINT64);
-
-cmdline_parse_inst_t cmd_fa_meter_config_bulk = {
-	.f = cmd_fa_meter_config_bulk_parsed,
-	.data = NULL,
-	.help_str = "Flow meter configuration (multiple flows)",
-	.tokens = {
-		(void *) &cmd_fa_meter_config_bulk_p_string,
-		(void *) &cmd_fa_meter_config_bulk_pipeline_id,
-		(void *) &cmd_fa_meter_config_bulk_flows_string,
-		(void *) &cmd_fa_meter_config_bulk_n_flows,
-		(void *) &cmd_fa_meter_config_bulk_meter_string,
-		(void *) &cmd_fa_meter_config_bulk_meter_id,
-		(void *) &cmd_fa_meter_config_bulk_trtcm_string,
-		(void *) &cmd_fa_meter_config_cir,
-		(void *) &cmd_fa_meter_config_pir,
-		(void *) &cmd_fa_meter_config_cbs,
-		(void *) &cmd_fa_meter_config_pbs,
-		NULL,
-	},
-};
-
 /*
- * Flow policer configuration (single flow)
+ * action
  *
- * p <pipeline ID> flow <flow ID> policer <policer ID>
- *    G <action> Y <action> R <action>
+ * flow meter, policer and output port configuration:
+ *    p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs>
  *
- * <action> = G (green) | Y (yellow) | R (red) | D (drop)
- */
-
-struct cmd_fa_policer_config_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flow_string;
-	uint32_t flow_id;
-	cmdline_fixed_string_t policer_string;
-	uint32_t policer_id;
-	cmdline_fixed_string_t green_string;
-	cmdline_fixed_string_t g_action;
-	cmdline_fixed_string_t yellow_string;
-	cmdline_fixed_string_t y_action;
-	cmdline_fixed_string_t red_string;
-	cmdline_fixed_string_t r_action;
-};
-
-static void
-cmd_fa_policer_config_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_policer_config_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_flow_params flow_params;
-	int status;
-
-	if (params->policer_id >= PIPELINE_FA_N_TC_MAX) {
-		printf("Command failed\n");
-		return;
-	}
-
-	status = string_to_policer_action(params->g_action,
-		&flow_params.p[params->policer_id].action[e_RTE_METER_GREEN]);
-	if (status)
-		printf("Invalid policer green action\n");
-
-	status = string_to_policer_action(params->y_action,
-		&flow_params.p[params->policer_id].action[e_RTE_METER_YELLOW]);
-	if (status)
-		printf("Invalid policer yellow action\n");
-
-	status = string_to_policer_action(params->r_action,
-		&flow_params.p[params->policer_id].action[e_RTE_METER_RED]);
-	if (status)
-		printf("Invalid policer red action\n");
-
-	status = app_pipeline_fa_flow_config(app,
-		params->pipeline_id,
-		params->flow_id,
-		0,
-		1 << params->policer_id,
-		0,
-		&flow_params);
-
-	if (status != 0)
-		printf("Command failed\n");
-
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_config_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_flow_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
-	flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_policer_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	policer_string, "policer");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_policer_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result,
-	policer_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_green_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	green_string, "G");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_g_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	g_action, "R#Y#G#D");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_yellow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	yellow_string, "Y");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_y_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	y_action, "R#Y#G#D");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_red_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	red_string, "R");
-
-cmdline_parse_token_string_t cmd_fa_policer_config_r_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result,
-	r_action, "R#Y#G#D");
-
-cmdline_parse_inst_t cmd_fa_policer_config = {
-	.f = cmd_fa_policer_config_parsed,
-	.data = NULL,
-	.help_str = "Flow policer configuration (single flow)",
-	.tokens = {
-		(void *) &cmd_fa_policer_config_p_string,
-		(void *) &cmd_fa_policer_config_pipeline_id,
-		(void *) &cmd_fa_policer_config_flow_string,
-		(void *) &cmd_fa_policer_config_flow_id,
-		(void *) &cmd_fa_policer_config_policer_string,
-		(void *) &cmd_fa_policer_config_policer_id,
-		(void *) &cmd_fa_policer_config_green_string,
-		(void *) &cmd_fa_policer_config_g_action,
-		(void *) &cmd_fa_policer_config_yellow_string,
-		(void *) &cmd_fa_policer_config_y_action,
-		(void *) &cmd_fa_policer_config_red_string,
-		(void *) &cmd_fa_policer_config_r_action,
-		NULL,
-	},
-};
-
-/*
- * Flow policer configuration (multiple flows)
+ *    p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction>
+ *  <action> is one of the following:
+ *      G = recolor to green
+ *      Y = recolor as yellow
+ *      R = recolor as red
+ *      D = drop
  *
- * p <pipeline ID> flows <n_flows> policer <policer ID>
- *    G <action> Y <action> R <action>
+ *    p <pipelineid> action flow <flowid> port <port ID>
  *
- * <action> = G (green) | Y (yellow) | R (red) | D (drop)
- */
+ *    p <pipelineid> action flow bulk <file>
+ *
+ * flow policer stats read:
+ *    p <pipelineid> action flow <flowid> stats
+ *
+ * flow ls:
+ *    p <pipelineid> action flow ls
+ *
+ * dscp table configuration:
+ *    p <pipelineid> action dscp <dscpid> class <class ID> color <color>
+ *
+ * dscp table ls:
+ *    p <pipelineid> action dscp ls
+**/
 
-struct cmd_fa_policer_config_bulk_result {
+struct cmd_action_result {
 	cmdline_fixed_string_t p_string;
 	uint32_t pipeline_id;
-	cmdline_fixed_string_t flows_string;
-	uint32_t n_flows;
-	cmdline_fixed_string_t policer_string;
-	uint32_t policer_id;
-	cmdline_fixed_string_t green_string;
-	cmdline_fixed_string_t g_action;
-	cmdline_fixed_string_t yellow_string;
-	cmdline_fixed_string_t y_action;
-	cmdline_fixed_string_t red_string;
-	cmdline_fixed_string_t r_action;
+	cmdline_fixed_string_t action_string;
+	cmdline_multi_string_t multi_string;
 };
 
 static void
-cmd_fa_policer_config_bulk_parsed(
+cmd_action_parsed(
 	void *parsed_result,
 	__rte_unused struct cmdline *cl,
 	void *data)
 {
-	struct cmd_fa_policer_config_bulk_result *params = parsed_result;
+	struct cmd_action_result *params = parsed_result;
 	struct app_params *app = data;
-	struct pipeline_fa_flow_params flow_template, *flow_params;
-	uint32_t *flow_id, i;
-	int status;
 
-	if ((params->n_flows == 0) ||
-		(params->policer_id >= PIPELINE_FA_N_TC_MAX)) {
-		printf("Invalid arguments\n");
-		return;
-	}
-
-	flow_id = (uint32_t *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(uint32_t),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_id == NULL) {
-		printf("Memory allocation failed\n");
-		return;
-	}
+	char *tokens[16];
+	uint32_t n_tokens = RTE_DIM(tokens);
+	int status;
 
-	flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_params == NULL) {
-		rte_free(flow_id);
-		printf("Memory allocation failed\n");
+	status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
+	if (status != 0) {
+		printf(CMD_MSG_TOO_MANY_ARGS, "action");
 		return;
 	}
 
-	memset(&flow_template, 0, sizeof(flow_template));
-
-	status = string_to_policer_action(params->g_action,
-		&flow_template.p[params->policer_id].action[e_RTE_METER_GREEN]);
-	if (status)
-		printf("Invalid policer green action\n");
-
-	status = string_to_policer_action(params->y_action,
-	 &flow_template.p[params->policer_id].action[e_RTE_METER_YELLOW]);
-	if (status)
-		printf("Invalid policer yellow action\n");
-
-	status = string_to_policer_action(params->r_action,
-		&flow_template.p[params->policer_id].action[e_RTE_METER_RED]);
-	if (status)
-		printf("Invalid policer red action\n");
-
-	for (i = 0; i < params->n_flows; i++) {
-		uint32_t pos = i % N_FLOWS_BULK;
-
-		flow_id[pos] = i;
-		memcpy(&flow_params[pos], &flow_template,
-			sizeof(flow_template));
-
-		if ((pos == N_FLOWS_BULK - 1) ||
-			(i == params->n_flows - 1)) {
-			int status;
-
-			status = app_pipeline_fa_flow_config_bulk(app,
-				params->pipeline_id,
-				flow_id,
-				pos + 1,
-				0,
-				1 << params->policer_id,
-				0,
-				flow_params);
-
-			if (status != 0) {
-				printf("Command failed\n");
-
-				break;
-			}
+	/* action flow meter */
+	if ((n_tokens >= 3) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		strcmp(tokens[1], "bulk") &&
+		strcmp(tokens[1], "ls") &&
+		(strcmp(tokens[2], "meter") == 0)) {
+		struct pipeline_fa_flow_params flow_params;
+		uint32_t flow_id, meter_id;
+
+		if (n_tokens != 9) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow meter");
+			return;
 		}
-	}
-
-	rte_free(flow_params);
-	rte_free(flow_id);
-
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_flows_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_n_flows =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_policer_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	policer_string, "policer");
 
-cmdline_parse_token_num_t cmd_fa_policer_config_bulk_policer_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	policer_id, UINT32);
+		memset(&flow_params, 0, sizeof(flow_params));
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_green_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	green_string, "G");
+		if (parser_read_uint32(&flow_id, tokens[1])) {
+			printf(CMD_MSG_INVALID_ARG, "flowid");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_g_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	g_action, "R#Y#G#D");
+		if (parser_read_uint32(&meter_id, tokens[3]) ||
+			(meter_id >= PIPELINE_FA_N_TC_MAX)) {
+			printf(CMD_MSG_INVALID_ARG, "meterid");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_yellow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	yellow_string, "Y");
+		if (strcmp(tokens[4], "trtcm")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "trtcm");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_y_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	y_action, "R#Y#G#D");
+		if (parser_read_uint64(&flow_params.m[meter_id].cir, tokens[5])) {
+			printf(CMD_MSG_INVALID_ARG, "cir");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_red_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	red_string, "R");
+		if (parser_read_uint64(&flow_params.m[meter_id].pir, tokens[6])) {
+			printf(CMD_MSG_INVALID_ARG, "pir");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_policer_config_bulk_r_action =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result,
-	r_action, "R#Y#G#D");
+		if (parser_read_uint64(&flow_params.m[meter_id].cbs, tokens[7])) {
+			printf(CMD_MSG_INVALID_ARG, "cbs");
+			return;
+		}
 
-cmdline_parse_inst_t cmd_fa_policer_config_bulk = {
-	.f = cmd_fa_policer_config_bulk_parsed,
-	.data = NULL,
-	.help_str = "Flow policer configuration (multiple flows)",
-	.tokens = {
-		(void *) &cmd_fa_policer_config_bulk_p_string,
-		(void *) &cmd_fa_policer_config_bulk_pipeline_id,
-		(void *) &cmd_fa_policer_config_bulk_flows_string,
-		(void *) &cmd_fa_policer_config_bulk_n_flows,
-		(void *) &cmd_fa_policer_config_bulk_policer_string,
-		(void *) &cmd_fa_policer_config_bulk_policer_id,
-		(void *) &cmd_fa_policer_config_bulk_green_string,
-		(void *) &cmd_fa_policer_config_bulk_g_action,
-		(void *) &cmd_fa_policer_config_bulk_yellow_string,
-		(void *) &cmd_fa_policer_config_bulk_y_action,
-		(void *) &cmd_fa_policer_config_bulk_red_string,
-		(void *) &cmd_fa_policer_config_bulk_r_action,
-		NULL,
-	},
-};
+		if (parser_read_uint64(&flow_params.m[meter_id].pbs, tokens[8])) {
+			printf(CMD_MSG_INVALID_ARG, "pbs");
+			return;
+		}
 
-/*
- * Flow output port configuration (single flow)
- *
- * p <pipeline ID> flow <flow ID> port <port ID>
- */
+		status = app_pipeline_fa_flow_config(app,
+			params->pipeline_id,
+			flow_id,
+			1 << meter_id,
+			0,
+			0,
+			&flow_params);
+		if (status)
+			printf(CMD_MSG_FAIL, "action flow meter");
 
-struct cmd_fa_output_port_config_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flow_string;
-	uint32_t flow_id;
-	cmdline_fixed_string_t port_string;
-	uint32_t port_id;
-};
+		return;
+	} /* action flow meter */
+
+	/* action flow policer */
+	if ((n_tokens >= 3) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		strcmp(tokens[1], "bulk") &&
+		strcmp(tokens[1], "ls") &&
+		(strcmp(tokens[2], "policer") == 0)) {
+		struct pipeline_fa_flow_params flow_params;
+		uint32_t flow_id, policer_id;
+
+		if (n_tokens != 10) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow policer");
+			return;
+		}
 
-static void
-cmd_fa_output_port_config_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_output_port_config_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_flow_params flow_params;
-	int status;
+		memset(&flow_params, 0, sizeof(flow_params));
 
-	flow_params.port_id = params->port_id;
+		if (parser_read_uint32(&flow_id, tokens[1])) {
+			printf(CMD_MSG_INVALID_ARG, "flowid");
+			return;
+		}
 
-	status = app_pipeline_fa_flow_config(app,
-		params->pipeline_id,
-		params->flow_id,
-		0,
-		0,
-		1,
-		&flow_params);
+		if (parser_read_uint32(&policer_id, tokens[3]) ||
+			(policer_id >= PIPELINE_FA_N_TC_MAX)) {
+			printf(CMD_MSG_INVALID_ARG, "policerid");
+			return;
+		}
 
-	if (status != 0)
-		printf("Command failed\n");
-}
+		if (strcmp(tokens[4], "g")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "g");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_output_port_config_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
-	p_string, "p");
+		if (string_to_policer_action(tokens[5],
+			&flow_params.p[policer_id].action[e_RTE_METER_GREEN])) {
+			printf(CMD_MSG_INVALID_ARG, "gaction");
+			return;
+		}
 
-cmdline_parse_token_num_t cmd_fa_output_port_config_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
-	pipeline_id, UINT32);
+		if (strcmp(tokens[6], "y")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "y");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_output_port_config_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
-	flow_string, "flow");
+		if (string_to_policer_action(tokens[7],
+			&flow_params.p[policer_id].action[e_RTE_METER_YELLOW])) {
+			printf(CMD_MSG_INVALID_ARG, "yaction");
+			return;
+		}
 
-cmdline_parse_token_num_t cmd_fa_output_port_config_flow_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
-	flow_id, UINT32);
+		if (strcmp(tokens[8], "r")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "r");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_output_port_config_port_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result,
-	port_string, "port");
+		if (string_to_policer_action(tokens[9],
+			&flow_params.p[policer_id].action[e_RTE_METER_RED])) {
+			printf(CMD_MSG_INVALID_ARG, "raction");
+			return;
+		}
 
-cmdline_parse_token_num_t cmd_fa_output_port_config_port_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result,
-	port_id, UINT32);
+		status = app_pipeline_fa_flow_config(app,
+			params->pipeline_id,
+			flow_id,
+			0,
+			1 << policer_id,
+			0,
+			&flow_params);
+		if (status != 0)
+			printf(CMD_MSG_FAIL, "action flow policer");
 
-cmdline_parse_inst_t cmd_fa_output_port_config = {
-	.f = cmd_fa_output_port_config_parsed,
-	.data = NULL,
-	.help_str = "Flow output port configuration (single flow)",
-	.tokens = {
-		(void *) &cmd_fa_output_port_config_p_string,
-		(void *) &cmd_fa_output_port_config_pipeline_id,
-		(void *) &cmd_fa_output_port_config_flow_string,
-		(void *) &cmd_fa_output_port_config_flow_id,
-		(void *) &cmd_fa_output_port_config_port_string,
-		(void *) &cmd_fa_output_port_config_port_id,
-		NULL,
-	},
-};
+		return;
+	} /* action flow policer */
+
+	/* action flow port */
+	if ((n_tokens >= 3) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		strcmp(tokens[1], "bulk") &&
+		strcmp(tokens[1], "ls") &&
+		(strcmp(tokens[2], "port") == 0)) {
+		struct pipeline_fa_flow_params flow_params;
+		uint32_t flow_id, port_id;
+
+		if (n_tokens != 4) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow port");
+			return;
+		}
 
-/*
- * Flow output port configuration (multiple flows)
- *
- * p <pipeline ID> flows <n_flows> ports <n_ports>
- */
+		memset(&flow_params, 0, sizeof(flow_params));
 
-struct cmd_fa_output_port_config_bulk_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flows_string;
-	uint32_t n_flows;
-	cmdline_fixed_string_t ports_string;
-	uint32_t n_ports;
-};
+		if (parser_read_uint32(&flow_id, tokens[1])) {
+			printf(CMD_MSG_INVALID_ARG, "flowid");
+			return;
+		}
 
-static void
-cmd_fa_output_port_config_bulk_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_output_port_config_bulk_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_flow_params *flow_params;
-	uint32_t *flow_id;
-	uint32_t i;
+		if (parser_read_uint32(&port_id, tokens[3])) {
+			printf(CMD_MSG_INVALID_ARG, "portid");
+			return;
+		}
 
-	if (params->n_flows == 0) {
-		printf("Invalid arguments\n");
-		return;
-	}
+		flow_params.port_id = port_id;
 
-	flow_id = (uint32_t *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(uint32_t),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_id == NULL) {
-		printf("Memory allocation failed\n");
-		return;
-	}
+		status = app_pipeline_fa_flow_config(app,
+			params->pipeline_id,
+			flow_id,
+			0,
+			0,
+			1,
+			&flow_params);
+		if (status)
+			printf(CMD_MSG_FAIL, "action flow port");
 
-	flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL,
-		N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params),
-		RTE_CACHE_LINE_SIZE);
-	if (flow_params == NULL) {
-		rte_free(flow_id);
-		printf("Memory allocation failed\n");
 		return;
-	}
-
-	for (i = 0; i < params->n_flows; i++) {
-		uint32_t pos = i % N_FLOWS_BULK;
-		uint32_t port_id = i % params->n_ports;
-
-		flow_id[pos] = i;
-
-		memset(&flow_params[pos], 0, sizeof(flow_params[pos]));
-		flow_params[pos].port_id = port_id;
+	} /* action flow port */
+
+	/* action flow stats */
+	if ((n_tokens >= 3) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		strcmp(tokens[1], "bulk") &&
+		strcmp(tokens[1], "ls") &&
+		(strcmp(tokens[2], "stats") == 0)) {
+		struct pipeline_fa_policer_stats stats;
+		uint32_t flow_id, policer_id;
+
+		if (n_tokens != 3) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow stats");
+			return;
+		}
 
-		if ((pos == N_FLOWS_BULK - 1) ||
-			(i == params->n_flows - 1)) {
-			int status;
+		if (parser_read_uint32(&flow_id, tokens[1])) {
+			printf(CMD_MSG_INVALID_ARG, "flowid");
+			return;
+		}
 
-			status = app_pipeline_fa_flow_config_bulk(app,
+		for (policer_id = 0;
+			policer_id < PIPELINE_FA_N_TC_MAX;
+			policer_id++) {
+			status = app_pipeline_fa_flow_policer_stats_read(app,
 				params->pipeline_id,
 				flow_id,
-				pos + 1,
-				0,
-				0,
+				policer_id,
 				1,
-				flow_params);
-
+				&stats);
 			if (status != 0) {
-				printf("Command failed\n");
-
-				break;
+				printf(CMD_MSG_FAIL, "action flow stats");
+				return;
 			}
-		}
-	}
-
-	rte_free(flow_params);
-	rte_free(flow_id);
-
-}
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_flows_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	flows_string, "flows");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_flows =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	n_flows, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_ports_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	ports_string, "ports");
-
-cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_ports =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result,
-	n_ports, UINT32);
-
-cmdline_parse_inst_t cmd_fa_output_port_config_bulk = {
-	.f = cmd_fa_output_port_config_bulk_parsed,
-	.data = NULL,
-	.help_str = "Flow output port configuration (multiple flows)",
-	.tokens = {
-		(void *) &cmd_fa_output_port_config_bulk_p_string,
-		(void *) &cmd_fa_output_port_config_bulk_pipeline_id,
-		(void *) &cmd_fa_output_port_config_bulk_flows_string,
-		(void *) &cmd_fa_output_port_config_bulk_n_flows,
-		(void *) &cmd_fa_output_port_config_bulk_ports_string,
-		(void *) &cmd_fa_output_port_config_bulk_n_ports,
-		NULL,
-	},
-};
-
-/*
- * Flow DiffServ Code Point (DSCP) translation table configuration
- *
- * p <pipeline ID> dscp <DSCP ID> class <traffic class ID> color <color>
- *
- * <color> = G (green) | Y (yellow) | R (red)
-*/
 
-struct cmd_fa_dscp_config_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t dscp_string;
-	uint32_t dscp_id;
-	cmdline_fixed_string_t class_string;
-	uint32_t traffic_class_id;
-	cmdline_fixed_string_t color_string;
-	cmdline_fixed_string_t color;
-
-};
-
-static void
-cmd_fa_dscp_config_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_dscp_config_result *params = parsed_result;
-	struct app_params *app = data;
-	enum rte_meter_color color;
-	int status;
+			/* Display stats */
+			printf("\tPolicer: %" PRIu32
+				"\tPkts G: %" PRIu64
+				"\tPkts Y: %" PRIu64
+				"\tPkts R: %" PRIu64
+				"\tPkts D: %" PRIu64 "\n",
+				policer_id,
+				stats.n_pkts[e_RTE_METER_GREEN],
+				stats.n_pkts[e_RTE_METER_YELLOW],
+				stats.n_pkts[e_RTE_METER_RED],
+				stats.n_pkts_drop);
+		}
 
-	status = string_to_color(params->color, &color);
-	if (status) {
-		printf("Invalid color\n");
 		return;
-	}
-
-	status = app_pipeline_fa_dscp_config(app,
-		params->pipeline_id,
-		params->dscp_id,
-		params->traffic_class_id,
-		color);
-
-	if (status != 0)
-		printf("Command failed\n");
-}
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_dscp_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
-	dscp_string, "dscp");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_dscp_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
-	dscp_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_class_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
-	class_string, "class");
-
-cmdline_parse_token_num_t cmd_fa_dscp_config_traffic_class_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result,
-	traffic_class_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_color_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
-	color_string, "color");
-
-cmdline_parse_token_string_t cmd_fa_dscp_config_color =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result,
-	color, "G#Y#R");
+	} /* action flow stats */
+
+	/* action flow bulk */
+	if ((n_tokens >= 2) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		(strcmp(tokens[1], "bulk") == 0)) {
+		struct pipeline_fa_flow_params *flow_params;
+		uint32_t *flow_ids, n_flows, line;
+		char *filename;
+
+		if (n_tokens != 3) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow bulk");
+			return;
+		}
 
-cmdline_parse_inst_t cmd_fa_dscp_config = {
-	.f = cmd_fa_dscp_config_parsed,
-	.data = NULL,
-	.help_str = "Flow DSCP translation table configuration",
-	.tokens = {
-		(void *) &cmd_fa_dscp_config_p_string,
-		(void *) &cmd_fa_dscp_config_pipeline_id,
-		(void *) &cmd_fa_dscp_config_dscp_string,
-		(void *) &cmd_fa_dscp_config_dscp_id,
-		(void *) &cmd_fa_dscp_config_class_string,
-		(void *) &cmd_fa_dscp_config_traffic_class_id,
-		(void *) &cmd_fa_dscp_config_color_string,
-		(void *) &cmd_fa_dscp_config_color,
-		NULL,
-	},
-};
+		filename = tokens[2];
 
-/*
- * Flow policer stats read
- *
- * p <pipeline ID> flow <flow ID> policer <policer ID> stats
- */
+		n_flows = APP_PIPELINE_FA_MAX_RECORDS_IN_FILE;
+		flow_ids = malloc(n_flows * sizeof(uint32_t));
+		if (flow_ids == NULL) {
+			printf(CMD_MSG_OUT_OF_MEMORY);
+			return;
+		}
 
-struct cmd_fa_policer_stats_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flow_string;
-	uint32_t flow_id;
-	cmdline_fixed_string_t policer_string;
-	uint32_t policer_id;
-	cmdline_fixed_string_t stats_string;
-};
+		flow_params = malloc(n_flows * sizeof(struct pipeline_fa_flow_params));
+		if (flow_params == NULL) {
+			printf(CMD_MSG_OUT_OF_MEMORY);
+			free(flow_ids);
+			return;
+		}
 
-static void
-cmd_fa_policer_stats_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_policer_stats_result *params = parsed_result;
-	struct app_params *app = data;
-	struct pipeline_fa_policer_stats stats;
-	int status;
+		status = app_pipeline_fa_load_file(filename,
+			flow_ids,
+			flow_params,
+			&n_flows,
+			&line);
+		if (status) {
+			printf(CMD_MSG_FILE_ERR, filename, line);
+			free(flow_params);
+			free(flow_ids);
+			return;
+		}
 
-	status = app_pipeline_fa_flow_policer_stats_read(app,
-		params->pipeline_id,
-		params->flow_id,
-		params->policer_id,
-		1,
-		&stats);
-	if (status != 0) {
-		printf("Command failed\n");
+		status = app_pipeline_fa_flow_config_bulk(app,
+			params->pipeline_id,
+			flow_ids,
+			n_flows,
+			0xF,
+			0xF,
+			1,
+			flow_params);
+		if (status)
+			printf(CMD_MSG_FAIL, "action flow bulk");
+
+		free(flow_params);
+		free(flow_ids);
 		return;
-	}
-
-	/* Display stats */
-	printf("\tPkts G: %" PRIu64
-		"\tPkts Y: %" PRIu64
-		"\tPkts R: %" PRIu64
-		"\tPkts D: %" PRIu64 "\n",
-		stats.n_pkts[e_RTE_METER_GREEN],
-		stats.n_pkts[e_RTE_METER_YELLOW],
-		stats.n_pkts[e_RTE_METER_RED],
-		stats.n_pkts_drop);
-}
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
-	p_string, "p");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
-	pipeline_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
-	flow_string, "flow");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_flow_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
-	flow_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_policer_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
-	policer_string, "policer");
-
-cmdline_parse_token_num_t cmd_fa_policer_stats_policer_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result,
-	policer_id, UINT32);
-
-cmdline_parse_token_string_t cmd_fa_policer_stats_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result,
-	stats_string, "stats");
-
-cmdline_parse_inst_t cmd_fa_policer_stats = {
-	.f = cmd_fa_policer_stats_parsed,
-	.data = NULL,
-	.help_str = "Flow policer stats read",
-	.tokens = {
-		(void *) &cmd_fa_policer_stats_p_string,
-		(void *) &cmd_fa_policer_stats_pipeline_id,
-		(void *) &cmd_fa_policer_stats_flow_string,
-		(void *) &cmd_fa_policer_stats_flow_id,
-		(void *) &cmd_fa_policer_stats_policer_string,
-		(void *) &cmd_fa_policer_stats_policer_id,
-		(void *) &cmd_fa_policer_stats_string,
-		NULL,
-	},
-};
-
-/*
- * Flow list
- *
- * p <pipeline ID> flow ls
- */
+	} /* action flow bulk */
+
+	/* action flow ls */
+	if ((n_tokens >= 2) &&
+		(strcmp(tokens[0], "flow") == 0) &&
+		(strcmp(tokens[1], "ls") == 0)) {
+		if (n_tokens != 2) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action flow ls");
+			return;
+		}
 
-struct cmd_fa_flow_ls_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t flow_string;
-	cmdline_fixed_string_t actions_string;
-	cmdline_fixed_string_t ls_string;
-};
+		status = app_pipeline_fa_flow_ls(app,
+			params->pipeline_id);
+		if (status)
+			printf(CMD_MSG_FAIL, "action flow ls");
 
-static void
-cmd_fa_flow_ls_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_flow_ls_result *params = parsed_result;
-	struct app_params *app = data;
-	int status;
-
-	status = app_pipeline_fa_flow_ls(app, params->pipeline_id);
-	if (status != 0)
-		printf("Command failed\n");
-}
+		return;
+	} /* action flow ls */
+
+	/* action dscp */
+	if ((n_tokens >= 2) &&
+		(strcmp(tokens[0], "dscp") == 0) &&
+		strcmp(tokens[1], "ls")) {
+		uint32_t dscp_id, tc_id;
+		enum rte_meter_color color;
+
+		if (n_tokens != 6) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action dscp");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_flow_ls_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
-	p_string, "p");
+		if (parser_read_uint32(&dscp_id, tokens[1])) {
+			printf(CMD_MSG_INVALID_ARG, "dscpid");
+			return;
+		}
 
-cmdline_parse_token_num_t cmd_fa_flow_ls_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_flow_ls_result,
-	pipeline_id, UINT32);
+		if (strcmp(tokens[2], "class")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "class");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_flow_ls_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
-	flow_string, "flow");
+		if (parser_read_uint32(&tc_id, tokens[3])) {
+			printf(CMD_MSG_INVALID_ARG, "classid");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_flow_ls_actions_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
-	actions_string, "actions");
+		if (strcmp(tokens[4], "color")) {
+			printf(CMD_MSG_ARG_NOT_FOUND, "color");
+			return;
+		}
 
-cmdline_parse_token_string_t cmd_fa_flow_ls_ls_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result,
-	ls_string, "ls");
+		if (string_to_color(tokens[5], &color)) {
+			printf(CMD_MSG_INVALID_ARG, "colorid");
+			return;
+		}
 
-cmdline_parse_inst_t cmd_fa_flow_ls = {
-	.f = cmd_fa_flow_ls_parsed,
-	.data = NULL,
-	.help_str = "Flow actions list",
-	.tokens = {
-		(void *) &cmd_fa_flow_ls_p_string,
-		(void *) &cmd_fa_flow_ls_pipeline_id,
-		(void *) &cmd_fa_flow_ls_flow_string,
-		(void *) &cmd_fa_flow_ls_actions_string,
-		(void *) &cmd_fa_flow_ls_ls_string,
-		NULL,
-	},
-};
+		status = app_pipeline_fa_dscp_config(app,
+			params->pipeline_id,
+			dscp_id,
+			tc_id,
+			color);
+		if (status != 0)
+			printf(CMD_MSG_FAIL, "action dscp");
 
-/*
- * Flow DiffServ Code Point (DSCP) translation table list
- *
- * p <pipeline ID> dscp ls
- */
+		return;
+	} /* action dscp */
+
+	/* action dscp ls */
+	if ((n_tokens >= 2) &&
+		(strcmp(tokens[0], "dscp") == 0) &&
+		(strcmp(tokens[1], "ls") == 0)) {
+		if (n_tokens != 2) {
+			printf(CMD_MSG_MISMATCH_ARGS, "action dscp ls");
+			return;
+		}
 
-struct cmd_fa_dscp_ls_result {
-	cmdline_fixed_string_t p_string;
-	uint32_t pipeline_id;
-	cmdline_fixed_string_t dscp_string;
-	cmdline_fixed_string_t ls_string;
-};
+		status = app_pipeline_fa_dscp_ls(app,
+			params->pipeline_id);
+		if (status)
+			printf(CMD_MSG_FAIL, "action dscp ls");
 
-static void
-cmd_fa_dscp_ls_parsed(
-	void *parsed_result,
-	__rte_unused struct cmdline *cl,
-	void *data)
-{
-	struct cmd_fa_dscp_ls_result *params = parsed_result;
-	struct app_params *app = data;
-	int status;
+		return;
+	} /* action dscp ls */
 
-	status = app_pipeline_fa_dscp_ls(app, params->pipeline_id);
-	if (status != 0)
-		printf("Command failed\n");
+	printf(CMD_MSG_FAIL, "action");
 }
 
-cmdline_parse_token_string_t cmd_fa_dscp_ls_p_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
-	p_string, "p");
+static cmdline_parse_token_string_t cmd_action_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_action_result, p_string, "p");
 
-cmdline_parse_token_num_t cmd_fa_dscp_ls_pipeline_id =
-	TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_ls_result,
-	pipeline_id, UINT32);
+static cmdline_parse_token_num_t cmd_action_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_action_result, pipeline_id, UINT32);
 
-cmdline_parse_token_string_t cmd_fa_dscp_ls_dscp_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result,
-	dscp_string, "dscp");
+static cmdline_parse_token_string_t cmd_action_action_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_action_result, action_string, "action");
 
-cmdline_parse_token_string_t cmd_fa_dscp_ls_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, ls_string,
-	"ls");
+static cmdline_parse_token_string_t cmd_action_multi_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_action_result, multi_string,
+	TOKEN_STRING_MULTI);
 
-cmdline_parse_inst_t cmd_fa_dscp_ls = {
-	.f = cmd_fa_dscp_ls_parsed,
+cmdline_parse_inst_t cmd_action = {
+	.f = cmd_action_parsed,
 	.data = NULL,
-	.help_str = "Flow DSCP translaton table list",
+	.help_str = "flow actions (meter, policer, policer stats, dscp table)",
 	.tokens = {
-		(void *) &cmd_fa_dscp_ls_p_string,
-		(void *) &cmd_fa_dscp_ls_pipeline_id,
-		(void *) &cmd_fa_dscp_ls_dscp_string,
-		(void *) &cmd_fa_dscp_ls_string,
+		(void *) &cmd_action_p_string,
+		(void *) &cmd_action_pipeline_id,
+		(void *) &cmd_action_action_string,
+		(void *) &cmd_action_multi_string,
 		NULL,
 	},
 };
 
 static cmdline_parse_ctx_t pipeline_cmds[] = {
-	(cmdline_parse_inst_t *) &cmd_fa_meter_config,
-	(cmdline_parse_inst_t *) &cmd_fa_meter_config_bulk,
-	(cmdline_parse_inst_t *) &cmd_fa_policer_config,
-	(cmdline_parse_inst_t *) &cmd_fa_policer_config_bulk,
-	(cmdline_parse_inst_t *) &cmd_fa_output_port_config,
-	(cmdline_parse_inst_t *) &cmd_fa_output_port_config_bulk,
-	(cmdline_parse_inst_t *) &cmd_fa_dscp_config,
-	(cmdline_parse_inst_t *) &cmd_fa_policer_stats,
-	(cmdline_parse_inst_t *) &cmd_fa_flow_ls,
-	(cmdline_parse_inst_t *) &cmd_fa_dscp_ls,
+	(cmdline_parse_inst_t *) &cmd_action,
 	NULL,
 };
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
index f2cd0cb..9c60974 100644
--- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
+++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h
@@ -73,6 +73,17 @@ app_pipeline_fa_flow_policer_stats_read(struct app_params *app,
 	int clear,
 	struct pipeline_fa_policer_stats *stats);
 
+#ifndef APP_PIPELINE_FA_MAX_RECORDS_IN_FILE
+#define APP_PIPELINE_FA_MAX_RECORDS_IN_FILE		65536
+#endif
+
+int
+app_pipeline_fa_load_file(char *filename,
+	uint32_t *flow_ids,
+	struct pipeline_fa_flow_params *p,
+	uint32_t *n_flows,
+	uint32_t *line);
+
 extern struct pipeline_type pipeline_flow_actions;
 
 #endif
-- 
1.7.9.5

  parent reply	other threads:[~2016-06-08 10:34 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-06 15:57 [PATCH 0/6] ip_pipeline: CLI rework and improvements Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 1/6] examples/ip_pipeline: add helper functions for parsing string Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 2/6] examples/ip_pipeline: modifies common pipeline CLI Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 3/6] examples/ip_pipeline: modifies routing commands Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 4/6] examples/ip_pipeline: modifies firewall pipeline CLI Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 5/6] examples/ip_pipeline: modifies flow classifications " Michal Jastrzebski
2016-05-06 15:57 ` [PATCH 6/6] examples/ip_pipeline: modifies flow action " Michal Jastrzebski
2016-05-20 14:35 ` [PATCH v2 0/7] examples/ip_pipeline: CLI rework and improvements Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 1/7] examples/ip_pipeline: add helper functions for parsing string Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 2/7] examples/ip_pipeline: modifies common pipeline CLI Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 3/7] examples/ip_pipeline: modifies firewall " Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 4/7] examples/ip_pipeline: modifies flow classifications " Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 5/7] examples/ip_pipeline: modifies flow action " Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 6/7] examples/ip_pipeline: modifies routing " Piotr Azarewicz
2016-05-20 14:35   ` [PATCH v2 7/7] examples/ip_pipeline: update edge router usecase Piotr Azarewicz
2016-06-07 20:34   ` [PATCH v2 0/7] examples/ip_pipeline: CLI rework and improvements Thomas Monjalon
2016-06-08 10:01     ` Azarewicz, PiotrX T
2016-06-08 10:35   ` [PATCH v3 " Piotr Azarewicz
2016-06-08 10:35     ` [PATCH v3 1/7] examples/ip_pipeline: add helper functions for parsing string Piotr Azarewicz
2016-06-08 10:35     ` [PATCH v3 2/7] examples/ip_pipeline: modifies common pipeline CLI Piotr Azarewicz
2016-06-08 10:35     ` [PATCH v3 3/7] examples/ip_pipeline: modifies firewall " Piotr Azarewicz
2016-06-08 10:35     ` [PATCH v3 4/7] examples/ip_pipeline: modifies flow classifications " Piotr Azarewicz
2016-06-08 10:35     ` Piotr Azarewicz [this message]
2016-06-08 10:35     ` [PATCH v3 6/7] examples/ip_pipeline: modifies routing " Piotr Azarewicz
2016-06-08 10:35     ` [PATCH v3 7/7] examples/ip_pipeline: update edge router usecase Piotr Azarewicz
2016-06-08 14:46     ` [PATCH v3 0/7] examples/ip_pipeline: CLI rework and improvements Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1465382125-2747-6-git-send-email-piotrx.t.azarewicz@intel.com \
    --to=piotrx.t.azarewicz@intel.com \
    --cc=dev@dpdk.org \
    --cc=marcinx.kerlin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.