[dpdk-dev] [PATCH 05/11] ip_pipeline: added master pipeline

Maciej Gajdzica maciejx.t.gajdzica at intel.com
Fri May 29 17:43:12 CEST 2015


Master pipeline is responsible for command line handling and
communicationg with all other pipelines via message queues. Removed
cmdline.c file, as its functionality will be split over multiple
pipeline files.

Signed-off-by: Jasvinder Singh <jasvinder.singh at intel.com>
---
 examples/ip_pipeline/Makefile                      |    6 +-
 examples/ip_pipeline/cmdline.c                     | 1976 --------------------
 examples/ip_pipeline/init.c                        |    3 +
 examples/ip_pipeline/pipeline/pipeline_common.c    |  412 ++++
 examples/ip_pipeline/pipeline/pipeline_common.h    |  241 +++
 .../ip_pipeline/pipeline/pipeline_common_ops.c     |  205 ++
 .../ip_pipeline/pipeline/pipeline_common_ops.h     |  150 ++
 examples/ip_pipeline/pipeline/pipeline_master.c    |  870 +++++++++
 examples/ip_pipeline/pipeline/pipeline_master.h    |   41 +
 .../ip_pipeline/pipeline/pipeline_master_ops.c     |  136 ++
 .../ip_pipeline/pipeline/pipeline_master_ops.h     |   41 +
 11 files changed, 2104 insertions(+), 1977 deletions(-)
 delete mode 100644 examples/ip_pipeline/cmdline.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_common.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_common.h
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_ops.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_common_ops.h
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_master.h
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_ops.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_master_ops.h

diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 9a1e19a..6269be1 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -53,7 +53,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c
-#SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cmdline.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_ops.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_ops.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
 #SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_rx.c
 #SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_tx.c
 #SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c
