All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
To: dev@dpdk.org
Subject: [PATCH v6 09/11] ip_pipeline: added new implementation of firewall pipeline
Date: Tue,  7 Jul 2015 10:09:33 +0200	[thread overview]
Message-ID: <1436256575-15107-10-git-send-email-maciejx.t.gajdzica@intel.com> (raw)
In-Reply-To: <1436256575-15107-1-git-send-email-maciejx.t.gajdzica@intel.com>

From: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>

Firewall pipeline implementation is split to two files.
pipeline_firewall.c file handles front-end functions (cli commands
parsing) pipeline_firewall_ops.c contains implementation of functions
done by pipeline (back-end).

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
---
 examples/ip_pipeline/Makefile                      |    2 +
 examples/ip_pipeline/init.c                        |    2 +
 examples/ip_pipeline/pipeline/pipeline_firewall.c  | 1164 ++++++++++++++++----
 examples/ip_pipeline/pipeline/pipeline_firewall.h  |   63 ++
 .../ip_pipeline/pipeline/pipeline_firewall_be.c    |  740 +++++++++++++
 .../ip_pipeline/pipeline/pipeline_firewall_be.h    |  138 +++
 6 files changed, 1872 insertions(+), 237 deletions(-)
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.c
 create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.h

diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
index 930dc61..382fee6 100644
--- a/examples/ip_pipeline/Makefile
+++ b/examples/ip_pipeline/Makefile
@@ -62,6 +62,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c
 
 CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline
 CFLAGS += -O3
diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c
index 0f3bf0b..6ba14da 100644
--- a/examples/ip_pipeline/init.c
+++ b/examples/ip_pipeline/init.c
@@ -47,6 +47,7 @@
 #include "pipeline_common_fe.h"
 #include "pipeline_master.h"
 #include "pipeline_passthrough.h"
+#include "pipeline_firewall.h"
 
 #define APP_NAME_SIZE	32
 
@@ -1287,6 +1288,7 @@ int app_init(struct app_params *app)
 	app_pipeline_common_cmd_push(app);
 	app_pipeline_type_register(app, &pipeline_master);
 	app_pipeline_type_register(app, &pipeline_passthrough);
+	app_pipeline_type_register(app, &pipeline_firewall);
 
 	app_init_pipelines(app);
 	app_init_threads(app);
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
index b70260e..f6924ab 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -32,282 +32,972 @@
  */
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
 
+#include <rte_common.h>
+#include <rte_hexdump.h>
 #include <rte_malloc.h>
-#include <rte_log.h>
-#include <rte_ethdev.h>
-#include <rte_ether.h>
-#include <rte_ip.h>
-#include <rte_byteorder.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 "app.h"
+#include "pipeline_common_fe.h"
+#include "pipeline_firewall.h"
+
+struct app_pipeline_firewall_rule {
+	struct pipeline_firewall_key key;
+	int32_t priority;
+	uint32_t port_id;
+	void *entry_ptr;
+
+	TAILQ_ENTRY(app_pipeline_firewall_rule) node;
+};
+
+struct app_pipeline_firewall {
+	/* parameters */
+	uint32_t n_ports_in;
+	uint32_t n_ports_out;
+
+	/* rules */
+	TAILQ_HEAD(, app_pipeline_firewall_rule) rules;
+	uint32_t n_rules;
+	uint32_t default_rule_present;
+	uint32_t default_rule_port_id;
+	void *default_rule_entry_ptr;
+};
 
