diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c
index f6924ab..4137923 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c
@@ -51,6 +51,8 @@
 #include "pipeline_common_fe.h"
 #include "pipeline_firewall.h"
 
+#define BUF_SIZE		1024
+
 struct app_pipeline_firewall_rule {
 	struct pipeline_firewall_key key;
 	int32_t priority;
@@ -73,6 +75,18 @@ struct app_pipeline_firewall {
 	void *default_rule_entry_ptr;
 };
 
+struct app_pipeline_add_bulk_params {
+	struct pipeline_firewall_key *keys;
+	uint32_t n_keys;
+	uint32_t *priorities;
+	uint32_t *port_ids;
+};
+
+struct app_pipeline_del_bulk_params {
+	struct pipeline_firewall_key *keys;
+	uint32_t n_keys;
+};
+
 static void
 print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule)
 {
@@ -256,6 +270,358 @@ app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key)
 	}
 }
 
+static int
+app_pipeline_add_bulk_parse_file(char *filename,
+		struct app_pipeline_add_bulk_params *params)
+{
+	FILE *f;
+	char file_buf[BUF_SIZE];
+	uint32_t i;
+	int status = 0;
+
+	f = fopen(filename, "r");
+	if (f == NULL)
+		return -1;
+
+	params->n_keys = 0;
+	while (fgets(file_buf, BUF_SIZE, f) != NULL)
+		params->n_keys++;
+	rewind(f);
+
+	if (params->n_keys == 0) {
+		status = -1;
+		goto end;
+	}
+
+	params->keys = rte_malloc(NULL,
+			params->n_keys * sizeof(struct pipeline_firewall_key),
+			RTE_CACHE_LINE_SIZE);
+	if (params->keys == NULL) {
+		status = -1;
+		goto end;
+	}
+
+	params->priorities = rte_malloc(NULL,
+			params->n_keys * sizeof(uint32_t),
+			RTE_CACHE_LINE_SIZE);
+	if (params->priorities == NULL) {
+		status = -1;
+		goto end;
+	}
+
+	params->port_ids = rte_malloc(NULL,
+			params->n_keys * sizeof(uint32_t),
+			RTE_CACHE_LINE_SIZE);
+	if (params->port_ids == NULL) {
+		status = -1;
+		goto end;
+	}
+
+	i = 0;
+	while (fgets(file_buf, BUF_SIZE, f) != NULL) {
+		char *str;
+
+		str = strtok(file_buf, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->priorities[i] = atoi(str);
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str);
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.proto = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		/* Need to add 2 to str to skip leading 0x */
+		params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->port_ids[i] = atoi(str);
+		params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+
+		i++;
+	}
+
+end:
+	fclose(f);
+	return status;
+}
+
+static int
+app_pipeline_del_bulk_parse_file(char *filename,
+		struct app_pipeline_del_bulk_params *params)
+{
+	FILE *f;
+	char file_buf[BUF_SIZE];
+	uint32_t i;
+	int status = 0;
+
+	f = fopen(filename, "r");
+	if (f == NULL)
+		return -1;
+
+	params->n_keys = 0;
+	while (fgets(file_buf, BUF_SIZE, f) != NULL)
+		params->n_keys++;
+	rewind(f);
+
+	if (params->n_keys == 0) {
+		status = -1;
+		goto end;
+	}
+
+	params->keys = rte_malloc(NULL,
+			params->n_keys * sizeof(struct pipeline_firewall_key),
+			RTE_CACHE_LINE_SIZE);
+	if (params->keys == NULL) {
+		status = -1;
+		goto end;
+	}
+
+	i = 0;
+	while (fgets(file_buf, BUF_SIZE, f) != NULL) {
+		char *str;
+
+		str = strtok(file_buf, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str);
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8;
+
+		str = strtok(NULL, " .");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		params->keys[i].key.ipv4_5tuple.proto = atoi(str);
+
+		str = strtok(NULL, " ");
+		if (str == NULL) {
+			status = -1;
+			goto end;
+		}
+		/* Need to add 2 to str to skip leading 0x */
+		params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16);
+
+		params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE;
+
+		i++;
+	}
+
+	for (i = 0; i < params->n_keys; i++) {
+		if (app_pipeline_firewall_key_check_and_normalize(&params->keys[i]) != 0) {
+			status = -1;
+			goto end;
+		}
+	}
+
+end:
+	fclose(f);
+	return status;
+}
+
 int
 app_pipeline_firewall_add_rule(struct app_params *app,
 	uint32_t pipeline_id,
@@ -407,6 +773,332 @@ app_pipeline_firewall_delete_rule(struct app_params *app,
 }
 
 int
+app_pipeline_firewall_add_bulk(struct app_params *app,
+		uint32_t pipeline_id,
+		struct pipeline_firewall_key *keys,
+		uint32_t n_keys,
+		uint32_t *priorities,
+		uint32_t *port_ids)
+{
+	struct app_pipeline_firewall *p;
+	struct pipeline_firewall_add_bulk_msg_req *req;
+	struct pipeline_firewall_add_bulk_msg_rsp *rsp;
+
+	struct app_pipeline_firewall_rule **rules;
+	int *new_rules;
+
+	int *keys_found;
+	void **entries_ptr;
+
+	uint32_t i;
+	int status = 0;
+
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return -1;
+
+	rules = rte_malloc(NULL,
+			n_keys * sizeof(struct app_pipeline_firewall_rule *),
+			RTE_CACHE_LINE_SIZE);
+	if (rules == NULL)
+		return -1;
+
+	new_rules = rte_malloc(NULL,
+			n_keys * sizeof(int),
+			RTE_CACHE_LINE_SIZE);
+	if (new_rules == NULL) {
+		rte_free(rules);
+		return -1;
+	}
+
+	/* check data integrity and add to rule list */
+	for (i = 0; i < n_keys; i++) {
+		if (port_ids[i]  >= p->n_ports_out) {
+			rte_free(rules);
+			rte_free(new_rules);
+			return -1;
+		}
+
+		if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) {
+			rte_free(rules);
+			rte_free(new_rules);
+			return -1;
+		}
+
+		rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]);
+		new_rules[i] = (rules[i] == NULL);
+		if (rules[i] == NULL) {
+			rules[i] = rte_malloc(NULL, sizeof(rules[i]),
+					RTE_CACHE_LINE_SIZE);
+
+			if (rules[i] == NULL) {
+				uint32_t j;
+
+				for (j = 0; j <= i; j++)
+					if (new_rules[j])
+						rte_free(rules[j]);
+
+				rte_free(rules);
+				rte_free(new_rules);
+				return -1;
+			}
+		}
+	}
+
+	keys_found = rte_malloc(NULL,
+			n_keys * sizeof(int),
+			RTE_CACHE_LINE_SIZE);
+	if (keys_found == NULL) {
+		uint32_t j;
+
+		for (j = 0; j < n_keys; j++)
+			if (new_rules[j])
+				rte_free(rules[j]);
+
+		rte_free(rules);
+		rte_free(new_rules);
+		return -1;
+	}
+
+	entries_ptr = rte_malloc(NULL,
+			n_keys * sizeof(struct rte_pipeline_table_entry *),
+			RTE_CACHE_LINE_SIZE);
+	if (entries_ptr == NULL) {
+		uint32_t j;
+
+		for (j = 0; j < n_keys; j++)
+			if (new_rules[j])
+				rte_free(rules[j]);
+
+		rte_free(rules);
+		rte_free(new_rules);
+		rte_free(keys_found);
+		return -1;
+	}
+	for (i = 0; i < n_keys; i++) {
+		entries_ptr[i] = rte_malloc(NULL,
+				sizeof(struct rte_pipeline_table_entry),
+				RTE_CACHE_LINE_SIZE);
+
+		if (entries_ptr[i] == NULL) {
+			uint32_t j;
+
+			for (j = 0; j < n_keys; j++)
+				if (new_rules[j])
+					rte_free(rules[j]);
+
+			for (j = 0; j <= i; j++)
+				rte_free(entries_ptr[j]);
+
+			rte_free(rules);
+			rte_free(new_rules);
+			rte_free(keys_found);
+			rte_free(entries_ptr);
+			return -1;
+		}
+	}
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL) {
+		uint32_t j;
+
+		for (j = 0; j < n_keys; j++)
+			if (new_rules[j])
+				rte_free(rules[j]);
+
+		for (j = 0; j < n_keys; j++)
+			rte_free(entries_ptr[j]);
+
+		rte_free(rules);
+		rte_free(new_rules);
+		rte_free(keys_found);
+		rte_free(entries_ptr);
+		return -1;
+	}
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_BULK;
+
+	req->keys = keys;
+	req->n_keys = n_keys;
+	req->port_ids = port_ids;
+	req->priorities = priorities;
+	req->keys_found = keys_found;
+	req->entries_ptr = entries_ptr;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL) {
+		uint32_t j;
+
+		for (j = 0; j < n_keys; j++)
+			if (new_rules[j])
+				rte_free(rules[j]);
+
+		for (j = 0; j < n_keys; j++)
+			rte_free(entries_ptr[j]);
+
+		rte_free(rules);
+		rte_free(new_rules);
+		rte_free(keys_found);
+		rte_free(entries_ptr);
+		return -1;
+	}
+
+	if (rsp->status) {
+		for (i = 0; i < n_keys; i++)
+			if (new_rules[i])
+				rte_free(rules[i]);
+
+		for (i = 0; i < n_keys; i++)
+			rte_free(entries_ptr[i]);
+
+		status = -1;
+		goto cleanup;
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		if (entries_ptr[i] == NULL ||
+			((new_rules[i] == 0) && (keys_found[i] == 0)) ||
+			((new_rules[i] == 1) && (keys_found[i] == 1))) {
+			for (i = 0; i < n_keys; i++)
+				if (new_rules[i])
+					rte_free(rules[i]);
+
+			for (i = 0; i < n_keys; i++)
+				rte_free(entries_ptr[i]);
+
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		memcpy(&rules[i]->key, &keys[i], sizeof(keys[i]));
+		rules[i]->priority = priorities[i];
+		rules[i]->port_id = port_ids[i];
+		rules[i]->entry_ptr = entries_ptr[i];
+
+		/* Commit rule */
+		if (new_rules[i]) {
+			TAILQ_INSERT_TAIL(&p->rules, rules[i], node);
+			p->n_rules++;
+		}
+
+		print_firewall_ipv4_rule(rules[i]);
+	}
+
+cleanup:
+	app_msg_free(app, rsp);
+	rte_free(rules);
+	rte_free(new_rules);
+	rte_free(keys_found);
+	rte_free(entries_ptr);
+
+	return status;
+}
+
+int
+app_pipeline_firewall_delete_bulk(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *keys,
+	uint32_t n_keys)
+{
+	struct app_pipeline_firewall *p;
+	struct pipeline_firewall_del_bulk_msg_req *req;
+	struct pipeline_firewall_del_bulk_msg_rsp *rsp;
+
+	struct app_pipeline_firewall_rule **rules;
+	int *keys_found;
+
+	uint32_t i;
+	int status = 0;
+
+	/* Check input arguments */
+	if (app == NULL)
+		return -1;
+
+	p = app_pipeline_data_fe(app, pipeline_id);
+	if (p == NULL)
+		return -1;
+
+	rules = rte_malloc(NULL,
+			n_keys * sizeof(struct app_pipeline_firewall_rule *),
+			RTE_CACHE_LINE_SIZE);
+	if (rules == NULL)
+		return -1;
+
+	for (i = 0; i < n_keys; i++) {
+		if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) {
+			return -1;
+		}
+
+		rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]);
+	}
+
+	keys_found = rte_malloc(NULL,
+			n_keys * sizeof(int),
+			RTE_CACHE_LINE_SIZE);
+	if (keys_found == NULL) {
+		rte_free(rules);
+		return -1;
+	}
+
+	/* Allocate and write request */
+	req = app_msg_alloc(app);
+	if (req == NULL) {
+		rte_free(rules);
+		rte_free(keys_found);
+		return -1;
+	}
+
+	req->type = PIPELINE_MSG_REQ_CUSTOM;
+	req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_BULK;
+
+	req->keys = keys;
+	req->n_keys = n_keys;
+	req->keys_found = keys_found;
+
+	/* Send request and wait for response */
+	rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
+	if (rsp == NULL) {
+		rte_free(rules);
+		rte_free(keys_found);
+		return -1;
+	}
+
+	if (rsp->status) {
+		status = -1;
+		goto cleanup;
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		if (keys_found[i] == 0) {
+			status = -1;
+			goto cleanup;
+		}
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		TAILQ_REMOVE(&p->rules, rules[i], node);
+		p->n_rules--;
+		rte_free(rules[i]);
+	}
+
+cleanup:
+	app_msg_free(app, rsp);
+	rte_free(rules);
+	rte_free(keys_found);
+
+	return status;
+}
+
+int
 app_pipeline_firewall_add_default_rule(struct app_params *app,
 	uint32_t pipeline_id,
 	uint32_t port_id)
