CHECK(entry, EINVAL);
CHECK(!table_entry_check(ctl, table_id, entry, 1, 1), EINVAL);
+ CHECK(table->actions[entry->action_id].action_is_for_table_entries, EINVAL);
+
new_entry = table_entry_duplicate(ctl, table_id, entry, 1, 1);
CHECK(new_entry, ENOMEM);
CHECK(entry, EINVAL);
CHECK(!table_entry_check(ctl, table_id, entry, 0, 1), EINVAL);
+ CHECK(table->actions[entry->action_id].action_is_for_default_entry, EINVAL);
+
new_entry = table_entry_duplicate(ctl, table_id, entry, 0, 1);
CHECK(new_entry, ENOMEM);
CHECK(entry, EINVAL);
CHECK(!learner_default_entry_check(ctl, learner_id, entry), EINVAL);
+ CHECK(l->actions[entry->action_id].action_is_for_default_entry, EINVAL);
+
new_entry = learner_default_entry_duplicate(ctl, learner_id, entry);
CHECK(new_entry, ENOMEM);
struct rte_swx_ctl_table_action_info {
/** Action ID. */
uint32_t action_id;
+
+ /** When non-zero (true), the action can be assigned to regular table entries. */
+ int action_is_for_table_entries;
+
+ /** When non-zero (true), the action can be assigned to the table default entry. */
+ int action_is_for_default_entry;
};
/**
uint32_t size)
{
struct table_type *type;
- struct table *t;
+ struct table *t = NULL;
struct action *default_action;
struct header *header = NULL;
uint32_t action_data_size_max = 0, i;
const char *action_name = params->action_names[i];
struct action *a;
uint32_t action_data_size;
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
CHECK_NAME(action_name, EINVAL);
action_data_size = a->st ? a->st->n_bits / 8 : 0;
if (action_data_size > action_data_size_max)
action_data_size_max = action_data_size;
+
+ if (params->action_is_for_table_entries)
+ action_is_for_table_entries = params->action_is_for_table_entries[i];
+ if (params->action_is_for_default_entry)
+ action_is_for_default_entry = params->action_is_for_default_entry[i];
+ CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
}
CHECK_NAME(params->default_action_name, EINVAL);
params->default_action_name))
break;
CHECK(i < params->n_actions, EINVAL);
+ CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
+ EINVAL);
+
default_action = action_find(p, params->default_action_name);
CHECK((default_action->st && params->default_action_data) ||
!params->default_action_data, EINVAL);
CHECK(t, ENOMEM);
t->fields = calloc(params->n_fields, sizeof(struct match_field));
- if (!t->fields) {
- free(t);
- CHECK(0, ENOMEM);
- }
+ if (!t->fields)
+ goto nomem;
t->actions = calloc(params->n_actions, sizeof(struct action *));
- if (!t->actions) {
- free(t->fields);
- free(t);
- CHECK(0, ENOMEM);
- }
+ if (!t->actions)
+ goto nomem;
if (action_data_size_max) {
t->default_action_data = calloc(1, action_data_size_max);
- if (!t->default_action_data) {
- free(t->actions);
- free(t->fields);
- free(t);
- CHECK(0, ENOMEM);
- }
+ if (!t->default_action_data)
+ goto nomem;
}
+ t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
+ if (!t->action_is_for_table_entries)
+ goto nomem;
+
+ t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
+ if (!t->action_is_for_default_entry)
+ goto nomem;
+
/* Node initialization. */
strcpy(t->name, name);
if (args && args[0])
t->n_fields = params->n_fields;
t->header = header;
- for (i = 0; i < params->n_actions; i++)
+ for (i = 0; i < params->n_actions; i++) {
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
+
+ if (params->action_is_for_table_entries)
+ action_is_for_table_entries = params->action_is_for_table_entries[i];
+ if (params->action_is_for_default_entry)
+ action_is_for_default_entry = params->action_is_for_default_entry[i];
+
t->actions[i] = action_find(p, params->action_names[i]);
+ t->action_is_for_table_entries[i] = action_is_for_table_entries;
+ t->action_is_for_default_entry[i] = action_is_for_default_entry;
+ }
t->default_action = default_action;
if (default_action->st)
memcpy(t->default_action_data,
p->n_tables++;
return 0;
+
+nomem:
+ if (!t)
+ return -ENOMEM;
+
+ free(t->action_is_for_default_entry);
+ free(t->action_is_for_table_entries);
+ free(t->default_action_data);
+ free(t->actions);
+ free(t->fields);
+ free(t);
+
+ return -ENOMEM;
}
static struct rte_swx_table_params *
/* Action checks. */
CHECK(params->n_actions, EINVAL);
-
CHECK(params->action_names, EINVAL);
for (i = 0; i < params->n_actions; i++) {
const char *action_name = params->action_names[i];
struct action *a;
uint32_t action_data_size;
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
CHECK_NAME(action_name, EINVAL);
action_data_size = a->st ? a->st->n_bits / 8 : 0;
if (action_data_size > action_data_size_max)
action_data_size_max = action_data_size;
+
+ if (params->action_is_for_table_entries)
+ action_is_for_table_entries = params->action_is_for_table_entries[i];
+ if (params->action_is_for_default_entry)
+ action_is_for_default_entry = params->action_is_for_default_entry[i];
+ CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL);
}
CHECK_NAME(params->default_action_name, EINVAL);
params->default_action_name))
break;
CHECK(i < params->n_actions, EINVAL);
+ CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i],
+ EINVAL);
default_action = action_find(p, params->default_action_name);
CHECK((default_action->st && params->default_action_data) ||
goto nomem;
}
+ l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int));
+ if (!l->action_is_for_table_entries)
+ goto nomem;
+
+ l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int));
+ if (!l->action_is_for_default_entry)
+ goto nomem;
+
/* Node initialization. */
strcpy(l->name, name);
l->header = header;
- for (i = 0; i < params->n_actions; i++)
+ for (i = 0; i < params->n_actions; i++) {
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
+
+ if (params->action_is_for_table_entries)
+ action_is_for_table_entries = params->action_is_for_table_entries[i];
+ if (params->action_is_for_default_entry)
+ action_is_for_default_entry = params->action_is_for_default_entry[i];
+
l->actions[i] = action_find(p, params->action_names[i]);
+ l->action_is_for_table_entries[i] = action_is_for_table_entries;
+ l->action_is_for_default_entry[i] = action_is_for_default_entry;
+ }
l->default_action = default_action;
if (!l)
return -ENOMEM;
+ free(l->action_is_for_default_entry);
+ free(l->action_is_for_table_entries);
+ free(l->default_action_data);
free(l->actions);
free(l->fields);
free(l);
table_action->action_id = t->actions[table_action_id]->id;
+ table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id];
+ table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id];
+
return 0;
}
learner_action->action_id = l->actions[learner_action_id]->id;
+ learner_action->action_is_for_table_entries =
+ l->action_is_for_table_entries[learner_action_id];
+
+ learner_action->action_is_for_default_entry =
+ l->action_is_for_default_entry[learner_action_id];
+
return 0;
}
/** The set of actions for the current table. */
const char **action_names;
+ /** Array of *n_actions* flags. For each action, the associated flag
+ * indicates whether the action can be assigned to regular table entries
+ * (when non-zero, i.e. true) or not (when zero, i.e. false). When set
+ * to NULL, it defaults to true for all actions.
+ */
+ int *action_is_for_table_entries;
+
+ /** Array of *n_actions* flags. For each action, the associated flag
+ * indicates whether the action can be assigned to the default table
+ * entry (when non-zero, i.e. true) or not (when zero, i.e. false).
+ * When set to NULL, it defaults to true for all actions.
+ */
+ int *action_is_for_default_entry;
+
/** The number of actions for the current table. Must be at least one.
*/
uint32_t n_actions;
/** The set of actions for the current table. */
const char **action_names;
+ /** Array of *n_actions* flags. For each action, the associated flag
+ * indicates whether the action can be assigned to regular table entries
+ * (when non-zero, i.e. true) or not (when zero, i.e. false). When set
+ * to NULL, it defaults to true for all actions.
+ */
+ int *action_is_for_table_entries;
+
+ /** Array of *n_actions* flags. For each action, the associated flag
+ * indicates whether the action can be assigned to the default table
+ * entry (when non-zero, i.e. true) or not (when zero, i.e. false).
+ * When set to NULL, it defaults to true for all actions.
+ */
+ int *action_is_for_default_entry;
+
/** The number of actions for the current table. Must be at least one.
*/
uint32_t n_actions;
uint32_t n_actions;
int default_action_is_const;
uint32_t action_data_size_max;
+ int *action_is_for_table_entries;
+ int *action_is_for_default_entry;
uint32_t size;
uint32_t id;
uint32_t n_actions;
int default_action_is_const;
uint32_t action_data_size_max;
+ int *action_is_for_table_entries;
+ int *action_is_for_default_entry;
uint32_t size;
uint32_t timeout;
* ...
* }
* actions {
- * ACTION_NAME
+ * ACTION_NAME [ @tableonly | @defaultonly ]
* ...
* }
* default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
free(s->params.default_action_data);
s->params.default_action_data = NULL;
+ free(s->params.action_is_for_table_entries);
+ s->params.action_is_for_table_entries = NULL;
+
+ free(s->params.action_is_for_default_entry);
+ s->params.action_is_for_default_entry = NULL;
+
s->params.default_action_is_const = 0;
free(s->recommended_table_type_name);
uint32_t *err_line,
const char **err_msg)
{
- const char **new_action_names;
- char *name;
+ const char **new_action_names = NULL;
+ int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
+ char *name = NULL;
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
/* Handle end of block. */
if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
}
/* Check input arguments. */
- if (n_tokens != 1) {
+ if ((n_tokens > 2) ||
+ ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
+ strcmp(tokens[1], "@defaultonly"))) {
if (err_line)
*err_line = n_lines;
if (err_msg)
}
name = strdup(tokens[0]);
- if (!name) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Memory allocation failed.";
- return -ENOMEM;
+
+ if (n_tokens == 2) {
+ if (!strcmp(tokens[1], "@tableonly"))
+ action_is_for_default_entry = 0;
+
+ if (!strcmp(tokens[1], "@defaultonly"))
+ action_is_for_table_entries = 0;
}
new_action_names = realloc(s->params.action_names,
(s->params.n_actions + 1) * sizeof(char *));
- if (!new_action_names) {
+ new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
+ (s->params.n_actions + 1) * sizeof(int));
+ new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
+ (s->params.n_actions + 1) * sizeof(int));
+
+ if (!name ||
+ !new_action_names ||
+ !new_action_is_for_table_entries ||
+ !new_action_is_for_default_entry) {
free(name);
+ free(new_action_names);
+ free(new_action_is_for_table_entries);
+ free(new_action_is_for_default_entry);
if (err_line)
*err_line = n_lines;
s->params.action_names = new_action_names;
s->params.action_names[s->params.n_actions] = name;
+
+ s->params.action_is_for_table_entries = new_action_is_for_table_entries;
+ s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
+
+ s->params.action_is_for_default_entry = new_action_is_for_default_entry;
+ s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
+
s->params.n_actions++;
return 0;
* ...
* }
* actions {
- * ACTION_NAME
+ * ACTION_NAME [ @tableonly | @defaultonly]
* ...
* }
* default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
free(s->params.default_action_data);
s->params.default_action_data = NULL;
+ free(s->params.action_is_for_table_entries);
+ s->params.action_is_for_table_entries = NULL;
+
+ free(s->params.action_is_for_default_entry);
+ s->params.action_is_for_default_entry = NULL;
+
s->params.default_action_is_const = 0;
s->size = 0;
const char **err_msg)
{
const char **new_action_names = NULL;
- char *action_name = NULL;
+ int *new_action_is_for_table_entries = NULL, *new_action_is_for_default_entry = NULL;
+ char *name = NULL;
+ int action_is_for_table_entries = 1, action_is_for_default_entry = 1;
/* Handle end of block. */
if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
}
/* Check input arguments. */
- if (n_tokens != 1) {
+ if ((n_tokens > 2) ||
+ ((n_tokens == 2) && strcmp(tokens[1], "@tableonly") &&
+ strcmp(tokens[1], "@defaultonly"))) {
if (err_line)
*err_line = n_lines;
if (err_msg)
return -EINVAL;
}
- action_name = strdup(tokens[0]);
+ name = strdup(tokens[0]);
+
+ if (n_tokens == 2) {
+ if (!strcmp(tokens[1], "@tableonly"))
+ action_is_for_default_entry = 0;
+
+ if (!strcmp(tokens[1], "@defaultonly"))
+ action_is_for_table_entries = 0;
+ }
new_action_names = realloc(s->params.action_names,
(s->params.n_actions + 1) * sizeof(char *));
-
- if (!action_name || !new_action_names) {
- free(action_name);
+ new_action_is_for_table_entries = realloc(s->params.action_is_for_table_entries,
+ (s->params.n_actions + 1) * sizeof(int));
+ new_action_is_for_default_entry = realloc(s->params.action_is_for_default_entry,
+ (s->params.n_actions + 1) * sizeof(int));
+
+ if (!name ||
+ !new_action_names ||
+ !new_action_is_for_table_entries ||
+ !new_action_is_for_default_entry) {
+ free(name);
free(new_action_names);
+ free(new_action_is_for_table_entries);
+ free(new_action_is_for_default_entry);
if (err_line)
*err_line = n_lines;
}
s->params.action_names = new_action_names;
- s->params.action_names[s->params.n_actions] = action_name;
+ s->params.action_names[s->params.n_actions] = name;
+
+ s->params.action_is_for_table_entries = new_action_is_for_table_entries;
+ s->params.action_is_for_table_entries[s->params.n_actions] = action_is_for_table_entries;
+
+ s->params.action_is_for_default_entry = new_action_is_for_default_entry;
+ s->params.action_is_for_default_entry[s->params.n_actions] = action_is_for_default_entry;
+
s->params.n_actions++;
return 0;