DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table
@ 2015-10-20 13:01 Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 1/5] table: added " Michal Jastrzebski
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

This patch adds bulk add/delete functions for tables used by pipelines. It
allows for adding/deleting many rules to pipeline tables in one function call.
It is particulary useful for firewall pipeline which is using ACL table. After
every add or delete, table is rebuild which leads to very long times when
trying to add/delete many entries.

v2:
* Incremented the LIBABIVER number
* Updated release notes
* Removed deprecation announce

v3:
* Updated a Doxygen comment

v4:
* Moved .map file to the second patch

Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Maciej Gajdzica (5):
  table: added bulk add/delete functions for table
  pipeline: added bulk add/delete functions for table
  test_table: added check for bulk add/delete to acl table unit test
  ip_pipline: added cli commands for bulk add/delete to firewall
    pipeline
  doc: modify release notes and deprecation notice for table and
    pipeline

 app/test/test_table_acl.c                          | 166 ++++
 doc/guides/rel_notes/deprecation.rst               |   3 -
 doc/guides/rel_notes/release_2_2.rst               |   2 +-
 examples/ip_pipeline/pipeline/pipeline_firewall.c  | 858 +++++++++++++++++++++
 examples/ip_pipeline/pipeline/pipeline_firewall.h  |  14 +
 .../ip_pipeline/pipeline/pipeline_firewall_be.c    | 157 ++++
 .../ip_pipeline/pipeline/pipeline_firewall_be.h    |  38 +
 lib/librte_pipeline/Makefile                       |   2 +-
 lib/librte_pipeline/rte_pipeline.c                 | 106 +++
 lib/librte_pipeline/rte_pipeline.h                 |  64 ++
 lib/librte_pipeline/rte_pipeline_version.map       |   9 +
 lib/librte_table/rte_table.h                       |  85 +-
 lib/librte_table/rte_table_acl.c                   | 309 ++++++++
 lib/librte_table/rte_table_array.c                 |   2 +
 lib/librte_table/rte_table_hash_ext.c              |   4 +
 lib/librte_table/rte_table_hash_key16.c            |   4 +
 lib/librte_table/rte_table_hash_key32.c            |   4 +
 lib/librte_table/rte_table_hash_key8.c             |   8 +
 lib/librte_table/rte_table_hash_lru.c              |   4 +
 lib/librte_table/rte_table_lpm.c                   |   2 +
 lib/librte_table/rte_table_lpm_ipv6.c              |   2 +
 lib/librte_table/rte_table_stub.c                  |   2 +
 22 files changed, 1834 insertions(+), 11 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 1/5] table: added bulk add/delete functions for table
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
@ 2015-10-20 13:01 ` Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 2/5] pipeline: " Michal Jastrzebski
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

New functions prototypes for bulk add/delete added to table API. New
functions allows adding/deleting multiple records with single function
call. For now those functions are implemented only for ACL table. For
other tables these function pointers are set to NULL.

Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/librte_table/rte_table.h            |  85 ++++++++-
 lib/librte_table/rte_table_acl.c        | 309 ++++++++++++++++++++++++++++++++
 lib/librte_table/rte_table_array.c      |   2 +
 lib/librte_table/rte_table_hash_ext.c   |   4 +
 lib/librte_table/rte_table_hash_key16.c |   4 +
 lib/librte_table/rte_table_hash_key32.c |   4 +
 lib/librte_table/rte_table_hash_key8.c  |   8 +
 lib/librte_table/rte_table_hash_lru.c   |   4 +
 lib/librte_table/rte_table_lpm.c        |   2 +
 lib/librte_table/rte_table_lpm_ipv6.c   |   2 +
 lib/librte_table/rte_table_stub.c       |   2 +
 11 files changed, 420 insertions(+), 6 deletions(-)

diff --git a/lib/librte_table/rte_table.h b/lib/librte_table/rte_table.h
index c13d40d..720514e 100644
--- a/lib/librte_table/rte_table.h
+++ b/lib/librte_table/rte_table.h
@@ -154,6 +154,77 @@ typedef int (*rte_table_op_entry_delete)(
 	void *entry);
 
 /**
+ * Lookup table entry add bulk
+ *
+ * @param table
+ *   Handle to lookup table instance
+ * @param key
+ *   Array containing lookup keys
+ * @param entries
+ *   Array containing data to be associated with each key. Every item in the
+ *   array has to point to a valid memory buffer where the first entry_size
+ *   bytes (table create parameter) are populated with the data.
+ * @param n_keys
+ *   Number of keys to add
+ * @param key_found
+ *   After successful invocation, key_found for every item in the array is set
+ *   to a value different than 0 if the current key is already present in the
+ *   table and to 0 if not. This pointer has to be set to a valid memory
+ *   location before the table entry add function is called.
+ * @param entries_ptr
+ *   After successful invocation, array *entries_ptr stores the handle to the
+ *   table entry containing the data associated with every key. This handle can
+ *   be used to perform further read-write accesses to this entry. This handle
+ *   is valid until the key is deleted from the table or the same key is
+ *   re-added to the table, typically to associate it with different data. This
+ *   pointer has to be set to a valid memory location before the function is
+ *   called.
+ * @return
+ *   0 on success, error code otherwise
+ */
+typedef int (*rte_table_op_entry_add_bulk)(
+	void *table,
+	void **keys,
+	void **entries,
+	uint32_t n_keys,
+	int *key_found,
+	void **entries_ptr);
+
+/**
+ * Lookup table entry delete bulk
+ *
+ * @param table
+ *   Handle to lookup table instance
+ * @param key
+ *   Array containing lookup keys
+ * @param n_keys
+ *   Number of keys to delete
+ * @param key_found
+ *   After successful invocation, key_found for every item in the array is set
+ *   to a value different than 0if the current key was present in the table
+ *   before the delete operation was performed and to 0 if not. This pointer
+ *   has to be set to a valid memory location before the table entry delete
+ *   function is called.
+ * @param entries
+ *   If entries pointer is NULL, this pointer is ignored for every entry found.
+ *   Else, after successful invocation, if specific key is found in the table
+ *   (key_found is different than 0 for this item after function call is
+ *   completed) and item of entry array points to a valid buffer (entry is set
+ *   to a value different than NULL before the function is called), then the
+ *   first entry_size bytes (table create parameter) in *entry store a copy of
+ *   table entry that contained the data associated with the current key before
+ *   the key was deleted.
+ * @return
+ *   0 on success, error code otherwise
+ */
+typedef int (*rte_table_op_entry_delete_bulk)(
+	void *table,
+	void **keys,
+	uint32_t n_keys,
+	int *key_found,
+	void **entries);
+
+/**
  * Lookup table lookup
  *
  * @param table
@@ -213,12 +284,14 @@ typedef int (*rte_table_op_stats_read)(
 
 /** Lookup table interface defining the lookup table operation */
 struct rte_table_ops {
-	rte_table_op_create f_create;       /**< Create */
-	rte_table_op_free f_free;           /**< Free */
-	rte_table_op_entry_add f_add;       /**< Entry add */
-	rte_table_op_entry_delete f_delete; /**< Entry delete */
-	rte_table_op_lookup f_lookup;       /**< Lookup */
-	rte_table_op_stats_read f_stats;	/**< Stats */
+	rte_table_op_create f_create;                 /**< Create */
+	rte_table_op_free f_free;                     /**< Free */
+	rte_table_op_entry_add f_add;                 /**< Entry add */
+	rte_table_op_entry_delete f_delete;           /**< Entry delete */
+	rte_table_op_entry_add_bulk f_add_bulk;       /**< Add entry bulk */
+	rte_table_op_entry_delete_bulk f_delete_bulk; /**< Delete entry bulk */
+	rte_table_op_lookup f_lookup;                 /**< Lookup */
+	rte_table_op_stats_read f_stats;              /**< Stats */
 };
 
 #ifdef __cplusplus
diff --git a/lib/librte_table/rte_table_acl.c b/lib/librte_table/rte_table_acl.c
index f02de3e..c1eb848 100644
--- a/lib/librte_table/rte_table_acl.c
+++ b/lib/librte_table/rte_table_acl.c
@@ -444,6 +444,313 @@ rte_table_acl_entry_delete(
 }
 
 static int
+rte_table_acl_entry_add_bulk(
+	void *table,
+	void **keys,
+	void **entries,
+	uint32_t n_keys,
+	int *key_found,
+	void **entries_ptr)
+{
+	struct rte_table_acl *acl = (struct rte_table_acl *) table;
+	struct rte_acl_ctx *ctx;
+	uint32_t rule_pos[n_keys];
+	uint32_t i;
+	int err = 0, build = 0;
+	int status;
+
+	/* Check input parameters */
+	if (table == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (keys == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: keys parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (entries == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: entries parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (n_keys == 0) {
+		RTE_LOG(ERR, TABLE, "%s: 0 rules to add\n", __func__);
+		return -EINVAL;
+	}
+	if (key_found == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (entries_ptr == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: entries_ptr parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	/* Check input parameters in arrays */
+	for (i = 0; i < n_keys; i++) {
+		struct rte_table_acl_rule_add_params *rule;
+
+		if (keys[i] == NULL) {
+			RTE_LOG(ERR, TABLE, "%s: keys[%" PRIu32 "] parameter is NULL\n",
+					__func__, i);
+			return -EINVAL;
+		}
+
+		if (entries[i] == NULL) {
+			RTE_LOG(ERR, TABLE, "%s: entries[%" PRIu32 "] parameter is NULL\n",
+					__func__, i);
+			return -EINVAL;
+		}
+
+		if (entries_ptr[i] == NULL) {
+			RTE_LOG(ERR, TABLE, "%s: entries_ptr[%" PRIu32 "] parameter is NULL\n",
+					__func__, i);
+			return -EINVAL;
+		}
+
+		rule = (struct rte_table_acl_rule_add_params *) keys[i];
+		if (rule->priority > RTE_ACL_MAX_PRIORITY) {
+			RTE_LOG(ERR, TABLE, "%s: Priority is too high\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	memset(rule_pos, 0, n_keys * sizeof(uint32_t));
+	memset(key_found, 0, n_keys * sizeof(int));
+	for (i = 0; i < n_keys; i++) {
+		struct rte_table_acl_rule_add_params *rule =
+				(struct rte_table_acl_rule_add_params *) keys[i];
+		struct rte_pipeline_acl_rule acl_rule;
+		struct rte_acl_rule *rule_location;
+		uint32_t free_pos, free_pos_valid, j;
+
+		/* Setup rule data structure */
+		memset(&acl_rule, 0, sizeof(acl_rule));
+		acl_rule.data.category_mask = 1;
+		acl_rule.data.priority = RTE_ACL_MAX_PRIORITY - rule->priority;
+		acl_rule.data.userdata = 0; /* To be set up later */
+		memcpy(&acl_rule.field[0],
+			&rule->field_value[0],
+			acl->cfg.num_fields * sizeof(struct rte_acl_field));
+
+		/* Look to see if the rule exists already in the table */
+		free_pos = 0;
+		free_pos_valid = 0;
+		for (j = 1; j < acl->n_rules; j++) {
+			if (acl->acl_rule_list[j] == NULL) {
+				if (free_pos_valid == 0) {
+					free_pos = j;
+					free_pos_valid = 1;
+				}
+
+				continue;
+			}
+
+			/* Compare the key fields */
+			status = memcmp(&acl->acl_rule_list[j]->field[0],
+				&rule->field_value[0],
+				acl->cfg.num_fields * sizeof(struct rte_acl_field));
+
+			/* Rule found: update data associated with the rule */
+			if (status == 0) {
+				key_found[i] = 1;
+				entries_ptr[i] = &acl->memory[j * acl->entry_size];
+				memcpy(entries_ptr[i], entries[i], acl->entry_size);
+
+				break;
+			}
+		}
+
+		/* Key already in the table */
+		if (key_found[i] != 0)
+			continue;
+
+		/* Maximum number of rules reached */
+		if (free_pos_valid == 0) {
+			err = 1;
+			break;
+		}
+
+		/* Add the new rule to the rule set */
+		acl_rule.data.userdata = free_pos;
+		rule_location = (struct rte_acl_rule *)
+			&acl->acl_rule_memory[free_pos * acl->acl_params.rule_size];
+		memcpy(rule_location, &acl_rule, acl->acl_params.rule_size);
+		acl->acl_rule_list[free_pos] = rule_location;
+		rule_pos[i] = free_pos;
+		build = 1;
+	}
+
+	if (err != 0) {
+		for (i = 0; i < n_keys; i++) {
+			if (rule_pos[i] == 0)
+				continue;
+
+			acl->acl_rule_list[rule_pos[i]] = NULL;
+		}
+
+		return -ENOSPC;
+	}
+
+	if (build == 0)
+		return 0;
+
+	/* Build low level ACL table */
+	acl->name_id ^= 1;
+	acl->acl_params.name = acl->name[acl->name_id];
+	status = rte_table_acl_build(acl, &ctx);
+	if (status != 0) {
+		/* Roll back changes */
+		for (i = 0; i < n_keys; i++) {
+			if (rule_pos[i] == 0)
+				continue;
+
+			acl->acl_rule_list[rule_pos[i]] = NULL;
+		}
+		acl->name_id ^= 1;
+
+		return -EINVAL;
+	}
+
+	/* Commit changes */
+	if (acl->ctx != NULL)
+		rte_acl_free(acl->ctx);
+	acl->ctx = ctx;
+
+	for (i = 0; i < n_keys; i++) {
+		if (rule_pos[i] == 0)
+			continue;
+
+		key_found[i] = 0;
+		entries_ptr[i] = &acl->memory[rule_pos[i] * acl->entry_size];
+		memcpy(entries_ptr[i], entries[i], acl->entry_size);
+	}
+
+	return 0;
+}
+
+static int
+rte_table_acl_entry_delete_bulk(
+	void *table,
+	void **keys,
+	uint32_t n_keys,
+	int *key_found,
+	void **entries)
+{
+	struct rte_table_acl *acl = (struct rte_table_acl *) table;
+	struct rte_acl_rule *deleted_rules[n_keys];
+	uint32_t rule_pos[n_keys];
+	struct rte_acl_ctx *ctx;
+	uint32_t i;
+	int status;
+	int build = 0;
+
+	/* Check input parameters */
+	if (table == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (keys == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+	if (n_keys == 0) {
+		RTE_LOG(ERR, TABLE, "%s: 0 rules to delete\n", __func__);
+		return -EINVAL;
+	}
+	if (key_found == NULL) {
+		RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		if (keys[i] == NULL) {
+			RTE_LOG(ERR, TABLE, "%s: keys[%" PRIu32 "] parameter is NULL\n",
+					__func__, i);
+			return -EINVAL;
+		}
+	}
+
+	memset(deleted_rules, 0, n_keys * sizeof(struct rte_acl_rule *));
+	memset(rule_pos, 0, n_keys * sizeof(uint32_t));
+	for (i = 0; i < n_keys; i++) {
+		struct rte_table_acl_rule_delete_params *rule =
+			(struct rte_table_acl_rule_delete_params *) keys[i];
+		uint32_t pos_valid, j;
+
+		/* Look for the rule in the table */
+		pos_valid = 0;
+		for (j = 1; j < acl->n_rules; j++) {
+			if (acl->acl_rule_list[j] == NULL)
+				continue;
+
+			/* Compare the key fields */
+			status = memcmp(&acl->acl_rule_list[j]->field[0],
+					&rule->field_value[0],
+					acl->cfg.num_fields * sizeof(struct rte_acl_field));
+
+			/* Rule found: remove from table */
+			if (status == 0) {
+				pos_valid = 1;
+
+				deleted_rules[i] = acl->acl_rule_list[j];
+				acl->acl_rule_list[j] = NULL;
+				rule_pos[i] = j;
+
+				build = 1;
+			}
+		}
+
+		if (pos_valid == 0) {
+			key_found[i] = 0;
+			continue;
+		}
+	}
+
+	/* Return if no changes to acl table */
+	if (build == 0) {
+		return 0;
+	}
+
+	/* Build low level ACL table */
+	acl->name_id ^= 1;
+	acl->acl_params.name = acl->name[acl->name_id];
+	status = rte_table_acl_build(acl, &ctx);
+	if (status != 0) {
+		/* Roll back changes */
+		for (i = 0; i < n_keys; i++) {
+			if (rule_pos[i] == 0)
+				continue;
+
+			acl->acl_rule_list[rule_pos[i]] = deleted_rules[i];
+		}
+
+		acl->name_id ^= 1;
+
+		return -EINVAL;
+	}
+
+	/* Commit changes */
+	if (acl->ctx != NULL)
+		rte_acl_free(acl->ctx);
+
+	acl->ctx = ctx;
+	for (i = 0; i < n_keys; i++) {
+		if (rule_pos[i] == 0)
+			continue;
+
+		key_found[i] = 1;
+		if (entries != NULL && entries[i] != NULL)
+			memcpy(entries[i], &acl->memory[rule_pos[i] * acl->entry_size],
+					acl->entry_size);
+	}
+
+	return 0;
+}
+
+static int
 rte_table_acl_lookup(
 	void *table,
 	struct rte_mbuf **pkts,
@@ -521,6 +828,8 @@ struct rte_table_ops rte_table_acl_ops = {
 	.f_free = rte_table_acl_free,
 	.f_add = rte_table_acl_entry_add,
 	.f_delete = rte_table_acl_entry_delete,
+	.f_add_bulk = rte_table_acl_entry_add_bulk,
+	.f_delete_bulk = rte_table_acl_entry_delete_bulk,
 	.f_lookup = rte_table_acl_lookup,
 	.f_stats = rte_table_acl_stats_read,
 };
diff --git a/lib/librte_table/rte_table_array.c b/lib/librte_table/rte_table_array.c
index 422f8c3..3bb68d1 100644
--- a/lib/librte_table/rte_table_array.c
+++ b/lib/librte_table/rte_table_array.c
@@ -230,6 +230,8 @@ struct rte_table_ops rte_table_array_ops = {
 	.f_free = rte_table_array_free,
 	.f_add = rte_table_array_entry_add,
 	.f_delete = NULL,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_array_lookup,
 	.f_stats = rte_table_array_stats_read,
 };
diff --git a/lib/librte_table/rte_table_hash_ext.c b/lib/librte_table/rte_table_hash_ext.c
index 1fa15c8..ebe952b 100644
--- a/lib/librte_table/rte_table_hash_ext.c
+++ b/lib/librte_table/rte_table_hash_ext.c
@@ -1139,6 +1139,8 @@ struct rte_table_ops rte_table_hash_ext_ops	 = {
 	.f_free = rte_table_hash_ext_free,
 	.f_add = rte_table_hash_ext_entry_add,
 	.f_delete = rte_table_hash_ext_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_ext_lookup,
 	.f_stats = rte_table_hash_ext_stats_read,
 };
@@ -1148,6 +1150,8 @@ struct rte_table_ops rte_table_hash_ext_dosig_ops  = {
 	.f_free = rte_table_hash_ext_free,
 	.f_add = rte_table_hash_ext_entry_add,
 	.f_delete = rte_table_hash_ext_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_ext_lookup_dosig,
 	.f_stats = rte_table_hash_ext_stats_read,
 };
diff --git a/lib/librte_table/rte_table_hash_key16.c b/lib/librte_table/rte_table_hash_key16.c
index f6a3306..35b7f10 100644
--- a/lib/librte_table/rte_table_hash_key16.c
+++ b/lib/librte_table/rte_table_hash_key16.c
@@ -1103,6 +1103,8 @@ struct rte_table_ops rte_table_hash_key16_lru_ops = {
 	.f_free = rte_table_hash_free_key16_lru,
 	.f_add = rte_table_hash_entry_add_key16_lru,
 	.f_delete = rte_table_hash_entry_delete_key16_lru,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key16_lru,
 	.f_stats = rte_table_hash_key16_stats_read,
 };
@@ -1112,6 +1114,8 @@ struct rte_table_ops rte_table_hash_key16_ext_ops = {
 	.f_free = rte_table_hash_free_key16_ext,
 	.f_add = rte_table_hash_entry_add_key16_ext,
 	.f_delete = rte_table_hash_entry_delete_key16_ext,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key16_ext,
 	.f_stats = rte_table_hash_key16_stats_read,
 };
diff --git a/lib/librte_table/rte_table_hash_key32.c b/lib/librte_table/rte_table_hash_key32.c
index 5fe4161..b3ae73e 100644
--- a/lib/librte_table/rte_table_hash_key32.c
+++ b/lib/librte_table/rte_table_hash_key32.c
@@ -1123,6 +1123,8 @@ struct rte_table_ops rte_table_hash_key32_lru_ops = {
 	.f_free = rte_table_hash_free_key32_lru,
 	.f_add = rte_table_hash_entry_add_key32_lru,
 	.f_delete = rte_table_hash_entry_delete_key32_lru,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key32_lru,
 	.f_stats = rte_table_hash_key32_stats_read,
 };
@@ -1132,6 +1134,8 @@ struct rte_table_ops rte_table_hash_key32_ext_ops = {
 	.f_free = rte_table_hash_free_key32_ext,
 	.f_add = rte_table_hash_entry_add_key32_ext,
 	.f_delete = rte_table_hash_entry_delete_key32_ext,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key32_ext,
 	.f_stats = rte_table_hash_key32_stats_read,
 };
diff --git a/lib/librte_table/rte_table_hash_key8.c b/lib/librte_table/rte_table_hash_key8.c
index b351a49..379748e 100644
--- a/lib/librte_table/rte_table_hash_key8.c
+++ b/lib/librte_table/rte_table_hash_key8.c
@@ -1394,6 +1394,8 @@ struct rte_table_ops rte_table_hash_key8_lru_ops = {
 	.f_free = rte_table_hash_free_key8_lru,
 	.f_add = rte_table_hash_entry_add_key8_lru,
 	.f_delete = rte_table_hash_entry_delete_key8_lru,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key8_lru,
 	.f_stats = rte_table_hash_key8_stats_read,
 };
@@ -1403,6 +1405,8 @@ struct rte_table_ops rte_table_hash_key8_lru_dosig_ops = {
 	.f_free = rte_table_hash_free_key8_lru,
 	.f_add = rte_table_hash_entry_add_key8_lru,
 	.f_delete = rte_table_hash_entry_delete_key8_lru,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key8_lru_dosig,
 	.f_stats = rte_table_hash_key8_stats_read,
 };
@@ -1412,6 +1416,8 @@ struct rte_table_ops rte_table_hash_key8_ext_ops = {
 	.f_free = rte_table_hash_free_key8_ext,
 	.f_add = rte_table_hash_entry_add_key8_ext,
 	.f_delete = rte_table_hash_entry_delete_key8_ext,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key8_ext,
 	.f_stats = rte_table_hash_key8_stats_read,
 };
@@ -1421,6 +1427,8 @@ struct rte_table_ops rte_table_hash_key8_ext_dosig_ops = {
 	.f_free = rte_table_hash_free_key8_ext,
 	.f_add = rte_table_hash_entry_add_key8_ext,
 	.f_delete = rte_table_hash_entry_delete_key8_ext,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lookup_key8_ext_dosig,
 	.f_stats = rte_table_hash_key8_stats_read,
 };
diff --git a/lib/librte_table/rte_table_hash_lru.c b/lib/librte_table/rte_table_hash_lru.c
index 1640dc9..14e9072 100644
--- a/lib/librte_table/rte_table_hash_lru.c
+++ b/lib/librte_table/rte_table_hash_lru.c
@@ -1082,6 +1082,8 @@ struct rte_table_ops rte_table_hash_lru_ops = {
 	.f_free = rte_table_hash_lru_free,
 	.f_add = rte_table_hash_lru_entry_add,
 	.f_delete = rte_table_hash_lru_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lru_lookup,
 	.f_stats = rte_table_hash_lru_stats_read,
 };
@@ -1091,6 +1093,8 @@ struct rte_table_ops rte_table_hash_lru_dosig_ops = {
 	.f_free = rte_table_hash_lru_free,
 	.f_add = rte_table_hash_lru_entry_add,
 	.f_delete = rte_table_hash_lru_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_hash_lru_lookup_dosig,
 	.f_stats = rte_table_hash_lru_stats_read,
 };
diff --git a/lib/librte_table/rte_table_lpm.c b/lib/librte_table/rte_table_lpm.c
index 849d899..673f401 100644
--- a/lib/librte_table/rte_table_lpm.c
+++ b/lib/librte_table/rte_table_lpm.c
@@ -377,6 +377,8 @@ struct rte_table_ops rte_table_lpm_ops = {
 	.f_free = rte_table_lpm_free,
 	.f_add = rte_table_lpm_entry_add,
 	.f_delete = rte_table_lpm_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_lpm_lookup,
 	.f_stats = rte_table_lpm_stats_read,
 };
diff --git a/lib/librte_table/rte_table_lpm_ipv6.c b/lib/librte_table/rte_table_lpm_ipv6.c
index e9bc6a7..836f4cf 100644
--- a/lib/librte_table/rte_table_lpm_ipv6.c
+++ b/lib/librte_table/rte_table_lpm_ipv6.c
@@ -391,6 +391,8 @@ struct rte_table_ops rte_table_lpm_ipv6_ops = {
 	.f_free = rte_table_lpm_ipv6_free,
 	.f_add = rte_table_lpm_ipv6_entry_add,
 	.f_delete = rte_table_lpm_ipv6_entry_delete,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_lpm_ipv6_lookup,
 	.f_stats = rte_table_lpm_ipv6_stats_read,
 };
diff --git a/lib/librte_table/rte_table_stub.c b/lib/librte_table/rte_table_stub.c
index c1065ef..691d681 100644
--- a/lib/librte_table/rte_table_stub.c
+++ b/lib/librte_table/rte_table_stub.c
@@ -114,6 +114,8 @@ struct rte_table_ops rte_table_stub_ops = {
 	.f_free = NULL,
 	.f_add = NULL,
 	.f_delete = NULL,
+	.f_add_bulk = NULL,
+	.f_delete_bulk = NULL,
 	.f_lookup = rte_table_stub_lookup,
 	.f_stats = rte_table_stub_stats_read,
 };
-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 2/5] pipeline: added bulk add/delete functions for table
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 1/5] table: added " Michal Jastrzebski
@ 2015-10-20 13:01 ` Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 3/5] test_table: added check for bulk add/delete to acl table unit test Michal Jastrzebski
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