-#include <rte_port_ring.h>
-#include <rte_table_acl.h>
-#include <rte_pipeline.h>
+static void
+print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule)
+{
+	printf("Prio = %" PRId32 " (SA = %" PRIu32 ".%" PRIu32
+		".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", "
+		"DA = %" PRIu32 ".%" PRIu32
+		".%"PRIu32 ".%" PRIu32 "/%" PRIu32 ", "
+		"SP = %" PRIu32 "-%" PRIu32 ", "
+		"DP = %" PRIu32 "-%" PRIu32 ", "
+		"Proto = %" PRIu32 " / 0x%" PRIx32 ") => "
+		"Port = %" PRIu32 " (entry ptr = %p)\n",
+
+		rule->priority,
+
+		(rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF,
+		(rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF,
+		(rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF,
+		rule->key.key.ipv4_5tuple.src_ip & 0xFF,
+		rule->key.key.ipv4_5tuple.src_ip_mask,
+
+		(rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF,
+		(rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF,
+		(rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF,
+		rule->key.key.ipv4_5tuple.dst_ip & 0xFF,
+		rule->key.key.ipv4_5tuple.dst_ip_mask,
+
+		rule->key.key.ipv4_5tuple.src_port_from,
+		rule->key.key.ipv4_5tuple.src_port_to,
+
+		rule->key.key.ipv4_5tuple.dst_port_from,
+		rule->key.key.ipv4_5tuple.dst_port_to,
+
+		rule->key.key.ipv4_5tuple.proto,
+		rule->key.key.ipv4_5tuple.proto_mask,
+
+		rule->port_id,
+		rule->entry_ptr);
+}
 
-#include "main.h"
+static struct app_pipeline_firewall_rule *
+app_pipeline_firewall_rule_find(struct app_pipeline_firewall *p,
+	struct pipeline_firewall_key *key)
+{
+	struct app_pipeline_firewall_rule *r;
 
-struct app_core_firewall_message_handle_params {
-	struct rte_ring *ring_req;
-	struct rte_ring *ring_resp;
+	TAILQ_FOREACH(r, &p->rules, node)
+		if (memcmp(key,
+			&r->key,
+			sizeof(struct pipeline_firewall_key)) == 0)
+			return r;
 
-	struct rte_pipeline *p;
-	uint32_t *port_out_id;
-	uint32_t table_id;
-};
+	return NULL;
+}
 
 static void
-app_message_handle(struct app_core_firewall_message_handle_params *params);
-
-enum {
-	PROTO_FIELD_IPV4,
-	SRC_FIELD_IPV4,
-	DST_FIELD_IPV4,
-	SRCP_FIELD_IPV4,
-	DSTP_FIELD_IPV4,
-	NUM_FIELDS_IPV4
-};
+app_pipeline_firewall_ls(
+	struct app_params *app,
+	uint32_t pipeline_id)
+{
+	struct app_pipeline_firewall *p;
+	struct app_pipeline_firewall_rule *rule;
+	uint32_t n_rules;
+	int priority;
 
-struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
-	{
-		.type = RTE_ACL_FIELD_TYPE_BITMASK,
-		.size = sizeof(uint8_t),
-		.field_index = PROTO_FIELD_IPV4,
-		.input_index = PROTO_FIELD_IPV4,
-		.offset = sizeof(struct ether_hdr) +
-			offsetof(struct ipv4_hdr, next_proto_id),
-	},
-	{
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = SRC_FIELD_IPV4,
-		.input_index = SRC_FIELD_IPV4,
-		.offset = sizeof(struct ether_hdr) +
-			offsetof(struct ipv4_hdr, src_addr),
-	},
-	{
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = DST_FIELD_IPV4,
-		.input_index = DST_FIELD_IPV4,
-		.offset = sizeof(struct ether_hdr) +
-			offsetof(struct ipv4_hdr, dst_addr),
-	},
-	{
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = SRCP_FIELD_IPV4,
-		.input_index = SRCP_FIELD_IPV4,
-		.offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr),
-	},
+	/* Check input arguments */
+	if (app == NULL)
+		return;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return;
+
+	n_rules = p->n_rules;
+	for (priority = 0; n_rules; priority++)
+		TAILQ_FOREACH(rule, &p->rules, node)
+			if (rule->priority == priority) {
+				print_firewall_ipv4_rule(rule);
+				n_rules--;
+			}
+
+	if (p->default_rule_present)
+		printf("Default rule: port %" PRIu32 " (entry ptr = %p)\n",
+			p->default_rule_port_id,
+			p->default_rule_entry_ptr);
+	else
+		printf("Default rule: DROP\n");
+
+	printf("\n");
+}
+
+static void*
+app_pipeline_firewall_init(struct pipeline_params *params,
+	__rte_unused void *arg)
+{
+	struct app_pipeline_firewall *p;
+	uint32_t size;
+
+	/* Check input arguments */
+	if ((params == NULL) ||
+		(params->n_ports_in == 0) ||
+		(params->n_ports_out == 0))
+		return NULL;
+
+	/* Memory allocation */
+	size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_firewall));
+	p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+	if (p == NULL)
+		return NULL;
+
+	/* Initialization */
+	p->n_ports_in = params->n_ports_in;
+	p->n_ports_out = params->n_ports_out;
+
+	TAILQ_INIT(&p->rules);
+	p->n_rules = 0;
+	p->default_rule_present = 0;
+	p->default_rule_port_id = 0;
+	p->default_rule_entry_ptr = NULL;
+
+	return (void *) p;
+}
+
+static int
+app_pipeline_firewall_free(void *pipeline)
+{
+	struct app_pipeline_firewall *p = pipeline;
+
+	/* Check input arguments */
+	if (p == NULL)
+		return -1;
+
+	/* Free resources */
+	while (!TAILQ_EMPTY(&p->rules)) {
+		struct app_pipeline_firewall_rule *rule;
+
+		rule = TAILQ_FIRST(&p->rules);
+		TAILQ_REMOVE(&p->rules, rule, node);
+		rte_free(rule);
+	}
+
+	rte_free(p);
+	return 0;
+}
+
+static int
+app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key)
+{
+	switch (key->type) {
+	case PIPELINE_FIREWALL_IPV4_5TUPLE:
 	{
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = DSTP_FIELD_IPV4,
-		.input_index = SRCP_FIELD_IPV4,
-		.offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
-			sizeof(uint16_t),
-	},
-};
+		uint32_t src_ip_depth = key->key.ipv4_5tuple.src_ip_mask;
+		uint32_t dst_ip_depth = key->key.ipv4_5tuple.dst_ip_mask;
+		uint16_t src_port_from = key->key.ipv4_5tuple.src_port_from;
+		uint16_t src_port_to = key->key.ipv4_5tuple.src_port_to;
+		uint16_t dst_port_from = key->key.ipv4_5tuple.dst_port_from;
+		uint16_t dst_port_to = key->key.ipv4_5tuple.dst_port_to;
 
-void
-app_main_loop_pipeline_firewall(void) {
-	struct rte_pipeline_params pipeline_params = {
-		.name = "pipeline",
-		.socket_id = rte_socket_id(),
-	};
+		uint32_t src_ip_netmask = 0;
+		uint32_t dst_ip_netmask = 0;
 
-	struct rte_pipeline *p;
-	uint32_t port_in_id[APP_MAX_PORTS];
-	uint32_t port_out_id[APP_MAX_PORTS];
-	uint32_t table_id;
-	uint32_t i;
+		if ((src_ip_depth > 32) ||
+			(dst_ip_depth > 32) ||
+			(src_port_from > src_port_to) ||
+			(dst_port_from > dst_port_to))
+			return -1;
 
-	uint32_t core_id = rte_lcore_id();
-	struct app_core_params *core_params = app_get_core_params(core_id);
-	struct app_core_firewall_message_handle_params mh_params;
+		if (src_ip_depth)
+			src_ip_netmask = (~0) << (32 - src_ip_depth);
 
-	if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW))
-		rte_panic("Core %u misconfiguration\n", core_id);
+		if (dst_ip_depth)
+			dst_ip_netmask = ((~0) << (32 - dst_ip_depth));
 
-	RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id);
+		key->key.ipv4_5tuple.src_ip &= src_ip_netmask;
+		key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask;
+
+		return 0;
+	}
+
+	default:
+		return -1;
+	}
+}
 
-	/* Pipeline configuration */
-	p = rte_pipeline_create(&pipeline_params);
+int
+app_pipeline_firewall_add_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *key,
+	uint32_t priority,
+	uint32_t port_id)
+{
+	struct app_pipeline_firewall *p;
+	struct app_pipeline_firewall_rule *rule;
+	struct pipeline_firewall_add_msg_req *req;
+	struct pipeline_firewall_add_msg_rsp *rsp;
+	int new_rule;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(key == NULL) ||
+		(key->type != PIPELINE_FIREWALL_IPV4_5TUPLE))
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
 	if (p == NULL)
-		rte_panic("Unable to configure the pipeline\n");
-
-	/* Input port configuration */
-	for (i = 0; i < app.n_ports; i++) {
-		struct rte_port_ring_reader_params port_ring_params = {
-			.ring = app.rings[core_params->swq_in[i]],
-		};
-
-		struct rte_pipeline_port_in_params port_params = {
-			.ops = &rte_port_ring_reader_ops,
-			.arg_create = (void *) &port_ring_params,
-			.f_action = NULL,
-			.arg_ah = NULL,
-			.burst_size = app.bsz_swq_rd,
-		};
-
-		if (rte_pipeline_port_in_create(p, &port_params,
-			&port_in_id[i]))
-			rte_panic("Unable to configure input port for "
-				"ring %d\n", i);
+		return -1;
+
+	if (port_id >= p->n_ports_out)
+		return -1;
+
+	if (app_pipeline_firewall_key_check_and_normalize(key) != 0)
+		return -1;
+
+	/* Find existing rule or allocate new rule */
+	rule = app_pipeline_firewall_rule_find(p, key);
+	new_rule = (rule == NULL);
+	if (rule == NULL) {
+		rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE);
+
+		if (rule == NULL)
+			return -1;
 	}
 
-	/* Output port configuration */
-	for (i = 0; i < app.n_ports; i++) {
-		struct rte_port_ring_writer_params port_ring_params = {
-			.ring = app.rings[core_params->swq_out[i]],
-			.tx_burst_sz = app.bsz_swq_wr,
-		};
-
-		struct rte_pipeline_port_out_params port_params = {
-			.ops = &rte_port_ring_writer_ops,
-			.arg_create = (void *) &port_ring_params,
-			.f_action = NULL,
-			.f_action_bulk = NULL,
-			.arg_ah = NULL,
-		};
-
-		if (rte_pipeline_port_out_create(p, &port_params,
-			&port_out_id[i]))
-			rte_panic("Unable to configure output port for "
-				"ring %d\n", i);
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL) {
+		if (new_rule)
+			rte_free(rule);
+		return -1;
 	}
 