@@ -795,6 +1487,170 @@ cmdline_parse_inst_t cmd_firewall_del_ipv4 = {
 };
 
 /*
+ * p firewall add bulk
+ */
+
+struct cmd_firewall_add_bulk_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 bulk_string;
+	cmdline_fixed_string_t file_path;
+};
+
+static void
+cmd_firewall_add_bulk_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_add_bulk_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	struct app_pipeline_add_bulk_params add_bulk_params;
+
+	status = app_pipeline_add_bulk_parse_file(params->file_path, &add_bulk_params);
+	if (status != 0) {
+		printf("Command failed\n");
+		goto end;
+	}
+
+	status = app_pipeline_firewall_add_bulk(app, params->pipeline_id, add_bulk_params.keys,
+			add_bulk_params.n_keys, add_bulk_params.priorities, add_bulk_params.port_ids);
+	if (status != 0) {
+		printf("Command failed\n");
+		goto end;
+	}
+
+end:
+	rte_free(add_bulk_params.keys);
+	rte_free(add_bulk_params.priorities);
+	rte_free(add_bulk_params.port_ids);
+}
+
+cmdline_parse_token_string_t cmd_firewall_add_bulk_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, p_string,
+		"p");
+
+cmdline_parse_token_num_t cmd_firewall_add_bulk_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_bulk_result, pipeline_id,
+		UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_add_bulk_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
+		firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_add_bulk_add_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
+		add_string, "add");
+
+cmdline_parse_token_string_t cmd_firewall_add_bulk_bulk_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
+		bulk_string, "bulk");
+
+cmdline_parse_token_string_t cmd_firewall_add_bulk_file_path_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result,
+		file_path, NULL);
+
+cmdline_parse_inst_t cmd_firewall_add_bulk = {
+	.f = cmd_firewall_add_bulk_parsed,
+	.data = NULL,
+	.help_str = "Firewall rule add bulk",
+	.tokens = {
+		(void *) &cmd_firewall_add_bulk_p_string,
+		(void *) &cmd_firewall_add_bulk_pipeline_id,
+		(void *) &cmd_firewall_add_bulk_firewall_string,
+		(void *) &cmd_firewall_add_bulk_add_string,
+		(void *) &cmd_firewall_add_bulk_bulk_string,
+		(void *) &cmd_firewall_add_bulk_file_path_string,
+		NULL,
+	},
+};
+
+/*
+ * p firewall del bulk
+ */
+
+struct cmd_firewall_del_bulk_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 bulk_string;
+	cmdline_fixed_string_t file_path;
+};
+
+static void
+cmd_firewall_del_bulk_parsed(
+	void *parsed_result,
+	__attribute__((unused)) struct cmdline *cl,
+	void *data)
+{
+	struct cmd_firewall_del_bulk_result *params = parsed_result;
+	struct app_params *app = data;
+	int status;
+
+	struct app_pipeline_del_bulk_params del_bulk_params;
+
+	status = app_pipeline_del_bulk_parse_file(params->file_path, &del_bulk_params);
+	if (status != 0) {
+		printf("Command failed\n");
+		goto end;
+	}
+
+	status = app_pipeline_firewall_delete_bulk(app, params->pipeline_id,
+			del_bulk_params.keys, del_bulk_params.n_keys);
+	if (status != 0) {
+		printf("Command failed\n");
+		goto end;
+	}
+
+end:
+	rte_free(del_bulk_params.keys);
+}
+
+cmdline_parse_token_string_t cmd_firewall_del_bulk_p_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, p_string,
+		"p");
+
+cmdline_parse_token_num_t cmd_firewall_del_bulk_pipeline_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_bulk_result, pipeline_id,
+		UINT32);
+
+cmdline_parse_token_string_t cmd_firewall_del_bulk_firewall_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
+		firewall_string, "firewall");
+
+cmdline_parse_token_string_t cmd_firewall_del_bulk_add_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
+		del_string, "del");
+
+cmdline_parse_token_string_t cmd_firewall_del_bulk_bulk_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
+		bulk_string, "bulk");
+
+cmdline_parse_token_string_t cmd_firewall_del_bulk_file_path_string =
+	TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result,
+		file_path, NULL);
+
+cmdline_parse_inst_t cmd_firewall_del_bulk = {
+	.f = cmd_firewall_del_bulk_parsed,
+	.data = NULL,
+	.help_str = "Firewall rule del bulk",
+	.tokens = {
+		(void *) &cmd_firewall_del_bulk_p_string,
+		(void *) &cmd_firewall_del_bulk_pipeline_id,
+		(void *) &cmd_firewall_del_bulk_firewall_string,
+		(void *) &cmd_firewall_del_bulk_add_string,
+		(void *) &cmd_firewall_del_bulk_bulk_string,
+		(void *) &cmd_firewall_del_bulk_file_path_string,
+		NULL,
+	},
+};
+
+/*
  * p firewall add default
  */
 struct cmd_firewall_add_default_result {
@@ -984,6 +1840,8 @@ cmdline_parse_inst_t cmd_firewall_ls = {
 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_bulk,
+	(cmdline_parse_inst_t *) &cmd_firewall_del_bulk,
 	(cmdline_parse_inst_t *) &cmd_firewall_add_default,
 	(cmdline_parse_inst_t *) &cmd_firewall_del_default,
 	(cmdline_parse_inst_t *) &cmd_firewall_ls,
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h
index 82e905d..ccc4e64 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall.h
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h
@@ -50,6 +50,20 @@ app_pipeline_firewall_delete_rule(struct app_params *app,
 	struct pipeline_firewall_key *key);
 
 int
+app_pipeline_firewall_add_bulk(struct app_params *app,
+		uint32_t pipeline_id,
+		struct pipeline_firewall_key *keys,
+		uint32_t n_keys,
+		uint32_t *priorities,
+		uint32_t *port_ids);
+
+int
+app_pipeline_firewall_delete_bulk(struct app_params *app,
+	uint32_t pipeline_id,
+	struct pipeline_firewall_key *keys,
+	uint32_t n_keys);
+
+int
 app_pipeline_firewall_add_default_rule(struct app_params *app,
 	uint32_t pipeline_id,
 	uint32_t port_id);
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
index b6f305f..1c376f7 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c
@@ -80,6 +80,12 @@ static void *
 pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg);
 
 static void *
+pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg);
+
+static void *
+pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg);
+
+static void *
 pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg);
 
 static void *
