From: Yogesh Jangra <yogesh.jangra@intel.com>
To: dev@dpdk.org
Cc: cristian.dumitrescu@intel.com, venkata.suresh.kumar.p@intel.com,
yogesh.jangra@intel.com
Subject: [dpdk-dev] [PATCH] pipeline: add support for action annotations
Date: Thu, 14 Oct 2021 07:09:03 -0400 [thread overview]
Message-ID: <1634209743-93477-1-git-send-email-yogesh.jangra@intel.com> (raw)
Enable restricting the scope of an action to regular table entries or
to the table default entry in order to support the P4 language
tableonly or defaultonly annotations.
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
lib/pipeline/rte_swx_ctl.c | 6 ++
lib/pipeline/rte_swx_ctl.h | 6 ++
lib/pipeline/rte_swx_pipeline.c | 105 +++++++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline.h | 28 +++++++++
lib/pipeline/rte_swx_pipeline_internal.h | 4 ++
lib/pipeline/rte_swx_pipeline_spec.c | 101 +++++++++++++++++++++++------
6 files changed, 212 insertions(+), 38 deletions(-)
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 86b58e2..1c908e3 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -1446,6 +1446,8 @@ struct rte_swx_ctl_pipeline *
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);
@@ -1651,6 +1653,8 @@ struct rte_swx_ctl_pipeline *
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);
@@ -2378,6 +2382,8 @@ struct rte_swx_ctl_pipeline *
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);
diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h
index 8075972..46d0582 100644
--- a/lib/pipeline/rte_swx_ctl.h
+++ b/lib/pipeline/rte_swx_ctl.h
@@ -301,6 +301,12 @@ struct rte_swx_ctl_table_match_field_info {
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;
};
/**
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 1cd09a4..f96d6ba 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -7309,7 +7309,7 @@ struct_field_parse(struct rte_swx_pipeline *p,
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;
@@ -7336,6 +7336,7 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -7346,6 +7347,12 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -7354,6 +7361,9 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -7380,28 +7390,27 @@ struct_field_parse(struct rte_swx_pipeline *p,
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])
@@ -7420,8 +7429,18 @@ struct_field_parse(struct rte_swx_pipeline *p,
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,
@@ -7439,6 +7458,19 @@ struct_field_parse(struct rte_swx_pipeline *p,
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 *
@@ -8179,12 +8211,12 @@ struct_field_parse(struct rte_swx_pipeline *p,
/* 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);
@@ -8201,6 +8233,12 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -8209,6 +8247,8 @@ struct_field_parse(struct rte_swx_pipeline *p,
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) ||
@@ -8237,6 +8277,14 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -8252,8 +8300,18 @@ struct_field_parse(struct rte_swx_pipeline *p,
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;
@@ -8284,6 +8342,9 @@ struct_field_parse(struct rte_swx_pipeline *p,
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);
@@ -9277,6 +9338,9 @@ struct meter_profile meter_profile_default = {
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;
}
@@ -9464,6 +9528,9 @@ struct meter_profile meter_profile_default = {
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;
}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 490ff60..9c3d081 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -567,6 +567,20 @@ struct rte_swx_pipeline_table_params {
/** 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;
@@ -692,6 +706,20 @@ struct rte_swx_pipeline_learner_params {
/** 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;
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index 4361c53..1921fdc 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -746,6 +746,8 @@ struct table {
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;
@@ -815,6 +817,8 @@ struct learner {
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;
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5c21a7a..8e9aa44 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -539,7 +539,7 @@ struct action_spec {
* ...
* }
* actions {
- * ACTION_NAME
+ * ACTION_NAME [ @tableonly | @defaultonly ]
* ...
* }
* default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
@@ -597,6 +597,12 @@ struct table_spec {
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);
@@ -730,8 +736,10 @@ struct table_spec {
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], "}")) {
@@ -740,7 +748,9 @@ struct table_spec {
}
/* 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)
@@ -749,18 +759,30 @@ struct table_spec {
}
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;
@@ -771,6 +793,13 @@ struct table_spec {
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;
@@ -1293,7 +1322,7 @@ struct selector_spec {
* ...
* }
* actions {
- * ACTION_NAME
+ * ACTION_NAME [ @tableonly | @defaultonly]
* ...
* }
* default_action ACTION_NAME args none | ARGS_BYTE_ARRAY [ const ]
@@ -1349,6 +1378,12 @@ struct learner_spec {
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;
@@ -1459,7 +1494,9 @@ struct learner_spec {
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], "}")) {
@@ -1468,7 +1505,9 @@ struct learner_spec {
}
/* 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)
@@ -1476,14 +1515,31 @@ struct learner_spec {
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;
@@ -1493,7 +1549,14 @@ struct learner_spec {
}
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;
--
1.8.3.1
next reply other threads:[~2021-10-14 18:21 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-14 11:09 Yogesh Jangra [this message]
2021-10-18 1:22 ` [dpdk-dev] [PATCH v2] " Yogesh Jangra
2021-10-25 12:54 ` Thomas Monjalon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1634209743-93477-1-git-send-email-yogesh.jangra@intel.com \
--to=yogesh.jangra@intel.com \
--cc=cristian.dumitrescu@intel.com \
--cc=dev@dpdk.org \
--cc=venkata.suresh.kumar.p@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).