-	/* Table configuration */
-	{
-		struct rte_table_acl_params table_acl_params = {
-			.name = "test", /* unique identifier for acl contexts */
-			.n_rules = app.max_firewall_rules,
-			.n_rule_fields = DIM(ipv4_field_formats),
-		};
-
-		struct rte_pipeline_table_params table_params = {
-			.ops = &rte_table_acl_ops,
-			.arg_create = &table_acl_params,
-			.f_action_hit = NULL,
-			.f_action_miss = NULL,
-			.arg_ah = NULL,
-			.action_data_size = 0,
-		};
-
-		memcpy(table_acl_params.field_format, ipv4_field_formats,
-			sizeof(ipv4_field_formats));
-
-		if (rte_pipeline_table_create(p, &table_params, &table_id))
-			rte_panic("Unable to configure the ACL table\n");
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD;
+	memcpy(&req->key, key, sizeof(*key));
+	req->priority = priority;
+	req->port_id = port_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL) {
+		if (new_rule)
+			rte_free(rule);
+		return -1;
+	}
+
+	/* Read response and write rule */
+	if (rsp->status ||
+		(rsp->entry_ptr == NULL) ||
+		((new_rule == 0) && (rsp->key_found == 0)) ||
+		((new_rule == 1) && (rsp->key_found == 1))) {
+		app_msg_free(app, rsp);
+		if (new_rule)
+			rte_free(rule);
+		return -1;
+	}
+
+	memcpy(&rule->key, key, sizeof(*key));
+	rule->priority = priority;
+	rule->port_id = port_id;
+	rule->entry_ptr = rsp->entry_ptr;
+
+	/* Commit rule */
+	if (new_rule) {
+		TAILQ_INSERT_TAIL(&p->rules, rule, node);
+		p->n_rules++;
 	}
 
-	/* Interconnecting ports and tables */
-	for (i = 0; i < app.n_ports; i++)
-		if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
-			table_id))
-			rte_panic("Unable to connect input port %u to "
-				"table %u\n", port_in_id[i],  table_id);
-
-	/* Enable input ports */
-	for (i = 0; i < app.n_ports; i++)
-		if (rte_pipeline_port_in_enable(p, port_in_id[i]))
-			rte_panic("Unable to enable input port %u\n",
-				port_in_id[i]);
-
-	/* Check pipeline consistency */
-	if (rte_pipeline_check(p) < 0)
-		rte_panic("Pipeline consistency check failed\n");
-
-	/* Message handling */
-	mh_params.ring_req = app_get_ring_req(
-		app_get_first_core_id(APP_CORE_FW));
-	mh_params.ring_resp = app_get_ring_resp(
-		app_get_first_core_id(APP_CORE_FW));
-	mh_params.p = p;
-	mh_params.port_out_id = port_out_id;
-	mh_params.table_id = table_id;
-
-	/* Run-time */
-	for (i = 0; ; i++) {
-		rte_pipeline_run(p);
-
-		if ((i & APP_FLUSH) == 0) {
-			rte_pipeline_flush(p);
-			app_message_handle(&mh_params);
-		}
+	print_firewall_ipv4_rule(rule);
+
+	/* Free response */
+	app_msg_free(app, rsp);
+
+	return 0;
+}
+
+int
+app_pipeline_firewall_delete_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *key)
+{
+	struct app_pipeline_firewall *p;
+	struct app_pipeline_firewall_rule *rule;
+	struct pipeline_firewall_del_msg_req *req;
+	struct pipeline_firewall_del_msg_rsp *rsp;
+
+	/* Check input arguments */
+	if ((app == NULL) ||
+		(key == NULL) ||
+		(key->type != PIPELINE_FIREWALL_IPV4_5TUPLE))
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return -1;
+
+	if (app_pipeline_firewall_key_check_and_normalize(key) != 0)
+		return -1;
+
+	/* Find rule */
+	rule = app_pipeline_firewall_rule_find(p, key);
+	if (rule == NULL)
+		return 0;
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL;
+	memcpy(&req->key, key, sizeof(*key));
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL)
+		return -1;
+
+	/* Read response */
+	if (rsp->status || !rsp->key_found) {
+		app_msg_free(app, rsp);
+		return -1;
 	}
+
+	/* Remove rule */
+	TAILQ_REMOVE(&p->rules, rule, node);
+	p->n_rules--;
+	rte_free(rule);
+
+	/* Free response */
+	app_msg_free(app, rsp);
+
+	return 0;
 }
 