@@ -90,6 +96,10 @@ static pipeline_msg_req_handler custom_handlers[] = {
 		pipeline_firewall_msg_req_add_handler,
 	[PIPELINE_FIREWALL_MSG_REQ_DEL] =
 		pipeline_firewall_msg_req_del_handler,
+	[PIPELINE_FIREWALL_MSG_REQ_ADD_BULK] =
+		pipeline_firewall_msg_req_add_bulk_handler,
+	[PIPELINE_FIREWALL_MSG_REQ_DEL_BULK] =
+		pipeline_firewall_msg_req_del_bulk_handler,
 	[PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] =
 		pipeline_firewall_msg_req_add_default_handler,
 	[PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] =
@@ -698,6 +708,153 @@ pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg)
 	return rsp;
 }
 
+static void *
+pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_add_bulk_msg_req *req = msg;
+	struct pipeline_firewall_add_bulk_msg_rsp *rsp = msg;
+
+	struct rte_table_acl_rule_add_params *params[req->n_keys];
+	struct firewall_table_entry *entries[req->n_keys];
+
+	uint32_t i, n_keys;
+
+	n_keys = req->n_keys;
+
+	for (i = 0; i < n_keys; i++) {
+		entries[i] = rte_malloc(NULL,
+				sizeof(struct firewall_table_entry),
+				RTE_CACHE_LINE_SIZE);
+		if (entries[i] == NULL) {
+			rsp->status = -1;
+			return rsp;
+		}
+
+		params[i] = rte_malloc(NULL,
+				sizeof(struct rte_table_acl_rule_add_params),
+				RTE_CACHE_LINE_SIZE);
+		if (params[i] == NULL) {
+			rsp->status = -1;
+			return rsp;
+		}
+
+		entries[i]->head.action = RTE_PIPELINE_ACTION_PORT;
+		entries[i]->head.port_id = p->port_out_id[req->port_ids[i]];
+
+		switch (req->keys[i].type) {
+		case PIPELINE_FIREWALL_IPV4_5TUPLE:
+			params[i]->priority = req->priorities[i];
+			params[i]->field_value[0].value.u8 =
+				req->keys[i].key.ipv4_5tuple.proto;
+			params[i]->field_value[0].mask_range.u8 =
+				req->keys[i].key.ipv4_5tuple.proto_mask;
+			params[i]->field_value[1].value.u32 =
+				req->keys[i].key.ipv4_5tuple.src_ip;
+			params[i]->field_value[1].mask_range.u32 =
+				req->keys[i].key.ipv4_5tuple.src_ip_mask;
+			params[i]->field_value[2].value.u32 =
+				req->keys[i].key.ipv4_5tuple.dst_ip;
+			params[i]->field_value[2].mask_range.u32 =
+				req->keys[i].key.ipv4_5tuple.dst_ip_mask;
+			params[i]->field_value[3].value.u16 =
+				req->keys[i].key.ipv4_5tuple.src_port_from;
+			params[i]->field_value[3].mask_range.u16 =
+				req->keys[i].key.ipv4_5tuple.src_port_to;
+			params[i]->field_value[4].value.u16 =
+				req->keys[i].key.ipv4_5tuple.dst_port_from;
+			params[i]->field_value[4].mask_range.u16 =
+				req->keys[i].key.ipv4_5tuple.dst_port_to;
+			break;
+
+		default:
+			rsp->status = -1; /* Error */
+
+			for (i = 0; i < n_keys; i++) {
+				rte_free(entries[i]);
+				rte_free(params[i]);
+			}
+
+			return rsp;
+		}
+	}
+
+	rsp->status = rte_pipeline_table_entry_add_bulk(p->p, p->table_id[0],
+			(void *)params, (struct rte_pipeline_table_entry **)entries,
+			n_keys, req->keys_found,
+			(struct rte_pipeline_table_entry **)req->entries_ptr);
+
+	for (i = 0; i < n_keys; i++) {
+		rte_free(entries[i]);
+		rte_free(params[i]);
+	}
+
+	return rsp;
+}
+
+static void *
+pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg)
+{
+	struct pipeline_firewall_del_bulk_msg_req *req = msg;
+	struct pipeline_firewall_del_bulk_msg_rsp *rsp = msg;
+
+	struct rte_table_acl_rule_delete_params *params[req->n_keys];
+
+	uint32_t i, n_keys;
+
+	n_keys = req->n_keys;
+
+	for (i = 0; i < n_keys; i++) {
+		params[i] = rte_malloc(NULL,
+				sizeof(struct rte_table_acl_rule_delete_params),
+				RTE_CACHE_LINE_SIZE);
+		if (params[i] == NULL) {
+			rsp->status = -1;
+			return rsp;
+		}
+
+		switch (req->keys[i].type) {
+		case PIPELINE_FIREWALL_IPV4_5TUPLE:
+			params[i]->field_value[0].value.u8 =
+				req->keys[i].key.ipv4_5tuple.proto;
+			params[i]->field_value[0].mask_range.u8 =
+				req->keys[i].key.ipv4_5tuple.proto_mask;
+			params[i]->field_value[1].value.u32 =
+				req->keys[i].key.ipv4_5tuple.src_ip;
+			params[i]->field_value[1].mask_range.u32 =
+				req->keys[i].key.ipv4_5tuple.src_ip_mask;
+			params[i]->field_value[2].value.u32 =
+				req->keys[i].key.ipv4_5tuple.dst_ip;
+			params[i]->field_value[2].mask_range.u32 =
+				req->keys[i].key.ipv4_5tuple.dst_ip_mask;
+			params[i]->field_value[3].value.u16 =
+				req->keys[i].key.ipv4_5tuple.src_port_from;
+			params[i]->field_value[3].mask_range.u16 =
+				req->keys[i].key.ipv4_5tuple.src_port_to;
+			params[i]->field_value[4].value.u16 =
+				req->keys[i].key.ipv4_5tuple.dst_port_from;
+			params[i]->field_value[4].mask_range.u16 =
+				req->keys[i].key.ipv4_5tuple.dst_port_to;
+			break;
+
+		default:
+			rsp->status = -1; /* Error */
+
+			for (i = 0; i < n_keys; i++)
+				rte_free(params[i]);
+
+			return rsp;
+		}
+	}
+
+	rsp->status = rte_pipeline_table_entry_delete_bulk(p->p, p->table_id[0],
+			(void **)&params, n_keys, req->keys_found, NULL);
+
+	for (i = 0; i < n_keys; i++)
+		rte_free(params[i]);
+
+	return rsp;
+}
+
 void *
 pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg)
 {
diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
index 8e1fd69..f5b0522 100644
--- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
+++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h
@@ -63,6 +63,8 @@ struct pipeline_firewall_key {
 enum pipeline_firewall_msg_req_type {
 	PIPELINE_FIREWALL_MSG_REQ_ADD = 0,
 	PIPELINE_FIREWALL_MSG_REQ_DEL,
+	PIPELINE_FIREWALL_MSG_REQ_ADD_BULK,
+	PIPELINE_FIREWALL_MSG_REQ_DEL_BULK,
 	PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT,
 	PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT,
 	PIPELINE_FIREWALL_MSG_REQS
@@ -106,6 +108,42 @@ struct pipeline_firewall_del_msg_rsp {
 };
 
 /*
+ * MSG ADD BULK
+ */
+struct pipeline_firewall_add_bulk_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+
+	struct pipeline_firewall_key *keys;
+	uint32_t n_keys;
+
+	uint32_t *priorities;
+	uint32_t *port_ids;
+	int *keys_found;
+	void **entries_ptr;
+};
+struct pipeline_firewall_add_bulk_msg_rsp {
+	int status;
+};
+
+/*
+ * MSG DEL BULK
+ */
+struct pipeline_firewall_del_bulk_msg_req {
+	enum pipeline_msg_req_type type;
+	enum pipeline_firewall_msg_req_type subtype;
+
+	/* key */
+	struct pipeline_firewall_key *keys;
+	uint32_t n_keys;
+	int *keys_found;
+};
+
+struct pipeline_firewall_del_bulk_msg_rsp {
+	int status;
+};
+
+/*
  * MSG ADD DEFAULT
  */
 struct pipeline_firewall_add_default_msg_req {
