From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH 3/5] pipeline: support non-incremental table updates
Date: Mon, 15 Feb 2021 16:21:49 +0000 [thread overview]
Message-ID: <20210215162151.5655-3-cristian.dumitrescu@intel.com> (raw)
In-Reply-To: <20210215162151.5655-1-cristian.dumitrescu@intel.com>
Some table types (e.g. exact match/hash) allow for incremental table
updates, while others (e.g. wildcard match/ACL) do not. The former is
already supported, the latter is enabled by this patch.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
lib/librte_pipeline/rte_swx_ctl.c | 258 +++++++++++++++++++++++-------
1 file changed, 197 insertions(+), 61 deletions(-)
diff --git a/lib/librte_pipeline/rte_swx_ctl.c b/lib/librte_pipeline/rte_swx_ctl.c
index 480e34238..20e2ac067 100644
--- a/lib/librte_pipeline/rte_swx_ctl.c
+++ b/lib/librte_pipeline/rte_swx_ctl.c
@@ -603,6 +603,31 @@ table_pending_default_free(struct table *table)
table->pending_default = NULL;
}
+static int
+table_is_update_pending(struct table *table, int consider_peding_default)
+{
+ struct rte_swx_table_entry *e;
+ uint32_t n = 0;
+
+ /* Pending add. */
+ TAILQ_FOREACH(e, &table->pending_add, node)
+ n++;
+
+ /* Pending modify. */
+ TAILQ_FOREACH(e, &table->pending_modify1, node)
+ n++;
+
+ /* Pending delete. */
+ TAILQ_FOREACH(e, &table->pending_delete, node)
+ n++;
+
+ /* Pending default. */
+ if (consider_peding_default && table->pending_default)
+ n++;
+
+ return n;
+}
+
static void
table_free(struct rte_swx_ctl_pipeline *ctl)
{
@@ -674,7 +699,7 @@ table_state_create(struct rte_swx_ctl_pipeline *ctl)
struct rte_swx_table_state *ts_next = &ctl->ts_next[i];
/* Table object. */
- if (!table->is_stub) {
+ if (!table->is_stub && table->ops.add) {
ts_next->obj = table->ops.create(&table->params,
&table->entries,
table->info.args,
@@ -685,6 +710,9 @@ table_state_create(struct rte_swx_ctl_pipeline *ctl)
}
}
+ if (!table->is_stub && !table->ops.add)
+ ts_next->obj = ts->obj;
+
/* Default action data: duplicate from current table state. */
ts_next->default_action_data =
malloc(table->params.action_data_size);
@@ -1108,52 +1136,145 @@ rte_swx_ctl_pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *ctl,
return 0;
}
+
+static void
+table_entry_list_free(struct rte_swx_table_entry_list *list)
+{
+ for ( ; ; ) {
+ struct rte_swx_table_entry *entry;
+
+ entry = TAILQ_FIRST(list);
+ if (!entry)
+ break;
+
+ TAILQ_REMOVE(list, entry, node);
+ table_entry_free(entry);
+ }
+}
+
static int
-table_rollfwd0(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id)
+table_entry_list_duplicate(struct rte_swx_ctl_pipeline *ctl,
+ uint32_t table_id,
+ struct rte_swx_table_entry_list *dst,
+ struct rte_swx_table_entry_list *src)
+{
+ struct rte_swx_table_entry *src_entry;
+
+ TAILQ_FOREACH(src_entry, src, node) {
+ struct rte_swx_table_entry *dst_entry;
+
+ dst_entry = table_entry_duplicate(ctl, table_id, src_entry, 1, 1);
+ if (!dst_entry)
+ goto error;
+
+ TAILQ_INSERT_TAIL(dst, dst_entry, node);
+ }
+
+ return 0;
+
+error:
+ table_entry_list_free(dst);
+ return -ENOMEM;
+}
+
+static int
+table_rollfwd0(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id, uint32_t after_swap)
{
struct table *table = &ctl->tables[table_id];
struct rte_swx_table_state *ts_next = &ctl->ts_next[table_id];
- struct rte_swx_table_entry *entry;
- /* Reset counters. */
- table->n_add = 0;
- table->n_modify = 0;
- table->n_delete = 0;
+ if (table->is_stub || !table_is_update_pending(table, 0))
+ return 0;
- /* Add pending rules. */
- TAILQ_FOREACH(entry, &table->pending_add, node) {
- int status;
+ if (table->ops.add) {
+ /* Reset counters. */
+ table->n_add = 0;
+ table->n_modify = 0;
+ table->n_delete = 0;
- status = table->ops.add(ts_next->obj, entry);
- if (status)
- return status;
+ /* Add pending rules. */
+ struct rte_swx_table_entry *entry;
- table->n_add++;
- }
+ TAILQ_FOREACH(entry, &table->pending_add, node) {
+ int status;
- /* Modify pending rules. */
- TAILQ_FOREACH(entry, &table->pending_modify1, node) {
- int status;
+ status = table->ops.add(ts_next->obj, entry);
+ if (status)
+ return status;
- status = table->ops.add(ts_next->obj, entry);
- if (status)
- return status;
+ table->n_add++;
+ }
- table->n_modify++;
- }
+ /* Modify pending rules. */
+ TAILQ_FOREACH(entry, &table->pending_modify1, node) {
+ int status;
- /* Delete pending rules. */
- TAILQ_FOREACH(entry, &table->pending_delete, node) {
- int status;
+ status = table->ops.add(ts_next->obj, entry);
+ if (status)
+ return status;
- status = table->ops.del(ts_next->obj, entry);
- if (status)
+ table->n_modify++;
+ }
+
+ /* Delete pending rules. */
+ TAILQ_FOREACH(entry, &table->pending_delete, node) {
+ int status;
+
+ status = table->ops.del(ts_next->obj, entry);
+ if (status)
+ return status;
+
+ table->n_delete++;
+ }
+
+ return 0;
+ } else {
+ if (!after_swap) {
+ struct rte_swx_table_entry_list list;
+ int status;
+
+ /* Create updated list of entries included. */
+ TAILQ_INIT(&list);
+
+ status = table_entry_list_duplicate(ctl, table_id, &list, &table->entries);
+ if (status)
+ goto error;
+
+ status = table_entry_list_duplicate(ctl, table_id, &list, &table->pending_add);
+ if (status)
+ goto error;
+
+ status = table_entry_list_duplicate(ctl, table_id, &list, &table->pending_modify1);
+ if (status)
+ goto error;
+
+ /* Create new table object with the updates included. */
+ ts_next->obj = table->ops.create(&table->params, &list, table->info.args, ctl->numa_node);
+ if (!ts_next->obj) {
+ status = -ENODEV;
+ goto error;
+ }
+
+ table_entry_list_free(&list);
+
+ return 0;
+
+error:
+ table_entry_list_free(&list);
return status;
+ } else {
+ struct rte_swx_table_state *ts = &ctl->ts[table_id];
- table->n_delete++;
- }
+ /* Free the old table object. */
+ if (ts_next->obj && table->ops.free)
+ table->ops.free(ts_next->obj);
- return 0;
+ /* Copy over the new table object. */
+ ts_next->obj = ts->obj;
+
+ return 0;
+ }
+ }
}
static void
@@ -1211,35 +1332,50 @@ table_rollback(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id)
{
struct table *table = &ctl->tables[table_id];
struct rte_swx_table_state *ts_next = &ctl->ts_next[table_id];
- struct rte_swx_table_entry *entry;
- /* Add back all the entries that were just deleted. */
- TAILQ_FOREACH(entry, &table->pending_delete, node) {
- if (!table->n_delete)
- break;
+ if (table->is_stub || !table_is_update_pending(table, 0))
+ return;
- table->ops.add(ts_next->obj, entry);
- table->n_delete--;
- }
+ if (table->ops.add) {
+ struct rte_swx_table_entry *entry;
- /* Add back the old copy for all the entries that were just
- * modified.
- */
- TAILQ_FOREACH(entry, &table->pending_modify0, node) {
- if (!table->n_modify)
- break;
+ /* Add back all the entries that were just deleted. */
+ TAILQ_FOREACH(entry, &table->pending_delete, node) {
+ if (!table->n_delete)
+ break;
- table->ops.add(ts_next->obj, entry);
- table->n_modify--;
- }
+ table->ops.add(ts_next->obj, entry);
+ table->n_delete--;
+ }
- /* Delete all the entries that were just added. */
- TAILQ_FOREACH(entry, &table->pending_add, node) {
- if (!table->n_add)
- break;
+ /* Add back the old copy for all the entries that were just
+ * modified.
+ */
+ TAILQ_FOREACH(entry, &table->pending_modify0, node) {
+ if (!table->n_modify)
+ break;
+
+ table->ops.add(ts_next->obj, entry);
+ table->n_modify--;
+ }
- table->ops.del(ts_next->obj, entry);
- table->n_add--;
+ /* Delete all the entries that were just added. */
+ TAILQ_FOREACH(entry, &table->pending_add, node) {
+ if (!table->n_add)
+ break;
+
+ table->ops.del(ts_next->obj, entry);
+ table->n_add--;
+ }
+ } else {
+ struct rte_swx_table_state *ts = &ctl->ts[table_id];
+
+ /* Free the new table object, as update was cancelled. */
+ if (ts_next->obj && table->ops.free)
+ table->ops.free(ts_next->obj);
+
+ /* Reinstate the old table object. */
+ ts_next->obj = ts->obj;
}
}
@@ -1284,7 +1420,7 @@ rte_swx_ctl_pipeline_commit(struct rte_swx_ctl_pipeline *ctl, int abort_on_fail)
* ts.
*/
for (i = 0; i < ctl->info.n_tables; i++) {
- status = table_rollfwd0(ctl, i);
+ status = table_rollfwd0(ctl, i, 0);
if (status)
goto rollback;
}
@@ -1304,7 +1440,7 @@ rte_swx_ctl_pipeline_commit(struct rte_swx_ctl_pipeline *ctl, int abort_on_fail)
/* Operate the changes on the current ts_next, which is the previous ts.
*/
for (i = 0; i < ctl->info.n_tables; i++) {
- table_rollfwd0(ctl, i);
+ table_rollfwd0(ctl, i, 1);
table_rollfwd1(ctl, i);
table_rollfwd2(ctl, i);
}
@@ -1438,11 +1574,11 @@ rte_swx_ctl_pipeline_table_entry_read(struct rte_swx_ctl_pipeline *ctl,
mask = field_hton(mask, mf->n_bits);
}
- /* Copy to entry. */
- if (entry->key_mask)
- memcpy(&entry->key_mask[offset],
- (uint8_t *)&mask,
- mf->n_bits / 8);
+ /* Copy to entry. */
+ if (entry->key_mask)
+ memcpy(&entry->key_mask[offset],
+ (uint8_t *)&mask,
+ mf->n_bits / 8);
/*
* Value.
--
2.17.1
next prev parent reply other threads:[~2021-02-15 16:22 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-15 16:21 [dpdk-dev] [PATCH 1/5] pipeline: improve table entry helpers Cristian Dumitrescu
2021-02-15 16:21 ` [dpdk-dev] [PATCH 2/5] pipeline: improve table entry parsing Cristian Dumitrescu
2021-02-15 16:21 ` Cristian Dumitrescu [this message]
2021-02-15 16:21 ` [dpdk-dev] [PATCH 4/5] table: add table entry priority Cristian Dumitrescu
2021-02-15 16:21 ` [dpdk-dev] [PATCH 5/5] table: add wildcard match table type Cristian Dumitrescu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210215162151.5655-3-cristian.dumitrescu@intel.com \
--to=cristian.dumitrescu@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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).