-void
-app_message_handle(struct app_core_firewall_message_handle_params *params)
+int
+app_pipeline_firewall_add_default_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id)
 {
-	struct rte_ring *ring_req = params->ring_req;
-	struct rte_ring *ring_resp;
-	struct rte_mbuf *msg;
-	struct app_msg_req *req;
-	struct app_msg_resp *resp;
-	struct rte_pipeline *p;
-	uint32_t *port_out_id;
-	uint32_t table_id;
-	int result;
-
-	/* Read request message */
-	result = rte_ring_sc_dequeue(ring_req, (void **) &msg);
-	if (result != 0)
-		return;
+	struct app_pipeline_firewall *p;
+	struct pipeline_firewall_add_default_msg_req *req;
+	struct pipeline_firewall_add_default_msg_rsp *rsp;
 
-	ring_resp = params->ring_resp;
-	p = params->p;
-	port_out_id = params->port_out_id;
-	table_id = params->table_id;
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
 
-	/* Handle request */
-	req = (struct app_msg_req *)rte_ctrlmbuf_data(msg);
-	switch (req->type) {
-	case APP_MSG_REQ_PING:
-	{
-		result = 0;
-		break;
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return -1;
+
+	if (port_id >= p->n_ports_out)
+		return -1;
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT;
+	req->port_id = port_id;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL)
+		return -1;
+
+	/* Read response and write rule */
+	if (rsp->status || (rsp->entry_ptr == NULL)) {
+		app_msg_free(app, rsp);
+		return -1;
 	}
 
-	case APP_MSG_REQ_FW_ADD:
-	{
-		struct rte_pipeline_table_entry entry = {
-			.action = RTE_PIPELINE_ACTION_PORT,
-			{.port_id = port_out_id[req->firewall_add.port]},
-		};
+	p->default_rule_port_id = port_id;
+	p->default_rule_entry_ptr = rsp->entry_ptr;
 
-		struct rte_pipeline_table_entry *entry_ptr;
+	/* Commit rule */
+	p->default_rule_present = 1;
 
-		int key_found;
+	/* Free response */
+	app_msg_free(app, rsp);
 
-		result = rte_pipeline_table_entry_add(p, table_id,
-			&req->firewall_add.add_params, &entry, &key_found,
-			&entry_ptr);
-		break;
+	return 0;
+}
+
+int
+app_pipeline_firewall_delete_default_rule(struct app_params *app,
+	uint32_t pipeline_id)
+{
+	struct app_pipeline_firewall *p;
+	struct pipeline_firewall_del_default_msg_req *req;
+	struct pipeline_firewall_del_default_msg_rsp *rsp;
+
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return -1;
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL)
+		return -1;
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL)
+		return -1;
+
+	/* Read response and write rule */
+	if (rsp->status) {
+		app_msg_free(app, rsp);
+		return -1;
 	}
 
-	case APP_MSG_REQ_FW_DEL:
-	{
-		int key_found;
+	/* Commit rule */
+	p->default_rule_present = 0;
+
+	/* Free response */
+	app_msg_free(app, rsp);
+
+	return 0;
+}
+
+/*
+ * p firewall add ipv4
+ */
+
+struct cmd_firewall_add_ipv4_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t firewall_string;
+	cmdline_fixed_string_t add_string;
+	cmdline_fixed_string_t ipv4_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_id;
+};
+
+static void
+cmd_firewall_add_ipv4_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_add_ipv4_result *params = parsed_result;
+	struct app_params *app = data;
+	struct pipeline_firewall_key key;
+	int status;
+
+	key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+	key.key.ipv4_5tuple.src_ip = rte_bswap32(
+		(uint32_t) params->src_ip.addr.ipv4.s_addr);
+	key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+	key.key.ipv4_5tuple.dst_ip = rte_bswap32(
+		(uint32_t) params->dst_ip.addr.ipv4.s_addr);
+	key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+	key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+	key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+	key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+	key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+	key.key.ipv4_5tuple.proto = params->proto;
+	key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+
+	status = app_pipeline_firewall_add_rule(app,
+		params->pipeline_id,
+		&key,
+		params->priority,
+		params->port_id);
+
+	if (status != 0) {
+		printf("Command failed\n");
+		return;
+	}
+}
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, p_string,
+		"p");
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, pipeline_id,
+		UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_add_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		add_string, "add");
+
+cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		ipv4_string, "ipv4");
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority,
+		INT32);
+
+cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip =
+	TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_ip_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip_mask,
+		UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_dst_ip =
+	TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_ip_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip_mask,
+		UINT32);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_from =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_to =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		src_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_from =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		dst_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_to =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		dst_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		proto, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		proto_mask, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_add_ipv4_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result,
+		port_id, UINT8);
+
+cmdline_parse_inst_t cmd_firewall_add_ipv4 = {
+	.f = cmd_firewall_add_ipv4_parsed,
+	.data = NULL,
+	.help_str = "Firewall rule add",
+	.tokens = {
+		(void *) &cmd_firewall_add_ipv4_p_string,
+		(void *) &cmd_firewall_add_ipv4_pipeline_id,
+		(void *) &cmd_firewall_add_ipv4_firewall_string,
+		(void *) &cmd_firewall_add_ipv4_add_string,
+		(void *) &cmd_firewall_add_ipv4_ipv4_string,
+		(void *) &cmd_firewall_add_ipv4_priority,
+		(void *) &cmd_firewall_add_ipv4_src_ip,
+		(void *) &cmd_firewall_add_ipv4_src_ip_mask,
+		(void *) &cmd_firewall_add_ipv4_dst_ip,
+		(void *) &cmd_firewall_add_ipv4_dst_ip_mask,
+		(void *) &cmd_firewall_add_ipv4_src_port_from,
+		(void *) &cmd_firewall_add_ipv4_src_port_to,
+		(void *) &cmd_firewall_add_ipv4_dst_port_from,
+		(void *) &cmd_firewall_add_ipv4_dst_port_to,
+		(void *) &cmd_firewall_add_ipv4_proto,
+		(void *) &cmd_firewall_add_ipv4_proto_mask,
+		(void *) &cmd_firewall_add_ipv4_port_id,
+		NULL,
+	},
+};
+
+/*
+ * p firewall del ipv4
+ */
+
+struct cmd_firewall_del_ipv4_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t firewall_string;
+	cmdline_fixed_string_t del_string;
+	cmdline_fixed_string_t ipv4_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;
+};
 
-		result = rte_pipeline_table_entry_delete(p, table_id,
-			&req->firewall_del.delete_params, &key_found, NULL);
-		break;
+static void
+cmd_firewall_del_ipv4_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_del_ipv4_result *params = parsed_result;
+	struct app_params *app = data;
+	struct pipeline_firewall_key key;
+	int status;
+
+	key.type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+	key.key.ipv4_5tuple.src_ip = rte_bswap32(
+		(uint32_t) params->src_ip.addr.ipv4.s_addr);
+	key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask;
+	key.key.ipv4_5tuple.dst_ip = rte_bswap32(
+		(uint32_t) params->dst_ip.addr.ipv4.s_addr);
+	key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask;
+	key.key.ipv4_5tuple.src_port_from = params->src_port_from;
+	key.key.ipv4_5tuple.src_port_to = params->src_port_to;
+	key.key.ipv4_5tuple.dst_port_from = params->dst_port_from;
+	key.key.ipv4_5tuple.dst_port_to = params->dst_port_to;
+	key.key.ipv4_5tuple.proto = params->proto;
+	key.key.ipv4_5tuple.proto_mask = params->proto_mask;
+
+	status = app_pipeline_firewall_delete_rule(app,
+		params->pipeline_id,
+		&key);
+
+	if (status != 0) {
+		printf("Command failed\n");
+		return;
 	}
+}
 
-	default:
-		rte_panic("FW unrecognized message type (%u)\n", req->type);
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, p_string,
+		"p");
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, pipeline_id,
+		UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_del_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		del_string, "del");
+
+cmdline_parse_token_string_t cmd_firewall_del_ipv4_ipv4_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		ipv4_string, "ipv4");
+
+cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_src_ip =
+	TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_ip_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip_mask,
+		UINT32);
+
+cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_dst_ip =
+	TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_ip_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip_mask,
+		UINT32);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_from =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		src_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_to =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_to,
+		UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_from =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		dst_port_from, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_to =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		dst_port_to, UINT16);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result,
+		proto, UINT8);
+
+cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask,
+		UINT8);
+
+cmdline_parse_inst_t cmd_firewall_del_ipv4 = {
+	.f = cmd_firewall_del_ipv4_parsed,
+	.data = NULL,
+	.help_str = "Firewall rule delete",
+	.tokens = {
+		(void *) &cmd_firewall_del_ipv4_p_string,
+		(void *) &cmd_firewall_del_ipv4_pipeline_id,
+		(void *) &cmd_firewall_del_ipv4_firewall_string,
+		(void *) &cmd_firewall_del_ipv4_del_string,
+		(void *) &cmd_firewall_del_ipv4_ipv4_string,
+		(void *) &cmd_firewall_del_ipv4_src_ip,
+		(void *) &cmd_firewall_del_ipv4_src_ip_mask,
+		(void *) &cmd_firewall_del_ipv4_dst_ip,
+		(void *) &cmd_firewall_del_ipv4_dst_ip_mask,
+		(void *) &cmd_firewall_del_ipv4_src_port_from,
+		(void *) &cmd_firewall_del_ipv4_src_port_to,
+		(void *) &cmd_firewall_del_ipv4_dst_port_from,
+		(void *) &cmd_firewall_del_ipv4_dst_port_to,
+		(void *) &cmd_firewall_del_ipv4_proto,
+		(void *) &cmd_firewall_del_ipv4_proto_mask,
+		NULL,
+	},
+};
+
+/*
+ * p firewall add default
+ */
+struct cmd_firewall_add_default_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t firewall_string;
+	cmdline_fixed_string_t add_string;
+	cmdline_fixed_string_t default_string;
+	uint8_t port_id;
+};
+
+static void
+cmd_firewall_add_default_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_add_default_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	status = app_pipeline_firewall_add_default_rule(app,
+		params->pipeline_id,
+		params->port_id);
+
+	if (status != 0) {
+		printf("Command failed\n");
+		return;
+	}
+}
+
+cmdline_parse_token_string_t cmd_firewall_add_default_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
+		p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_add_default_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result,
+		pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_add_default_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
+	firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_add_default_add_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
+	add_string, "add");
+
+cmdline_parse_token_string_t cmd_firewall_add_default_default_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result,
+		default_string, "default");
+
+cmdline_parse_token_num_t cmd_firewall_add_default_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id,
+		UINT8);
+
+cmdline_parse_inst_t cmd_firewall_add_default = {
+	.f = cmd_firewall_add_default_parsed,
+	.data = NULL,
+	.help_str = "Firewall default rule add",
+	.tokens = {
+		(void *) &cmd_firewall_add_default_p_string,
+		(void *) &cmd_firewall_add_default_pipeline_id,
+		(void *) &cmd_firewall_add_default_firewall_string,
+		(void *) &cmd_firewall_add_default_add_string,
+		(void *) &cmd_firewall_add_default_default_string,
+		(void *) &cmd_firewall_add_default_port_id,
+		NULL,
+	},
+};
+
+/*
+ * p firewall del default
+ */
+struct cmd_firewall_del_default_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t firewall_string;
+	cmdline_fixed_string_t del_string;
+	cmdline_fixed_string_t default_string;
+};
+
+static void
+cmd_firewall_del_default_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_del_default_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	status = app_pipeline_firewall_delete_default_rule(app,
+		params->pipeline_id);
+
+	if (status != 0) {
+		printf("Command failed\n");
+		return;
 	}