diff --git a/examples/ip_pipeline/cmdline.c b/examples/ip_pipeline/cmdline.c
deleted file mode 100644
index 3173fd0..0000000
--- a/examples/ip_pipeline/cmdline.c
+++ /dev/null
@@ -1,1976 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- */
-
-#include <stdio.h>
-#include <termios.h>
-#include <inttypes.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <rte_ether.h>
-#include <rte_byteorder.h>
-#include <rte_ring.h>
-#include <rte_mbuf.h>
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-#include <cmdline_rdline.h>
-#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 <cmdline_socket.h>
-#include <cmdline.h>
-
-#include "main.h"
-
-#define IS_RULE_PRESENT(res, rule_key, table, type)			\
-do {									\
-	struct app_rule *it;						\
-									\
-	(res) = NULL;							\
-	TAILQ_FOREACH(it, &table, entries) {				\
-		if (memcmp(&rule_key, &it->type.key, sizeof(rule_key)) == 0) {\
-			(res) = it;					\
-			break;						\
-		}							\
-	}								\
-} while (0)
-
-/* Rules */
-static void
-app_init_rule_tables(void);
-
-TAILQ_HEAD(linked_list, app_rule) arp_table, routing_table, firewall_table,
-	flow_table;
-
-uint32_t n_arp_rules;
-uint32_t n_routing_rules;
-uint32_t n_firewall_rules;
-uint32_t n_flow_rules;
-
-struct app_arp_rule {
-	struct {
-		uint8_t out_iface;
-		uint32_t nh_ip;
-	} key;
-
-	struct ether_addr nh_arp;
-};
-
-struct app_routing_rule {
-	struct {
-		uint32_t ip;
-		uint8_t depth;
-	} key;
-
-	uint8_t port;
-	uint32_t nh_ip;
-};
-
-struct app_firewall_rule {
-	struct {
-		uint32_t src_ip;
-		uint32_t src_ip_mask;
-		uint32_t dst_ip;
-		uint32_t dst_ip_mask;
-		uint16_t src_port_from;
-		uint16_t src_port_to;
-		uint16_t dst_port_from;
-		uint16_t dst_port_to;
-		uint8_t proto;
-		uint8_t proto_mask;
-	} key;
-
-	int32_t priority;
-	uint8_t port;
-};
-
-struct app_flow_rule {
-	struct {
-		uint32_t src_ip;
-		uint32_t dst_ip;
-		uint16_t src_port;
-		uint16_t dst_port;
-		uint8_t proto;
-	} key;
-
-	uint8_t port;
-};
-
-struct app_rule {
-	union {
-		struct app_arp_rule arp;
-		struct app_routing_rule routing;
-		struct app_firewall_rule firewall;
-		struct app_flow_rule flow;
-	};
-
-	TAILQ_ENTRY(app_rule) entries;
-};
-
-/* Initialization */
-static void
-app_init_rule_tables(void)
-{
-	TAILQ_INIT(&arp_table);
-	TAILQ_INIT(&routing_table);
-	TAILQ_INIT(&firewall_table);
-	TAILQ_INIT(&flow_table);
-
-	n_arp_rules = 0;
-	n_routing_rules = 0;
-	n_firewall_rules = 0;
-	n_flow_rules = 0;
-}
-
-/* Printing */
-static void
-print_arp_rule(struct app_arp_rule rule)
-{
-	printf("(Iface = %u, Address = %u.%u.%u.%u) => "
-		"HWaddress = %02x:%02x:%02x:%02x:%02x:%02x\n",
-		rule.key.out_iface,
-		(rule.key.nh_ip >> 24) & 0xFF,
-		(rule.key.nh_ip >> 16) & 0xFF,
-		(rule.key.nh_ip >> 8) & 0xFF,
-		rule.key.nh_ip & 0xFF,
-
-		rule.nh_arp.addr_bytes[0],
-		rule.nh_arp.addr_bytes[1],
-		rule.nh_arp.addr_bytes[2],
-		rule.nh_arp.addr_bytes[3],
-		rule.nh_arp.addr_bytes[4],
-		rule.nh_arp.addr_bytes[5]);
-}
-
-static void
-print_routing_rule(struct app_routing_rule rule)
-{
-	printf("IP Prefix = %u.%u.%u.%u/%u => "
-		"(Iface = %u, Gateway = %u.%u.%u.%u)\n",
-		(rule.key.ip >> 24) & 0xFF,
-		(rule.key.ip >> 16) & 0xFF,
-		(rule.key.ip >> 8) & 0xFF,
-		rule.key.ip & 0xFF,
-
-		rule.key.depth,
-		rule.port,
-
-		(rule.nh_ip >> 24) & 0xFF,
-		(rule.nh_ip >> 16) & 0xFF,
-		(rule.nh_ip >> 8) & 0xFF,
-		rule.nh_ip & 0xFF);
-}
-
-#ifdef RTE_LIBRTE_ACL
-
-static void
-print_firewall_rule(struct app_firewall_rule rule)
-{
-	printf("Priority %d: (IP Src = %u.%u.%u.%u/%u, "
-		"IP Dst = %u.%u.%u.%u/%u, "
-		"Port Src = %u-%u, Port Dst = %u-%u, Proto = %u (%u)) => "
-		"Port = %u\n",
-		rule.priority,
-
-		(rule.key.src_ip >> 24) & 0xFF,
-		(rule.key.src_ip >> 16) & 0xFF,
-		(rule.key.src_ip >> 8) & 0xFF,
-		rule.key.src_ip & 0xFF,
-		rule.key.src_ip_mask,
-
-		(rule.key.dst_ip >> 24) & 0xFF,
-		(rule.key.dst_ip >> 16) & 0xFF,
-		(rule.key.dst_ip >> 8) & 0xFF,
-		rule.key.dst_ip & 0xFF,
-		rule.key.dst_ip_mask,
-
-		rule.key.src_port_from,
-		rule.key.src_port_to,
-		rule.key.dst_port_from,
-		rule.key.dst_port_to,
-		rule.key.proto,
-		rule.key.proto_mask,
-		rule.port);
-}
-
-#endif
-
-static void
-print_flow_rule(struct app_flow_rule rule)
-{
-	printf("(IP Src = %u.%u.%u.%u, IP Dst = %u.%u.%u.%u, Port Src = %u, "
-		"Port Dst = %u, Proto = %u) => Port = %u\n",
-		(rule.key.src_ip >> 24) & 0xFF,
-		(rule.key.src_ip >> 16) & 0xFF,
-		(rule.key.src_ip >> 8) & 0xFF,
-		rule.key.src_ip & 0xFF,
-
-		(rule.key.dst_ip >> 24) & 0xFF,
-		(rule.key.dst_ip >> 16) & 0xFF,
-		(rule.key.dst_ip >> 8) & 0xFF,
-		rule.key.dst_ip  & 0xFF,
-
-		rule.key.src_port,
-		rule.key.dst_port,
-		(uint32_t) rule.key.proto,
-		rule.port);
-}
-
-/* Commands */
-
-/* *** Run file (script) *** */
-struct cmd_run_file_result {
-	cmdline_fixed_string_t run_string;
-	char file_path[100];
-};
-
-static void
-cmd_run_file_parsed(
-	void *parsed_result,
-	struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_run_file_result *params = parsed_result;
-	struct cmdline *file_cl;
-	int fd;
-
-	fd = open(params->file_path, O_RDONLY, 0);
-	if (fd < 0) {
-		printf("Illegal value for file path (%s)\n", params->file_path);
-		return;
-	}
-
-	file_cl = cmdline_new(cl->ctx, "", fd, 1);
-	cmdline_interact(file_cl);
-	close(fd);
-}
-
-cmdline_parse_token_string_t cmd_run_file_run_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
-
-cmdline_parse_token_string_t cmd_run_file_file_path =
-	TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_path, NULL);
-
-cmdline_parse_inst_t cmd_run_file = {
-	.f = cmd_run_file_parsed,
-	.data = NULL,
-	.help_str = "Run commands from file",
-	.tokens = {
-		(void *)&cmd_run_file_run_string,
-		(void *)&cmd_run_file_file_path,
-		NULL,
-	},
-};
-
-/* *** Link - Enable *** */
-struct cmd_link_enable_result {
-	cmdline_fixed_string_t link_string;
-	uint8_t port;
-	cmdline_fixed_string_t up_string;
-};
-
-static void
-cmd_link_enable_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_link_enable_result *params = parsed_result;
-	void *msg;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("RX core not preformed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->port >= app.n_ports) {
-		printf("Illegal value for port parameter (%u)\n", params->port);
-		return;
-	}
-
-	printf("Enabling port %d\n", params->port);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_RX_PORT_ENABLE;
-	req->rx_up.port = params->port;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request LINK_UP failed (%u)\n", resp->result);
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_link_enable_link_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, link_string,
-	"link");
-
-cmdline_parse_token_num_t cmd_link_enable_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_link_enable_result, port, UINT8);
-
-cmdline_parse_token_string_t cmd_link_enable_up_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_link_enable_result, up_string,
-	"up");
-
-cmdline_parse_inst_t cmd_link_enable = {
-	.f = cmd_link_enable_parsed,
-	.data = NULL,
-	.help_str = "Link down",
-	.tokens = {
-		(void *)&cmd_link_enable_link_string,
-		(void *)&cmd_link_enable_port,
-		(void *)&cmd_link_enable_up_string,
-		NULL,
-	},
-};
-
-/* *** Link - Disable *** */
-struct cmd_link_disable_result {
-	cmdline_fixed_string_t link_string;
-	uint8_t port;
-	cmdline_fixed_string_t down_string;
-};
-
-static void
-cmd_link_disable_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_link_disable_result *params = parsed_result;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RX);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("RX not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->port >= app.n_ports) {
-		printf("Illegal value for port parameter (%u)\n", params->port);
-		return;
-	}
-
-	printf("Disabling port %d\n", params->port);
-
-	/* Allocate message buffer */
-	msg = rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_RX_PORT_DISABLE;
-	req->rx_down.port = params->port;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request LINK_DOWN failed (%u)\n", resp->result);
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_link_disable_link_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, link_string,
-	"link");
-
-cmdline_parse_token_num_t cmd_link_disable_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_link_disable_result, port, UINT8);
-
-cmdline_parse_token_string_t cmd_link_disable_down_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_link_disable_result, down_string,
-	"down");
-
-cmdline_parse_inst_t cmd_link_disable = {
-	.f = cmd_link_disable_parsed,
-	.data = NULL,
-	.help_str = "Link up",
-	.tokens = {
-		(void *)&cmd_link_disable_link_string,
-		(void *)&cmd_link_disable_port,
-		(void *)&cmd_link_disable_down_string,
-		NULL,
-	},
-};
-
-
-/* *** ARP - Add *** */
-struct cmd_arp_add_result {
-	cmdline_fixed_string_t arp_string;
-	cmdline_fixed_string_t add_string;
-	uint8_t out_iface;
-	cmdline_ipaddr_t nh_ip;
-	struct ether_addr nh_arp;
-
-};
-
-static void
-cmd_arp_add_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_arp_add_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("ARP not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->out_iface >= app.n_ports) {
-		printf("Illegal value for output interface parameter (%u)\n",
-			params->out_iface);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.arp.key.out_iface = params->out_iface;
-	rule.arp.key.nh_ip =
-		rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-	rule.arp.nh_arp = params->nh_arp;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
-	if ((old_rule == NULL) && (n_arp_rules == app.max_arp_rules)) {
-		printf("ARP table is full.\n");
-		return;
-	}
-
-	printf("Adding ARP entry: ");
-	print_arp_rule(rule.arp);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_ARP_ADD;
-	req->arp_add.out_iface = rule.arp.key.out_iface;
-	req->arp_add.nh_ip = rule.arp.key.nh_ip;
-	req->arp_add.nh_arp = rule.arp.nh_arp;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request ARP_ADD failed (%u)\n", resp->result);
-	else {
-		if (old_rule == NULL) {
-			struct app_rule *new_rule = (struct app_rule *)
-				rte_zmalloc_socket("CLI",
-				sizeof(struct app_rule),
-				RTE_CACHE_LINE_SIZE,
-				rte_socket_id());
-
-			if (new_rule == NULL)
-				rte_panic("Unable to allocate new rule\n");
-
-			memcpy(new_rule, &rule, sizeof(rule));
-			TAILQ_INSERT_TAIL(&arp_table, new_rule, entries);
-			n_arp_rules++;
-		} else
-			old_rule->arp.nh_arp = rule.arp.nh_arp;
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_arp_add_arp_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp");
-
-cmdline_parse_token_string_t cmd_arp_add_add_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add");
-
-cmdline_parse_token_num_t cmd_arp_add_out_iface =
-	TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, out_iface, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_arp_add_nh_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_arp_add_result, nh_ip);
-
-cmdline_parse_token_etheraddr_t cmd_arp_add_nh_arp =
-	TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, nh_arp);
-
-cmdline_parse_inst_t cmd_arp_add = {
-	.f = cmd_arp_add_parsed,
-	.data = NULL,
-	.help_str = "ARP add",
-	.tokens = {
-		(void *)&cmd_arp_add_arp_string,
-		(void *)&cmd_arp_add_add_string,
-		(void *)&cmd_arp_add_out_iface,
-		(void *)&cmd_arp_add_nh_ip,
-		(void *)&cmd_arp_add_nh_arp,
-		NULL,
-	},
-	};
-
-/* *** ARP - Del *** */
-struct cmd_arp_del_result {
-	cmdline_fixed_string_t arp_string;
-	cmdline_fixed_string_t del_string;
-	uint8_t out_iface;
-	cmdline_ipaddr_t nh_ip;
-};
-
-static void
-cmd_arp_del_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_arp_del_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("ARP not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->out_iface > app.n_ports) {
-		printf("Illegal value for output interface parameter (%u)\n",
-			params->out_iface);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.arp.key.out_iface = params->out_iface;
-	rule.arp.key.nh_ip =
-		rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.arp.key, arp_table, arp);
-	if (old_rule == NULL)
-		return;
-
-	printf("Deleting ARP entry: ");
-	print_arp_rule(old_rule->arp);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_ARP_DEL;
-	req->arp_del.out_iface = rule.arp.key.out_iface;
-	req->arp_del.nh_ip = rule.arp.key.nh_ip;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request ARP_DEL failed (%u)\n", resp->result);
-	else {
-		TAILQ_REMOVE(&arp_table, old_rule, entries);
-		n_arp_rules--;
-		rte_free(old_rule);
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_arp_del_arp_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp");
-
-cmdline_parse_token_string_t cmd_arp_del_del_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del");
-
-cmdline_parse_token_num_t cmd_arp_del_out_iface =
-	TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, out_iface, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_arp_del_nh_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_arp_del_result, nh_ip);
-
-cmdline_parse_inst_t cmd_arp_del = {
-	.f = cmd_arp_del_parsed,
-	.data = NULL,
-	.help_str = "ARP delete",
-	.tokens = {
-		(void *)&cmd_arp_del_arp_string,
-		(void *)&cmd_arp_del_del_string,
-		(void *)&cmd_arp_del_out_iface,
-		(void *)&cmd_arp_del_nh_ip,
-		NULL,
-	},
-};
-
-/* *** ARP - Print *** */
-struct cmd_arp_print_result {
-	cmdline_fixed_string_t arp_string;
-	cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_arp_print_parsed(
-	__attribute__((unused)) void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct app_rule *it;
-
-	TAILQ_FOREACH(it, &arp_table, entries) {
-		print_arp_rule(it->arp);
-	}
-}
-
-cmdline_parse_token_string_t cmd_arp_print_arp_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, arp_string,
-	"arp");
-
-cmdline_parse_token_string_t cmd_arp_print_print_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_arp_print_result, print_string,
-	"ls");
-
-cmdline_parse_inst_t cmd_arp_print = {
-	.f = cmd_arp_print_parsed,
-	.data = NULL,
-	.help_str = "ARP list",
-	.tokens = {
-		(void *)&cmd_arp_print_arp_string,
-		(void *)&cmd_arp_print_print_string,
-		NULL,
-	},
-};
-
-/* *** Routing - Add *** */
-struct cmd_route_add_result {
-	cmdline_fixed_string_t route_string;
-	cmdline_fixed_string_t add_string;
-	cmdline_ipaddr_t ip;
-	uint8_t depth;
-	uint8_t port;
-	cmdline_ipaddr_t nh_ip;
-};
-
-static void
-cmd_route_add_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_route_add_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Routing not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if ((params->depth == 0) || (params->depth > 32)) {
-		printf("Illegal value for depth parameter (%u)\n",
-			params->depth);
-		return;
-	}
-
-	if (params->port >= app.n_ports) {
-		printf("Illegal value for port parameter (%u)\n", params->port);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.routing.key.ip = rte_bswap32((uint32_t)
-		params->ip.addr.ipv4.s_addr);
-	rule.routing.key.depth = params->depth;
-	rule.routing.port = params->port;
-	rule.routing.nh_ip =
-		rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr);
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
-	if ((old_rule == NULL) && (n_routing_rules == app.max_routing_rules)) {
-		printf("Routing table is full.\n");
-		return;
-	}
-
-	printf("Adding route: ");
-	print_routing_rule(rule.routing);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_RT_ADD;
-	req->routing_add.ip = rule.routing.key.ip;
-	req->routing_add.depth = rule.routing.key.depth;
-	req->routing_add.port = rule.routing.port;
-	req->routing_add.nh_ip = rule.routing.nh_ip;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request ROUTE_ADD failed (%u)\n", resp->result);
-	else {
-		if (old_rule == NULL) {
-			struct app_rule *new_rule = (struct app_rule *)
-				rte_zmalloc_socket("CLI",
-				sizeof(struct app_rule),
-				RTE_CACHE_LINE_SIZE,
-				rte_socket_id());
-
-			if (new_rule == NULL)
-				rte_panic("Unable to allocate new rule\n");
-
-			memcpy(new_rule, &rule, sizeof(rule));
-			TAILQ_INSERT_TAIL(&routing_table, new_rule, entries);
-			n_routing_rules++;
-		} else {
-			old_rule->routing.port = rule.routing.port;
-			old_rule->routing.nh_ip = rule.routing.nh_ip;
-		}
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *) msg);
-}
-
-cmdline_parse_token_string_t cmd_route_add_route_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string,
-	"route");
-
-cmdline_parse_token_string_t cmd_route_add_add_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string,
-	"add");
-
-cmdline_parse_token_ipaddr_t cmd_route_add_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, ip);
-
-cmdline_parse_token_num_t cmd_route_add_depth =
-	TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT8);
-
-cmdline_parse_token_num_t cmd_route_add_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT8);
-
-cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_route_add_result, nh_ip);
-
-cmdline_parse_inst_t cmd_route_add = {
-	.f = cmd_route_add_parsed,
-	.data = NULL,
-	.help_str = "Route add",
-	.tokens = {
-		(void *)&cmd_route_add_route_string,
-		(void *)&cmd_route_add_add_string,
-		(void *)&cmd_route_add_ip,
-		(void *)&cmd_route_add_depth,
-		(void *)&cmd_route_add_port,
-		(void *)&cmd_route_add_nh_ip,
-		NULL,
-	},
-};
-
-/* *** Routing - Del *** */
-struct cmd_route_del_result {
-	cmdline_fixed_string_t route_string;
-	cmdline_fixed_string_t del_string;
-	cmdline_ipaddr_t ip;
-	uint8_t depth;
-};
-
-static void
-cmd_route_del_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_route_del_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_RT);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Routing not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if ((params->depth == 0) || (params->depth > 32)) {
-		printf("Illegal value for depth parameter (%u)\n",
-			params->depth);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.routing.key.ip = rte_bswap32((uint32_t)
-		params->ip.addr.ipv4.s_addr);
-	rule.routing.key.depth = params->depth;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.routing.key, routing_table, routing);
-	if (old_rule == NULL)
-		return;
-
-	printf("Deleting route: ");
-	print_routing_rule(old_rule->routing);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	req->type = APP_MSG_REQ_RT_DEL;
-	req->routing_del.ip = rule.routing.key.ip;
-	req->routing_del.depth = rule.routing.key.depth;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request ROUTE_DEL failed %u)\n", resp->result);
-	else {
-		TAILQ_REMOVE(&routing_table, old_rule, entries);
-		rte_free(old_rule);
-		n_routing_rules--;
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_route_del_route_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string,
-	"route");
-
-cmdline_parse_token_string_t cmd_route_del_del_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string,
-	"del");
-
-cmdline_parse_token_ipaddr_t cmd_route_del_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_route_del_result, ip);
-
-cmdline_parse_token_num_t cmd_route_del_depth =
-	TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT8);
-
-cmdline_parse_inst_t cmd_route_del = {
-	.f = cmd_route_del_parsed,
-	.data = NULL,
-	.help_str = "Route delete",
-	.tokens = {
-		(void *)&cmd_route_del_route_string,
-		(void *)&cmd_route_del_del_string,
-		(void *)&cmd_route_del_ip,
-		(void *)&cmd_route_del_depth,
-		NULL,
-	},
-};
-
-/* *** Routing - Print *** */
-struct cmd_routing_print_result {
-	cmdline_fixed_string_t routing_string;
-	cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_routing_print_parsed(
-	__attribute__((unused)) void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct app_rule *it;
-
-	TAILQ_FOREACH(it, &routing_table, entries) {
-		print_routing_rule(it->routing);
-	}
-}
-
-cmdline_parse_token_string_t cmd_routing_print_routing_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result,
-	routing_string, "route");
-
-cmdline_parse_token_string_t cmd_routing_print_print_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_routing_print_result, print_string,
-	"ls");
-
-cmdline_parse_inst_t cmd_routing_print = {
-	.f = cmd_routing_print_parsed,
-	.data = NULL,
-	.help_str = "Route list",
-	.tokens = {
-		(void *)&cmd_routing_print_routing_string,
-		(void *)&cmd_routing_print_print_string,
-		NULL,
-	},
-};
-
-#ifdef RTE_LIBRTE_ACL
-
-/* *** Firewall - Add *** */
-struct cmd_firewall_add_result {
-	cmdline_fixed_string_t firewall_string;
-	cmdline_fixed_string_t add_string;
-	int32_t priority;
-	cmdline_ipaddr_t src_ip;
-	uint32_t src_ip_mask;
-	cmdline_ipaddr_t dst_ip;
-	uint32_t dst_ip_mask;
-	uint16_t src_port_from;
-	uint16_t src_port_to;
-	uint16_t dst_port_from;
-	uint16_t dst_port_to;
-	uint8_t proto;
-	uint8_t proto_mask;
-	uint8_t port;
-};
-
-static void
-cmd_firewall_add_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_firewall_add_result *params = parsed_result;
-	struct app_rule rule, *old_rule, *new_rule = NULL;
-	struct rte_mbuf *msg;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Firewall not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->port >= app.n_ports) {
-		printf("Illegal value for port parameter (%u)\n", params->port);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.firewall.priority = params->priority;
-	rule.firewall.key.src_ip =
-		rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
-	rule.firewall.key.src_ip_mask = params->src_ip_mask;
-	rule.firewall.key.dst_ip =
-		rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
-	rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
-	rule.firewall.key.src_port_from = params->src_port_from;
-	rule.firewall.key.src_port_to = params->src_port_to;
-	rule.firewall.key.dst_port_from = params->dst_port_from;
-	rule.firewall.key.dst_port_to = params->dst_port_to;
-	rule.firewall.key.proto = params->proto;
-	rule.firewall.key.proto_mask = params->proto_mask;
-	rule.firewall.port = params->port;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
-	if ((old_rule == NULL) &&
-		(n_firewall_rules == app.max_firewall_rules)) {
-		printf("Firewall table is full.\n");
-		return;
-	}
-
-	printf("Adding firewall rule: ");
-	print_firewall_rule(rule.firewall);
-
-	/* Allocate message buffer */
-	msg = rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* if we need a new rule structure, allocate it before we go further */
-	if (old_rule == NULL) {
-		new_rule = rte_zmalloc_socket("CLI", sizeof(struct app_rule),
-				RTE_CACHE_LINE_SIZE, rte_socket_id());
-		if (new_rule == NULL) {
-			printf("Cannot allocate memory for new rule\n");
-			rte_ctrlmbuf_free(msg);
-			return;
-		}
-	}
-
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
-	req->type = APP_MSG_REQ_FW_ADD;
-	req->firewall_add.add_params.priority = rule.firewall.priority;
-	req->firewall_add.add_params.field_value[1].value.u32 =
-		rule.firewall.key.src_ip;
-	req->firewall_add.add_params.field_value[1].mask_range.u32 =
-		rule.firewall.key.src_ip_mask;
-	req->firewall_add.add_params.field_value[2].value.u32 =
-		rule.firewall.key.dst_ip;
-	req->firewall_add.add_params.field_value[2].mask_range.u32 =
-		rule.firewall.key.dst_ip_mask;
-	req->firewall_add.add_params.field_value[3].value.u16 =
-		rule.firewall.key.src_port_from;
-	req->firewall_add.add_params.field_value[3].mask_range.u16 =
-		rule.firewall.key.src_port_to;
-	req->firewall_add.add_params.field_value[4].value.u16 =
-		rule.firewall.key.dst_port_from;
-	req->firewall_add.add_params.field_value[4].mask_range.u16 =
-		rule.firewall.key.dst_port_to;
-	req->firewall_add.add_params.field_value[0].value.u8 =
-		rule.firewall.key.proto;
-	req->firewall_add.add_params.field_value[0].mask_range.u8 =
-		rule.firewall.key.proto_mask;
-	req->firewall_add.port = rule.firewall.port;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, (void *) msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request FIREWALL_ADD failed (%u)\n", resp->result);
-	else {
-		if (old_rule == NULL) {
-			memcpy(new_rule, &rule, sizeof(rule));
-			TAILQ_INSERT_TAIL(&firewall_table, new_rule, entries);
-			n_firewall_rules++;
-		} else {
-			old_rule->firewall.priority = rule.firewall.priority;
-			old_rule->firewall.port = rule.firewall.port;
-		}
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_firewall_add_firewall_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result,
-	firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_add_add_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_result, add_string,
-	"add");
-
-cmdline_parse_token_num_t cmd_firewall_add_priority =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, priority, INT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_add_src_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, src_ip);
-cmdline_parse_token_num_t cmd_firewall_add_src_ip_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_ip_mask,
-	UINT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_add_dst_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_result, dst_ip);
-cmdline_parse_token_num_t cmd_firewall_add_dst_ip_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_ip_mask,
-	UINT32);
-
-cmdline_parse_token_num_t cmd_firewall_add_src_port_from =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_from,
-	UINT16);
-cmdline_parse_token_num_t cmd_firewall_add_src_port_to =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, src_port_to,
-	UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_add_dst_port_from =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_from,
-	UINT16);
-cmdline_parse_token_num_t cmd_firewall_add_dst_port_to =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, dst_port_to,
-	UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_add_proto =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto, UINT8);
-cmdline_parse_token_num_t cmd_firewall_add_proto_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, proto_mask,
-	UINT8);
-cmdline_parse_token_num_t cmd_firewall_add_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_result, port, UINT8);
-
-cmdline_parse_inst_t cmd_firewall_add = {
-	.f = cmd_firewall_add_parsed,
-	.data = NULL,
-	.help_str = "Firewall rule add",
-	.tokens = {
-		(void *)&cmd_firewall_add_firewall_string,
-		(void *)&cmd_firewall_add_add_string,
-		(void *)&cmd_firewall_add_priority,
-		(void *)&cmd_firewall_add_src_ip,
-		(void *)&cmd_firewall_add_src_ip_mask,
-		(void *)&cmd_firewall_add_dst_ip,
-		(void *)&cmd_firewall_add_dst_ip_mask,
-		(void *)&cmd_firewall_add_src_port_from,
-		(void *)&cmd_firewall_add_src_port_to,
-		(void *)&cmd_firewall_add_dst_port_from,
-		(void *)&cmd_firewall_add_dst_port_to,
-		(void *)&cmd_firewall_add_proto,
-		(void *)&cmd_firewall_add_proto_mask,
-		(void *)&cmd_firewall_add_port,
-		NULL,
-	},
-};
-
-/* *** firewall - Del *** */
-struct cmd_firewall_del_result {
-	cmdline_fixed_string_t firewall_string;
-	cmdline_fixed_string_t del_string;
-	cmdline_ipaddr_t src_ip;
-	uint32_t src_ip_mask;
-	cmdline_ipaddr_t dst_ip;
-	uint32_t dst_ip_mask;
-	uint16_t src_port_from;
-	uint16_t src_port_to;
-	uint16_t dst_port_from;
-	uint16_t dst_port_to;
-	uint8_t proto;
-	uint8_t proto_mask;
-};
-
-static void
-cmd_firewall_del_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_firewall_del_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct rte_mbuf *msg;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_FW);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Firewall not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.firewall.key.src_ip =
-		rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr);
-	rule.firewall.key.src_ip_mask = params->src_ip_mask;
-	rule.firewall.key.dst_ip =
-		rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr);
-	rule.firewall.key.dst_ip_mask = params->dst_ip_mask;
-	rule.firewall.key.src_port_from = params->src_port_from;
-	rule.firewall.key.src_port_to = params->src_port_to;
-	rule.firewall.key.dst_port_from = params->dst_port_from;
-	rule.firewall.key.dst_port_to = params->dst_port_to;
-	rule.firewall.key.proto = params->proto;
-	rule.firewall.key.proto_mask = params->proto_mask;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.firewall.key, firewall_table, firewall);
-	if (old_rule == NULL)
-		return;
-
-	printf("Deleting firewall rule: ");
-	print_firewall_rule(old_rule->firewall);
-
-	/* Allocate message buffer */
-	msg = rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
-	memset(&req->firewall_del, 0, sizeof(req->firewall_del));
-	req->type = APP_MSG_REQ_FW_DEL;
-	req->firewall_del.delete_params.field_value[1].value.u32 =
-		rule.firewall.key.src_ip;
-	req->firewall_del.delete_params.field_value[1].mask_range.u32 =
-		rule.firewall.key.src_ip_mask;
-	req->firewall_del.delete_params.field_value[2].value.u32 =
-		rule.firewall.key.dst_ip;
-	req->firewall_del.delete_params.field_value[2].mask_range.u32 =
-		rule.firewall.key.dst_ip_mask;
-	req->firewall_del.delete_params.field_value[3].value.u16 =
-		rule.firewall.key.src_port_from;
-	req->firewall_del.delete_params.field_value[3].mask_range.u16 =
-		rule.firewall.key.src_port_to;
-	req->firewall_del.delete_params.field_value[4].value.u16 =
-		rule.firewall.key.dst_port_from;
-	req->firewall_del.delete_params.field_value[4].mask_range.u16 =
-		rule.firewall.key.dst_port_to;
-	req->firewall_del.delete_params.field_value[0].value.u8 =
-		rule.firewall.key.proto;
-	req->firewall_del.delete_params.field_value[0].mask_range.u8 =
-		rule.firewall.key.proto_mask;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, (void *) msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, (void **) &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request FIREWALL_DEL failed %u)\n", resp->result);
-	else {
-		TAILQ_REMOVE(&firewall_table, old_rule, entries);
-		rte_free(old_rule);
-		n_firewall_rules--;
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free(msg);
-}
-
-cmdline_parse_token_string_t cmd_firewall_del_firewall_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result,
-	firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_del_del_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_result, del_string,
-	"del");
-
-cmdline_parse_token_ipaddr_t cmd_firewall_del_src_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, src_ip);
-cmdline_parse_token_num_t cmd_firewall_del_src_ip_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_ip_mask,
-	UINT32);
-
-cmdline_parse_token_ipaddr_t cmd_firewall_del_dst_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_result, dst_ip);
-cmdline_parse_token_num_t cmd_firewall_del_dst_ip_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_ip_mask,
-	UINT32);
-
-cmdline_parse_token_num_t cmd_firewall_del_src_port_from =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_from,
-	UINT16);
-cmdline_parse_token_num_t cmd_firewall_del_src_port_to =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, src_port_to,
-	UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_del_dst_port_from =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_from,
-	UINT16);
-cmdline_parse_token_num_t cmd_firewall_del_dst_port_to =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, dst_port_to,
-	UINT16);
-
-cmdline_parse_token_num_t cmd_firewall_del_proto =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto, UINT8);
-cmdline_parse_token_num_t cmd_firewall_del_proto_mask =
-	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_result, proto_mask,
-	UINT8);
-
-cmdline_parse_inst_t cmd_firewall_del = {
-	.f = cmd_firewall_del_parsed,
-	.data = NULL,
-	.help_str = "Firewall rule delete",
-	.tokens = {
-		(void *)&cmd_firewall_del_firewall_string,
-		(void *)&cmd_firewall_del_del_string,
-		(void *)&cmd_firewall_del_src_ip,
-		(void *)&cmd_firewall_del_src_ip_mask,
-		(void *)&cmd_firewall_del_dst_ip,
-		(void *)&cmd_firewall_del_dst_ip_mask,
-		(void *)&cmd_firewall_del_src_port_from,
-		(void *)&cmd_firewall_del_src_port_to,
-		(void *)&cmd_firewall_del_dst_port_from,
-		(void *)&cmd_firewall_del_dst_port_to,
-		(void *)&cmd_firewall_del_proto,
-		(void *)&cmd_firewall_del_proto_mask,
-		NULL,
-	},
-};
-
-/* *** Firewall - Print *** */
-struct cmd_firewall_print_result {
-	cmdline_fixed_string_t firewall_string;
-	cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_firewall_print_parsed(
-	__attribute__((unused)) void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct app_rule *it;
-
-	TAILQ_FOREACH(it, &firewall_table, entries) {
-		print_firewall_rule(it->firewall);
-	}
-}
-
-cmdline_parse_token_string_t cmd_firewall_print_firewall_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result,
-	firewall_string, "firewall");
-
-cmdline_parse_token_string_t cmd_firewall_print_print_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_firewall_print_result, print_string,
-	"ls");
-
-cmdline_parse_inst_t cmd_firewall_print = {
-	.f = cmd_firewall_print_parsed,
-	.data = NULL,
-	.help_str = "Firewall rules list",
-	.tokens = {
-		(void *)&cmd_firewall_print_firewall_string,
-		(void *)&cmd_firewall_print_print_string,
-		NULL,
-	},
-};
-
-#endif
-
-/* *** Flow Classification - Add All *** */
-struct cmd_flow_add_all_result {
-	cmdline_fixed_string_t flow_string;
-	cmdline_fixed_string_t add_string;
-	cmdline_fixed_string_t all_string;
-};
-
-static void
-cmd_flow_add_all_parsed(
-	__attribute__((unused)) void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	struct rte_ring *ring_req =
-		app_get_ring_req(app_get_first_core_id(APP_CORE_FC));
-	struct rte_ring *ring_resp =
-		app_get_ring_resp(app_get_first_core_id(APP_CORE_FC));
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	memset(req, 0, sizeof(struct app_msg_req));
-
-	req->type = APP_MSG_REQ_FC_ADD_ALL;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request FLOW_ADD_ALL failed (%u)\n", resp->result);
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_add_all_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, flow_string,
-	"flow");
-
-cmdline_parse_token_string_t cmd_flow_add_all_add_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, add_string,
-	"add");
-
-cmdline_parse_token_string_t cmd_flow_add_all_all_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_add_all_result, all_string,
-	"all");
-
-cmdline_parse_inst_t cmd_flow_add_all = {
-	.f = cmd_flow_add_all_parsed,
-	.data = NULL,
-	.help_str = "Flow table initialization based on hard-coded rule",
-	.tokens = {
-		(void *)&cmd_flow_add_all_flow_string,
-		(void *)&cmd_flow_add_all_add_string,
-		(void *)&cmd_flow_add_all_all_string,
-		NULL,
-	},
-};
-
-/* *** Flow Classification - Add *** */
-struct cmd_flow_add_result {
-	cmdline_fixed_string_t flow_string;
-	cmdline_fixed_string_t add_string;
-	cmdline_ipaddr_t src_ip;
-	cmdline_ipaddr_t dst_ip;
-	uint16_t src_port;
-	uint16_t dst_port;
-	uint8_t proto;
-	uint8_t port;
-};
-
-static void
-cmd_flow_add_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_flow_add_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Flow classification not performed by any CPU core\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Check params */
-	if (params->port >= app.n_ports) {
-		printf("Illegal value for port parameter (%u)\n", params->port);
-		return;
-	}
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.flow.key.src_ip =
-		rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
-	rule.flow.key.dst_ip =
-		rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
-	rule.flow.key.src_port = params->src_port;
-	rule.flow.key.dst_port = params->dst_port;
-	rule.flow.key.proto = params->proto;
-	rule.flow.port = params->port;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
-	if ((old_rule == NULL) && (n_flow_rules == app.max_flow_rules)) {
-		printf("Flow table is full.\n");
-		return;
-	}
-
-	printf("Adding flow: ");
-	print_flow_rule(rule.flow);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	memset(req, 0, sizeof(struct app_msg_req));
-
-	req->type = APP_MSG_REQ_FC_ADD;
-	req->flow_classif_add.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
-	req->flow_classif_add.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
-	req->flow_classif_add.key.port_src =
-		rte_bswap16(rule.flow.key.src_port);
-	req->flow_classif_add.key.port_dst =
-		rte_bswap16(rule.flow.key.dst_port);
-	req->flow_classif_add.key.proto = rule.flow.key.proto;
-	req->flow_classif_add.port = rule.flow.port;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request FLOW_ADD failed (%u)\n", resp->result);
-	else {
-		if (old_rule == NULL) {
-			struct app_rule *new_rule = (struct app_rule *)
-				rte_zmalloc_socket("CLI",
-				sizeof(struct app_rule),
-				RTE_CACHE_LINE_SIZE,
-				rte_socket_id());
-
-			if (new_rule == NULL)
-				rte_panic("Unable to allocate new rule\n");
-
-			memcpy(new_rule, &rule, sizeof(rule));
-			TAILQ_INSERT_TAIL(&flow_table, new_rule, entries);
-			n_flow_rules++;
-		} else
-			old_rule->flow.port = rule.flow.port;
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_add_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, flow_string,
-	"flow");
-
-cmdline_parse_token_string_t cmd_flow_add_add_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_add_result, add_string, "add");
-
-cmdline_parse_token_ipaddr_t cmd_flow_add_src_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, src_ip);
-
-cmdline_parse_token_ipaddr_t cmd_flow_add_dst_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_flow_add_result, dst_ip);
-
-cmdline_parse_token_num_t cmd_flow_add_src_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, src_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_add_dst_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, dst_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_add_proto =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, proto, UINT8);
-
-cmdline_parse_token_num_t cmd_flow_add_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_add_result, port, UINT8);
-
-cmdline_parse_inst_t cmd_flow_add = {
-	.f = cmd_flow_add_parsed,
-	.data = NULL,
-	.help_str = "Flow add",
-	.tokens = {
-		(void *)&cmd_flow_add_flow_string,
-		(void *)&cmd_flow_add_add_string,
-		(void *)&cmd_flow_add_src_ip,
-		(void *)&cmd_flow_add_dst_ip,
-		(void *)&cmd_flow_add_src_port,
-		(void *)&cmd_flow_add_dst_port,
-		(void *)&cmd_flow_add_proto,
-		(void *)&cmd_flow_add_port,
-		NULL,
-	},
-};
-
-/* *** Flow Classification - Del *** */
-struct cmd_flow_del_result {
-	cmdline_fixed_string_t flow_string;
-	cmdline_fixed_string_t del_string;
-	cmdline_ipaddr_t src_ip;
-	cmdline_ipaddr_t dst_ip;
-	uint16_t src_port;
-	uint16_t dst_port;
-	uint8_t proto;
-};
-
-static void
-cmd_flow_del_parsed(
-	void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct cmd_flow_del_result *params = parsed_result;
-	struct app_rule rule, *old_rule;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	void *msg;
-	int status;
-
-	uint32_t core_id = app_get_first_core_id(APP_CORE_FC);
-
-	if (core_id == RTE_MAX_LCORE) {
-		printf("Flow classification not performed by any CPU core.\n");
-		return;
-	}
-
-	struct rte_ring *ring_req = app_get_ring_req(core_id);
-	struct rte_ring *ring_resp = app_get_ring_resp(core_id);
-
-	/* Create rule */
-	memset(&rule, 0, sizeof(rule));
-	rule.flow.key.src_ip =
-		rte_bswap32((uint32_t)params->src_ip.addr.ipv4.s_addr);
-	rule.flow.key.dst_ip =
-		rte_bswap32((uint32_t)params->dst_ip.addr.ipv4.s_addr);
-	rule.flow.key.src_port = params->src_port;
-	rule.flow.key.dst_port = params->dst_port;
-	rule.flow.key.proto = params->proto;
-
-	/* Check rule existence */
-	IS_RULE_PRESENT(old_rule, rule.flow.key, flow_table, flow);
-	if (old_rule == NULL)
-		return;
-
-	printf("Deleting flow: ");
-	print_flow_rule(old_rule->flow);
-
-	/* Allocate message buffer */
-	msg = (void *)rte_ctrlmbuf_alloc(app.msg_pool);
-	if (msg == NULL)
-		rte_panic("Unable to allocate new message\n");
-
-	/* Fill request message */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-	memset(req, 0, sizeof(struct app_msg_req));
-
-	req->type = APP_MSG_REQ_FC_DEL;
-	req->flow_classif_del.key.ip_src = rte_bswap32(rule.flow.key.src_ip);
-	req->flow_classif_del.key.ip_dst = rte_bswap32(rule.flow.key.dst_ip);
-	req->flow_classif_del.key.port_src =
-		rte_bswap32(rule.flow.key.src_port);
-	req->flow_classif_del.key.port_dst =
-		rte_bswap32(rule.flow.key.dst_port);
-	req->flow_classif_del.key.proto = rule.flow.key.proto;
-
-	/* Send request */
-	do {
-		status = rte_ring_sp_enqueue(ring_req, msg);
-	} while (status == -ENOBUFS);
-
-	/* Wait for response */
-	do {
-		status = rte_ring_sc_dequeue(ring_resp, &msg);
-	} while (status != 0);
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg);
-
-	/* Check response */
-	if (resp->result != 0)
-		printf("Request FLOW_DEL failed (%u)\n", resp->result);
-	else {
-		TAILQ_REMOVE(&flow_table, old_rule, entries);
-		rte_free(old_rule);
-		n_flow_rules--;
-	}
-
-	/* Free message buffer */
-	rte_ctrlmbuf_free((struct rte_mbuf *)msg);
-}
-
-cmdline_parse_token_string_t cmd_flow_del_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, flow_string,
-	"flow");
-
-cmdline_parse_token_string_t cmd_flow_del_del_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_del_result, del_string, "del");
-
-cmdline_parse_token_ipaddr_t cmd_flow_del_src_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, src_ip);
-
-cmdline_parse_token_ipaddr_t cmd_flow_del_dst_ip =
-	TOKEN_IPADDR_INITIALIZER(struct cmd_flow_del_result, dst_ip);
-
-cmdline_parse_token_num_t cmd_flow_del_src_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, src_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_del_dst_port =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, dst_port, UINT16);
-
-cmdline_parse_token_num_t cmd_flow_del_proto =
-	TOKEN_NUM_INITIALIZER(struct cmd_flow_del_result, proto, UINT8);
-
-cmdline_parse_inst_t cmd_flow_del = {
-	.f = cmd_flow_del_parsed,
-	.data = NULL,
-	.help_str = "Flow delete",
-	.tokens = {
-		(void *)&cmd_flow_del_flow_string,
-		(void *)&cmd_flow_del_del_string,
-		(void *)&cmd_flow_del_src_ip,
-		(void *)&cmd_flow_del_dst_ip,
-		(void *)&cmd_flow_del_src_port,
-		(void *)&cmd_flow_del_dst_port,
-		(void *)&cmd_flow_del_proto,
-		NULL,
-	},
-};
-
-/* *** Flow Classification - Print *** */
-struct cmd_flow_print_result {
-	cmdline_fixed_string_t flow_string;
-	cmdline_fixed_string_t print_string;
-};
-
-static void
-cmd_flow_print_parsed(
-	__attribute__((unused)) void *parsed_result,
-	__attribute__((unused)) struct cmdline *cl,
-	__attribute__((unused)) void *data)
-{
-	struct app_rule *it;
-
-	TAILQ_FOREACH(it, &flow_table, entries) {
-		print_flow_rule(it->flow);
-	}
-}
-
-cmdline_parse_token_string_t cmd_flow_print_flow_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, flow_string,
-	"flow");
-
-cmdline_parse_token_string_t cmd_flow_print_print_string =
-	TOKEN_STRING_INITIALIZER(struct cmd_flow_print_result, print_string,
-	"ls");
-
-cmdline_parse_inst_t cmd_flow_print = {
-	.f = cmd_flow_print_parsed,
-	.data = NULL,
-	.help_str = "Flow list",
-	.tokens = {
-		(void *)&cmd_flow_print_flow_string,
-		(void *)&cmd_flow_print_print_string,
-		NULL,
-	},
-};
-
-/* *** QUIT *** */
-struct cmd_quit_result {
-	cmdline_fixed_string_t quit;
-};
-
-static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
-		struct cmdline *cl,
-		__attribute__((unused)) void *data)
-{
-	cmdline_quit(cl);
-}
-
-cmdline_parse_token_string_t cmd_quit_quit =
-		TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
-
-cmdline_parse_inst_t cmd_quit = {
-	.f = cmd_quit_parsed,
-	.data = NULL,
-	.help_str = "Exit application",
-	.tokens = {
-		(void *)&cmd_quit_quit,
-		NULL,
-	},
-};
-
-/* List of commands */
-cmdline_parse_ctx_t main_ctx[] = {
-	(cmdline_parse_inst_t *)&cmd_flow_add,
-	(cmdline_parse_inst_t *)&cmd_flow_del,
-	(cmdline_parse_inst_t *)&cmd_flow_add_all,
-	(cmdline_parse_inst_t *)&cmd_flow_print,
-#ifdef RTE_LIBRTE_ACL
-	(cmdline_parse_inst_t *)&cmd_firewall_add,
-	(cmdline_parse_inst_t *)&cmd_firewall_del,
-	(cmdline_parse_inst_t *)&cmd_firewall_print,
-#endif
-	(cmdline_parse_inst_t *)&cmd_route_add,
-	(cmdline_parse_inst_t *)&cmd_route_del,
-	(cmdline_parse_inst_t *)&cmd_routing_print,
-	(cmdline_parse_inst_t *)&cmd_arp_add,
-	(cmdline_parse_inst_t *)&cmd_arp_del,
-	(cmdline_parse_inst_t *)&cmd_arp_print,
-	(cmdline_parse_inst_t *)&cmd_run_file,
-	(cmdline_parse_inst_t *)&cmd_link_enable,
-	(cmdline_parse_inst_t *)&cmd_link_disable,
-	(cmdline_parse_inst_t *)&cmd_quit,
-	NULL,
-};
-
-/* Main loop */
-void
-app_main_loop_cmdline(void)
-{
-	struct cmdline *cl;
-	uint32_t core_id = rte_lcore_id();
-
-	RTE_LOG(INFO, USER1, "Core %u is running the command line interface\n",
-		core_id);
-
-	n_arp_rules = 0;
-	n_routing_rules = 0;
-	n_firewall_rules = 0;
-	n_flow_rules = 0;
-
-	app_init_rule_tables();
-
-	cl = cmdline_stdin_new(main_ctx, "pipeline> ");
-	if (cl == NULL)
-		return;
-	cmdline_interact(cl);
-	cmdline_stdin_exit(cl);
-}
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 77d5f07..b066476 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -43,6 +43,7 @@
 
 #include "app.h"
 #include "pipeline.h"
