pipeline: improve handling of learner action arguments
The arguments of actions that are learned are now specified as part of the learn instruction as opposed to being statically specified as part of the learner table configuration. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
1c6571c837
commit
175d213bf8
@ -84,7 +84,7 @@ action learn_action args none {
|
||||
// Add the current lookup key to the table with fwd_action as the key action. The action
|
||||
// arguments are read from the packet meta-data (the m.fwd_action_arg_port_out field). These
|
||||
// packet meta-data fields have to be written before the "learn" instruction is invoked.
|
||||
learn fwd_action
|
||||
learn fwd_action m.fwd_action_arg_port_out
|
||||
|
||||
// Send the current packet to the same output port.
|
||||
mov m.port_out m.fwd_action_arg_port_out
|
||||
@ -101,9 +101,9 @@ learner fwd_table {
|
||||
}
|
||||
|
||||
actions {
|
||||
fwd_action args m.fwd_action_arg_port_out
|
||||
fwd_action
|
||||
|
||||
learn_action args none
|
||||
learn_action
|
||||
}
|
||||
|
||||
default_action learn_action args none
|
||||
|
@ -2359,6 +2359,9 @@ action_find(struct rte_swx_pipeline *p, const char *name);
|
||||
static int
|
||||
action_has_nbo_args(struct action *a);
|
||||
|
||||
static int
|
||||
learner_action_args_check(struct rte_swx_pipeline *p, struct action *a, const char *mf_name);
|
||||
|
||||
static int
|
||||
instr_learn_translate(struct rte_swx_pipeline *p,
|
||||
struct action *action,
|
||||
@ -2368,16 +2371,31 @@ instr_learn_translate(struct rte_swx_pipeline *p,
|
||||
struct instruction_data *data __rte_unused)
|
||||
{
|
||||
struct action *a;
|
||||
const char *mf_name;
|
||||
uint32_t mf_offset = 0;
|
||||
|
||||
CHECK(action, EINVAL);
|
||||
CHECK(n_tokens == 2, EINVAL);
|
||||
CHECK((n_tokens == 2) || (n_tokens == 3), EINVAL);
|
||||
|
||||
a = action_find(p, tokens[1]);
|
||||
CHECK(a, EINVAL);
|
||||
CHECK(!action_has_nbo_args(a), EINVAL);
|
||||
|
||||
mf_name = (n_tokens > 2) ? tokens[2] : NULL;
|
||||
CHECK(!learner_action_args_check(p, a, mf_name), EINVAL);
|
||||
|
||||
if (mf_name) {
|
||||
struct field *mf;
|
||||
|
||||
mf = metadata_field_parse(p, mf_name);
|
||||
CHECK(mf, EINVAL);
|
||||
|
||||
mf_offset = mf->offset / 8;
|
||||
}
|
||||
|
||||
instr->type = INSTR_LEARNER_LEARN;
|
||||
instr->learn.action_id = a->id;
|
||||
instr->learn.mf_offset = mf_offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -8165,7 +8183,6 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
CHECK(params->action_names, EINVAL);
|
||||
for (i = 0; i < params->n_actions; i++) {
|
||||
const char *action_name = params->action_names[i];
|
||||
const char *action_field_name = params->action_field_names[i];
|
||||
struct action *a;
|
||||
uint32_t action_data_size;
|
||||
|
||||
@ -8174,10 +8191,6 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
a = action_find(p, action_name);
|
||||
CHECK(a, EINVAL);
|
||||
|
||||
status = learner_action_args_check(p, a, action_field_name);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = learner_action_learning_check(p,
|
||||
a,
|
||||
params->action_names,
|
||||
@ -8218,10 +8231,6 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
if (!l->actions)
|
||||
goto nomem;
|
||||
|
||||
l->action_arg = calloc(params->n_actions, sizeof(struct field *));
|
||||
if (!l->action_arg)
|
||||
goto nomem;
|
||||
|
||||
if (action_data_size_max) {
|
||||
l->default_action_data = calloc(1, action_data_size_max);
|
||||
if (!l->default_action_data)
|
||||
@ -8243,14 +8252,9 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
|
||||
l->header = header;
|
||||
|
||||
for (i = 0; i < params->n_actions; i++) {
|
||||
const char *mf_name = params->action_field_names[i];
|
||||
|
||||
for (i = 0; i < params->n_actions; i++)
|
||||
l->actions[i] = action_find(p, params->action_names[i]);
|
||||
|
||||
l->action_arg[i] = mf_name ? metadata_field_parse(p, mf_name) : NULL;
|
||||
}
|
||||
|
||||
l->default_action = default_action;
|
||||
|
||||
if (default_action->st)
|
||||
@ -8280,7 +8284,6 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p,
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
free(l->action_arg);
|
||||
free(l->actions);
|
||||
free(l->fields);
|
||||
free(l);
|
||||
@ -8375,7 +8378,6 @@ learner_build_free(struct rte_swx_pipeline *p)
|
||||
struct learner_runtime *r = &t->learners[j];
|
||||
|
||||
free(r->mailbox);
|
||||
free(r->action_data);
|
||||
}
|
||||
|
||||
free(t->learners);
|
||||
@ -8419,7 +8421,6 @@ learner_build(struct rte_swx_pipeline *p)
|
||||
TAILQ_FOREACH(l, &p->learners, node) {
|
||||
struct learner_runtime *r = &t->learners[l->id];
|
||||
uint64_t size;
|
||||
uint32_t j;
|
||||
|
||||
/* r->mailbox. */
|
||||
size = rte_swx_table_learner_mailbox_size_get();
|
||||
@ -8435,21 +8436,6 @@ learner_build(struct rte_swx_pipeline *p)
|
||||
r->key = l->header ?
|
||||
&t->structs[l->header->struct_id] :
|
||||
&t->structs[p->metadata_struct_id];
|
||||
|
||||
/* r->action_data. */
|
||||
r->action_data = calloc(p->n_actions, sizeof(uint8_t *));
|
||||
if (!r->action_data) {
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (j = 0; j < l->n_actions; j++) {
|
||||
struct action *a = l->actions[j];
|
||||
struct field *mf = l->action_arg[j];
|
||||
uint8_t *m = t->structs[p->metadata_struct_id];
|
||||
|
||||
r->action_data[a->id] = mf ? &m[mf->offset / 8] : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8476,7 +8462,6 @@ learner_free(struct rte_swx_pipeline *p)
|
||||
TAILQ_REMOVE(&p->learners, l, node);
|
||||
free(l->fields);
|
||||
free(l->actions);
|
||||
free(l->action_arg);
|
||||
free(l->default_action_data);
|
||||
free(l);
|
||||
}
|
||||
|
@ -696,16 +696,6 @@ struct rte_swx_pipeline_learner_params {
|
||||
*/
|
||||
uint32_t n_actions;
|
||||
|
||||
/** This table type allows adding the latest lookup key (typically done
|
||||
* only in the case of lookup miss) to the table with a given action.
|
||||
* The action arguments are picked up from the packet meta-data: for
|
||||
* each action, a set of successive meta-data fields (with the name of
|
||||
* the first such field provided here) is 1:1 mapped to the action
|
||||
* arguments. These meta-data fields must be set with the actual values
|
||||
* of the action arguments before the key add operation.
|
||||
*/
|
||||
const char **action_field_names;
|
||||
|
||||
/** The default table action that gets executed on lookup miss. Must be
|
||||
* one of the table actions included in the *action_names*.
|
||||
*/
|
||||
|
@ -448,7 +448,7 @@ enum instruction_type {
|
||||
INSTR_LEARNER,
|
||||
INSTR_LEARNER_AF,
|
||||
|
||||
/* learn LEARNER ACTION_NAME */
|
||||
/* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
|
||||
INSTR_LEARNER_LEARN,
|
||||
|
||||
/* forget */
|
||||
@ -583,6 +583,7 @@ struct instr_table {
|
||||
|
||||
struct instr_learn {
|
||||
uint8_t action_id;
|
||||
uint8_t mf_offset;
|
||||
};
|
||||
|
||||
struct instr_extern_obj {
|
||||
@ -809,7 +810,6 @@ struct learner {
|
||||
|
||||
/* Action. */
|
||||
struct action **actions;
|
||||
struct field **action_arg;
|
||||
struct action *default_action;
|
||||
uint8_t *default_action_data;
|
||||
uint32_t n_actions;
|
||||
@ -826,7 +826,6 @@ TAILQ_HEAD(learner_tailq, learner);
|
||||
struct learner_runtime {
|
||||
void *mailbox;
|
||||
uint8_t **key;
|
||||
uint8_t **action_data;
|
||||
};
|
||||
|
||||
struct learner_statistics {
|
||||
@ -2017,6 +2016,7 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
|
||||
const struct instruction *ip)
|
||||
{
|
||||
uint64_t action_id = ip->learn.action_id;
|
||||
uint32_t mf_offset = ip->learn.mf_offset;
|
||||
uint32_t learner_id = t->learner_id;
|
||||
struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
|
||||
p->n_selectors + learner_id];
|
||||
@ -2029,7 +2029,7 @@ __instr_learn_exec(struct rte_swx_pipeline *p,
|
||||
l->mailbox,
|
||||
t->time,
|
||||
action_id,
|
||||
l->action_data[action_id]);
|
||||
&t->metadata[mf_offset]);
|
||||
|
||||
TRACE("[Thread %2u] learner %u learn %s\n",
|
||||
p->thread_id,
|
||||
|
@ -1293,7 +1293,7 @@ selector_block_parse(struct selector_spec *s,
|
||||
* ...
|
||||
* }
|
||||
* actions {
|
||||
* ACTION_NAME args METADATA_FIELD_NAME
|
||||
* ACTION_NAME
|
||||
* ...
|
||||
* }
|
||||
* default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
|
||||
@ -1340,15 +1340,6 @@ learner_spec_free(struct learner_spec *s)
|
||||
free(s->params.action_names);
|
||||
s->params.action_names = NULL;
|
||||
|
||||
for (i = 0; i < s->params.n_actions; i++) {
|
||||
uintptr_t name = (uintptr_t)s->params.action_field_names[i];
|
||||
|
||||
free((void *)name);
|
||||
}
|
||||
|
||||
free(s->params.action_field_names);
|
||||
s->params.action_field_names = NULL;
|
||||
|
||||
s->params.n_actions = 0;
|
||||
|
||||
default_action_name = (uintptr_t)s->params.default_action_name;
|
||||
@ -1468,9 +1459,7 @@ learner_actions_block_parse(struct learner_spec *s,
|
||||
const char **err_msg)
|
||||
{
|
||||
const char **new_action_names = NULL;
|
||||
const char **new_action_field_names = NULL;
|
||||
char *action_name = NULL, *action_field_name = NULL;
|
||||
int has_args = 1;
|
||||
char *action_name = NULL;
|
||||
|
||||
/* Handle end of block. */
|
||||
if ((n_tokens == 1) && !strcmp(tokens[0], "}")) {
|
||||
@ -1479,7 +1468,7 @@ learner_actions_block_parse(struct learner_spec *s,
|
||||
}
|
||||
|
||||
/* Check input arguments. */
|
||||
if ((n_tokens != 3) || strcmp(tokens[1], "args")) {
|
||||
if (n_tokens != 1) {
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
if (err_msg)
|
||||
@ -1487,28 +1476,14 @@ learner_actions_block_parse(struct learner_spec *s,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strcmp(tokens[2], "none"))
|
||||
has_args = 0;
|
||||
|
||||
action_name = strdup(tokens[0]);
|
||||
|
||||
if (has_args)
|
||||
action_field_name = strdup(tokens[2]);
|
||||
|
||||
new_action_names = realloc(s->params.action_names,
|
||||
(s->params.n_actions + 1) * sizeof(char *));
|
||||
|
||||
new_action_field_names = realloc(s->params.action_field_names,
|
||||
(s->params.n_actions + 1) * sizeof(char *));
|
||||
|
||||
if (!action_name ||
|
||||
(has_args && !action_field_name) ||
|
||||
!new_action_names ||
|
||||
!new_action_field_names) {
|
||||
if (!action_name || !new_action_names) {
|
||||
free(action_name);
|
||||
free(action_field_name);
|
||||
free(new_action_names);
|
||||
free(new_action_field_names);
|
||||
|
||||
if (err_line)
|
||||
*err_line = n_lines;
|
||||
@ -1519,8 +1494,6 @@ learner_actions_block_parse(struct learner_spec *s,
|
||||
|
||||
s->params.action_names = new_action_names;
|
||||
s->params.action_names[s->params.n_actions] = action_name;
|
||||
s->params.action_field_names = new_action_field_names;
|
||||
s->params.action_field_names[s->params.n_actions] = action_field_name;
|
||||
s->params.n_actions++;
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user