+}
+
+cmdline_parse_token_string_t cmd_firewall_del_default_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
+		p_string, "p");
+
+cmdline_parse_token_num_t cmd_firewall_del_default_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_default_result,
+		pipeline_id, UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_del_default_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
+	firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_del_default_del_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
+		del_string, "del");
+
+cmdline_parse_token_string_t cmd_firewall_del_default_default_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result,
+		default_string, "default");
+
+cmdline_parse_inst_t cmd_firewall_del_default = {
+	.f = cmd_firewall_del_default_parsed,
+	.data = NULL,
+	.help_str = "Firewall default rule delete",
+	.tokens = {
+		(void *) &cmd_firewall_del_default_p_string,
+		(void *) &cmd_firewall_del_default_pipeline_id,
+		(void *) &cmd_firewall_del_default_firewall_string,
+		(void *) &cmd_firewall_del_default_del_string,
+		(void *) &cmd_firewall_del_default_default_string,
+		NULL,
+	},
+};
 
-	/* Fill in response message */
-	resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg);
-	resp->result = result;
+/*
+ * p firewall ls
+ */
+
+struct cmd_firewall_ls_result {
+	cmdline_fixed_string_t p_string;
+	uint32_t pipeline_id;
+	cmdline_fixed_string_t firewall_string;
+	cmdline_fixed_string_t ls_string;
+};
+
+static void
+cmd_firewall_ls_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_ls_result *params = parsed_result;
+	struct app_params *app = data;
 
-	/* Send response */
-	do {
-		result = rte_ring_sp_enqueue(ring_resp, (void *) msg);
-	} while (result == -ENOBUFS);
+	app_pipeline_firewall_ls(app, params->pipeline_id);
 }
