From d526f6e2d0dca8e1b5106d92a40238e09f0fc7db Mon Sep 17 00:00:00 2001 From: Cristian Dumitrescu Date: Tue, 16 Feb 2021 20:46:42 +0000 Subject: [PATCH] pipeline: improve table entry helpers Improve the internal table entry helper routines for key comparison, entry duplication and checks. Signed-off-by: Cristian Dumitrescu --- lib/librte_pipeline/rte_swx_ctl.c | 120 ++++++++++++++++-------------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/lib/librte_pipeline/rte_swx_ctl.c b/lib/librte_pipeline/rte_swx_ctl.c index ee6df4544f..af653d7f4b 100644 --- a/lib/librte_pipeline/rte_swx_ctl.c +++ b/lib/librte_pipeline/rte_swx_ctl.c @@ -234,6 +234,26 @@ error: return NULL; } +static int +table_entry_key_check_em(struct table *table, struct rte_swx_table_entry *entry) +{ + uint8_t *key_mask0 = table->params.key_mask0; + uint32_t key_size = table->params.key_size, i; + + if (!entry->key_mask) + return 0; + + for (i = 0; i < key_size; i++) { + uint8_t km0 = key_mask0[i]; + uint8_t km = entry->key_mask[i]; + + if ((km & km0) != km0) + return -EINVAL; + } + + return 0; +} + static int table_entry_check(struct rte_swx_ctl_pipeline *ctl, uint32_t table_id, @@ -242,6 +262,7 @@ table_entry_check(struct rte_swx_ctl_pipeline *ctl, int data_check) { struct table *table = &ctl->tables[table_id]; + int status; CHECK(entry, EINVAL); @@ -266,7 +287,9 @@ table_entry_check(struct rte_swx_ctl_pipeline *ctl, break; case RTE_SWX_TABLE_MATCH_EXACT: - CHECK(!entry->key_mask, EINVAL); + status = table_entry_key_check_em(table, entry); + if (status) + return status; break; default: @@ -327,10 +350,7 @@ table_entry_duplicate(struct rte_swx_ctl_pipeline *ctl, new_entry->key_signature = entry->key_signature; /* key_mask. */ - if (table->params.match_type != RTE_SWX_TABLE_MATCH_EXACT) { - if (!entry->key_mask) - goto error; - + if (entry->key_mask) { new_entry->key_mask = malloc(table->params.key_size); if (!new_entry->key_mask) goto error; @@ -357,18 +377,24 @@ table_entry_duplicate(struct rte_swx_ctl_pipeline *ctl, /* action_data. */ a = &ctl->actions[entry->action_id]; - if (a->data_size) { - if (!entry->action_data) - goto error; + if (a->data_size && !entry->action_data) + goto error; - new_entry->action_data = malloc(a->data_size); - if (!new_entry->action_data) - goto error; + /* The table layer provisions a constant action data size per + * entry, which should be the largest data size for all the + * actions enabled for the current table, and attempts to copy + * this many bytes each time a table entry is added, even if the + * specific action requires less data or even no data at all, + * hence we always have to allocate the max. + */ + new_entry->action_data = calloc(1, table->params.action_data_size); + if (!new_entry->action_data) + goto error; + if (a->data_size) memcpy(new_entry->action_data, entry->action_data, a->data_size); - } } return new_entry; @@ -378,58 +404,36 @@ error: return NULL; } -static int -entry_keycmp_em(struct rte_swx_table_entry *e0, - struct rte_swx_table_entry *e1, - uint32_t key_size) -{ - if (e0->key_signature != e1->key_signature) - return 1; /* Not equal. */ - - if (memcmp(e0->key, e1->key, key_size)) - return 1; /* Not equal. */ - - return 0; /* Equal */ -} - -static int -entry_keycmp_wm(struct rte_swx_table_entry *e0 __rte_unused, - struct rte_swx_table_entry *e1 __rte_unused, - uint32_t key_size __rte_unused) -{ - /* TBD */ - - return 1; /* Not equal */ -} - -static int -entry_keycmp_lpm(struct rte_swx_table_entry *e0 __rte_unused, - struct rte_swx_table_entry *e1 __rte_unused, - uint32_t key_size __rte_unused) -{ - /* TBD */ - - return 1; /* Not equal */ -} - static int table_entry_keycmp(struct table *table, struct rte_swx_table_entry *e0, struct rte_swx_table_entry *e1) { - switch (table->params.match_type) { - case RTE_SWX_TABLE_MATCH_EXACT: - return entry_keycmp_em(e0, e1, table->params.key_size); + uint32_t key_size = table->params.key_size; + uint32_t i; + + for (i = 0; i < key_size; i++) { + uint8_t *key_mask0 = table->params.key_mask0; + uint8_t km0, km[2], k[2]; + + km0 = key_mask0 ? key_mask0[i] : 0xFF; + + km[0] = e0->key_mask ? e0->key_mask[i] : 0xFF; + km[1] = e1->key_mask ? e1->key_mask[i] : 0xFF; - case RTE_SWX_TABLE_MATCH_WILDCARD: - return entry_keycmp_wm(e0, e1, table->params.key_size); + k[0] = e0->key[i]; + k[1] = e1->key[i]; - case RTE_SWX_TABLE_MATCH_LPM: - return entry_keycmp_lpm(e0, e1, table->params.key_size); + /* Mask comparison. */ + if ((km[0] & km0) != (km[1] & km0)) + return 1; /* Not equal. */ - default: - return 1; /* Not equal. */ + /* Value comparison. */ + if ((k[0] & km[0] & km0) != (k[1] & km[1] & km0)) + return 1; /* Not equal. */ } + + return 0; /* Equal. */ } static struct rte_swx_table_entry * @@ -893,6 +897,9 @@ rte_swx_ctl_pipeline_table_entry_add(struct rte_swx_ctl_pipeline *ctl, CHECK(table, EINVAL); table_id = table - ctl->tables; + CHECK(entry, EINVAL); + CHECK(!table_entry_check(ctl, table_id, entry, 1, 1), EINVAL); + new_entry = table_entry_duplicate(ctl, table_id, entry, 1, 1); CHECK(new_entry, ENOMEM); @@ -1095,6 +1102,9 @@ rte_swx_ctl_pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *ctl, table_id = table - ctl->tables; CHECK(!table->info.default_action_is_const, EINVAL); + CHECK(entry, EINVAL); + CHECK(!table_entry_check(ctl, table_id, entry, 0, 1), EINVAL); + new_entry = table_entry_duplicate(ctl, table_id, entry, 0, 1); CHECK(new_entry, ENOMEM); -- 2.20.1