Added functions for adding/deleting multiple records to table owned by
pipeline. The LIBABIVER number is incremented for table and pipeline
libraries.

Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
Signed-off-by: Marcin Kerlin <marcinx.kerlin@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 lib/librte_pipeline/Makefile                 |   2 +-
 lib/librte_pipeline/rte_pipeline.c           | 106 +++++++++++++++++++++++++++
 lib/librte_pipeline/rte_pipeline.h           |  64 ++++++++++++++++
 lib/librte_pipeline/rte_pipeline_version.map |   9 +++
 4 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/lib/librte_pipeline/Makefile b/lib/librte_pipeline/Makefile
index 15e406b..1166d3c 100644
--- a/lib/librte_pipeline/Makefile
+++ b/lib/librte_pipeline/Makefile
@@ -41,7 +41,7 @@ CFLAGS += $(WERROR_FLAGS)
 
 EXPORT_MAP := rte_pipeline_version.map
 
-LIBABIVER := 1
+LIBABIVER := 2
 
 #
 # all source are stored in SRCS-y
diff --git a/lib/librte_pipeline/rte_pipeline.c b/lib/librte_pipeline/rte_pipeline.c
index bd700d2..56022f4 100644
--- a/lib/librte_pipeline/rte_pipeline.c
+++ b/lib/librte_pipeline/rte_pipeline.c
@@ -587,6 +587,112 @@ rte_pipeline_table_entry_delete(struct rte_pipeline *p,
 	return (table->ops.f_delete)(table->h_table, key, key_found, entry);
 }
 