+
+cmdline_parse_token_string_t cmd_firewall_ls_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string,
+		"p");
+
+cmdline_parse_token_num_t cmd_firewall_ls_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_ls_result, pipeline_id,
+		UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_ls_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result,
+	firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_ls_ls_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, ls_string,
+	"ls");
+
+cmdline_parse_inst_t cmd_firewall_ls = {
+	.f = cmd_firewall_ls_parsed,
+	.data = NULL,
+	.help_str = "Firewall rule list",
+	.tokens = {
+		(void *) &cmd_firewall_ls_p_string,
+		(void *) &cmd_firewall_ls_pipeline_id,
+		(void *) &cmd_firewall_ls_firewall_string,
+		(void *) &cmd_firewall_ls_ls_string,
+		NULL,
+	},
+};
+
+static cmdline_parse_ctx_t pipeline_cmds[] = {
+	(cmdline_parse_inst_t *) &cmd_firewall_add_ipv4,
+	(cmdline_parse_inst_t *) &cmd_firewall_del_ipv4,
+	(cmdline_parse_inst_t *) &cmd_firewall_add_default,
+	(cmdline_parse_inst_t *) &cmd_firewall_del_default,
+	(cmdline_parse_inst_t *) &cmd_firewall_ls,
+	NULL,
+};
+
+static struct pipeline_fe_ops pipeline_firewall_fe_ops = {
+	.f_init = app_pipeline_firewall_init,
+	.f_free = app_pipeline_firewall_free,
+	.cmds = pipeline_cmds,
+};
+
+struct pipeline_type pipeline_firewall = {
+	.name = "FIREWALL",
+	.be_ops = &pipeline_firewall_be_ops,
+	.fe_ops = &pipeline_firewall_fe_ops,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h
new file mode 100644
index 0000000..82e905d
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h
@@ -0,0 +1,63 @@
+/*-
+ *   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_FIREWALL_H__
+#define __INCLUDE_PIPELINE_FIREWALL_H__
+
+#include "pipeline.h"
+#include "pipeline_firewall_be.h"
+
+int
+app_pipeline_firewall_add_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *key,
+	uint32_t priority,
+	uint32_t port_id);
+
+int
+app_pipeline_firewall_delete_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *key);
+
+int
+app_pipeline_firewall_add_default_rule(struct app_params *app,
+	uint32_t pipeline_id,
+	uint32_t port_id);
+
+int
+app_pipeline_firewall_delete_default_rule(struct app_params *app,
+	uint32_t pipeline_id);
+
+extern struct pipeline_type pipeline_firewall;
+
+#endif
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
new file mode 100644
index 0000000..b6f305f
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
@@ -0,0 +1,740 @@
+/*-
+ *   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 <string.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_byteorder.h>
+#include <rte_table_acl.h>
+
+#include "pipeline_firewall_be.h"
+
+struct pipeline_firewall {
+	struct pipeline p;
+	pipeline_msg_req_handler custom_handlers[PIPELINE_FIREWALL_MSG_REQS];
+
+	uint32_t n_rules;
+	uint32_t n_rule_fields;
+	struct rte_acl_field_def *field_format;
+	uint32_t field_format_size;
+} __rte_cache_aligned;
+
+static void *
+pipeline_firewall_msg_req_custom_handler(struct pipeline *p, void *msg);
+
+static pipeline_msg_req_handler handlers[] = {
+	[PIPELINE_MSG_REQ_PING] =
+		pipeline_msg_req_ping_handler,
+	[PIPELINE_MSG_REQ_STATS_PORT_IN] =
+		pipeline_msg_req_stats_port_in_handler,
+	[PIPELINE_MSG_REQ_STATS_PORT_OUT] =
+		pipeline_msg_req_stats_port_out_handler,
+	[PIPELINE_MSG_REQ_STATS_TABLE] =
+		pipeline_msg_req_stats_table_handler,
+	[PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
+		pipeline_msg_req_port_in_enable_handler,
+	[PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
+		pipeline_msg_req_port_in_disable_handler,
+	[PIPELINE_MSG_REQ_CUSTOM] =
+		pipeline_firewall_msg_req_custom_handler,
+};
+
+static void *
+pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg);
+
+static void *
+pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg);
+
+static void *
+pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg);
+
+static void *
+pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg);
+
+static pipeline_msg_req_handler custom_handlers[] = {
+	[PIPELINE_FIREWALL_MSG_REQ_ADD] =
+		pipeline_firewall_msg_req_add_handler,
+	[PIPELINE_FIREWALL_MSG_REQ_DEL] =
+		pipeline_firewall_msg_req_del_handler,
+	[PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] =
+		pipeline_firewall_msg_req_add_default_handler,
+	[PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] =
+		pipeline_firewall_msg_req_del_default_handler,
+};
+
+/*
+ * Firewall table
+ */
+struct firewall_table_entry {
+	struct rte_pipeline_table_entry head;
+};
+
+static struct rte_acl_field_def field_format_ipv4[] = {
+	/* Protocol */
+	[0] = {
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint8_t),
+		.field_index = 0,
+		.input_index = 0,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, next_proto_id),
+	},
+
+	/* Source IP address (IPv4) */
+	[1] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 1,
+		.input_index = 1,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, src_addr),
+	},
+
+	/* Destination IP address (IPv4) */
+	[2] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 2,
+		.input_index = 2,
+		.offset = sizeof(struct ether_hdr) +
+			offsetof(struct ipv4_hdr, dst_addr),
+	},
+
+	/* Source Port */
+	[3] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 3,
+		.input_index = 3,
+		.offset = sizeof(struct ether_hdr) +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, src_port),
+	},
+
+	/* Destination Port */
+	[4] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 4,
+		.input_index = 4,
+		.offset = sizeof(struct ether_hdr) +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, dst_port),
+	},
+};
+
+#define SIZEOF_VLAN_HDR                          4
+
+static struct rte_acl_field_def field_format_vlan_ipv4[] = {
+	/* Protocol */
+	[0] = {
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint8_t),
+		.field_index = 0,
+		.input_index = 0,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_VLAN_HDR +
+			offsetof(struct ipv4_hdr, next_proto_id),
+	},
+
+	/* Source IP address (IPv4) */
+	[1] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 1,
+		.input_index = 1,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_VLAN_HDR +
+			offsetof(struct ipv4_hdr, src_addr),
+	},
+
+	/* Destination IP address (IPv4) */
+	[2] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 2,
+		.input_index = 2,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_VLAN_HDR +
+			offsetof(struct ipv4_hdr, dst_addr),
+	},
+
+	/* Source Port */
+	[3] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 3,
+		.input_index = 3,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_VLAN_HDR +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, src_port),
+	},
+
+	/* Destination Port */
+	[4] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 4,
+		.input_index = 4,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_VLAN_HDR +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, dst_port),
+	},
+};
+
+#define SIZEOF_QINQ_HEADER                       8
+
+static struct rte_acl_field_def field_format_qinq_ipv4[] = {
+	/* Protocol */
+	[0] = {
+		.type = RTE_ACL_FIELD_TYPE_BITMASK,
+		.size = sizeof(uint8_t),
+		.field_index = 0,
+		.input_index = 0,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_QINQ_HEADER +
+			offsetof(struct ipv4_hdr, next_proto_id),
+	},
+
+	/* Source IP address (IPv4) */
+	[1] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 1,
+		.input_index = 1,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_QINQ_HEADER +
+			offsetof(struct ipv4_hdr, src_addr),
+	},
+
+	/* Destination IP address (IPv4) */
+	[2] = {
+		.type = RTE_ACL_FIELD_TYPE_MASK,
+		.size = sizeof(uint32_t),
+		.field_index = 2,
+		.input_index = 2,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_QINQ_HEADER +
+			offsetof(struct ipv4_hdr, dst_addr),
+	},
+
+	/* Source Port */
+	[3] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 3,
+		.input_index = 3,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_QINQ_HEADER +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, src_port),
+	},
+
+	/* Destination Port */
+	[4] = {
+		.type = RTE_ACL_FIELD_TYPE_RANGE,
+		.size = sizeof(uint16_t),
+		.field_index = 4,
+		.input_index = 4,
+		.offset = sizeof(struct ether_hdr) +
+			SIZEOF_QINQ_HEADER +
+			sizeof(struct ipv4_hdr) +
+			offsetof(struct tcp_hdr, dst_port),
+	},
+};
+
+static int
+pipeline_firewall_parse_args(struct pipeline_firewall *p,
+	struct pipeline_params *params)
+{
+	uint32_t n_rules_present = 0;
+	uint32_t pkt_type_present = 0;
+	uint32_t i;
+
+	/* defaults */
+	p->n_rules = 4 * 1024;
+	p->n_rule_fields = RTE_DIM(field_format_ipv4);
+	p->field_format = field_format_ipv4;
+	p->field_format_size = sizeof(field_format_ipv4);
+
+	for (i = 0; i < params->n_args; i++) {
+		char *arg_name = params->args_name[i];
+		char *arg_value = params->args_value[i];
+
+		if (strcmp(arg_name, "n_rules") == 0) {
+			if (n_rules_present)
+				return -1;
+			n_rules_present = 1;
+
+			p->n_rules = atoi(arg_value);
+			continue;
+		}
+
+		if (strcmp(arg_name, "pkt_type") == 0) {
+			if (pkt_type_present)
+				return -1;
+			pkt_type_present = 1;
+
+			/* ipv4 */
+			if (strcmp(arg_value, "ipv4") == 0) {
+				p->n_rule_fields = RTE_DIM(field_format_ipv4);
+				p->field_format = field_format_ipv4;
+				p->field_format_size =
+					sizeof(field_format_ipv4);
+				continue;
+			}
+
+			/* vlan_ipv4 */
+			if (strcmp(arg_value, "vlan_ipv4") == 0) {
+				p->n_rule_fields =
+					RTE_DIM(field_format_vlan_ipv4);
+				p->field_format = field_format_vlan_ipv4;
+				p->field_format_size =
+					sizeof(field_format_vlan_ipv4);
+				continue;
+			}
+
+			/* qinq_ipv4 */
+			if (strcmp(arg_value, "qinq_ipv4") == 0) {
+				p->n_rule_fields =
+					RTE_DIM(field_format_qinq_ipv4);
+				p->field_format = field_format_qinq_ipv4;
+				p->field_format_size =
+					sizeof(field_format_qinq_ipv4);
+				continue;
+			}
+
+			/* other */
+			return -1;
+		}
+
+		/* other */
+		return -1;
+	}
+
+	return 0;
+}
+
+static void *
+pipeline_firewall_init(struct pipeline_params *params,
+	__rte_unused void *arg)
+{
+	struct pipeline *p;
+	struct pipeline_firewall *p_fw;
+	uint32_t size, i;
+
+	/* Check input arguments */
+	if ((params == NULL) ||
+		(params->n_ports_in == 0) ||
+		(params->n_ports_out == 0))
+		return NULL;
+
+	/* Memory allocation */
+	size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_firewall));
+	p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+	p_fw = (struct pipeline_firewall *) p;
+	if (p == NULL)
+		return NULL;
+
+	strcpy(p->name, params->name);
+	p->log_level = params->log_level;
+
+	PLOG(p, HIGH, "Firewall");
+
+	/* Parse arguments */
+	if (pipeline_firewall_parse_args(p_fw, params))
+		return NULL;
+
+	/* Pipeline */
+	{
+		struct rte_pipeline_params pipeline_params = {
+			.name = params->name,
+			.socket_id = params->socket_id,
+			.offset_port_id = 0,
+		};
+
+		p->p = rte_pipeline_create(&pipeline_params);
+		if (p->p == NULL) {
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Input ports */
+	p->n_ports_in = params->n_ports_in;
+	for (i = 0; i < p->n_ports_in; i++) {
+		struct rte_pipeline_port_in_params port_params = {
+			.ops = pipeline_port_in_params_get_ops(
+				&params->port_in[i]),
+			.arg_create = pipeline_port_in_params_convert(
+				&params->port_in[i]),
+			.f_action = NULL,
+			.arg_ah = NULL,
+			.burst_size = params->port_in[i].burst_size,
+		};
+
+		int status = rte_pipeline_port_in_create(p->p,
+			&port_params,
+			&p->port_in_id[i]);
+
+		if (status) {
+			rte_pipeline_free(p->p);
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Output ports */
+	p->n_ports_out = params->n_ports_out;
+	for (i = 0; i < p->n_ports_out; i++) {
+		struct rte_pipeline_port_out_params port_params = {
+			.ops = pipeline_port_out_params_get_ops(
+				&params->port_out[i]),
+			.arg_create = pipeline_port_out_params_convert(
+				&params->port_out[i]),
+			.f_action = NULL,
+			.f_action_bulk = NULL,
+			.arg_ah = NULL,
+		};
+
+		int status = rte_pipeline_port_out_create(p->p,
+			&port_params,
+			&p->port_out_id[i]);
+
+		if (status) {
+			rte_pipeline_free(p->p);
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Tables */
+	p->n_tables = 1;
+	{
+		struct rte_table_acl_params table_acl_params = {
+			.name = params->name,
+			.n_rules = p_fw->n_rules,
+			.n_rule_fields = p_fw->n_rule_fields,
+		};
+
+		struct rte_pipeline_table_params table_params = {
+				.ops = &rte_table_acl_ops,
+				.arg_create = &table_acl_params,
+				.f_action_hit = NULL,
+				.f_action_miss = NULL,
+				.arg_ah = NULL,
+				.action_data_size =
+					sizeof(struct firewall_table_entry) -
+					sizeof(struct rte_pipeline_table_entry),
+			};
+
+		int status;
+
+		memcpy(table_acl_params.field_format,
+			p_fw->field_format,
+			p_fw->field_format_size);
+
+		status = rte_pipeline_table_create(p->p,
+			&table_params,
+			&p->table_id[0]);
+
+		if (status) {
+			rte_pipeline_free(p->p);
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Connecting input ports to tables */
+	for (i = 0; i < p->n_ports_in; i++) {
+		int status = rte_pipeline_port_in_connect_to_table(p->p,
+			p->port_in_id[i],
+			p->table_id[0]);
+
+		if (status) {
+			rte_pipeline_free(p->p);
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Enable input ports */
+	for (i = 0; i < p->n_ports_in; i++) {
+		int status = rte_pipeline_port_in_enable(p->p,
+			p->port_in_id[i]);
+
+		if (status) {
+			rte_pipeline_free(p->p);
+			rte_free(p);
+			return NULL;
+		}
+	}
+
+	/* Check pipeline consistency */
+	if (rte_pipeline_check(p->p) < 0) {
+		rte_pipeline_free(p->p);
+		rte_free(p);
+		return NULL;
+	}
+
+	/* Message queues */
+	p->n_msgq = params->n_msgq;
+	for (i = 0; i < p->n_msgq; i++)
+		p->msgq_in[i] = params->msgq_in[i];
+	for (i = 0; i < p->n_msgq; i++)
+		p->msgq_out[i] = params->msgq_out[i];
+
+	/* Message handlers */
+	memcpy(p->handlers, handlers, sizeof(p->handlers));
+	memcpy(p_fw->custom_handlers,
+		custom_handlers,
+		sizeof(p_fw->custom_handlers));
+
+	return p;
+}
+
+static int
+pipeline_firewall_free(void *pipeline)
+{
+	struct pipeline *p = (struct pipeline *) pipeline;
+
+	/* Check input arguments */
+	if (p == NULL)
+		return -1;
+
+	/* Free resources */
+	rte_pipeline_free(p->p);
+	rte_free(p);
+	return 0;
+}
+
+static int
+pipeline_firewall_track(void *pipeline,
+	__rte_unused uint32_t port_in,
+	uint32_t *port_out)
+{
+	struct pipeline *p = (struct pipeline *) pipeline;
+
+	/* Check input arguments */
+	if ((p == NULL) ||
+		(port_in >= p->n_ports_in) ||
+		(port_out == NULL))
+		return -1;
+
+	if (p->n_ports_in == 1) {
+		*port_out = 0;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int
+pipeline_firewall_timer(void *pipeline)
+{
+	struct pipeline *p = (struct pipeline *) pipeline;
+
+	pipeline_msg_req_handle(p);
+	rte_pipeline_flush(p->p);
+
+	return 0;
+}
+
+void *
+pipeline_firewall_msg_req_custom_handler(struct pipeline *p,
+	void *msg)
+{
+	struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p;
+	struct pipeline_custom_msg_req *req = msg;
+	pipeline_msg_req_handler f_handle;
+
+	f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS) ?
+		p_fw->custom_handlers[req->subtype] :
+		pipeline_msg_req_invalid_handler;
+
+	if (f_handle == NULL)
+		f_handle = pipeline_msg_req_invalid_handler;
+
+	return f_handle(p, req);
+}
+
+void *
+pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_add_msg_req *req = msg;
+	struct pipeline_firewall_add_msg_rsp *rsp = msg;
+
+	struct rte_table_acl_rule_add_params params;
+	struct firewall_table_entry entry = {
+		.head = {
+			.action = RTE_PIPELINE_ACTION_PORT,
+			{.port_id = p->port_out_id[req->port_id]},
+		},
+	};
+
+	memset(&params, 0, sizeof(params));
+
+	switch (req->key.type) {
+	case PIPELINE_FIREWALL_IPV4_5TUPLE:
+		params.priority = req->priority;
+		params.field_value[0].value.u8 =
+			req->key.key.ipv4_5tuple.proto;
+		params.field_value[0].mask_range.u8 =
+			req->key.key.ipv4_5tuple.proto_mask;
+		params.field_value[1].value.u32 =
+			req->key.key.ipv4_5tuple.src_ip;
+		params.field_value[1].mask_range.u32 =
+			req->key.key.ipv4_5tuple.src_ip_mask;
+		params.field_value[2].value.u32 =
+			req->key.key.ipv4_5tuple.dst_ip;
+		params.field_value[2].mask_range.u32 =
+			req->key.key.ipv4_5tuple.dst_ip_mask;
+		params.field_value[3].value.u16 =
+			req->key.key.ipv4_5tuple.src_port_from;
+		params.field_value[3].mask_range.u16 =
+			req->key.key.ipv4_5tuple.src_port_to;
+		params.field_value[4].value.u16 =
+			req->key.key.ipv4_5tuple.dst_port_from;
+		params.field_value[4].mask_range.u16 =
+			req->key.key.ipv4_5tuple.dst_port_to;
+		break;
+
+	default:
+		rsp->status = -1; /* Error */
+		return rsp;
+	}
+
+	rsp->status = rte_pipeline_table_entry_add(p->p,
+		p->table_id[0],
+		&params,
+		(struct rte_pipeline_table_entry *) &entry,
+		&rsp->key_found,
+		(struct rte_pipeline_table_entry **) &rsp->entry_ptr);
+
+	return rsp;
+}
+
+void *
+pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_del_msg_req *req = msg;
+	struct pipeline_firewall_del_msg_rsp *rsp = msg;
+
+	struct rte_table_acl_rule_delete_params params;
+
+	memset(&params, 0, sizeof(params));
+
+	switch (req->key.type) {
+	case PIPELINE_FIREWALL_IPV4_5TUPLE:
+		params.field_value[0].value.u8 =
+			req->key.key.ipv4_5tuple.proto;
+		params.field_value[0].mask_range.u8 =
+			req->key.key.ipv4_5tuple.proto_mask;
+		params.field_value[1].value.u32 =
+			req->key.key.ipv4_5tuple.src_ip;
+		params.field_value[1].mask_range.u32 =
+			req->key.key.ipv4_5tuple.src_ip_mask;
+		params.field_value[2].value.u32 =
+			req->key.key.ipv4_5tuple.dst_ip;
+		params.field_value[2].mask_range.u32 =
+			req->key.key.ipv4_5tuple.dst_ip_mask;
+		params.field_value[3].value.u16 =
+			req->key.key.ipv4_5tuple.src_port_from;
+		params.field_value[3].mask_range.u16 =
+			req->key.key.ipv4_5tuple.src_port_to;
+		params.field_value[4].value.u16 =
+			req->key.key.ipv4_5tuple.dst_port_from;
+		params.field_value[4].mask_range.u16 =
+			req->key.key.ipv4_5tuple.dst_port_to;
+		break;
+
+	default:
+		rsp->status = -1; /* Error */
+		return rsp;
+	}
+
+	rsp->status = rte_pipeline_table_entry_delete(p->p,
+		p->table_id[0],
+		&params,
+		&rsp->key_found,
+		NULL);
+
+	return rsp;
+}
+
+void *
+pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_add_default_msg_req *req = msg;
+	struct pipeline_firewall_add_default_msg_rsp *rsp = msg;
+
+	struct firewall_table_entry default_entry = {
+		.head = {
+			.action = RTE_PIPELINE_ACTION_PORT,
+			{.port_id = p->port_out_id[req->port_id]},
+		},
+	};
+
+	rsp->status = rte_pipeline_table_default_entry_add(p->p,
+		p->table_id[0],
+		(struct rte_pipeline_table_entry *) &default_entry,
+		(struct rte_pipeline_table_entry **) &rsp->entry_ptr);
+
+	return rsp;
+}
+
+void *
+pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_del_default_msg_rsp *rsp = msg;
+
+	rsp->status = rte_pipeline_table_default_entry_delete(p->p,
+		p->table_id[0],
+		NULL);
+
+	return rsp;
+}
+
+struct pipeline_be_ops pipeline_firewall_be_ops = {
+	.f_init = pipeline_firewall_init,
+	.f_free = pipeline_firewall_free,
+	.f_run = NULL,
+	.f_timer = pipeline_firewall_timer,
+	.f_track = pipeline_firewall_track,
+};
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
new file mode 100644
index 0000000..8e1fd69
--- /dev/null
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
@@ -0,0 +1,138 @@
+/*-
+ *   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_FIREWALL_BE_H__
+#define __INCLUDE_PIPELINE_FIREWALL_BE_H__
+
+#include "pipeline_common_be.h"
+
+enum pipeline_firewall_key_type {
+	PIPELINE_FIREWALL_IPV4_5TUPLE,
+};
+
+struct pipeline_firewall_key_ipv4_5tuple {
+	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;
+};
+
+struct pipeline_firewall_key {
+	enum pipeline_firewall_key_type type;
+	union {
+		struct pipeline_firewall_key_ipv4_5tuple ipv4_5tuple;
+	} key;
+};
+
+enum pipeline_firewall_msg_req_type {
+	PIPELINE_FIREWALL_MSG_REQ_ADD = 0,
+	PIPELINE_FIREWALL_MSG_REQ_DEL,
+	PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT,
+	PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT,
+	PIPELINE_FIREWALL_MSG_REQS
+};
+
+/*
+ * MSG ADD
+ */
+struct pipeline_firewall_add_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+
+	/* key */
+	struct pipeline_firewall_key key;
+
+	/* data */
+	int32_t priority;
+	uint32_t port_id;
+};
+
+struct pipeline_firewall_add_msg_rsp {
+	int status;
+	int key_found;
+	void *entry_ptr;
+};
+
+/*
+ * MSG DEL
+ */
+struct pipeline_firewall_del_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+
+	/* key */
+	struct pipeline_firewall_key key;
+};
+
+struct pipeline_firewall_del_msg_rsp {
+	int status;
+	int key_found;
+};
+
+/*
+ * MSG ADD DEFAULT
+ */
+struct pipeline_firewall_add_default_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+
+	/* data */
+	uint32_t port_id;
+};
+
+struct pipeline_firewall_add_default_msg_rsp {
+	int status;
+	void *entry_ptr;
+};
+
+/*
+ * MSG DEL DEFAULT
+ */
+struct pipeline_firewall_del_default_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+};
+
+struct pipeline_firewall_del_default_msg_rsp {
+	int status;
+};
+
+extern struct pipeline_be_ops pipeline_firewall_be_ops;
+
+#endif
-- 
1.7.9.5

  parent reply	other threads:[~2015-07-07  8:45 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-07  8:09 [PATCH v6 00/11] ip_pipeline: ip_pipeline application enhancements Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 01/11] ip_pipeline: add parsing for config files with new syntax Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 02/11] ip_pipeline: added config checks Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 03/11] ip_pipeline: modified init to match new params struct Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 04/11] ip_pipeline: moved pipelines to separate folder Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 05/11] ip_pipeline: added master pipeline Maciej Gajdzica