+#include "pipeline_master.h"
 
 #define APP_NAME_SIZE	32
 
@@ -1142,6 +1143,8 @@ int app_init(struct app_params *app)
 	app_init_tm(app);
 	app_init_msgq(app);
 
+	app_pipeline_type_register(app, &pipeline_master);
+
 	app_init_pipelines(app);
 	app_init_threads(app);
 
diff --git a/examples/ip_pipeline/pipeline/pipeline_common.c b/examples/ip_pipeline/pipeline/pipeline_common.c
new file mode 100644
index 0000000..09bcc9a
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common.c
@@ -0,0 +1,412 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#include <rte_ring.h>
+#include <rte_malloc.h>
+
+#include "pipeline_ops.h"
+#include "pipeline_common_ops.h"
+#include "pipeline.h"
+#include "pipeline_common.h"
+
+int
+app_pipeline_ping(struct app_params *app,
+	uint32_t pipeline_id)
+{
+	struct pipeline_msg_req *req;
+	struct pipeline_msg_rsp *rsp;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines))
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_PING;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_pipeline_stats_port_in(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id,
+	struct rte_pipeline_port_in_stats *stats)
+{
+	struct pipeline_stats_msg_req *req;
+	struct pipeline_stats_port_in_msg_rsp *rsp;
+	struct app_pipeline_params *p;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines) ||
+		(stats == NULL))
+		return -1;
+	
+	p = &app->pipeline_params[pipeline_id];
+	if (port_id >= p->n_pktq_in)
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_STATS_PORT_IN;
+	req->id = port_id;
+
+	/* Send request and wait for response */
+	rsp = (struct pipeline_stats_port_in_msg_rsp *)
+		app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+	memcpy(stats, &rsp->stats, sizeof(rsp->stats));
+	
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_pipeline_stats_port_out(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id,
+	struct rte_pipeline_port_out_stats *stats)
+{
+	struct pipeline_stats_msg_req *req;
+	struct pipeline_stats_port_out_msg_rsp *rsp;
+	struct app_pipeline_params *p;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines) ||
+		(stats == NULL))
+		return -1;
+	
+	p = &app->pipeline_params[pipeline_id];
+	if (port_id >= p->n_pktq_out)
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_STATS_PORT_OUT;
+	req->id = port_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+	memcpy(stats, &rsp->stats, sizeof(rsp->stats));
+	
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_pipeline_stats_table(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t table_id,
+	struct rte_pipeline_table_stats *stats)
+{
+	struct pipeline_stats_msg_req *req;
+	struct pipeline_stats_table_msg_rsp *rsp;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines) ||
+		(stats == NULL))
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_STATS_TABLE;
+	req->id = table_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+	memcpy(stats, &rsp->stats, sizeof(rsp->stats));
+	
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_pipeline_port_in_enable(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id)
+{
+	struct pipeline_port_in_msg_req *req;
+	struct pipeline_msg_rsp *rsp;
+	struct app_pipeline_params *p;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines))
+		return -1;
+	
+	p = &app->pipeline_params[pipeline_id];
+	if (port_id >= p->n_pktq_in)
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_PORT_IN_ENABLE;
+	req->port_id = port_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+	
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_pipeline_port_in_disable(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id)
+{
+	struct pipeline_port_in_msg_req *req;
+	struct pipeline_msg_rsp *rsp;
+	struct app_pipeline_params *p;
+	int status = 0;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(pipeline_id >= app->n_pipelines))
+		return -1;
+
+	p = &app->pipeline_params[pipeline_id];
+	if (port_id >= p->n_pktq_in)
+		return -1;
+
+	/* Message buffer allocation */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	/* Fill in request */
+	req->type = PIPELINE_MSG_REQ_PORT_IN_DISABLE;
+	req->port_id = port_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, 1);
+	if (rsp == NULL)
+		return -1;
+
+	/* Check response */
+	status = rsp->status;
+	
+	/* Message buffer free */
+	app_msg_free(app, rsp);
+
+	return status;
+}
+
+int
+app_link_config(struct app_params *app,
+	uint32_t link_id,
+	uint32_t ip,
+	uint32_t depth)
+{
+	struct app_link_params *p;
+	uint32_t i, netmask, host, bcast;
+	int status = 0;
+	
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	if (link_id >= app->n_links) {
+		RTE_LOG(ERR, USER1, "LINK%u is not a valid link\n", link_id);
+		return -1;
+	}
+
+	if ((depth == 0) || (depth > 32)) {
+		RTE_LOG(ERR, USER1, "Illegal value for depth parameter (%u)\n", depth);
+		return -1;
+	}
+
+	netmask = (~0) << (32 - depth);
+	host = ip & netmask;
+	bcast = host | (~netmask);
+	
+	if ((ip == 0) ||
+		(ip == UINT32_MAX) ||
+		(ip == host) ||
+		(ip == bcast)) {
+		RTE_LOG(ERR, USER1, "Illegal IP address\n");
+		return -1;
+	}
+
+	for (i = 0; i < app->n_links; i++) {
+		uint32_t id;
+
+		p = &app->link_params[i];
+		APP_PARAM_GET_ID(p, "LINK", id);
+		
+		if (link_id == id)
+			continue;
+
+		if (p->ip == ip) {
+			RTE_LOG(ERR, USER1, "%s is already assigned this IP address\n", p->name);
+			return -1;
+		}
+	}
+
+	APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+	if (p->state) {
+		RTE_LOG(ERR, USER1, "%s is UP, please bring it DOWN first\n", p->name);
+		return -1;
+	}
+
+	/* Save link parameters */
+	p->ip = ip;
+	p->depth = depth;		
+
+	return status;
+}
+
+int
+app_link_up(struct app_params *app,
+	uint32_t link_id)
+{
+	struct app_link_params *p;
+	int status = 0;
+	
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	if (link_id >= app->n_links) {
+		RTE_LOG(ERR, USER1, "LINK%u is not a valid link\n", link_id);
+		return -1;
+	}
+
+	APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+
+	/* Check link state */
+	if (p->state) {
+		RTE_LOG(ERR, USER1,"%s is already UP\n", p->name);
+		return 0;
+	}
+
+	app_link_up_internal(app, p);
+
+	return status;
+}
+
+int
+app_link_down(struct app_params *app,
+	uint32_t link_id)
+{
+	struct app_link_params *p;
+	int status =0;
+	
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	if (link_id >= app->n_links) {
+		RTE_LOG(ERR, USER1,"LINK%u is not a valid link\n", link_id);
+		return -1;
+	}
+
+	APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+	
+	/* Check link state */
+	if (p->state == 0) {
+		RTE_LOG(ERR, USER1,"%s is already DOWN\n", p->name);
+		return 0;
+	}
+
+	app_link_down_internal(app, p);
+
+	return status;
+}
diff --git a/examples/ip_pipeline/pipeline/pipeline_common.h b/examples/ip_pipeline/pipeline/pipeline_common.h
new file mode 100644
index 0000000..d1ded0a
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common.h
@@ -0,0 +1,241 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_COMMON_H__
+#define __INCLUDE_PIPELINE_COMMON_H__
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <cmdline_parse.h>
+
+#include "pipeline_common_ops.h"
+#include "pipeline.h"
+#include "app.h"
+
+static inline struct app_pipeline_data *
+app_pipeline_data(struct app_params *app, uint32_t id)
+{
+	struct app_pipeline_params *params;
+
+	APP_CHECK(app != NULL, "BUG: %s(): app == NULL", __func__);
+
+	APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", id, params);
+
+	if (params == NULL) {
+		printf("Pipeline %" PRIu32 " not found\n", id);
+		return NULL;
+	}
+
+	return &app->pipeline_data[params - app->pipeline_params];
+}
+
+static inline void *
+app_pipeline_data_fe(struct app_params *app, uint32_t id)
+{
+	struct app_pipeline_data *pipeline_data;
+
+	pipeline_data = app_pipeline_data(app, id);
+
+	if (pipeline_data == NULL)
+		return NULL;
+
+	return pipeline_data->fe;
+}
+
+static inline struct rte_ring *
+app_pipeline_msgq_in_get(struct app_params *app,
+	uint32_t pipeline_id)
+{	
+	char msgq_name[APP_PARAM_NAME_SIZE];
+	struct app_pipeline_params *p = &app->pipeline_params[pipeline_id];
+	uint32_t i;
+
+	sprintf(msgq_name, "MSGQ-REQ-PIPELINE%u", pipeline_id);
+	
+	for (i = 0; i < p->n_msgq_in; i++){
+		uint32_t msgq_id = p->msgq_in[i];
+		struct app_msgq_params *p_msgq = &app->msgq_params[msgq_id];
+		struct rte_ring *r = app->msgq[msgq_id];
+		
+		if (strcmp(p_msgq->name, msgq_name) == 0)
+			return r;
+	}
+
+	APP_CHECK(1, "%s not found\n", msgq_name);
+	return NULL;
+}
+
+static inline struct rte_ring *
+app_pipeline_msgq_out_get(struct app_params *app,
+	uint32_t pipeline_id)
+{
+	char msgq_name[APP_PARAM_NAME_SIZE];
+	struct app_pipeline_params *p = &app->pipeline_params[pipeline_id];
+	uint32_t i;
+
+	sprintf(msgq_name, "MSGQ-RSP-PIPELINE%u", pipeline_id);
+	
+	for (i = 0; i < p->n_msgq_out; i++){
+		uint32_t msgq_id = p->msgq_out[i];
+		struct app_msgq_params *p_msgq = &app->msgq_params[msgq_id];
+		struct rte_ring *r = app->msgq[msgq_id];
+		
+		if (strcmp(p_msgq->name, msgq_name) == 0)
+			return r;
+	}
+
+	APP_CHECK(1, "%s not found\n", msgq_name);
+	return NULL;
+}
+
+static inline void *
+app_msg_alloc(__rte_unused struct app_params *app)
+{
+	return rte_malloc(NULL, 2048, RTE_CACHE_LINE_SIZE);
+}
+
+static inline void
+app_msg_free(__rte_unused struct app_params *app,
+	void *msg)
+{
+	rte_free(msg);
+}
+
+static inline void
+app_msg_send(struct app_params *app,
+	uint32_t pipeline_id,
+	void *msg)
+{
+	struct rte_ring *r = app_pipeline_msgq_in_get(app, pipeline_id);
+	int status;
+
+	do {
+		status = rte_ring_sp_enqueue(r, msg);
+	} while (status == -ENOBUFS);
+}
+
+static inline void *
+app_msg_recv(struct app_params *app,
+	uint32_t pipeline_id)
+{
+	struct rte_ring *r = app_pipeline_msgq_out_get(app, pipeline_id);
+	void *msg;
+	int status = rte_ring_sc_dequeue(r, &msg);
+
+	if (status != 0)
+		return NULL;
+
+	return msg;
+}
+
+static inline void *
+app_msg_send_recv(struct app_params *app,
+	uint32_t pipeline_id,
+	void *msg,
+	uint32_t timeout_ms)
+{
+	struct rte_ring *r_req = app_pipeline_msgq_in_get(app, pipeline_id);
+	struct rte_ring *r_rsp = app_pipeline_msgq_out_get(app, pipeline_id);
+	uint64_t hz = rte_get_tsc_hz();
+	void *msg_recv;
+	uint64_t deadline;
+	int status;
+
+	/* send */
+	do {
+		status = rte_ring_sp_enqueue(r_req, (void *) msg);
+	} while (status == -ENOBUFS);
+
+	/* recv */
+	deadline = (timeout_ms)?
+		(rte_rdtsc() + ((hz * timeout_ms) / 1000)) :
+		UINT64_MAX;
+
+	do {
+		if (rte_rdtsc() > deadline)
+			return NULL;
+
+		status = rte_ring_sc_dequeue(r_rsp, &msg_recv);
+	} while (status != 0);
+
+	return msg_recv;
+}
+
+int
+app_pipeline_ping(struct app_params *app,
+	uint32_t pipeline_id);
+
+int
+app_pipeline_stats_port_in(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id,
+	struct rte_pipeline_port_in_stats *stats);
+
+int
+app_pipeline_stats_port_out(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id,
+	struct rte_pipeline_port_out_stats *stats);
+
+int
+app_pipeline_stats_table(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t table_id,
+	struct rte_pipeline_table_stats *stats);
+
+int
+app_pipeline_port_in_enable(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id);
+
+int
+app_pipeline_port_in_disable(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id);
+
+int
+app_link_config(struct app_params *app,
+	uint32_t link_id,
+	uint32_t ip,
+	uint32_t depth);
+
+int
+app_link_up(struct app_params *app,
+	uint32_t link_id);
+
+int
+app_link_down(struct app_params *app,
+	uint32_t link_id);
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_ops.c b/examples/ip_pipeline/pipeline/pipeline_common_ops.c
new file mode 100644
index 0000000..0624172
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_ops.c
@@ -0,0 +1,205 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#include <rte_common.h>
+#include <rte_ring.h>
+#include <rte_malloc.h>
+
+#include "pipeline_ops.h"
+#include "pipeline_common_ops.h"
+
+void *
+pipeline_msg_req_ping_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_msg_rsp *rsp = msg;
+
+	rsp->status = 0; /* OK */
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_stats_port_in_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_stats_msg_req *req = msg;
+	struct pipeline_stats_port_in_msg_rsp *rsp = msg;
+	uint32_t port_id;
+
+	/* Check request */
+	if (req->id >= p->n_ports_in){
+		rsp->status = -1;
+		return rsp;
+	}
+	port_id = p->port_in_id[req->id];
+
+	/* Process request */
+	rsp->status = rte_pipeline_port_in_stats_read(p->p,
+		port_id,
+		&rsp->stats,
+		1);
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_stats_port_out_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_stats_msg_req *req = msg;
+	struct pipeline_stats_port_out_msg_rsp *rsp = msg;
+	uint32_t port_id;
+
+	/* Check request */
+	if (req->id >= p->n_ports_out){
+		rsp->status = -1;
+		return rsp;
+	}
+	port_id = p->port_out_id[req->id];
+
+	/* Process request */
+	rsp->status = rte_pipeline_port_out_stats_read(p->p,
+		port_id,
+		&rsp->stats,
+		1);
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_stats_table_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_stats_msg_req *req = msg;
+	struct pipeline_stats_table_msg_rsp *rsp = msg;
+	uint32_t table_id;
+
+	/* Check request */
+	if (req->id >= p->n_tables){
+		rsp->status = -1;
+		return rsp;
+	}
+	table_id = p->table_id[req->id];
+
+	/* Process request */
+	rsp->status = rte_pipeline_table_stats_read(p->p,
+		table_id,
+		&rsp->stats,
+		1);
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_port_in_enable_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_port_in_msg_req *req = msg;
+	struct pipeline_msg_rsp *rsp = msg;
+	uint32_t port_id;
+
+	/* Check request */
+	if (req->port_id >= p->n_ports_in){
+		rsp->status = -1;
+		return rsp;
+	}
+	port_id = p->port_in_id[req->port_id];
+
+	/* Process request */
+	rsp->status = rte_pipeline_port_in_enable(p->p,
+		port_id);
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_port_in_disable_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_port_in_msg_req *req = msg;
+	struct pipeline_msg_rsp *rsp = msg;
+	uint32_t port_id;
+
+	/* Check request */
+	if (req->port_id >= p->n_ports_in){
+		rsp->status = -1;
+		return rsp;
+	}
+	port_id = p->port_in_id[req->port_id];
+
+	/* Process request */
+	rsp->status = rte_pipeline_port_in_disable(p->p,
+		port_id);
+
+	return rsp;
+}
+
+void *
+pipeline_msg_req_invalid_handler(__rte_unused struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_msg_rsp *rsp = msg;
+
+	rsp->status = -1; /* Error */
+
+	return rsp;
+}
+
+int
+pipeline_msg_req_handle(struct pipeline *p)
+{
+	uint32_t msgq_id;
+
+	for (msgq_id = 0; msgq_id < p->n_msgq; msgq_id++) {
+		for ( ; ; ) {
+			struct pipeline_msg_req *req;
+			pipeline_msg_req_handler f_handle;
+
+			req = pipeline_msg_recv(p, msgq_id);
+			if (req == NULL)
+				break;
+
+			f_handle = (req->type < PIPELINE_MSG_REQS)?
+				p->handlers[req->type] :
+				pipeline_msg_req_invalid_handler;
+
+			if (f_handle == NULL)
+				f_handle = pipeline_msg_req_invalid_handler;
+
+			pipeline_msg_send(p, msgq_id, f_handle(p, (void *) req));
+		}
+	}
+
+	return 0;
+}
diff --git a/examples/ip_pipeline/pipeline/pipeline_common_ops.h b/examples/ip_pipeline/pipeline/pipeline_common_ops.h
new file mode 100644
index 0000000..7181483
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_common_ops.h
@@ -0,0 +1,150 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_COMMON_OPS_H__
+#define __INCLUDE_PIPELINE_COMMON_OPS_H__
+
+#include <rte_common.h>
+#include <rte_ring.h>
+#include <rte_pipeline.h>
+
+#include "pipeline_ops.h"
+
+struct pipeline;
+
+enum pipeline_msg_req_type {
+	PIPELINE_MSG_REQ_PING = 0,
+	PIPELINE_MSG_REQ_STATS_PORT_IN,
+	PIPELINE_MSG_REQ_STATS_PORT_OUT,
+	PIPELINE_MSG_REQ_STATS_TABLE,
+	PIPELINE_MSG_REQ_PORT_IN_ENABLE,
+	PIPELINE_MSG_REQ_PORT_IN_DISABLE,
+	PIPELINE_MSG_REQ_CUSTOM,
+	PIPELINE_MSG_REQS
+};
+
+typedef void *(*pipeline_msg_req_handler)(struct pipeline *p, void *msg);
+
+struct pipeline {
+	struct rte_pipeline *p;
+	uint32_t port_in_id[PIPELINE_MAX_PORT_IN];
+	uint32_t port_out_id[PIPELINE_MAX_PORT_OUT];
+	uint32_t table_id[PIPELINE_MAX_TABLES];
+	struct rte_ring *msgq_in[PIPELINE_MAX_MSGQ_IN];
+	struct rte_ring *msgq_out[PIPELINE_MAX_MSGQ_OUT];
+
+	uint32_t n_ports_in;
+	uint32_t n_ports_out;
+	uint32_t n_tables;
+	uint32_t n_msgq;
+
+	pipeline_msg_req_handler handlers[PIPELINE_MSG_REQS];
+	char name[PIPELINE_NAME_SIZE];
+};
+
+static inline void *
+pipeline_msg_recv(struct pipeline *p,
+	uint32_t msgq_id)
+{
+	struct rte_ring *r = p->msgq_in[msgq_id];
+	void *msg;
+	int status = rte_ring_sc_dequeue(r, &msg);
+
+	if (status != 0)
+		return NULL;
+
+	return msg;
+}
+
+static inline void
+pipeline_msg_send(struct pipeline *p,
+	uint32_t msgq_id,
+	void *msg)
+{
+	struct rte_ring *r = p->msgq_out[msgq_id];
+	int status;
+
+	do {
+		status = rte_ring_sp_enqueue(r, msg);
+	} while (status == -ENOBUFS);
+}
+
+struct pipeline_msg_req {
+	enum pipeline_msg_req_type type;
+};
+
+struct pipeline_stats_msg_req {
+	enum pipeline_msg_req_type type;
+	uint32_t id;
+};
+
+struct pipeline_port_in_msg_req {
+	enum pipeline_msg_req_type type;
+	uint32_t port_id;
+};
+
+struct pipeline_custom_msg_req {
+	enum pipeline_msg_req_type type;
+	uint32_t subtype;
+};
+
+struct pipeline_msg_rsp {
+	int status;
+};
+
+struct pipeline_stats_port_in_msg_rsp {
+	int status;
+	struct rte_pipeline_port_in_stats stats;
+};
+
+struct pipeline_stats_port_out_msg_rsp {
+	int status;
+	struct rte_pipeline_port_out_stats stats;
+};
+
+struct pipeline_stats_table_msg_rsp {
+	int status;
+	struct rte_pipeline_table_stats stats;
+};
+
+void *pipeline_msg_req_ping_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_stats_port_in_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_stats_port_out_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_stats_table_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_port_in_enable_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_port_in_disable_handler(struct pipeline *p, void *msg);
+void *pipeline_msg_req_invalid_handler(struct pipeline *p, void *msg);
+
+int pipeline_msg_req_handle(struct pipeline *p);
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c
new file mode 100644
index 0000000..ee14948
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master.c
@@ -0,0 +1,870 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cmdline_rdline.h>
+#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 <cmdline_socket.h>
+#include <cmdline.h> 
+
+#include "app.h"
+#include "pipeline_common.h"
+#include "pipeline_master_ops.h"
+#include "pipeline_master.h"
+
+/*
+ * run
+ */
+
+static void
+app_run_file(
+	cmdline_parse_ctx_t *ctx,
+	const char *file_name)
+{
+	struct cmdline *file_cl;
+
+	int fd = open(file_name, O_RDONLY);
+	if (fd < 0) {
+		printf("Cannot open file \"%s\"\n", file_name);
+		return;
+	}
+
+	file_cl = cmdline_new(ctx, "", fd, 1);
+	cmdline_interact(file_cl);
+	close(fd);
+}
+
+struct cmd_run_file_result {
+	cmdline_fixed_string_t run_string;
+	char file_name[APP_FILE_NAME_SIZE];
+};
+
+static void
+cmd_run_parsed(
+	void *parsed_result,
+	struct cmdline *cl,
+	__attribute__((unused)) void *data)
+{
+	struct cmd_run_file_result *params = parsed_result;
+
+	app_run_file(cl->ctx, params->file_name);
+}
+
+cmdline_parse_token_string_t cmd_run_run_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run");
+
+cmdline_parse_token_string_t cmd_run_file_name =
+	TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_name, NULL);
+
+cmdline_parse_inst_t cmd_run = {
+	.f = cmd_run_parsed,
+	.data = NULL,
+	.help_str = "Run CLI script file",
+	.tokens = {
+		(void *) &cmd_run_run_string,
+		(void *) &cmd_run_file_name,
+		NULL,
+	},
+};
+
+/*
+ * quit
+ */
+
+struct cmd_quit_result {
+	cmdline_fixed_string_t quit;
+};
+
+static void
+cmd_quit_parsed(
+	__rte_unused void *parsed_result,
+	struct cmdline *cl,
+	__rte_unused void *data)
+{
+	cmdline_quit(cl);
+}
+
+static cmdline_parse_token_string_t cmd_quit_quit =
+	TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
+
+static cmdline_parse_inst_t cmd_quit = {
+	.f = cmd_quit_parsed,
+	.data = NULL,
+	.help_str = "Quit",
+	.tokens = {
+		(void *) &cmd_quit_quit,
+		NULL,
+	},
+};
+
+/* 
+ * link config
+ */
+
+static void 
+print_link_info(struct app_link_params *p)
+{
+	struct rte_eth_stats stats;
+	struct ether_addr *mac_addr;
+	uint32_t netmask =(~0) << (32 - p->depth);
+ 	uint32_t host = p->ip & netmask;
+	uint32_t bcast = host | (~netmask);
+
+	memset(&stats, 0, sizeof(stats));
+	rte_eth_stats_get(p->pmd_id, &stats);
+
+	mac_addr = (struct ether_addr *) &p->mac_addr;
+	
+	printf("%s: flags=<%s>\n", 
+		p->name,
+		(p->state)? "UP" : "DOWN");
+
+	if (p->ip)
+		printf("\tinet %u.%u.%u.%u  netmask %u.%u.%u.%u broadcast %u.%u.%u.%u\n",
+			(p->ip >> 24) & 0xFF,
+			(p->ip >> 16) & 0xFF,
+			(p->ip >> 8) & 0xFF,
+			p->ip & 0xFF,
+			(netmask >> 24) & 0xFF,
+			(netmask >> 16) & 0xFF,
+			(netmask >> 8) & 0xFF,
+			netmask & 0xFF,
+			(bcast >> 24) & 0xFF,
+			(bcast >> 16) & 0xFF,
+			(bcast >> 8) & 0xFF,
+			bcast & 0xFF);
+
+	printf("\tether %02x:%02x:%02x:%02x:%02x:%02x\n",
+		mac_addr->addr_bytes[0],
+		mac_addr->addr_bytes[1],
+		mac_addr->addr_bytes[2],
+		mac_addr->addr_bytes[3],
+		mac_addr->addr_bytes[4],
+		mac_addr->addr_bytes[5]);
+
+	printf("\tRX packets %" PRIu64 
+		"  bytes %" PRIu64
+		"\n",
+		stats.ipackets,
+		stats.ibytes);
+
+	printf("\tRX mcast %" PRIu64
+		"  fdirmatch %" PRIu64
+		"  fdirmiss %" PRIu64
+		"  lb-packets %" PRIu64
+		"  lb-bytes %" PRIu64
+		"  xon %" PRIu64
+		"  xoff %" PRIu64 "\n",
+		stats.imcasts,
+		stats.fdirmatch,
+		stats.fdirmiss,
+		stats.ilbpackets,
+		stats.ilbbytes,
+		stats.rx_pause_xon,
+		stats.rx_pause_xoff);
+
+	printf("\tRX errors %" PRIu64
+		"  missed %" PRIu64
+		"  badcrc %" PRIu64
+		"  badlen %" PRIu64
+		"  no-mbuf %" PRIu64
+		"\n",
+		stats.ierrors,
+		stats.imissed,
+		stats.ibadcrc,
+		stats.ibadlen,
+		stats.rx_nombuf);
+
+	printf("\tTX packets %" PRIu64
+		"  bytes %" PRIu64 "\n", 
+		stats.opackets, 
+		stats.obytes);
+
+	printf("\tTX lb-packets %" PRIu64
+		"  lb-bytes %" PRIu64
+		"  xon %" PRIu64
+		"  xoff %" PRIu64
+		"\n",
+		stats.olbpackets,
+		stats.olbbytes,
+		stats.tx_pause_xon,
+		stats.tx_pause_xoff);
+
+	printf("\tTX errors %" PRIu64
+		"\n",
+		stats.oerrors);
+
+	printf("\n");
+}
+
+struct cmd_link_config_result {
+	cmdline_fixed_string_t link_string;
+	uint32_t link_id;
+	cmdline_fixed_string_t config_string;
+	cmdline_ipaddr_t ip;
+	uint32_t depth;
+};
+
+static void
+cmd_link_config_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	 void *data)
+{
+	struct cmd_link_config_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	uint32_t link_id = params->link_id;
+	uint32_t ip  = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr);
+	uint32_t depth = params->depth;
+
+	status = app_link_config(app, link_id, ip, depth);
+	if(status)
+		printf("link config failed\n");
+	else {
+		struct app_link_params *p;
+
+		APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+		print_link_info(p);
+	}
+}
+
+cmdline_parse_token_string_t cmd_link_config_link_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_config_link_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_config_config_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, config_string, "config");
+
+cmdline_parse_token_ipaddr_t cmd_link_config_ip =
+	TOKEN_IPADDR_INITIALIZER(struct cmd_link_config_result, ip);
+
+cmdline_parse_token_num_t cmd_link_config_depth =
+	TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, depth, UINT32);
+
+cmdline_parse_inst_t cmd_link_config = {
+	.f = cmd_link_config_parsed,
+	.data = NULL,
+	.help_str = "Link configuration",
+	.tokens = {
+		(void *)&cmd_link_config_link_string,
+		(void *)&cmd_link_config_link_id,
+		(void *)&cmd_link_config_config_string,
+		(void *)&cmd_link_config_ip,
+		(void *)&cmd_link_config_depth,
+		NULL,
+	},
+};
+
+/* 
+ * link up
+ */
+
+struct cmd_link_up_result {
+	cmdline_fixed_string_t link_string;
+	uint32_t link_id;
+	cmdline_fixed_string_t up_string;
+};
+
+static void
+cmd_link_up_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_link_up_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	status = app_link_up(app, params->link_id);
+	if(status != 0)
+		printf("link up failed \n");
+	else {
+		struct app_link_params *p;
+
+		APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p);
+		print_link_info(p);
+	}
+}
+
+cmdline_parse_token_string_t cmd_link_up_link_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_up_link_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_link_up_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_up_up_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up");
+
+cmdline_parse_inst_t cmd_link_up = {
+	.f = cmd_link_up_parsed,
+	.data = NULL,
+	.help_str = "Link UP",
+	.tokens = {
+		(void *)&cmd_link_up_link_string,
+		(void *)&cmd_link_up_link_id,
+		(void *)&cmd_link_up_up_string,
+		NULL,
+	},
+};
+
+/*
+ * link down
+ */
+
+struct cmd_link_down_result {
+	cmdline_fixed_string_t link_string;
+	uint32_t link_id;
+	cmdline_fixed_string_t down_string;
+};
+
+static void
+cmd_link_down_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_link_down_result *params = parsed_result;
+	struct app_params *app = data;	
+	int status;
+	
+	status = app_link_down(app, params->link_id);
+	if(status != 0)
+		printf("link down failed\n");
+	else {
+		struct app_link_params *p;
+
+		APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p);
+		print_link_info(p);
+	}
+}
+
+cmdline_parse_token_string_t cmd_link_down_link_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string, "link");
+
+cmdline_parse_token_num_t cmd_link_down_link_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32);
+
+cmdline_parse_token_string_t cmd_link_down_down_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string, "down");
+
+cmdline_parse_inst_t cmd_link_down = {
+	.f = cmd_link_down_parsed,
+	.data = NULL,
+	.help_str = "Link DOWN",
+	.tokens = {
+		(void *) &cmd_link_down_link_string,
+		(void *) &cmd_link_down_link_id,
+		(void *) &cmd_link_down_down_string,
+		NULL,
+	},
+};
+
+/*
+ * link ls
+ */
+
+struct cmd_link_ls_result {
+	cmdline_fixed_string_t link_string;
+	cmdline_fixed_string_t ls_string;
+};
+
+static void
+cmd_link_ls_parsed(
+	__attribute__((unused)) void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	 void *data)
+{
+	struct app_params *app = data;
+	uint32_t link_id;
+
+	for (link_id = 0; link_id < app->n_links; link_id++) {
+		struct app_link_params *p;
+
+		APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p);
+		print_link_info(p);
+	}
+}
+
+cmdline_parse_token_string_t cmd_link_ls_link_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string, "link");
+
+cmdline_parse_token_string_t cmd_link_ls_ls_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, ls_string, "ls");
+
+cmdline_parse_inst_t cmd_link_ls = {
+	.f = cmd_link_ls_parsed,
+	.data = NULL,
+	.help_str = "Link list",
+	.tokens = {
+		(void *)&cmd_link_ls_link_string,
+		(void *)&cmd_link_ls_ls_string,
+		NULL,
+	},
+};
+
+/* 
+ * ping 
+ */
+
+struct cmd_ping_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t ping_string;
+};
+
+static void
+cmd_ping_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	struct cmd_ping_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	status = app_pipeline_ping(app,	params->pipeline_id);
+	if(status != 0)
+		printf("ping failed\n");
+}
+
+cmdline_parse_token_string_t cmd_ping_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_ping_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_ping_ping_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping");
+
+cmdline_parse_inst_t cmd_ping = {
+	.f = cmd_ping_parsed,
+	.data = NULL,
+	.help_str = "Ping pipeline instance",
+	.tokens = {
+		(void *) &cmd_ping_p_string,
+		(void *) &cmd_ping_pipeline_id,
+		(void *) &cmd_ping_ping_string,
+		NULL,
+	},
+};
+
+/*
+ * stats port in
+ */
+
+struct cmd_stats_port_in_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t stats_string;
+	cmdline_fixed_string_t port_string;
+	cmdline_fixed_string_t in_string;
+	uint32_t port_in_id;
+	
+};
+static void
+cmd_stats_port_in_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	struct cmd_stats_port_in_result *params = parsed_result;
+	struct app_params *app = data;
+	struct rte_pipeline_port_in_stats stats;
+	int status;
+	
+	status = app_pipeline_stats_port_in(app,
+			params->pipeline_id,
+			params->port_in_id,
+			&stats);
+
+	if(status != 0) {
+		printf("stats port in failed\n");
+		return;
+	}
+	
+	/* Display stats */
+	printf("Pipeline %u port IN %u stats:\n",
+		params->pipeline_id, params->port_in_id);
+	printf("Pkts in: %lu\n", stats.stats.n_pkts_in);
+	printf("Pkts in dropped: %lu\n", stats.stats.n_pkts_drop);
+	printf("Pkts in dropped by port action handler: %lu\n", stats.n_pkts_dropped_by_ah);
+}
+
+cmdline_parse_token_string_t cmd_stats_port_in_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_port_in_stats_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_port_in_port_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string, "port");
+
+cmdline_parse_token_string_t cmd_stats_port_in_in_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string, "in");
+
+	cmdline_parse_token_num_t cmd_stats_port_in_port_in_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id, UINT32);
+
+cmdline_parse_inst_t cmd_stats_port_in = {
+	.f = cmd_stats_port_in_parsed,
+	.data = NULL,
+	.help_str = "Stats for pipeline input port",
+	.tokens = {
+		(void *) &cmd_stats_port_in_p_string,
+		(void *) &cmd_stats_port_in_pipeline_id,
+		(void *) &cmd_stats_port_in_stats_string,
+		(void *) &cmd_stats_port_in_port_string,
+		(void *) &cmd_stats_port_in_in_string,
+		(void *) &cmd_stats_port_in_port_in_id,
+		NULL,
+	},
+};
+
+/*
+ * stats port out
+ */
+
+struct cmd_stats_port_out_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t stats_string;
+	cmdline_fixed_string_t port_string;
+	cmdline_fixed_string_t out_string;
+	uint32_t port_out_id;
+};
+
+static void
+cmd_stats_port_out_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	
+	struct cmd_stats_port_out_result *params = parsed_result;
+	struct app_params *app = data;
+	struct rte_pipeline_port_out_stats stats;
+	int status;
+	
+	status = app_pipeline_stats_port_out(app,
+			params->pipeline_id,
+			params->port_out_id,
+			&stats);
+
+	if(status != 0) {
+		printf("stats port out failed\n");
+		return;
+	}
+
+	/* Display stats */
+	printf("Pipeline %u port out %u stats:\n", params->port_out_id, params->pipeline_id);
+	printf("Pkts in: %lu\n", stats.stats.n_pkts_in);
+	printf("Pkts in dropped: %lu\n", stats.stats.n_pkts_drop);
+	printf("Pkts in dropped by port action handler: %lu\n", stats.n_pkts_dropped_by_ah);	
+}	
+
+cmdline_parse_token_string_t cmd_stats_port_out_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string,
+	"p");
+
+cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_port_out_stats_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_port_out_port_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string, "port");
+
+cmdline_parse_token_string_t cmd_stats_port_out_out_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string, "out");
+
+cmdline_parse_token_num_t cmd_stats_port_out_port_out_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id, UINT32);
+
+cmdline_parse_inst_t cmd_stats_port_out = {
+	.f = cmd_stats_port_out_parsed,
+	.data = NULL,
+	.help_str = "Stats for pipeline output port",
+	.tokens = {
+		(void *) &cmd_stats_port_out_p_string,
+		(void *) &cmd_stats_port_out_pipeline_id,
+		(void *) &cmd_stats_port_out_stats_string,
+		(void *) &cmd_stats_port_out_port_string,
+		(void *) &cmd_stats_port_out_out_string,
+		(void *) &cmd_stats_port_out_port_out_id,
+		NULL,
+	},
+};
+
+/*
+ * stats table
+ */
+
+struct cmd_stats_table_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t stats_string;
+	cmdline_fixed_string_t table_string;
+	uint32_t table_id;
+};
+
+static void
+cmd_stats_table_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	struct cmd_stats_table_result *params = parsed_result;
+	struct app_params *app = data;
+	struct rte_pipeline_table_stats stats;
+	int status;
+
+	status = app_pipeline_stats_table(app,
+			params->pipeline_id,
+			params->table_id,
+			&stats);
+
+	if(status != 0) {
+		printf("stats table failed\n");
+		return;
+	}
+
+	/* Display stats */
+	printf("Pipeline %u table %u stats:\n", params->table_id, params->pipeline_id);
+	printf("Pkts in: %lu\n", stats.stats.n_pkts_in);
+	printf("Pkts in with lookup miss: %lu\n", stats.stats.n_pkts_lookup_miss);
+	printf("Pkts in dropped on lookup hit: %lu\n", stats.n_pkts_dropped_lkp_hit);
+	printf("Pkts in dropped on lookup hit by AH: %lu\n", stats.n_pkts_dropped_by_lkp_hit_ah);
+	printf("Pkts in dropped on lookup miss: %lu\n", stats.n_pkts_dropped_lkp_miss);
+	printf("Pkts in dropped on lookup miss by AH: %lu\n", stats.n_pkts_dropped_by_lkp_miss_ah);
+}
+
+cmdline_parse_token_string_t cmd_stats_table_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_stats_table_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_stats_table_stats_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string, "stats");
+
+cmdline_parse_token_string_t cmd_stats_table_table_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string, "table");
+
+cmdline_parse_token_num_t cmd_stats_table_table_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32);
+
+cmdline_parse_inst_t cmd_stats_table = {
+	.f = cmd_stats_table_parsed,
+	.data = NULL,
+	.help_str = "Stats for pipeline table",
+	.tokens = {
+		(void *) &cmd_stats_table_p_string,
+		(void *) &cmd_stats_table_pipeline_id,
+		(void *) &cmd_stats_table_stats_string,
+		(void *) &cmd_stats_table_table_string,
+		(void *) &cmd_stats_table_table_id,
+		NULL,
+	},
+};	
+ 
+/*
+ * port in enable
+ */
+
+struct cmd_port_in_enable_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t port_string;
+	cmdline_fixed_string_t in_string;
+	uint32_t port_in_id;
+	cmdline_fixed_string_t enable_string;
+};
+
+static void
+cmd_port_in_enable_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	struct cmd_port_in_enable_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	status = app_pipeline_port_in_enable(app,
+			params->pipeline_id,
+			params->port_in_id);
+
+	if(status != 0)
+		printf("port in enable failed\n");
+}
+	
+cmdline_parse_token_string_t cmd_port_in_enable_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_port_in_enable_port_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string,
+	"port");
+
+cmdline_parse_token_string_t cmd_port_in_enable_in_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string, "in");
+	
+cmdline_parse_token_num_t cmd_port_in_enable_port_in_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id, UINT32);
+	
+cmdline_parse_token_string_t cmd_port_in_enable_enable_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, enable_string, "enable");
+
+cmdline_parse_inst_t cmd_port_in_enable = {
+	.f = cmd_port_in_enable_parsed,
+	.data = NULL,
+	.help_str = "Pipeline input port enable",
+	.tokens = {
+		(void *) &cmd_port_in_enable_p_string,
+		(void *) &cmd_port_in_enable_pipeline_id,
+		(void *) &cmd_port_in_enable_port_string,
+		(void *) &cmd_port_in_enable_in_string,
+		(void *) &cmd_port_in_enable_port_in_id,
+		(void *) &cmd_port_in_enable_enable_string,
+		NULL,
+	},
+};	
+
+/*
+ * port in disable
+ */
+
+struct cmd_port_in_disable_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t port_string;
+	cmdline_fixed_string_t in_string;
+	uint32_t port_in_id;
+	cmdline_fixed_string_t disable_string;
+};
+
+static void
+cmd_port_in_disable_parsed(
+	void *parsed_result,
+	__rte_unused struct cmdline *cl,
+	void *data)
+{
+	struct cmd_port_in_disable_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+	
+	status = app_pipeline_port_in_disable(app,
+			params->pipeline_id,
+			params->port_in_id);
+
+	if(status != 0)
+		printf("port in disable failed\n");
+}
+
+cmdline_parse_token_string_t cmd_port_in_disable_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string, "p");
+
+cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_port_in_disable_port_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string, "port");
+	
+cmdline_parse_token_string_t cmd_port_in_disable_in_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string, "in");
+
+cmdline_parse_token_num_t cmd_port_in_disable_port_in_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id, UINT32);
+	
+cmdline_parse_token_string_t cmd_port_in_disable_disable_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, disable_string, "disable");	
+
+cmdline_parse_inst_t cmd_port_in_disable = {
+	.f = cmd_port_in_disable_parsed,
+	.data = NULL,
+	.help_str = "Pipeline input port disable",
+	.tokens = {
+		(void *) &cmd_port_in_disable_p_string,
+		(void *) &cmd_port_in_disable_pipeline_id,
+		(void *) &cmd_port_in_disable_port_string,
+		(void *) &cmd_port_in_disable_in_string,
+		(void *) &cmd_port_in_disable_port_in_id,
+		(void *) &cmd_port_in_disable_disable_string,
+		NULL,
+	},
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+	(cmdline_parse_inst_t *) &cmd_run,
+	(cmdline_parse_inst_t *) &cmd_quit,
+	(cmdline_parse_inst_t *) &cmd_ping,
+	(cmdline_parse_inst_t *) &cmd_stats_port_in,
+	(cmdline_parse_inst_t *) &cmd_stats_port_out,
+	(cmdline_parse_inst_t *) &cmd_stats_table,
+	(cmdline_parse_inst_t *) &cmd_port_in_enable,
+	(cmdline_parse_inst_t *) &cmd_port_in_disable,
+	(cmdline_parse_inst_t *) &cmd_link_config,
+	(cmdline_parse_inst_t *) &cmd_link_up,
+	(cmdline_parse_inst_t *) &cmd_link_down,
+	(cmdline_parse_inst_t *) &cmd_link_ls,
+	NULL,
+};
+
+static struct pipeline_fe_ops pipeline_master_fe_ops = {
+	.f_init = NULL,
+	.f_free = NULL,
+	.cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_master = {
+	.name = "MASTER",
+	.ops = &pipeline_master_ops,
+	.fe_ops = &pipeline_master_fe_ops,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_master.h b/examples/ip_pipeline/pipeline/pipeline_master.h
new file mode 100644
index 0000000..3fe3030
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master.h
@@ -0,0 +1,41 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_MASTER_H__
+#define __INCLUDE_PIPELINE_MASTER_H__
+
+#include "pipeline.h"
+
+extern struct pipeline_type pipeline_master;
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_master_ops.c b/examples/ip_pipeline/pipeline/pipeline_master_ops.c
new file mode 100644
index 0000000..8e0bf1b
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master_ops.c
@@ -0,0 +1,136 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include "app.h"
+#include "pipeline_master_ops.h"
+
+struct pipeline_master {
+	struct cmdline *cl;
+};
+
+static void*
+pipeline_init(__rte_unused struct pipeline_params *params, void *arg)
+{
+	struct app_params *app = (struct app_params *) arg;
+	struct pipeline_master *p;
+	uint32_t size;
+
+	/* Check input arguments */
+	if ((params == NULL) ||
+		(app == 0))
+		return NULL;
+
+	/* Memory allocation */
+	size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_master));
+	p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+	if (p == NULL)
+		return NULL;
+
+	p->cl = cmdline_stdin_new(app->cmds, "pipeline> ");
+	if (p->cl == NULL) {
+		rte_free(p);
+		return NULL;
+	}
+
+	if (strlen(app->script_file)) {
+		int fd = open(app->script_file, O_RDONLY);
+
+		if (fd < 0)
+			printf("Cannot open CLI script file \"%s\"\n", app->script_file);
+		else {
+			printf("Running CLI script file \"%s\" ...\n", app->script_file);
+			struct cmdline *file_cl = cmdline_new(p->cl->ctx, "", fd, 1);
+			cmdline_interact(file_cl);
+			close(fd);
+		}
+	}
+
+	return (void *) p;
+}
+
+static int
+pipeline_free(void *pipeline)
+{
+	struct pipeline_master *p = (struct pipeline_master *) pipeline;
+
+	if (p == NULL)
+		return -EINVAL;
+
+	cmdline_stdin_exit(p->cl);
+	rte_free(p);
+
+	return 0;
+}
+
+static int
+pipeline_run(void *pipeline)
+{
+	struct pipeline_master *p = (struct pipeline_master *) pipeline;
+	int status;
+
+	status = cmdline_poll(p->cl);
+	if (status < 0)
+		rte_panic("CLI poll error (%d)\n", status);
+	else if(status == RDLINE_EXITED) {
+		cmdline_stdin_exit(p->cl);
+		rte_exit(0, "Bye!\n");
+	}
+
+	return 0;
+}
+
+static int
+pipeline_timer(__rte_unused void *pipeline)
+{
+	//printf("Master timer\n");
+	return 0;
+}
+
+struct pipeline_ops pipeline_master_ops = {
+		.f_init = pipeline_init,
+		.f_free = pipeline_free,
+		.f_run = pipeline_run,
+		.f_timer = pipeline_timer,
+		.f_track = NULL,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_master_ops.h b/examples/ip_pipeline/pipeline/pipeline_master_ops.h
new file mode 100644
index 0000000..86c1e31
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_master_ops.h
@@ -0,0 +1,41 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2015 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.
+ */
+
+#ifndef __INCLUDE_PIPELINE_MASTER_OPS_H__
+#define __INCLUDE_PIPELINE_MASTER_OPS_H__
+
+#include "pipeline_ops.h"
+
+extern struct pipeline_ops pipeline_master_ops;
+
+#endif
-- 
1.7.9.5



More information about the dev mailing list