pipeline: improve table entry helpers

Improve the internal table entry helper routines for key comparison,
entry duplication and checks.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
Cristian Dumitrescu 2021-02-16 20:46:42 +00:00 committed by Thomas Monjalon
parent 75a09af1b4
commit d526f6e2d0

View File

@ -234,6 +234,26 @@ table_entry_alloc(struct table *table)
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 @@ table_entry_duplicate(struct rte_swx_ctl_pipeline *ctl,
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;
case RTE_SWX_TABLE_MATCH_WILDCARD:
return entry_keycmp_wm(e0, e1, table->params.key_size);
for (i = 0; i < key_size; i++) {
uint8_t *key_mask0 = table->params.key_mask0;
uint8_t km0, km[2], k[2];
case RTE_SWX_TABLE_MATCH_LPM:
return entry_keycmp_lpm(e0, e1, table->params.key_size);
km0 = key_mask0 ? key_mask0[i] : 0xFF;
default:
return 1; /* Not equal. */
km[0] = e0->key_mask ? e0->key_mask[i] : 0xFF;
km[1] = e1->key_mask ? e1->key_mask[i] : 0xFF;
k[0] = e0->key[i];
k[1] = e1->key[i];
/* Mask comparison. */
if ((km[0] & km0) != (km[1] & km0))
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);