2015-07-08 22:33   ` Thomas Monjalon
2015-07-09  8:03     ` Gajdzica, MaciejX T
2015-07-09  9:58     ` Gajdzica, MaciejX T
2015-07-09 10:00       ` Dumitrescu, Cristian
2015-07-09 10:06         ` Gajdzica, MaciejX T
2015-07-07  8:09 ` [PATCH v6 06/11] ip_pipeline: added application thread Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 07/11] ip_pipeline: moved config files to separate folder Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 08/11] ip_pipeline: added new implementation of passthrough pipeline Maciej Gajdzica
2015-07-07  8:09 ` Maciej Gajdzica [this message]
2015-07-07  8:09 ` [PATCH v6 10/11] ip_pipeline: added new implementation of routing pipeline Maciej Gajdzica
2015-07-07  8:09 ` [PATCH v6 11/11] ip_pipeline: added new implementation of flow classification pipeline Maciej Gajdzica
2015-07-07  8:27 ` [PATCH v6 00/11] ip_pipeline: ip_pipeline application enhancements Thomas Monjalon
2015-07-07 11:33   ` Dumitrescu, Cristian
2015-07-07  9:23 ` Dumitrescu, Cristian
2015-07-09 15:27   ` Thomas Monjalon

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=1436256575-15107-10-git-send-email-maciejx.t.gajdzica@intel.com \
    --to=maciejx.t.gajdzica@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

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

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