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,
int data_check)
{
struct table *table = &ctl->tables[table_id];
+ int status;
CHECK(entry, EINVAL);
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:
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;
/* 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;
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 *
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);
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);