+int rte_pipeline_table_entry_add_bulk(struct rte_pipeline *p,
+	uint32_t table_id,
+	void **keys,
+	struct rte_pipeline_table_entry **entries,
+	uint32_t n_keys,
+	int *key_found,
+	struct rte_pipeline_table_entry **entries_ptr)
+{
+	struct rte_table *table;
+	uint32_t i;
+
+	/* Check input arguments */
+	if (p == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (keys == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: keys parameter is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (entries == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: entries parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (table_id >= p->num_tables) {
+		RTE_LOG(ERR, PIPELINE,
+			"%s: table_id %d out of range\n", __func__, table_id);
+		return -EINVAL;
+	}
+
+	table = &p->tables[table_id];
+
+	if (table->ops.f_add_bulk == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: f_add_bulk function pointer NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < n_keys; i++) {
+		if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) &&
+			table->table_next_id_valid &&
+			(entries[i]->table_id != table->table_next_id)) {
+			RTE_LOG(ERR, PIPELINE,
+				"%s: Tree-like topologies not allowed\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	/* Add entry */
+	for (i = 0; i < n_keys; i++) {
+		if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) &&
+			(table->table_next_id_valid == 0)) {
+			table->table_next_id = entries[i]->table_id;
+			table->table_next_id_valid = 1;
+		}
+	}
+
+	return (table->ops.f_add_bulk)(table->h_table, keys, (void **) entries,
+		n_keys, key_found, (void **) entries_ptr);
+}
+
+int rte_pipeline_table_entry_delete_bulk(struct rte_pipeline *p,
+	uint32_t table_id,
+	void **keys,
+	uint32_t n_keys,
+	int *key_found,
+	struct rte_pipeline_table_entry **entries)
+{
+	struct rte_table *table;
+
+	/* Check input arguments */
+	if (p == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (keys == NULL) {
+		RTE_LOG(ERR, PIPELINE, "%s: key parameter is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (table_id >= p->num_tables) {
+		RTE_LOG(ERR, PIPELINE,
+			"%s: table_id %d out of range\n", __func__, table_id);
+		return -EINVAL;
+	}
+
+	table = &p->tables[table_id];
+
+	if (table->ops.f_delete_bulk == NULL) {
+		RTE_LOG(ERR, PIPELINE,
+			"%s: f_delete function pointer NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	return (table->ops.f_delete_bulk)(table->h_table, keys, n_keys, key_found,
+			(void **) entries);
+}
+
 /*
  * Port
  *
diff --git a/lib/librte_pipeline/rte_pipeline.h b/lib/librte_pipeline/rte_pipeline.h
index 59e0710..5459324 100644
--- a/lib/librte_pipeline/rte_pipeline.h
+++ b/lib/librte_pipeline/rte_pipeline.h
@@ -466,6 +466,70 @@ int rte_pipeline_table_entry_delete(struct rte_pipeline *p,
 	struct rte_pipeline_table_entry *entry);
 
 /**
+ * Pipeline table entry add bulk
+ *
+ * @param p
+ *   Handle to pipeline instance
+ * @param table_id
+ *   Table ID (returned by previous invocation of pipeline table create)
+ * @param keys
+ *   Array containing table entry keys
+ * @param entries
+ *   Array containung new contents for every table entry identified by key
+ * @param n_keys
+ *   Number of keys to add
+ * @param key_found
+ *   On successful invocation, key_found for every item in the array is set to
+ *   TRUE (value different than 0) if key was already present in the table
+ *   before the add operation and to FALSE (value 0) if not
+ * @param entries_ptr
+ *   On successful invocation, array *entries_ptr stores pointer to every table
+ *   entry associated with key. This can be used for further read-write accesses
+ *   to this table entry and is valid until the key is deleted from the table or
+ *   re-added (usually for associating different actions and/or action meta-data
+ *   to the current key)
+ * @return
+ *   0 on success, error code otherwise
+ */
+int rte_pipeline_table_entry_add_bulk(struct rte_pipeline *p,
+	uint32_t table_id,
+	void **keys,
+	struct rte_pipeline_table_entry **entries,
+	uint32_t n_keys,
+	int *key_found,
+	struct rte_pipeline_table_entry **entries_ptr);
+
+/**
+ * Pipeline table entry delete bulk
+ *
+ * @param p
+ *   Handle to pipeline instance
+ * @param table_id
+ *   Table ID (returned by previous invocation of pipeline table create)
+ * @param keys
+ *   Array containing table entry keys
+ * @param n_keys
+ *   Number of keys to delete
+ * @param key_found
+ *   On successful invocation, key_found for every item in the array is set to
+ *   TRUE (value different than 0) if key was found in the table before the
+ *   delete operation and to FALSE (value 0) if not
+ * @param entries
+ *   If entries pointer is NULL, this pointer is ignored for every entry found.
+ *   Else, after successful invocation, if specific key is found in the table
+ *   and entry points to a valid buffer, the table entry contents (as it was
+ *   before the delete was performed) is copied to this buffer.
+ * @return
+ *   0 on success, error code otherwise
+ */
+int rte_pipeline_table_entry_delete_bulk(struct rte_pipeline *p,
+	uint32_t table_id,
+	void **keys,
+	uint32_t n_keys,
+	int *key_found,
+	struct rte_pipeline_table_entry **entries);
+
+/**
  * Read pipeline table stats.
  *
  * This function reads table statistics identified by *table_id* of given
diff --git a/lib/librte_pipeline/rte_pipeline_version.map b/lib/librte_pipeline/rte_pipeline_version.map
index 8f25d0f..1ff953e 100644
--- a/lib/librte_pipeline/rte_pipeline_version.map
+++ b/lib/librte_pipeline/rte_pipeline_version.map
@@ -29,3 +29,12 @@ DPDK_2.1 {
 	rte_pipeline_table_stats_read;
 
 } DPDK_2.0;
+
+
+DPDK_2.2 {
+	global:
+
+	rte_pipeline_table_entry_add_bulk;
+	rte_pipeline_table_entry_delete_bulk;
+
+} DPDK_2.1;
\ No newline at end of file
-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 3/5] test_table: added check for bulk add/delete to acl table unit test
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 1/5] table: added " Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 2/5] pipeline: " Michal Jastrzebski
@ 2015-10-20 13:01 ` Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 4/5] ip_pipline: added cli commands for bulk add/delete to firewall pipeline Michal Jastrzebski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

Added to acl table unit test check for bulk add and bulk delete.

Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 app/test/test_table_acl.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/app/test/test_table_acl.c b/app/test/test_table_acl.c
index e4e9b9c..fe8e545 100644
--- a/app/test/test_table_acl.c
+++ b/app/test/test_table_acl.c
@@ -253,6 +253,94 @@ parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
 	return 0;
 }
 
+static int
+parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v)
+{
+	int i, rc;
+	char *s, *sp, *in[CB_FLD_NUM];
+	static const char *dlm = " \t\n";
+
+	/*
+	** Skip leading '@'
+	*/
+	if (strchr(str, '@') != str)
+		return -EINVAL;
+
+	s = str + 1;
+
+	/*
+	* Populate the 'in' array with the location of each
+	* field in the string we're parsing
+	*/
+	for (i = 0; i != DIM(in); i++) {
+		in[i] = strtok_r(s, dlm, &sp);
+		if (in[i] == NULL)
+			return -EINVAL;
+		s = NULL;
+	}
+
+	/* Parse x.x.x.x/x */
+	rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
+		&v->field_value[SRC_FIELD_IPV4].value.u32,
+		&v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+	if (rc != 0) {
+		RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
+			in[CB_FLD_SRC_ADDR]);
+		return rc;
+	}
+
+	printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
+		v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+
+	/* Parse x.x.x.x/x */
+	rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
+		&v->field_value[DST_FIELD_IPV4].value.u32,
+		&v->field_value[DST_FIELD_IPV4].mask_range.u32);
+	if (rc != 0) {
+		RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
+			in[CB_FLD_DST_ADDR]);
+		return rc;
+	}
+
+	printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
+	v->field_value[DST_FIELD_IPV4].mask_range.u32);
+	/* Parse n:n */
+	rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
+		&v->field_value[SRCP_FIELD_IPV4].value.u16,
+		&v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+	if (rc != 0) {
+		RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
+			in[CB_FLD_SRC_PORT_RANGE]);
+		return rc;
+	}
+
+	printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
+		v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+	/* Parse n:n */
+	rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
+		&v->field_value[DSTP_FIELD_IPV4].value.u16,
+		&v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+	if (rc != 0) {
+		RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
+			in[CB_FLD_DST_PORT_RANGE]);
+		return rc;
+	}
+
+	printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
+		v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+	/* parse 0/0xnn */
+	GET_CB_FIELD(in[CB_FLD_PROTO],
+		v->field_value[PROTO_FIELD_IPV4].value.u8,
+		0, UINT8_MAX, '/');
+	GET_CB_FIELD(in[CB_FLD_PROTO],
+		v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
+		0, UINT8_MAX, 0);
+
+	printf("V=%u, mask=%u\n",
+		(unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
+		v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
+	return 0;
+}
 
 /*
  * The format for these rules DO NOT need the port ranges to be
@@ -393,6 +481,84 @@ setup_acl_pipeline(void)
 		}
 	}
 
+	/* Add bulk entries to tables */
+	for (i = 0; i < N_PORTS; i++) {
+		struct rte_table_acl_rule_add_params keys[5];
+		struct rte_pipeline_table_entry entries[5];
+		struct rte_table_acl_rule_add_params *key_array[5];
+		struct rte_pipeline_table_entry *table_entries[5];
+		int key_found[5];
+		struct rte_pipeline_table_entry *table_entries_ptr[5];
+		struct rte_pipeline_table_entry entries_ptr[5];
+
+		parser = parse_cb_ipv4_rule;
+		for (n = 0; n < 5; n++) {
+			memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
+			key_array[n] = &keys[n];
+
+			snprintf(line, sizeof(line), "%s", lines[n]);
+			printf("PARSING [%s]\n", line);
+
+			ret = parser(line, &keys[n]);
+			if (ret != 0) {
+				RTE_LOG(ERR, PIPELINE,
+					"line %u: parse_cb_ipv4vlan_rule"
+					" failed, error code: %d (%s)\n",
+					n, ret, strerror(-ret));
+				return ret;
+			}
+
+			keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
+
+			entries[n].action = RTE_PIPELINE_ACTION_PORT;
+			entries[n].port_id = port_out_id[i^1];
+			table_entries[n] = &entries[n];
+			table_entries_ptr[n] = &entries_ptr[n];
+		}
+
+		ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
+				(void **)key_array, table_entries, 5, key_found, table_entries_ptr);
+		if (ret < 0) {
+			rte_panic("Add entry bulk to table %u failed (%d)\n",
+				table_id[i], ret);
+			goto fail;
+		}
+	}
+
+	/* Delete bulk entries from tables */
+	for (i = 0; i < N_PORTS; i++) {
+		struct rte_table_acl_rule_delete_params keys[5];
+		struct rte_table_acl_rule_delete_params *key_array[5];
+		struct rte_pipeline_table_entry *table_entries[5];
+		int key_found[5];
+
+		for (n = 0; n < 5; n++) {
+			memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
+			key_array[n] = &keys[n];
+
+			snprintf(line, sizeof(line), "%s", lines[n]);
+			printf("PARSING [%s]\n", line);
+
+			ret = parse_cb_ipv4_rule_del(line, &keys[n]);
+			if (ret != 0) {
+				RTE_LOG(ERR, PIPELINE,
+					"line %u: parse_cb_ipv4vlan_rule"
+					" failed, error code: %d (%s)\n",
+					n, ret, strerror(-ret));
+				return ret;
+			}
+		}
+
+		ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
+			(void **)key_array, 5, key_found, table_entries);
+		if (ret < 0) {
+			rte_panic("Delete bulk entries from table %u failed (%d)\n",
+				table_id[i], ret);
+			goto fail;
+		} else
+			printf("Bulk deleted rules.\n");
+	}
+
 	/* Add entries to tables */
 	for (i = 0; i < N_PORTS; i++) {
 		struct rte_pipeline_table_entry table_entry = {
-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 4/5] ip_pipline: added cli commands for bulk add/delete to firewall pipeline
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
                   ` (2 preceding siblings ...)
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 3/5] test_table: added check for bulk add/delete to acl table unit test Michal Jastrzebski
@ 2015-10-20 13:01 ` Michal Jastrzebski
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 5/5] doc: modify release notes and deprecation notice for table and pipeline Michal Jastrzebski
  2015-11-25 22:20 ` [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

Added two new cli commands to firewall pipeline. Commands bulk add and
bulk delete takes as argument a file with rules to add/delete. The file
is parsed, and then rules are passed to backend functions which
add/delete records from pipeline tables.

Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 examples/ip_pipeline/pipeline/pipeline_firewall.c  | 858 +++++++++++++++++++++
 examples/ip_pipeline/pipeline/pipeline_firewall.h  |  14 +
 .../ip_pipeline/pipeline/pipeline_firewall_be.c    | 157 ++++
 .../ip_pipeline/pipeline/pipeline_firewall_be.h    |  38 +
 4 files changed, 1067 insertions(+)

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 {
-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v4 5/5] doc: modify release notes and deprecation notice for table and pipeline
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
                   ` (3 preceding siblings ...)
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 4/5] ip_pipline: added cli commands for bulk add/delete to firewall pipeline Michal Jastrzebski
@ 2015-10-20 13:01 ` Michal Jastrzebski
  2015-11-25 22:20 ` [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Michal Jastrzebski @ 2015-10-20 13:01 UTC (permalink / raw)
  To: dev

From: Marcin Kerlin <marcinx.kerlin@intel.com>

The release notes is updated and the deprecation announce is removed.

Signed-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>
Signed-off-by: Marcin Kerlin <marcinx.kerlin@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 doc/guides/rel_notes/deprecation.rst | 3 ---
 doc/guides/rel_notes/release_2_2.rst | 2 +-
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 018a119..5be498a 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -45,9 +45,6 @@ Deprecation Notices
   the value of macros CFG_NAME_LEN and CFG_NAME_VAL will be increased.
   Most likely, the new values will be 64 and 256, respectively.
 
-* librte_table: New functions for table entry bulk add/delete will be added
-  to the table operations structure.
-
 * librte_table hash: Key mask parameter will be added to the hash table
   parameter structure for 8-byte key and 16-byte key extendible bucket and
   LRU tables.
diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 89cba4d..fa85c9f 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -128,7 +128,7 @@ The libraries prepended with a plus sign were incremented in this version.
    + librte_mbuf.so.2
      librte_mempool.so.1
      librte_meter.so.1
-     librte_pipeline.so.1
+   + librte_pipeline.so.2
      librte_pmd_bond.so.1
    + librte_pmd_ring.so.2
    + librte_port.so.2
-- 
1.9.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table
  2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
                   ` (4 preceding siblings ...)
  2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 5/5] doc: modify release notes and deprecation notice for table and pipeline Michal Jastrzebski
@ 2015-11-25 22:20 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Monjalon @ 2015-11-25 22:20 UTC (permalink / raw)
  To: Michal Jastrzebski; +Cc: dev

2015-10-20 15:01, Michal Jastrzebski:
> From: Marcin Kerlin <marcinx.kerlin@intel.com>
> 
> This patch adds bulk add/delete functions for tables used by pipelines. It
> allows for adding/deleting many rules to pipeline tables in one function call.
> It is particulary useful for firewall pipeline which is using ACL table. After
> every add or delete, table is rebuild which leads to very long times when
> trying to add/delete many entries.
> 
> v2:
> * Incremented the LIBABIVER number
> * Updated release notes
> * Removed deprecation announce
> 
> v3:
> * Updated a Doxygen comment
> 
> v4:
> * Moved .map file to the second patch
> 
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> 
> Maciej Gajdzica (5):
>   table: added bulk add/delete functions for table
>   pipeline: added bulk add/delete functions for table
>   test_table: added check for bulk add/delete to acl table unit test
>   ip_pipline: added cli commands for bulk add/delete to firewall
>     pipeline
>   doc: modify release notes and deprecation notice for table and
>     pipeline

Applied, thanks

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-11-25 22:21 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-20 13:01 [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Michal Jastrzebski
2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 1/5] table: added " Michal Jastrzebski
2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 2/5] pipeline: " Michal Jastrzebski
2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 3/5] test_table: added check for bulk add/delete to acl table unit test Michal Jastrzebski
2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 4/5] ip_pipline: added cli commands for bulk add/delete to firewall pipeline Michal Jastrzebski
2015-10-20 13:01 ` [dpdk-dev] [PATCH v4 5/5] doc: modify release notes and deprecation notice for table and pipeline Michal Jastrzebski
2015-11-25 22:20 ` [dpdk-dev] [PATCH v4 0/5] pipeline: add bulk add/delete functions for table Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).