* [PATCH 1/9] pipeline: move specification data structures to internal header
@ 2022-07-18 13:07 Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
` (9 more replies)
0 siblings, 10 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Move all the pipeline object specification data structures to an
internal header file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 126 +------------------
lib/pipeline/rte_swx_pipeline_spec.h | 176 +++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 125 deletions(-)
create mode 100644 lib/pipeline/rte_swx_pipeline_spec.h
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 904b9eb471..5e07b4f794 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,7 +9,7 @@
#include <rte_common.h>
-#include "rte_swx_pipeline.h"
+#include "rte_swx_pipeline_spec.h"
#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 2048
@@ -34,15 +34,7 @@
/*
* extobj.
- *
- * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
*/
-struct extobj_spec {
- char *name;
- char *extern_type_name;
- char *pragma;
-};
-
static void
extobj_spec_free(struct extobj_spec *s)
{
@@ -104,18 +96,7 @@ extobj_statement_parse(struct extobj_spec *s,
/*
* struct.
*
- * struct STRUCT_TYPE_NAME {
- * bit<SIZE> | varbit<SIZE> FIELD_NAME
- * ...
- * }
*/
-struct struct_spec {
- char *name;
- struct rte_swx_field_params *fields;
- uint32_t n_fields;
- int varbit;
-};
-
static void
struct_spec_free(struct struct_spec *s)
{
@@ -293,13 +274,7 @@ struct_block_parse(struct struct_spec *s,
/*
* header.
*
- * header HEADER_NAME instanceof STRUCT_TYPE_NAME
*/
-struct header_spec {
- char *name;
- char *struct_type_name;
-};
-
static void
header_spec_free(struct header_spec *s)
{
@@ -351,12 +326,7 @@ header_statement_parse(struct header_spec *s,
/*
* metadata.
*
- * metadata instanceof STRUCT_TYPE_NAME
*/
-struct metadata_spec {
- char *struct_type_name;
-};
-
static void
metadata_spec_free(struct metadata_spec *s)
{
@@ -400,18 +370,7 @@ metadata_statement_parse(struct metadata_spec *s,
/*
* action.
*
- * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
- * INSTRUCTION
- * ...
- * }
*/
-struct action_spec {
- char *name;
- char *args_struct_type_name;
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
action_spec_free(struct action_spec *s)
{
@@ -540,29 +499,7 @@ action_block_parse(struct action_spec *s,
/*
* table.
*
- * table TABLE_NAME {
- * key {
- * MATCH_FIELD_NAME exact | wildcard | lpm
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly ]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * instanceof TABLE_TYPE_NAME
- * pragma ARGS
- * size SIZE
- * }
*/
-struct table_spec {
- char *name;
- struct rte_swx_pipeline_table_params params;
- char *recommended_table_type_name;
- char *args;
- uint32_t size;
-};
-
static void
table_spec_free(struct table_spec *s)
{
@@ -1084,22 +1021,7 @@ table_block_parse(struct table_spec *s,
/*
* selector.
*
- * selector SELECTOR_NAME {
- * group_id FIELD_NAME
- * selector {
- * FIELD_NAME
- * ...
- * }
- * member_id FIELD_NAME
- * n_groups N_GROUPS
- * n_members_per_group N_MEMBERS_PER_GROUP
- * }
*/
-struct selector_spec {
- char *name;
- struct rte_swx_pipeline_selector_params params;
-};
-
static void
selector_spec_free(struct selector_spec *s)
{
@@ -1385,31 +1307,7 @@ selector_block_parse(struct selector_spec *s,
/*
* learner.
*
- * learner LEARNER_NAME {
- * key {
- * MATCH_FIELD_NAME
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * size SIZE
- * timeout {
- * TIMEOUT_IN_SECONDS
- * ...
- * }
- * }
*/
-struct learner_spec {
- char *name;
- struct rte_swx_pipeline_learner_params params;
- uint32_t size;
- uint32_t *timeout;
- uint32_t n_timeouts;
-};
-
static void
learner_spec_free(struct learner_spec *s)
{
@@ -1958,14 +1856,7 @@ learner_block_parse(struct learner_spec *s,
/*
* regarray.
*
- * regarray NAME size SIZE initval INITVAL
*/
-struct regarray_spec {
- char *name;
- uint64_t init_val;
- uint32_t size;
-};
-
static void
regarray_spec_free(struct regarray_spec *s)
{
@@ -2033,13 +1924,7 @@ regarray_statement_parse(struct regarray_spec *s,
/*
* metarray.
*
- * metarray NAME size SIZE
*/
-struct metarray_spec {
- char *name;
- uint32_t size;
-};
-
static void
metarray_spec_free(struct metarray_spec *s)
{
@@ -2095,16 +1980,7 @@ metarray_statement_parse(struct metarray_spec *s,
/*
* apply.
*
- * apply {
- * INSTRUCTION
- * ...
- * }
*/
-struct apply_spec {
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
apply_spec_free(struct apply_spec *s)
{
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
new file mode 100644
index 0000000000..8458de878a
--- /dev/null
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+
+#include <rte_swx_pipeline.h>
+
+/*
+ * extobj.
+ *
+ * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
+ */
+struct extobj_spec {
+ char *name;
+ char *extern_type_name;
+ char *pragma;
+};
+
+/*
+ * struct.
+ *
+ * struct STRUCT_TYPE_NAME {
+ * bit<SIZE> | varbit<SIZE> FIELD_NAME
+ * ...
+ * }
+ */
+struct struct_spec {
+ char *name;
+ struct rte_swx_field_params *fields;
+ uint32_t n_fields;
+ int varbit;
+};
+
+/*
+ * header.
+ *
+ * header HEADER_NAME instanceof STRUCT_TYPE_NAME
+ */
+struct header_spec {
+ char *name;
+ char *struct_type_name;
+};
+
+/*
+ * metadata.
+ *
+ * metadata instanceof STRUCT_TYPE_NAME
+ */
+struct metadata_spec {
+ char *struct_type_name;
+};
+
+/*
+ * action.
+ *
+ * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct action_spec {
+ char *name;
+ char *args_struct_type_name;
+ const char **instructions;
+ uint32_t n_instructions;
+};
+
+/*
+ * table.
+ *
+ * table TABLE_NAME {
+ * key {
+ * MATCH_FIELD_NAME exact | wildcard | lpm
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly ]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * instanceof TABLE_TYPE_NAME
+ * pragma ARGS
+ * size SIZE
+ * }
+ */
+struct table_spec {
+ char *name;
+ struct rte_swx_pipeline_table_params params;
+ char *recommended_table_type_name;
+ char *args;
+ uint32_t size;
+};
+
+/*
+ * selector.
+ *
+ * selector SELECTOR_NAME {
+ * group_id FIELD_NAME
+ * selector {
+ * FIELD_NAME
+ * ...
+ * }
+ * member_id FIELD_NAME
+ * n_groups N_GROUPS
+ * n_members_per_group N_MEMBERS_PER_GROUP
+ * }
+ */
+struct selector_spec {
+ char *name;
+ struct rte_swx_pipeline_selector_params params;
+};
+
+/*
+ * learner.
+ *
+ * learner LEARNER_NAME {
+ * key {
+ * MATCH_FIELD_NAME
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * size SIZE
+ * timeout {
+ * TIMEOUT_IN_SECONDS
+ * ...
+ * }
+ * }
+ */
+struct learner_spec {
+ char *name;
+ struct rte_swx_pipeline_learner_params params;
+ uint32_t size;
+ uint32_t *timeout;
+ uint32_t n_timeouts;
+};
+
+/*
+ * regarray.
+ *
+ * regarray NAME size SIZE initval INITVAL
+ */
+struct regarray_spec {
+ char *name;
+ uint64_t init_val;
+ uint32_t size;
+};
+
+/*
+ * metarray.
+ *
+ * metarray NAME size SIZE
+ */
+struct metarray_spec {
+ char *name;
+ uint32_t size;
+};
+
+/*
+ * apply.
+ *
+ * apply {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct apply_spec {
+ const char **instructions;
+ uint32_t n_instructions;
+};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 2/9] pipeline: add pipeline specification data structure
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 3/9] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
` (8 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure for the entire pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 21 ++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 32 ++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5e07b4f794..642091b678 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2082,6 +2082,27 @@ apply_block_parse(struct apply_spec *s,
/*
* Pipeline.
*/
+void
+pipeline_spec_free(struct pipeline_spec *s)
+{
+ if (!s)
+ return;
+
+ free(s->extobjs);
+ free(s->structs);
+ free(s->headers);
+ free(s->metadata);
+ free(s->actions);
+ free(s->tables);
+ free(s->selectors);
+ free(s->learners);
+ free(s->regarrays);
+ free(s->metarrays);
+ free(s->apply);
+
+ memset(s, 0, sizeof(struct pipeline_spec));
+}
+
int
rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
FILE *spec,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 8458de878a..e1170a33b1 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -174,3 +174,35 @@ struct apply_spec {
const char **instructions;
uint32_t n_instructions;
};
+
+/*
+ * Pipeline.
+ */
+struct pipeline_spec {
+ struct extobj_spec *extobjs;
+ struct struct_spec *structs;
+ struct header_spec *headers;
+ struct metadata_spec *metadata;
+ struct action_spec *actions;
+ struct table_spec *tables;
+ struct selector_spec *selectors;
+ struct learner_spec *learners;
+ struct regarray_spec *regarrays;
+ struct metarray_spec *metarrays;
+ struct apply_spec *apply;
+
+ uint32_t n_extobjs;
+ uint32_t n_structs;
+ uint32_t n_headers;
+ uint32_t n_metadata;
+ uint32_t n_actions;
+ uint32_t n_tables;
+ uint32_t n_selectors;
+ uint32_t n_learners;
+ uint32_t n_regarrays;
+ uint32_t n_metarrays;
+ uint32_t n_apply;
+};
+
+void
+pipeline_spec_free(struct pipeline_spec *s);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 3/9] pipeline: rework the specification file-based pipeline build
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 4/9] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
` (7 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the specification file-based pipeline build operation to first
parse the specification file into the previously introduced pipeline
specification data structure, then use this structure to configure
and build the pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 478 +++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline_spec.h | 9 +
2 files changed, 385 insertions(+), 102 deletions(-)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 642091b678..cbbcef852b 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2103,11 +2103,10 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg)
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
{
struct extobj_spec extobj_spec = {0};
struct struct_spec struct_spec = {0};
@@ -2120,26 +2119,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0};
- uint32_t n_lines;
+ struct pipeline_spec *s = NULL;
+ uint32_t n_lines = 0;
uint32_t block_mask = 0;
- int status;
+ int status = 0;
/* Check the input arguments. */
- if (!p) {
+ if (!spec) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null pipeline argument.";
+ *err_msg = "Invalid input argument.";
status = -EINVAL;
goto error;
}
- if (!spec) {
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_spec), 1);
+ if (!s) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null specification file argument.";
- status = -EINVAL;
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
@@ -2200,6 +2202,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* struct block. */
if (block_mask & (1 << STRUCT_BLOCK)) {
+ struct struct_spec *new_structs;
+
status = struct_block_parse(&struct_spec,
&block_mask,
tokens,
@@ -2214,26 +2218,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_struct_type_register(p,
- struct_spec.name,
- struct_spec.fields,
- struct_spec.n_fields,
- struct_spec.varbit);
- if (status) {
+ new_structs = realloc(s->structs,
+ (s->n_structs + 1) * sizeof(struct struct_spec));
+ if (!new_structs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Struct registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- struct_spec_free(&struct_spec);
+ s->structs = new_structs;
+ memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
+ s->n_structs++;
+ memset(&struct_spec, 0, sizeof(struct struct_spec));
continue;
}
/* action block. */
if (block_mask & (1 << ACTION_BLOCK)) {
+ struct action_spec *new_actions;
+
status = action_block_parse(&action_spec,
&block_mask,
tokens,
@@ -2248,26 +2255,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_action_config(p,
- action_spec.name,
- action_spec.args_struct_type_name,
- action_spec.instructions,
- action_spec.n_instructions);
- if (status) {
+ new_actions = realloc(s->actions,
+ (s->n_actions + 1) * sizeof(struct action_spec));
+ if (!new_actions) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Action config error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- action_spec_free(&action_spec);
+ s->actions = new_actions;
+ memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
+ s->n_actions++;
+ memset(&action_spec, 0, sizeof(struct action_spec));
continue;
}
/* table block. */
if (block_mask & (1 << TABLE_BLOCK)) {
+ struct table_spec *new_tables;
+
status = table_block_parse(&table_spec,
&block_mask,
tokens,
@@ -2282,27 +2292,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_table_config(p,
- table_spec.name,
- &table_spec.params,
- table_spec.recommended_table_type_name,
- table_spec.args,
- table_spec.size);
- if (status) {
+ new_tables = realloc(s->tables,
+ (s->n_tables + 1) * sizeof(struct table_spec));
+ if (!new_tables) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- table_spec_free(&table_spec);
+ s->tables = new_tables;
+ memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
+ s->n_tables++;
+ memset(&table_spec, 0, sizeof(struct table_spec));
continue;
}
/* selector block. */
if (block_mask & (1 << SELECTOR_BLOCK)) {
+ struct selector_spec *new_selectors;
+
status = selector_block_parse(&selector_spec,
&block_mask,
tokens,
@@ -2317,24 +2329,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_selector_config(p,
- selector_spec.name,
- &selector_spec.params);
- if (status) {
+ new_selectors = realloc(s->selectors,
+ (s->n_selectors + 1) * sizeof(struct selector_spec));
+ if (!new_selectors) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Selector configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- selector_spec_free(&selector_spec);
+ s->selectors = new_selectors;
+ memcpy(&s->selectors[s->n_selectors],
+ &selector_spec,
+ sizeof(struct selector_spec));
+ s->n_selectors++;
+ memset(&selector_spec, 0, sizeof(struct selector_spec));
continue;
}
/* learner block. */
if (block_mask & (1 << LEARNER_BLOCK)) {
+ struct learner_spec *new_learners;
+
status = learner_block_parse(&learner_spec,
&block_mask,
tokens,
@@ -2349,27 +2368,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_learner_config(p,
- learner_spec.name,
- &learner_spec.params,
- learner_spec.size,
- learner_spec.timeout,
- learner_spec.n_timeouts);
- if (status) {
+ new_learners = realloc(s->learners,
+ (s->n_learners + 1) * sizeof(struct learner_spec));
+ if (!new_learners) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Learner table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- learner_spec_free(&learner_spec);
+ s->learners = new_learners;
+ memcpy(&s->learners[s->n_learners],
+ &learner_spec,
+ sizeof(struct learner_spec));
+ s->n_learners++;
+ memset(&learner_spec, 0, sizeof(struct learner_spec));
continue;
}
/* apply block. */
if (block_mask & (1 << APPLY_BLOCK)) {
+ struct apply_spec *new_apply;
+
status = apply_block_parse(&apply_spec,
&block_mask,
tokens,
@@ -2384,24 +2407,28 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_instructions_config(p,
- apply_spec.instructions,
- apply_spec.n_instructions);
- if (status) {
+ new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
+ if (!new_apply) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Pipeline instructions err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- apply_spec_free(&apply_spec);
+ s->apply = new_apply;
+ memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
+ s->n_apply++;
+ memset(&apply_spec, 0, sizeof(struct apply_spec));
continue;
}
/* extobj. */
if (!strcmp(tokens[0], "extobj")) {
+ struct extobj_spec *new_extobjs;
+
status = extobj_statement_parse(&extobj_spec,
tokens,
n_tokens,
@@ -2411,19 +2438,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_extern_object_config(p,
- extobj_spec.name,
- extobj_spec.extern_type_name,
- extobj_spec.pragma);
- if (status) {
+ new_extobjs = realloc(s->extobjs,
+ (s->n_extobjs + 1) * sizeof(struct extobj_spec));
+ if (!new_extobjs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Extern object config err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- extobj_spec_free(&extobj_spec);
+ s->extobjs = new_extobjs;
+ memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
+ s->n_extobjs++;
+ memset(&extobj_spec, 0, sizeof(struct extobj_spec));
continue;
}
@@ -2445,6 +2474,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* header. */
if (!strcmp(tokens[0], "header")) {
+ struct header_spec *new_headers;
+
status = header_statement_parse(&header_spec,
tokens,
n_tokens,
@@ -2454,24 +2485,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_header_register(p,
- header_spec.name,
- header_spec.struct_type_name);
- if (status) {
+ new_headers = realloc(s->headers,
+ (s->n_headers + 1) * sizeof(struct header_spec));
+ if (!new_headers) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Header registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- header_spec_free(&header_spec);
+ s->headers = new_headers;
+ memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
+ s->n_headers++;
+ memset(&header_spec, 0, sizeof(struct header_spec));
continue;
}
/* metadata. */
if (!strcmp(tokens[0], "metadata")) {
+ struct metadata_spec *new_metadata;
+
status = metadata_statement_parse(&metadata_spec,
tokens,
n_tokens,
@@ -2481,17 +2517,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_metadata_register(p,
- metadata_spec.struct_type_name);
- if (status) {
+ new_metadata = realloc(s->metadata,
+ (s->n_metadata + 1) * sizeof(struct metadata_spec));
+ if (!new_metadata) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meta-data reg err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metadata_spec_free(&metadata_spec);
+ s->metadata = new_metadata;
+ memcpy(&s->metadata[s->n_metadata],
+ &metadata_spec,
+ sizeof(struct metadata_spec));
+ s->n_metadata++;
+ memset(&metadata_spec, 0, sizeof(struct metadata_spec));
continue;
}
@@ -2558,6 +2600,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* regarray. */
if (!strcmp(tokens[0], "regarray")) {
+ struct regarray_spec *new_regarrays;
+
status = regarray_statement_parse(®array_spec,
tokens,
n_tokens,
@@ -2567,25 +2611,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_regarray_config(p,
- regarray_spec.name,
- regarray_spec.size,
- regarray_spec.init_val);
- if (status) {
+ new_regarrays = realloc(s->regarrays,
+ (s->n_regarrays + 1) * sizeof(struct regarray_spec));
+ if (!new_regarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Register array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- regarray_spec_free(®array_spec);
+ s->regarrays = new_regarrays;
+ memcpy(&s->regarrays[s->n_regarrays],
+ ®array_spec,
+ sizeof(struct regarray_spec));
+ s->n_regarrays++;
+ memset(®array_spec, 0, sizeof(struct regarray_spec));
continue;
}
/* metarray. */
if (!strcmp(tokens[0], "metarray")) {
+ struct metarray_spec *new_metarrays;
+
status = metarray_statement_parse(&metarray_spec,
tokens,
n_tokens,
@@ -2595,18 +2645,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_metarray_config(p,
- metarray_spec.name,
- metarray_spec.size);
- if (status) {
+ new_metarrays = realloc(s->metarrays,
+ (s->n_metarrays + 1) * sizeof(struct metarray_spec));
+ if (!new_metarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meter array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metarray_spec_free(&metarray_spec);
+ s->metarrays = new_metarrays;
+ memcpy(&s->metarrays[s->n_metarrays],
+ &metarray_spec,
+ sizeof(struct metarray_spec));
+ s->n_metarrays++;
+ memset(&metarray_spec, 0, sizeof(struct metarray_spec));
continue;
}
@@ -2644,17 +2699,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
goto error;
}
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
+ return s;
error:
extobj_spec_free(&extobj_spec);
@@ -2668,5 +2713,234 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
regarray_spec_free(®array_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec);
+ pipeline_spec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* extobj. */
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ status = rte_swx_pipeline_extern_object_config(p,
+ extobj_spec->name,
+ extobj_spec->extern_type_name,
+ extobj_spec->pragma);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Extern object configuration error.";
+ return status;
+ }
+ }
+
+ /* regarray. */
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ status = rte_swx_pipeline_regarray_config(p,
+ regarray_spec->name,
+ regarray_spec->size,
+ regarray_spec->init_val);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Register array configuration error.";
+ return status;
+ }
+ }
+
+ /* metarray. */
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ status = rte_swx_pipeline_metarray_config(p,
+ metarray_spec->name,
+ metarray_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meter array configuration error.";
+ return status;
+ }
+ }
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ status = rte_swx_pipeline_struct_type_register(p,
+ struct_spec->name,
+ struct_spec->fields,
+ struct_spec->n_fields,
+ struct_spec->varbit);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Struct type registration error.";
+ return status;
+ }
+ }
+
+ /* header. */
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ status = rte_swx_pipeline_packet_header_register(p,
+ header_spec->name,
+ header_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Header configuration error.";
+ return status;
+ }
+ }
+
+ /* metadata. */
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ status = rte_swx_pipeline_packet_metadata_register(p,
+ metadata_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meta-data registration error.";
+ return status;
+ }
+ }
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ status = rte_swx_pipeline_action_config(p,
+ action_spec->name,
+ action_spec->args_struct_type_name,
+ action_spec->instructions,
+ action_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Action configuration error.";
+ return status;
+ }
+ }
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ status = rte_swx_pipeline_table_config(p,
+ table_spec->name,
+ &table_spec->params,
+ table_spec->recommended_table_type_name,
+ table_spec->args,
+ table_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Table configuration error.";
+ return status;
+ }
+ }
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ status = rte_swx_pipeline_selector_config(p,
+ selector_spec->name,
+ &selector_spec->params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Selector table configuration error.";
+ return status;
+ }
+ }
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ status = rte_swx_pipeline_learner_config(p,
+ learner_spec->name,
+ &learner_spec->params,
+ learner_spec->size,
+ learner_spec->timeout,
+ learner_spec->n_timeouts);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Learner table configuration error.";
+ return status;
+ }
+ }
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+
+ status = rte_swx_pipeline_instructions_config(p,
+ apply_spec->instructions,
+ apply_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline instructions configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
+ FILE *spec_file,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_spec *s = NULL;
+ int status = 0;
+
+ /* Check the input arguments. */
+ if (!p || !spec_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Spec file parse. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Pipeline configure. */
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto error;
+ }
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline build error.";
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pipeline_spec_free(s);
return status;
}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index e1170a33b1..4f3a0b5958 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,3 +206,12 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 4/9] pipeline: generate the code for pipeline specification structure
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 3/9] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 5/9] pipeline: add API for pipeline code generation Cristian Dumitrescu
` (6 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add support to export the pipeline specification data structure to a C
source code file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 621 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 5 +
2 files changed, 626 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index cbbcef852b..05cf952816 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2,6 +2,7 @@
* Copyright(c) 2020 Intel Corporation
*/
#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -2103,6 +2104,626 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
+static const char *
+match_type_string_get(enum rte_swx_table_match_type match_type)
+{
+ switch (match_type) {
+ case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
+ case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
+ case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
+ default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
+ }
+}
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s)
+{
+ uint32_t i;
+
+ /* Check the input arguments. */
+ if (!f || !s)
+ return;
+
+ /* extobj. */
+ fprintf(f, "static struct extobj_spec extobjs[] = {\n");
+
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
+ fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
+ if (extobj_spec->pragma)
+ fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
+ else
+ fprintf(f, "\t\t.pragma = NULL,\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* regarray. */
+ fprintf(f, "static struct regarray_spec regarrays[] = {\n");
+
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
+ fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
+ fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metarray. */
+ fprintf(f, "static struct metarray_spec metarrays[] = {\n");
+
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
+ fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+ uint32_t j;
+
+ fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
+ struct_spec->name);
+
+ for (j = 0; j < struct_spec->n_fields; j++) {
+ struct rte_swx_field_params *field = &struct_spec->fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct struct_spec structs[] = {\n");
+
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
+ fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
+ fprintf(f, "\t\t.n_fields = "
+ "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
+ struct_spec->name,
+ struct_spec->name);
+ fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* header. */
+ fprintf(f, "static struct header_spec headers[] = {\n");
+
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metadata. */
+ fprintf(f, "static struct metadata_spec metadata[] = {\n");
+
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
+ action_spec->name);
+
+ for (j = 0; j < action_spec->n_instructions; j++) {
+ const char *instr = action_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct action_spec actions[] = {\n");
+
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
+
+ if (action_spec->args_struct_type_name)
+ fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
+ action_spec->args_struct_type_name);
+ else
+ fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
+
+ fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
+ action_spec->name);
+ fprintf(f, "\t\t.n_instructions = "
+ "sizeof(action_%s_initial_instructions) / "
+ "sizeof(action_%s_initial_instructions[0]),\n",
+ action_spec->name,
+ action_spec->name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+ uint32_t j;
+
+ /* fields. */
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "static struct rte_swx_match_field_params "
+ "table_%s_fields[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_fields; j++) {
+ struct rte_swx_match_field_params *field =
+ &table_spec->params.fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.match_type = %s,\n",
+ match_type_string_get(field->match_type));
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (table_spec->params.action_names && table_spec->params.n_actions) {
+ fprintf(f, "static const char *table_%s_action_names[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ const char *action_name = table_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (table_spec->params.action_is_for_table_entries &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (table_spec->params.action_is_for_default_entry &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct table_spec tables[] = {\n");
+
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.fields = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (table_spec->params.action_names && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "table_%s_action_is_for_table_entries,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "table_%s_action_is_for_default_entry,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
+ "sizeof(table_%s_action_names[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = 0,\n");
+
+ if (table_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ table_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (table_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ table_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ table_spec->params.default_action_is_const);
+ fprintf(f, "\t\t},\n");
+
+ if (table_spec->recommended_table_type_name)
+ fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
+ table_spec->recommended_table_type_name);
+ else
+ fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
+
+ if (table_spec->args)
+ fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
+ else
+ fprintf(f, "\t\t.args = NULL,\n");
+
+ fprintf(f, "\t\t.size = %u,\n", table_spec->size);
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+ uint32_t j;
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "static const char *selector_%s_field_names[] = {\n",
+ selector_spec->name);
+
+ for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
+ const char *field_name =
+ selector_spec->params.selector_field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct selector_spec selectors[] = {\n");
+
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+
+ fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
+ fprintf(f, "\t\t.params = {\n");
+
+ if (selector_spec->params.group_id_field_name)
+ fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
+ selector_spec->params.group_id_field_name);
+ else
+ fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
+ selector_spec->name);
+ fprintf(f, "\t\t\t.n_selector_fields = "
+ "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
+ selector_spec->name,
+ selector_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
+ }
+
+ if (selector_spec->params.member_id_field_name)
+ fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
+ selector_spec->params.member_id_field_name);
+ else
+ fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
+
+ fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
+
+ fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
+ selector_spec->params.n_members_per_group_max);
+
+ fprintf(f, "\t\t},\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+ uint32_t j;
+
+ /* field_names. */
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "static const char *learner_%s_field_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_fields; j++) {
+ const char *field_name = learner_spec->params.field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (learner_spec->params.action_names && learner_spec->params.n_actions) {
+ fprintf(f, "static const char *learner_%s_action_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ const char *action_name = learner_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* timeout. */
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "static uint32_t learner_%s_timeout[] = {\n", learner_spec->name);
+
+ for (j = 0; j < learner_spec->n_timeouts; j++) {
+ uint32_t value = learner_spec->timeout[j];
+
+ fprintf(f, "\t[%d] = %u,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct learner_spec learners[] = {\n");
+
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
+ learner_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(learner_%s_field_names) / "
+ "sizeof(learner_%s_field_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "learner_%s_action_is_for_table_entries,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "learner_%s_action_is_for_default_entry,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = "
+ "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = NULL,\n");
+
+ if (learner_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ learner_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (learner_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ learner_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ learner_spec->params.default_action_is_const);
+
+ fprintf(f, "\t\t},\n");
+
+ fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
+
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
+ fprintf(f, "\t\t\t.n_timeouts = "
+ "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t.timeout = NULL,\n");
+ fprintf(f, "\t\t\t.n_timeouts = 0,\n");
+ }
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
+
+ for (j = 0; j < apply_spec->n_instructions; j++) {
+ const char *instr = apply_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct apply_spec apply[] = {\n");
+
+ for (i = 0; i < s->n_apply; i++) {
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
+ fprintf(f, "\t.n_instructions = "
+ "sizeof(apply%u_initial_instructions) / "
+ "sizeof(apply%u_initial_instructions[0]),\n",
+ i,
+ i);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* pipeline. */
+ fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
+ fprintf(f, "\t.extobjs = extobjs,\n");
+ fprintf(f, "\t.structs = structs,\n");
+ fprintf(f, "\t.headers = headers,\n");
+ fprintf(f, "\t.metadata = metadata,\n");
+ fprintf(f, "\t.actions = actions,\n");
+ fprintf(f, "\t.tables = tables,\n");
+ fprintf(f, "\t.selectors = selectors,\n");
+ fprintf(f, "\t.learners = learners,\n");
+ fprintf(f, "\t.regarrays = regarrays,\n");
+ fprintf(f, "\t.metarrays = metarrays,\n");
+ fprintf(f, "\t.apply = apply,\n");
+ fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
+ fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
+ fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
+ fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
+ fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
+ fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
+ fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
+ fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
+ fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
+ fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
+ fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
+ fprintf(f, "};\n");
+}
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 4f3a0b5958..707b99ba09 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,6 +206,11 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s);
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 5/9] pipeline: add API for pipeline code generation
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (2 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 4/9] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 6/9] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
` (5 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the C code generation for the pipeline was hidden under
the hood; now, we make this an explicit API operation. Besides the
functions for the pipeline actions and the pipeline instructions,
the generated C source code now includes the pipeline specification
structure required for the pipeline configuration operations.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline.c | 94 +++++++++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline.h | 25 +++++++++
lib/pipeline/version.map | 3 ++
3 files changed, 122 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 3e1c6e9edb..52760111fd 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -18,6 +18,7 @@
#include <rte_swx_table_wm.h>
#include "rte_swx_pipeline_internal.h"
+#include "rte_swx_pipeline_spec.h"
#define CHECK(condition, err_code) \
do { \
@@ -13476,3 +13477,96 @@ pipeline_compile(struct rte_swx_pipeline *p)
return status;
}
+
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg)
+
+{
+ struct rte_swx_pipeline *p = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!spec_file || !code_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ status = rte_swx_pipeline_config(&p, 0);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline configuration error.";
+ goto free;
+ }
+
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto free;
+ }
+
+ /*
+ * Pipeline code generation.
+ */
+
+ /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
+ * but there is no need for the pipeline build to be done as well.
+ */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
+ goto free;
+ }
+
+ /* Header file inclusion. */
+ fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
+ fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
+
+ /* Code generation for the pipeline specification. */
+ pipeline_spec_codegen(code_file, s);
+ fprintf(code_file, "\n");
+
+ /* Code generation for the action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
+
+ action_data_codegen(a, code_file);
+ fprintf(code_file, "\n");
+
+ action_instr_codegen(a, code_file);
+ fprintf(code_file, "\n");
+ }
+
+ /* Code generation for the pipeline instructions. */
+ instruction_group_list_codegen(igl, p, code_file);
+
+free:
+ instruction_group_list_free(igl);
+ rte_swx_pipeline_free(p);
+ pipeline_spec_free(s);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index c41ca5cb15..2bd019b05f 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -941,6 +941,31 @@ __rte_experimental
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p);
+/**
+ * Pipeline C code generate based on input specification file
+ *
+ * @param[in] spec_file
+ * Pipeline specification file (.spec) provided as input.
+ * @param[in] code_file
+ * Pipeline C language file (.c) to be generated.
+ * @param[out] err_line
+ * In case of error and non-NULL, the line number within the *spec* file where
+ * the error occurred. The first line number in the file is 1.
+ * @param[out] err_msg
+ * In case of error and non-NULL, the error message.
+ * @return
+ * 0 on success or the following error codes otherwise:
+ * -EINVAL: Invalid argument;
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Resource with the same name already exists.
+ */
+__rte_experimental
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg);
+
/**
* Pipeline build from specification file
*
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8312307a7a..51165d48cf 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -145,4 +145,7 @@ EXPERIMENTAL {
rte_swx_ctl_pipeline_learner_timeout_get;
rte_swx_ctl_pipeline_learner_timeout_set;
rte_swx_pipeline_hash_func_register;
+
+ #added in 22.11
+ rte_swx_pipeline_codegen;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 6/9] pipeline: add API for shared library-based pipeline build
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (3 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 5/9] pipeline: add API for pipeline code generation Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 7/9] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
` (4 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the pipeline build operation was done based on the
specification file (typically produced by the P4 compiler), then the C
code with optimized functions for the pipeline actions and
instructions was generated, built into a shared object library, loaded
and installed into the pipeline in a completely hardcoded and
non-customizable way.
Now, this process is split into three explicit stages:
i) code generation (specification file -> C file);
ii) code build (C file -> shared object library);
iii) code installation (library load into the pipeline).
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 20 +-
lib/pipeline/rte_swx_pipeline.c | 289 +++++++++------------------
lib/pipeline/rte_swx_pipeline.h | 22 +-
lib/pipeline/rte_swx_pipeline_spec.c | 51 -----
lib/pipeline/version.map | 2 +-
5 files changed, 108 insertions(+), 276 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ad553f19ab..1f75b5dc9d 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -984,7 +984,7 @@ cmd_pipeline_port_out(char **tokens,
}
static const char cmd_pipeline_build_help[] =
-"pipeline <pipeline_name> build <spec_file>\n";
+"pipeline <pipeline_name> build <lib_file>\n";
static void
cmd_pipeline_build(char **tokens,
@@ -994,9 +994,6 @@ cmd_pipeline_build(char **tokens,
void *obj)
{
struct pipeline *p = NULL;
- FILE *spec = NULL;
- uint32_t err_line;
- const char *err_msg;
int status;
if (n_tokens != 4) {
@@ -1010,20 +1007,9 @@ cmd_pipeline_build(char **tokens,
return;
}
- spec = fopen(tokens[3], "r");
- if (!spec) {
- snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
- return;
- }
-
- status = rte_swx_pipeline_build_from_spec(p->p,
- spec,
- &err_line,
- &err_msg);
- fclose(spec);
+ status = rte_swx_pipeline_build_from_lib(p->p, tokens[3]);
if (status) {
- snprintf(out, out_size, "Error %d at line %u: %s\n.",
- status, err_line, err_msg);
+ snprintf(out, out_size, "Pipeline build error (%d).", status);
return;
}
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 52760111fd..03414bfd1f 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9807,9 +9807,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
return 0;
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p);
-
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
{
@@ -9899,8 +9896,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
p->build_done = 1;
- pipeline_compile(p);
-
return 0;
error:
@@ -13222,160 +13217,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *
return n_custom_instr;
}
-static int
-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- FILE *f = NULL;
-
- /* Create the .c file. */
- f = fopen("/tmp/pipeline.c", "w");
- if (!f)
- return -EIO;
-
- /* Include the .h file. */
- fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
-
- /* Add the code for each action. */
- TAILQ_FOREACH(a, &p->actions, node) {
- fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
-
- action_data_codegen(a, f);
-
- fprintf(f, "\n");
-
- action_instr_codegen(a, f);
-
- fprintf(f, "\n");
- }
-
- /* Add the pipeline code. */
- instruction_group_list_codegen(igl, p, f);
-
- /* Close the .c file. */
- fclose(f);
-
- return 0;
-}
-
-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
-#endif
-
-static int
-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- struct instruction_group *g;
- char *dir_in, *buffer = NULL;
- const char *dir_out;
- int status = 0;
-
- /* Get the environment variables. */
- dir_in = getenv("RTE_INSTALL_DIR");
- if (!dir_in) {
- status = -EINVAL;
- goto free;
- }
-
- dir_out = "/tmp";
-
- /* Memory allocation for the command buffer. */
- buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
- if (!buffer) {
- status = -ENOMEM;
- goto free;
- }
-
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
- "-I %s/lib/pipeline "
- "-I %s/lib/eal/include "
- "-I %s/lib/eal/x86/include "
- "-I %s/lib/eal/include/generic "
- "-I %s/lib/meter "
- "-I %s/lib/port "
- "-I %s/lib/table "
- "-I %s/lib/pipeline "
- "-I %s/config "
- "-I %s/build "
- "-I %s/lib/eal/linux/include "
- ">%s/pipeline.log 2>&1 "
- "&& "
- "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
- ">>%s/pipeline.log 2>&1",
- dir_out,
- dir_out,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_out,
- dir_out,
- dir_out,
- dir_out);
-
- /* Build the shared object library. */
- status = system(buffer);
- if (status)
- goto free;
-
- /* Open library. */
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "%s/libpipeline.so",
- dir_out);
-
- p->lib = dlopen(buffer, RTLD_LAZY);
- if (!p->lib) {
- status = -EIO;
- goto free;
- }
-
- /* Get the action function symbols. */
- TAILQ_FOREACH(a, &p->actions, node) {
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
-
- p->action_funcs[a->id] = dlsym(p->lib, buffer);
- if (!p->action_funcs[a->id]) {
- status = -EINVAL;
- goto free;
- }
- }
-
- /* Get the pipeline function symbols. */
- TAILQ_FOREACH(g, igl, node) {
- if (g->first_instr_id == g->last_instr_id)
- continue;
-
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
-
- g->func = dlsym(p->lib, buffer);
- if (!g->func) {
- status = -EINVAL;
- goto free;
- }
- }
-
-free:
- if (status && p->lib) {
- dlclose(p->lib);
- p->lib = NULL;
- }
-
- free(buffer);
-
- return status;
-}
-
static int
pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
struct instruction_group_list *igl)
@@ -13443,41 +13284,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p)
-{
- struct instruction_group_list *igl = NULL;
- int status = 0;
-
- igl = instruction_group_list_create(p);
- if (!igl) {
- status = -ENOMEM;
- goto free;
- }
-
- /* Code generation. */
- status = pipeline_codegen(p, igl);
- if (status)
- goto free;
-
- /* Build and load the shared object library. */
- status = pipeline_libload(p, igl);
- if (status)
- goto free;
-
- /* Adjust instructions. */
- status = pipeline_adjust_check(p, igl);
- if (status)
- goto free;
-
- pipeline_adjust(p, igl);
-
-free:
- instruction_group_list_free(igl);
-
- return status;
-}
-
int
rte_swx_pipeline_codegen(FILE *spec_file,
FILE *code_file,
@@ -13570,3 +13376,98 @@ rte_swx_pipeline_codegen(FILE *spec_file,
return status;
}
+
+int
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline *p,
+ const char *lib_file_name)
+{
+ void *lib = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ struct instruction_group *g;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!p || p->build_done || !lib_file_name || !lib_file_name[0]) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Open the library. */
+ lib = dlopen(lib_file_name, RTLD_LAZY);
+ if (!lib) {
+ status = -EIO;
+ goto free;
+ }
+
+ /* Get the pipeline specification structure from the library. */
+ s = dlsym(lib, "pipeline_spec");
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration based on the specification structure. */
+ status = pipeline_spec_configure(p, s, NULL);
+ if (status)
+ goto free;
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status)
+ goto free;
+
+ /* Action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ snprintf(name, sizeof(name), "action_%s_run", a->name);
+
+ p->action_funcs[a->id] = dlsym(lib, name);
+ if (!p->action_funcs[a->id]) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ /* Pipeline instructions. */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ status = -ENOMEM;
+ goto free;
+ }
+
+ TAILQ_FOREACH(g, igl, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ if (g->first_instr_id == g->last_instr_id)
+ continue;
+
+ snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
+
+ g->func = dlsym(lib, name);
+ if (!g->func) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ status = pipeline_adjust_check(p, igl);
+ if (status)
+ goto free;
+
+ pipeline_adjust(p, igl);
+
+ p->lib = lib;
+
+free:
+ if (status && lib) {
+ dlclose(lib);
+ p->lib = NULL;
+ }
+
+ instruction_group_list_free(igl);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 2bd019b05f..cb834cd64d 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -967,30 +967,26 @@ rte_swx_pipeline_codegen(FILE *spec_file,
const char **err_msg);
/**
- * Pipeline build from specification file
+ * Pipeline build from shared object library
+ *
+ * The shared object library must be built from the C language source code file
+ * previously generated by the rte_swx_pipeline_codegen() API function.
*
* @param[in] p
* Pipeline handle.
- * @param[in] spec
- * Pipeline specification file.
- * @param[out] err_line
- * In case of error and non-NULL, the line number within the *spec* file where
- * the error occurred. The first line number in the file is 1.
- * @param[out] err_msg
- * In case of error and non-NULL, the error message.
+ * @param[in] lib_file_name
+ * Shared object library file name.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
- * -EEXIST: Resource with the same name already exists;
+ * -EEXIST: Pipeline was already built successfully;
* -ENODEV: Extern object or table creation error.
*/
__rte_experimental
int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg);
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline *p,
+ const char *lib_file_name);
/**
* Pipeline run
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 05cf952816..206b514856 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -3514,54 +3514,3 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,
return 0;
}
-
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec_file,
- uint32_t *err_line,
- const char **err_msg)
-{
- struct pipeline_spec *s = NULL;
- int status = 0;
-
- /* Check the input arguments. */
- if (!p || !spec_file) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Invalid input argument.";
- status = -EINVAL;
- goto error;
- }
-
- /* Spec file parse. */
- s = pipeline_spec_parse(spec_file, err_line, err_msg);
- if (!s) {
- status = -EINVAL;
- goto error;
- }
-
- /* Pipeline configure. */
- status = pipeline_spec_configure(p, s, err_msg);
- if (status) {
- if (err_line)
- *err_line = 0;
- goto error;
- }
-
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
-
-error:
- pipeline_spec_free(s);
- return status;
-}
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 51165d48cf..810cc56467 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -82,7 +82,6 @@ EXPERIMENTAL {
rte_swx_ctl_table_ops_get;
rte_swx_pipeline_action_config;
rte_swx_pipeline_build;
- rte_swx_pipeline_build_from_spec;
rte_swx_pipeline_config;
rte_swx_pipeline_extern_func_register;
rte_swx_pipeline_extern_object_config;
@@ -148,4 +147,5 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_pipeline_codegen;
+ rte_swx_pipeline_build_from_lib;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 7/9] examples/pipeline: add CLI command for pipeline code generation
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (4 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 6/9] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 8/9] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
` (3 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the pipeline code generation operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 1f75b5dc9d..fdaf5dd16b 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -983,6 +983,53 @@ cmd_pipeline_port_out(char **tokens,
}
}
+static const char cmd_pipeline_codegen_help[] =
+"pipeline codegen <spec_file> <code_file>\n";
+
+static void
+cmd_pipeline_codegen(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ FILE *spec_file = NULL;
+ FILE *code_file = NULL;
+ uint32_t err_line;
+ const char *err_msg;
+ int status;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ spec_file = fopen(tokens[2], "r");
+ if (!spec_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+ return;
+ }
+
+ code_file = fopen(tokens[3], "w");
+ if (!code_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ return;
+ }
+
+ status = rte_swx_pipeline_codegen(spec_file,
+ code_file,
+ &err_line,
+ &err_msg);
+
+ fclose(spec_file);
+ fclose(code_file);
+
+ if (status) {
+ snprintf(out, out_size, "Error %d at line %u: %s\n.",
+ status, err_line, err_msg);
+ return;
+ }
+}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build <lib_file>\n";
@@ -2962,6 +3009,7 @@ cmd_help(char **tokens,
"\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
+ "\tpipeline codegen\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3031,6 +3079,12 @@ cmd_help(char **tokens,
}
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3309,6 +3363,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "codegen") == 0)) {
+ cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 8/9] examples/pipeline: add CLI command for shared library build
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (5 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 7/9] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:07 ` [PATCH 9/9] examples/pipeline: call CLI commands for code generation and build Cristian Dumitrescu
` (2 subsequent siblings)
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the shared object library build operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 147 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 143 insertions(+), 4 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index fdaf5dd16b..f1d2fbf52d 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_ethdev.h>
@@ -25,6 +26,10 @@
#define CMD_MAX_TOKENS 256
#endif
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
@@ -1030,6 +1035,130 @@ cmd_pipeline_codegen(char **tokens,
return;
}
}
+
+static const char cmd_pipeline_libbuild_help[] =
+"pipeline libbuild <code_file> <lib_file>\n";
+
+static void
+cmd_pipeline_libbuild(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+ char *install_dir, *buffer = NULL;
+ size_t length;
+ int status = 0;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ goto free;
+ }
+
+ install_dir = getenv("RTE_INSTALL_DIR");
+ if (!install_dir) {
+ snprintf(out, out_size, "Error: Environment variable RTE_INSTALL_DIR is not set.");
+ return;
+ }
+
+ snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+ out_size -= strlen(out);
+ out += strlen(out);
+
+ code_file = tokens[2];
+ length = strnlen(code_file, MAX_LINE_SIZE);
+ if ((length < 3) ||
+ (code_file[length - 2] != '.') ||
+ (code_file[length - 1] != 'c')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+ goto free;
+ }
+
+ lib_file = tokens[3];
+ length = strnlen(lib_file, MAX_LINE_SIZE);
+ if ((length < 4) ||
+ (lib_file[length - 3] != '.') ||
+ (lib_file[length - 2] != 's') ||
+ (lib_file[length - 1] != 'o')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+ goto free;
+ }
+
+ obj_file = malloc(length);
+ log_file = malloc(length + 2);
+ if (!obj_file || !log_file) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ memcpy(obj_file, lib_file, length - 2);
+ obj_file[length - 2] = 'o';
+ obj_file[length - 1] = 0;
+
+ memcpy(log_file, lib_file, length - 2);
+ log_file[length - 2] = 'l';
+ log_file[length - 1] = 'o';
+ log_file[length] = 'g';
+ log_file[length + 1] = 0;
+
+ buffer = malloc(MAX_LINE_SIZE);
+ if (!buffer) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ return;
+ }
+
+ snprintf(buffer,
+ MAX_LINE_SIZE,
+ "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+ "-I %s/lib/pipeline "
+ "-I %s/lib/eal/include "
+ "-I %s/lib/eal/x86/include "
+ "-I %s/lib/eal/include/generic "
+ "-I %s/lib/meter "
+ "-I %s/lib/port "
+ "-I %s/lib/table "
+ "-I %s/lib/pipeline "
+ "-I %s/config "
+ "-I %s/build "
+ "-I %s/lib/eal/linux/include "
+ ">%s 2>&1 "
+ "&& "
+ "gcc -shared %s -o %s "
+ ">>%s 2>&1",
+ obj_file,
+ code_file,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ log_file,
+ obj_file,
+ lib_file,
+ log_file);
+
+ status = system(buffer);
+ if (status) {
+ snprintf(out,
+ out_size,
+ "Library build failed, see file \"%s\" for details.\n",
+ log_file);
+ goto free;
+ }
+
+free:
+ free(obj_file);
+ free(log_file);
+ free(buffer);
+}
+
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build <lib_file>\n";
@@ -1080,10 +1209,6 @@ table_entry_free(struct rte_swx_table_entry *entry)
free(entry);
}
-#ifndef MAX_LINE_SIZE
-#define MAX_LINE_SIZE 2048
-#endif
-
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
@@ -3010,6 +3135,7 @@ cmd_help(char **tokens,
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
+ "\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3085,6 +3211,12 @@ cmd_help(char **tokens,
return;
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3370,6 +3502,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "libbuild") == 0)) {
+ cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH 9/9] examples/pipeline: call CLI commands for code generation and build
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (6 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 8/9] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
@ 2022-07-18 13:07 ` Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-28 15:11 ` [PATCH V6 00/17] pipeline: pipeline configuration and build improvements Cristian Dumitrescu
9 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:07 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Update the example CLI scripts with the commands for code generation
and shared object library build.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/examples/fib.cli | 8 +++++++-
examples/pipeline/examples/hash_func.cli | 8 +++++++-
examples/pipeline/examples/l2fwd.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_macswp.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_macswp_pcap.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_pcap.cli | 8 +++++++-
examples/pipeline/examples/learner.cli | 8 +++++++-
examples/pipeline/examples/meter.cli | 8 +++++++-
examples/pipeline/examples/mirroring.cli | 8 +++++++-
examples/pipeline/examples/recirculation.cli | 8 +++++++-
examples/pipeline/examples/registers.cli | 8 +++++++-
examples/pipeline/examples/selector.cli | 8 +++++++-
examples/pipeline/examples/varbit.cli | 8 +++++++-
examples/pipeline/examples/vxlan.cli | 8 +++++++-
examples/pipeline/examples/vxlan_pcap.cli | 8 +++++++-
15 files changed, 105 insertions(+), 15 deletions(-)
diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli
index 93ab2b08f8..8b55175bf3 100644
--- a/examples/pipeline/examples/fib.cli
+++ b/examples/pipeline/examples/fib.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/fib.spec /tmp/fib.c
+pipeline libbuild /tmp/fib.c /tmp/fib.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/fib.spec
+pipeline PIPELINE0 build /tmp/fib.so
;
; Initial set of table entries.
diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli
index d65cd62d17..f7bb28b28b 100644
--- a/examples/pipeline/examples/hash_func.cli
+++ b/examples/pipeline/examples/hash_func.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/hash_func.spec /tmp/hash_func.c
+pipeline libbuild /tmp/hash_func.c /tmp/hash_func.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/hash_func.spec
+pipeline PIPELINE0 build /tmp/hash_func.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli
index d89caf2d0a..a71727309b 100644
--- a/examples/pipeline/examples/l2fwd.cli
+++ b/examples/pipeline/examples/l2fwd.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,6 +26,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+pipeline PIPELINE0 build /tmp/l2fwd.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli
index 0f2a89ac5b..d8f5f9f735 100644
--- a/examples/pipeline/examples/l2fwd_macswp.cli
+++ b/examples/pipeline/examples/l2fwd_macswp.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,6 +26,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+pipeline PIPELINE0 build /tmp/l2fwd_macswp.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
index e9656fe3c2..bd077876ff 100644
--- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,6 +21,6 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+pipeline PIPELINE0 build /tmp/l2fwd_macswp.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli
index 23fcb199f1..2e56a116af 100644
--- a/examples/pipeline/examples/l2fwd_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,6 +21,6 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+pipeline PIPELINE0 build /tmp/l2fwd.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli
index 688ce34f34..10eb2af417 100644
--- a/examples/pipeline/examples/learner.cli
+++ b/examples/pipeline/examples/learner.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/learner.spec /tmp/learner.c
+pipeline libbuild /tmp/learner.c /tmp/learner.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/learner.spec
+pipeline PIPELINE0 build /tmp/learner.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli
index b29ed24022..9c22014f46 100644
--- a/examples/pipeline/examples/meter.cli
+++ b/examples/pipeline/examples/meter.cli
@@ -4,6 +4,12 @@
; Example command line:
; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/meter.spec /tmp/meter.c
+pipeline libbuild /tmp/meter.c /tmp/meter.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -23,7 +29,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/meter.spec
+pipeline PIPELINE0 build /tmp/meter.so
pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli
index 46d57db4ec..9614f64d38 100644
--- a/examples/pipeline/examples/mirroring.cli
+++ b/examples/pipeline/examples/mirroring.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/mirroring.spec /tmp/mirroring.c
+pipeline libbuild /tmp/mirroring.c /tmp/mirroring.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -27,7 +33,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/mirroring.spec
+pipeline PIPELINE0 build /tmp/mirroring.so
;
; Packet mirroring sessions.
diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli
index f855c5c327..bd114e91cd 100644
--- a/examples/pipeline/examples/recirculation.cli
+++ b/examples/pipeline/examples/recirculation.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/recirculation.spec /tmp/recirculation.c
+pipeline libbuild /tmp/recirculation.c /tmp/recirculation.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/recirculation.spec
+pipeline PIPELINE0 build /tmp/recirculation.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli
index 8d026294cb..3d9eeb0d5c 100644
--- a/examples/pipeline/examples/registers.cli
+++ b/examples/pipeline/examples/registers.cli
@@ -4,6 +4,12 @@
; Example command line:
; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/registers.spec /tmp/registers.c
+pipeline libbuild /tmp/registers.c /tmp/registers.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -23,6 +29,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/registers.spec
+pipeline PIPELINE0 build /tmp/registers.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli
index 123782c57b..6c7d032b10 100644
--- a/examples/pipeline/examples/selector.cli
+++ b/examples/pipeline/examples/selector.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/selector.spec /tmp/selector.c
+pipeline libbuild /tmp/selector.c /tmp/selector.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,7 +26,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/selector.spec
+pipeline PIPELINE0 build /tmp/selector.so
pipeline PIPELINE0 selector s group add
pipeline PIPELINE0 selector s group member add ./examples/pipeline/examples/selector.txt
diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli
index 9caeb9ca26..545cde262e 100644
--- a/examples/pipeline/examples/varbit.cli
+++ b/examples/pipeline/examples/varbit.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/varbit.spec /tmp/varbit.c
+pipeline libbuild /tmp/varbit.c /tmp/varbit.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/varbit.spec
+pipeline PIPELINE0 build /tmp/varbit.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli
index 444f3f7bd8..321a28ba44 100644
--- a/examples/pipeline/examples/vxlan.cli
+++ b/examples/pipeline/examples/vxlan.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,7 +26,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+pipeline PIPELINE0 build /tmp/vxlan.so
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli
index 83fca8d0d9..596169f933 100644
--- a/examples/pipeline/examples/vxlan_pcap.cli
+++ b/examples/pipeline/examples/vxlan_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,7 +21,7 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+pipeline PIPELINE0 build /tmp/vxlan.so
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 1/9] pipeline: move specification data structures to internal header
2022-07-18 13:07 [PATCH 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (7 preceding siblings ...)
2022-07-18 13:07 ` [PATCH 9/9] examples/pipeline: call CLI commands for code generation and build Cristian Dumitrescu
@ 2022-07-18 13:25 ` Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
` (8 more replies)
2022-07-28 15:11 ` [PATCH V6 00/17] pipeline: pipeline configuration and build improvements Cristian Dumitrescu
9 siblings, 9 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:25 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Move all the pipeline object specification data structures to an
internal header file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 126 +------------------
lib/pipeline/rte_swx_pipeline_spec.h | 176 +++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 125 deletions(-)
create mode 100644 lib/pipeline/rte_swx_pipeline_spec.h
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 904b9eb471..5e07b4f794 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,7 +9,7 @@
#include <rte_common.h>
-#include "rte_swx_pipeline.h"
+#include "rte_swx_pipeline_spec.h"
#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 2048
@@ -34,15 +34,7 @@
/*
* extobj.
- *
- * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
*/
-struct extobj_spec {
- char *name;
- char *extern_type_name;
- char *pragma;
-};
-
static void
extobj_spec_free(struct extobj_spec *s)
{
@@ -104,18 +96,7 @@ extobj_statement_parse(struct extobj_spec *s,
/*
* struct.
*
- * struct STRUCT_TYPE_NAME {
- * bit<SIZE> | varbit<SIZE> FIELD_NAME
- * ...
- * }
*/
-struct struct_spec {
- char *name;
- struct rte_swx_field_params *fields;
- uint32_t n_fields;
- int varbit;
-};
-
static void
struct_spec_free(struct struct_spec *s)
{
@@ -293,13 +274,7 @@ struct_block_parse(struct struct_spec *s,
/*
* header.
*
- * header HEADER_NAME instanceof STRUCT_TYPE_NAME
*/
-struct header_spec {
- char *name;
- char *struct_type_name;
-};
-
static void
header_spec_free(struct header_spec *s)
{
@@ -351,12 +326,7 @@ header_statement_parse(struct header_spec *s,
/*
* metadata.
*
- * metadata instanceof STRUCT_TYPE_NAME
*/
-struct metadata_spec {
- char *struct_type_name;
-};
-
static void
metadata_spec_free(struct metadata_spec *s)
{
@@ -400,18 +370,7 @@ metadata_statement_parse(struct metadata_spec *s,
/*
* action.
*
- * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
- * INSTRUCTION
- * ...
- * }
*/
-struct action_spec {
- char *name;
- char *args_struct_type_name;
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
action_spec_free(struct action_spec *s)
{
@@ -540,29 +499,7 @@ action_block_parse(struct action_spec *s,
/*
* table.
*
- * table TABLE_NAME {
- * key {
- * MATCH_FIELD_NAME exact | wildcard | lpm
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly ]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * instanceof TABLE_TYPE_NAME
- * pragma ARGS
- * size SIZE
- * }
*/
-struct table_spec {
- char *name;
- struct rte_swx_pipeline_table_params params;
- char *recommended_table_type_name;
- char *args;
- uint32_t size;
-};
-
static void
table_spec_free(struct table_spec *s)
{
@@ -1084,22 +1021,7 @@ table_block_parse(struct table_spec *s,
/*
* selector.
*
- * selector SELECTOR_NAME {
- * group_id FIELD_NAME
- * selector {
- * FIELD_NAME
- * ...
- * }
- * member_id FIELD_NAME
- * n_groups N_GROUPS
- * n_members_per_group N_MEMBERS_PER_GROUP
- * }
*/
-struct selector_spec {
- char *name;
- struct rte_swx_pipeline_selector_params params;
-};
-
static void
selector_spec_free(struct selector_spec *s)
{
@@ -1385,31 +1307,7 @@ selector_block_parse(struct selector_spec *s,
/*
* learner.
*
- * learner LEARNER_NAME {
- * key {
- * MATCH_FIELD_NAME
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * size SIZE
- * timeout {
- * TIMEOUT_IN_SECONDS
- * ...
- * }
- * }
*/
-struct learner_spec {
- char *name;
- struct rte_swx_pipeline_learner_params params;
- uint32_t size;
- uint32_t *timeout;
- uint32_t n_timeouts;
-};
-
static void
learner_spec_free(struct learner_spec *s)
{
@@ -1958,14 +1856,7 @@ learner_block_parse(struct learner_spec *s,
/*
* regarray.
*
- * regarray NAME size SIZE initval INITVAL
*/
-struct regarray_spec {
- char *name;
- uint64_t init_val;
- uint32_t size;
-};
-
static void
regarray_spec_free(struct regarray_spec *s)
{
@@ -2033,13 +1924,7 @@ regarray_statement_parse(struct regarray_spec *s,
/*
* metarray.
*
- * metarray NAME size SIZE
*/
-struct metarray_spec {
- char *name;
- uint32_t size;
-};
-
static void
metarray_spec_free(struct metarray_spec *s)
{
@@ -2095,16 +1980,7 @@ metarray_statement_parse(struct metarray_spec *s,
/*
* apply.
*
- * apply {
- * INSTRUCTION
- * ...
- * }
*/
-struct apply_spec {
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
apply_spec_free(struct apply_spec *s)
{
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
new file mode 100644
index 0000000000..8458de878a
--- /dev/null
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+
+#include <rte_swx_pipeline.h>
+
+/*
+ * extobj.
+ *
+ * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
+ */
+struct extobj_spec {
+ char *name;
+ char *extern_type_name;
+ char *pragma;
+};
+
+/*
+ * struct.
+ *
+ * struct STRUCT_TYPE_NAME {
+ * bit<SIZE> | varbit<SIZE> FIELD_NAME
+ * ...
+ * }
+ */
+struct struct_spec {
+ char *name;
+ struct rte_swx_field_params *fields;
+ uint32_t n_fields;
+ int varbit;
+};
+
+/*
+ * header.
+ *
+ * header HEADER_NAME instanceof STRUCT_TYPE_NAME
+ */
+struct header_spec {
+ char *name;
+ char *struct_type_name;
+};
+
+/*
+ * metadata.
+ *
+ * metadata instanceof STRUCT_TYPE_NAME
+ */
+struct metadata_spec {
+ char *struct_type_name;
+};
+
+/*
+ * action.
+ *
+ * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct action_spec {
+ char *name;
+ char *args_struct_type_name;
+ const char **instructions;
+ uint32_t n_instructions;
+};
+
+/*
+ * table.
+ *
+ * table TABLE_NAME {
+ * key {
+ * MATCH_FIELD_NAME exact | wildcard | lpm
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly ]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * instanceof TABLE_TYPE_NAME
+ * pragma ARGS
+ * size SIZE
+ * }
+ */
+struct table_spec {
+ char *name;
+ struct rte_swx_pipeline_table_params params;
+ char *recommended_table_type_name;
+ char *args;
+ uint32_t size;
+};
+
+/*
+ * selector.
+ *
+ * selector SELECTOR_NAME {
+ * group_id FIELD_NAME
+ * selector {
+ * FIELD_NAME
+ * ...
+ * }
+ * member_id FIELD_NAME
+ * n_groups N_GROUPS
+ * n_members_per_group N_MEMBERS_PER_GROUP
+ * }
+ */
+struct selector_spec {
+ char *name;
+ struct rte_swx_pipeline_selector_params params;
+};
+
+/*
+ * learner.
+ *
+ * learner LEARNER_NAME {
+ * key {
+ * MATCH_FIELD_NAME
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * size SIZE
+ * timeout {
+ * TIMEOUT_IN_SECONDS
+ * ...
+ * }
+ * }
+ */
+struct learner_spec {
+ char *name;
+ struct rte_swx_pipeline_learner_params params;
+ uint32_t size;
+ uint32_t *timeout;
+ uint32_t n_timeouts;
+};
+
+/*
+ * regarray.
+ *
+ * regarray NAME size SIZE initval INITVAL
+ */
+struct regarray_spec {
+ char *name;
+ uint64_t init_val;
+ uint32_t size;
+};
+
+/*
+ * metarray.
+ *
+ * metarray NAME size SIZE
+ */
+struct metarray_spec {
+ char *name;
+ uint32_t size;
+};
+
+/*
+ * apply.
+ *
+ * apply {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct apply_spec {
+ const char **instructions;
+ uint32_t n_instructions;
+};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 2/9] pipeline: add pipeline specification data structure
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
@ 2022-07-18 13:25 ` Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 3/9] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
` (7 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:25 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure for the entire pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 21 ++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 32 ++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5e07b4f794..642091b678 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2082,6 +2082,27 @@ apply_block_parse(struct apply_spec *s,
/*
* Pipeline.
*/
+void
+pipeline_spec_free(struct pipeline_spec *s)
+{
+ if (!s)
+ return;
+
+ free(s->extobjs);
+ free(s->structs);
+ free(s->headers);
+ free(s->metadata);
+ free(s->actions);
+ free(s->tables);
+ free(s->selectors);
+ free(s->learners);
+ free(s->regarrays);
+ free(s->metarrays);
+ free(s->apply);
+
+ memset(s, 0, sizeof(struct pipeline_spec));
+}
+
int
rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
FILE *spec,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 8458de878a..e1170a33b1 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -174,3 +174,35 @@ struct apply_spec {
const char **instructions;
uint32_t n_instructions;
};
+
+/*
+ * Pipeline.
+ */
+struct pipeline_spec {
+ struct extobj_spec *extobjs;
+ struct struct_spec *structs;
+ struct header_spec *headers;
+ struct metadata_spec *metadata;
+ struct action_spec *actions;
+ struct table_spec *tables;
+ struct selector_spec *selectors;
+ struct learner_spec *learners;
+ struct regarray_spec *regarrays;
+ struct metarray_spec *metarrays;
+ struct apply_spec *apply;
+
+ uint32_t n_extobjs;
+ uint32_t n_structs;
+ uint32_t n_headers;
+ uint32_t n_metadata;
+ uint32_t n_actions;
+ uint32_t n_tables;
+ uint32_t n_selectors;
+ uint32_t n_learners;
+ uint32_t n_regarrays;
+ uint32_t n_metarrays;
+ uint32_t n_apply;
+};
+
+void
+pipeline_spec_free(struct pipeline_spec *s);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 3/9] pipeline: rework the specification file-based pipeline build
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
@ 2022-07-18 13:25 ` Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 4/9] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
` (6 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:25 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the specification file-based pipeline build operation to first
parse the specification file into the previously introduced pipeline
specification data structure, then use this structure to configure
and build the pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 478 +++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline_spec.h | 9 +
2 files changed, 385 insertions(+), 102 deletions(-)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 642091b678..62929a9da6 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2103,11 +2103,10 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg)
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
{
struct extobj_spec extobj_spec = {0};
struct struct_spec struct_spec = {0};
@@ -2120,26 +2119,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0};
- uint32_t n_lines;
+ struct pipeline_spec *s = NULL;
+ uint32_t n_lines = 0;
uint32_t block_mask = 0;
- int status;
+ int status = 0;
/* Check the input arguments. */
- if (!p) {
+ if (!spec) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null pipeline argument.";
+ *err_msg = "Invalid input argument.";
status = -EINVAL;
goto error;
}
- if (!spec) {
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_spec), 1);
+ if (!s) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null specification file argument.";
- status = -EINVAL;
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
@@ -2200,6 +2202,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* struct block. */
if (block_mask & (1 << STRUCT_BLOCK)) {
+ struct struct_spec *new_structs;
+
status = struct_block_parse(&struct_spec,
&block_mask,
tokens,
@@ -2214,26 +2218,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_struct_type_register(p,
- struct_spec.name,
- struct_spec.fields,
- struct_spec.n_fields,
- struct_spec.varbit);
- if (status) {
+ new_structs = realloc(s->structs,
+ (s->n_structs + 1) * sizeof(struct struct_spec));
+ if (!new_structs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Struct registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- struct_spec_free(&struct_spec);
+ s->structs = new_structs;
+ memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
+ s->n_structs++;
+ memset(&struct_spec, 0, sizeof(struct struct_spec));
continue;
}
/* action block. */
if (block_mask & (1 << ACTION_BLOCK)) {
+ struct action_spec *new_actions;
+
status = action_block_parse(&action_spec,
&block_mask,
tokens,
@@ -2248,26 +2255,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_action_config(p,
- action_spec.name,
- action_spec.args_struct_type_name,
- action_spec.instructions,
- action_spec.n_instructions);
- if (status) {
+ new_actions = realloc(s->actions,
+ (s->n_actions + 1) * sizeof(struct action_spec));
+ if (!new_actions) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Action config error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- action_spec_free(&action_spec);
+ s->actions = new_actions;
+ memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
+ s->n_actions++;
+ memset(&action_spec, 0, sizeof(struct action_spec));
continue;
}
/* table block. */
if (block_mask & (1 << TABLE_BLOCK)) {
+ struct table_spec *new_tables;
+
status = table_block_parse(&table_spec,
&block_mask,
tokens,
@@ -2282,27 +2292,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_table_config(p,
- table_spec.name,
- &table_spec.params,
- table_spec.recommended_table_type_name,
- table_spec.args,
- table_spec.size);
- if (status) {
+ new_tables = realloc(s->tables,
+ (s->n_tables + 1) * sizeof(struct table_spec));
+ if (!new_tables) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- table_spec_free(&table_spec);
+ s->tables = new_tables;
+ memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
+ s->n_tables++;
+ memset(&table_spec, 0, sizeof(struct table_spec));
continue;
}
/* selector block. */
if (block_mask & (1 << SELECTOR_BLOCK)) {
+ struct selector_spec *new_selectors;
+
status = selector_block_parse(&selector_spec,
&block_mask,
tokens,
@@ -2317,24 +2329,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_selector_config(p,
- selector_spec.name,
- &selector_spec.params);
- if (status) {
+ new_selectors = realloc(s->selectors,
+ (s->n_selectors + 1) * sizeof(struct selector_spec));
+ if (!new_selectors) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Selector configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- selector_spec_free(&selector_spec);
+ s->selectors = new_selectors;
+ memcpy(&s->selectors[s->n_selectors],
+ &selector_spec,
+ sizeof(struct selector_spec));
+ s->n_selectors++;
+ memset(&selector_spec, 0, sizeof(struct selector_spec));
continue;
}
/* learner block. */
if (block_mask & (1 << LEARNER_BLOCK)) {
+ struct learner_spec *new_learners;
+
status = learner_block_parse(&learner_spec,
&block_mask,
tokens,
@@ -2349,27 +2368,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_learner_config(p,
- learner_spec.name,
- &learner_spec.params,
- learner_spec.size,
- learner_spec.timeout,
- learner_spec.n_timeouts);
- if (status) {
+ new_learners = realloc(s->learners,
+ (s->n_learners + 1) * sizeof(struct learner_spec));
+ if (!new_learners) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Learner table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- learner_spec_free(&learner_spec);
+ s->learners = new_learners;
+ memcpy(&s->learners[s->n_learners],
+ &learner_spec,
+ sizeof(struct learner_spec));
+ s->n_learners++;
+ memset(&learner_spec, 0, sizeof(struct learner_spec));
continue;
}
/* apply block. */
if (block_mask & (1 << APPLY_BLOCK)) {
+ struct apply_spec *new_apply;
+
status = apply_block_parse(&apply_spec,
&block_mask,
tokens,
@@ -2384,24 +2407,28 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_instructions_config(p,
- apply_spec.instructions,
- apply_spec.n_instructions);
- if (status) {
+ new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
+ if (!new_apply) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Pipeline instructions err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- apply_spec_free(&apply_spec);
+ s->apply = new_apply;
+ memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
+ s->n_apply++;
+ memset(&apply_spec, 0, sizeof(struct apply_spec));
continue;
}
/* extobj. */
if (!strcmp(tokens[0], "extobj")) {
+ struct extobj_spec *new_extobjs;
+
status = extobj_statement_parse(&extobj_spec,
tokens,
n_tokens,
@@ -2411,19 +2438,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_extern_object_config(p,
- extobj_spec.name,
- extobj_spec.extern_type_name,
- extobj_spec.pragma);
- if (status) {
+ new_extobjs = realloc(s->extobjs,
+ (s->n_extobjs + 1) * sizeof(struct extobj_spec));
+ if (!new_extobjs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Extern object config err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- extobj_spec_free(&extobj_spec);
+ s->extobjs = new_extobjs;
+ memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
+ s->n_extobjs++;
+ memset(&extobj_spec, 0, sizeof(struct extobj_spec));
continue;
}
@@ -2445,6 +2474,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* header. */
if (!strcmp(tokens[0], "header")) {
+ struct header_spec *new_headers;
+
status = header_statement_parse(&header_spec,
tokens,
n_tokens,
@@ -2454,24 +2485,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_header_register(p,
- header_spec.name,
- header_spec.struct_type_name);
- if (status) {
+ new_headers = realloc(s->headers,
+ (s->n_headers + 1) * sizeof(struct header_spec));
+ if (!new_headers) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Header registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- header_spec_free(&header_spec);
+ s->headers = new_headers;
+ memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
+ s->n_headers++;
+ memset(&header_spec, 0, sizeof(struct header_spec));
continue;
}
/* metadata. */
if (!strcmp(tokens[0], "metadata")) {
+ struct metadata_spec *new_metadata;
+
status = metadata_statement_parse(&metadata_spec,
tokens,
n_tokens,
@@ -2481,17 +2517,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_metadata_register(p,
- metadata_spec.struct_type_name);
- if (status) {
+ new_metadata = realloc(s->metadata,
+ (s->n_metadata + 1) * sizeof(struct metadata_spec));
+ if (!new_metadata) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meta-data reg err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metadata_spec_free(&metadata_spec);
+ s->metadata = new_metadata;
+ memcpy(&s->metadata[s->n_metadata],
+ &metadata_spec,
+ sizeof(struct metadata_spec));
+ s->n_metadata++;
+ memset(&metadata_spec, 0, sizeof(struct metadata_spec));
continue;
}
@@ -2558,6 +2600,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* regarray. */
if (!strcmp(tokens[0], "regarray")) {
+ struct regarray_spec *new_regarrays;
+
status = regarray_statement_parse(®array_spec,
tokens,
n_tokens,
@@ -2567,25 +2611,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_regarray_config(p,
- regarray_spec.name,
- regarray_spec.size,
- regarray_spec.init_val);
- if (status) {
+ new_regarrays = realloc(s->regarrays,
+ (s->n_regarrays + 1) * sizeof(struct regarray_spec));
+ if (!new_regarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Register array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- regarray_spec_free(®array_spec);
+ s->regarrays = new_regarrays;
+ memcpy(&s->regarrays[s->n_regarrays],
+ ®array_spec,
+ sizeof(struct regarray_spec));
+ s->n_regarrays++;
+ memset(®array_spec, 0, sizeof(struct regarray_spec));
continue;
}
/* metarray. */
if (!strcmp(tokens[0], "metarray")) {
+ struct metarray_spec *new_metarrays;
+
status = metarray_statement_parse(&metarray_spec,
tokens,
n_tokens,
@@ -2595,18 +2645,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_metarray_config(p,
- metarray_spec.name,
- metarray_spec.size);
- if (status) {
+ new_metarrays = realloc(s->metarrays,
+ (s->n_metarrays + 1) * sizeof(struct metarray_spec));
+ if (!new_metarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meter array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metarray_spec_free(&metarray_spec);
+ s->metarrays = new_metarrays;
+ memcpy(&s->metarrays[s->n_metarrays],
+ &metarray_spec,
+ sizeof(struct metarray_spec));
+ s->n_metarrays++;
+ memset(&metarray_spec, 0, sizeof(struct metarray_spec));
continue;
}
@@ -2644,17 +2699,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
goto error;
}
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
+ return s;
error:
extobj_spec_free(&extobj_spec);
@@ -2668,5 +2713,234 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
regarray_spec_free(®array_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec);
+ pipeline_spec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* extobj. */
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ status = rte_swx_pipeline_extern_object_config(p,
+ extobj_spec->name,
+ extobj_spec->extern_type_name,
+ extobj_spec->pragma);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Extern object configuration error.";
+ return status;
+ }
+ }
+
+ /* regarray. */
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ status = rte_swx_pipeline_regarray_config(p,
+ regarray_spec->name,
+ regarray_spec->size,
+ regarray_spec->init_val);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Register array configuration error.";
+ return status;
+ }
+ }
+
+ /* metarray. */
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ status = rte_swx_pipeline_metarray_config(p,
+ metarray_spec->name,
+ metarray_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meter array configuration error.";
+ return status;
+ }
+ }
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ status = rte_swx_pipeline_struct_type_register(p,
+ struct_spec->name,
+ struct_spec->fields,
+ struct_spec->n_fields,
+ struct_spec->varbit);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Struct type registration error.";
+ return status;
+ }
+ }
+
+ /* header. */
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ status = rte_swx_pipeline_packet_header_register(p,
+ header_spec->name,
+ header_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Header configuration error.";
+ return status;
+ }
+ }
+
+ /* metadata. */
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ status = rte_swx_pipeline_packet_metadata_register(p,
+ metadata_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meta-data registration error.";
+ return status;
+ }
+ }
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ status = rte_swx_pipeline_action_config(p,
+ action_spec->name,
+ action_spec->args_struct_type_name,
+ action_spec->instructions,
+ action_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Action configuration error.";
+ return status;
+ }
+ }
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ status = rte_swx_pipeline_table_config(p,
+ table_spec->name,
+ &table_spec->params,
+ table_spec->recommended_table_type_name,
+ table_spec->args,
+ table_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Table configuration error.";
+ return status;
+ }
+ }
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ status = rte_swx_pipeline_selector_config(p,
+ selector_spec->name,
+ &selector_spec->params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Selector table configuration error.";
+ return status;
+ }
+ }
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ status = rte_swx_pipeline_learner_config(p,
+ learner_spec->name,
+ &learner_spec->params,
+ learner_spec->size,
+ learner_spec->timeout,
+ learner_spec->n_timeouts);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Learner table configuration error.";
+ return status;
+ }
+ }
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+
+ status = rte_swx_pipeline_instructions_config(p,
+ apply_spec->instructions,
+ apply_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline instructions configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
+ FILE *spec_file,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_spec *s = NULL;
+ int status = 0;
+
+ /* Check the input arguments. */
+ if (!p || !spec_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Spec file parse. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Pipeline configure. */
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto error;
+ }
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline build error.";
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pipeline_spec_free(s);
return status;
}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index e1170a33b1..4f3a0b5958 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,3 +206,12 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 4/9] pipeline: generate the code for pipeline specification structure
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 2/9] pipeline: add pipeline specification data structure Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 3/9] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
@ 2022-07-18 13:25 ` Cristian Dumitrescu
2022-07-18 13:25 ` [PATCH V2 5/9] pipeline: add API for pipeline code generation Cristian Dumitrescu
` (5 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:25 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add support to export the pipeline specification data structure to a C
source code file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 622 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 5 +
2 files changed, 627 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 62929a9da6..bf21fe17ba 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2,6 +2,7 @@
* Copyright(c) 2020 Intel Corporation
*/
#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -2103,6 +2104,627 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
+static const char *
+match_type_string_get(enum rte_swx_table_match_type match_type)
+{
+ switch (match_type) {
+ case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
+ case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
+ case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
+ default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
+ }
+}
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s)
+{
+ uint32_t i;
+
+ /* Check the input arguments. */
+ if (!f || !s)
+ return;
+
+ /* extobj. */
+ fprintf(f, "static struct extobj_spec extobjs[] = {\n");
+
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
+ fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
+ if (extobj_spec->pragma)
+ fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
+ else
+ fprintf(f, "\t\t.pragma = NULL,\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* regarray. */
+ fprintf(f, "static struct regarray_spec regarrays[] = {\n");
+
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
+ fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
+ fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metarray. */
+ fprintf(f, "static struct metarray_spec metarrays[] = {\n");
+
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
+ fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+ uint32_t j;
+
+ fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
+ struct_spec->name);
+
+ for (j = 0; j < struct_spec->n_fields; j++) {
+ struct rte_swx_field_params *field = &struct_spec->fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct struct_spec structs[] = {\n");
+
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
+ fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
+ fprintf(f, "\t\t.n_fields = "
+ "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
+ struct_spec->name,
+ struct_spec->name);
+ fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* header. */
+ fprintf(f, "static struct header_spec headers[] = {\n");
+
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metadata. */
+ fprintf(f, "static struct metadata_spec metadata[] = {\n");
+
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
+ action_spec->name);
+
+ for (j = 0; j < action_spec->n_instructions; j++) {
+ const char *instr = action_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct action_spec actions[] = {\n");
+
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
+
+ if (action_spec->args_struct_type_name)
+ fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
+ action_spec->args_struct_type_name);
+ else
+ fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
+
+ fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
+ action_spec->name);
+ fprintf(f, "\t\t.n_instructions = "
+ "sizeof(action_%s_initial_instructions) / "
+ "sizeof(action_%s_initial_instructions[0]),\n",
+ action_spec->name,
+ action_spec->name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+ uint32_t j;
+
+ /* fields. */
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "static struct rte_swx_match_field_params "
+ "table_%s_fields[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_fields; j++) {
+ struct rte_swx_match_field_params *field =
+ &table_spec->params.fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.match_type = %s,\n",
+ match_type_string_get(field->match_type));
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (table_spec->params.action_names && table_spec->params.n_actions) {
+ fprintf(f, "static const char *table_%s_action_names[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ const char *action_name = table_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (table_spec->params.action_is_for_table_entries &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (table_spec->params.action_is_for_default_entry &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct table_spec tables[] = {\n");
+
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.fields = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (table_spec->params.action_names && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "table_%s_action_is_for_table_entries,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "table_%s_action_is_for_default_entry,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
+ "sizeof(table_%s_action_names[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = 0,\n");
+
+ if (table_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ table_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (table_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ table_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ table_spec->params.default_action_is_const);
+ fprintf(f, "\t\t},\n");
+
+ if (table_spec->recommended_table_type_name)
+ fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
+ table_spec->recommended_table_type_name);
+ else
+ fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
+
+ if (table_spec->args)
+ fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
+ else
+ fprintf(f, "\t\t.args = NULL,\n");
+
+ fprintf(f, "\t\t.size = %u,\n", table_spec->size);
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+ uint32_t j;
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "static const char *selector_%s_field_names[] = {\n",
+ selector_spec->name);
+
+ for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
+ const char *field_name =
+ selector_spec->params.selector_field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct selector_spec selectors[] = {\n");
+
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+
+ fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
+ fprintf(f, "\t\t.params = {\n");
+
+ if (selector_spec->params.group_id_field_name)
+ fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
+ selector_spec->params.group_id_field_name);
+ else
+ fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
+ selector_spec->name);
+ fprintf(f, "\t\t\t.n_selector_fields = "
+ "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
+ selector_spec->name,
+ selector_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
+ }
+
+ if (selector_spec->params.member_id_field_name)
+ fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
+ selector_spec->params.member_id_field_name);
+ else
+ fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
+
+ fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
+
+ fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
+ selector_spec->params.n_members_per_group_max);
+
+ fprintf(f, "\t\t},\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+ uint32_t j;
+
+ /* field_names. */
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "static const char *learner_%s_field_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_fields; j++) {
+ const char *field_name = learner_spec->params.field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (learner_spec->params.action_names && learner_spec->params.n_actions) {
+ fprintf(f, "static const char *learner_%s_action_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ const char *action_name = learner_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* timeout. */
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->n_timeouts; j++) {
+ uint32_t value = learner_spec->timeout[j];
+
+ fprintf(f, "\t[%d] = %u,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct learner_spec learners[] = {\n");
+
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
+ learner_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(learner_%s_field_names) / "
+ "sizeof(learner_%s_field_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "learner_%s_action_is_for_table_entries,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "learner_%s_action_is_for_default_entry,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = "
+ "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = NULL,\n");
+
+ if (learner_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ learner_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (learner_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ learner_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ learner_spec->params.default_action_is_const);
+
+ fprintf(f, "\t\t},\n");
+
+ fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
+
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
+ fprintf(f, "\t\t\t.n_timeouts = "
+ "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t.timeout = NULL,\n");
+ fprintf(f, "\t\t\t.n_timeouts = 0,\n");
+ }
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
+
+ for (j = 0; j < apply_spec->n_instructions; j++) {
+ const char *instr = apply_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct apply_spec apply[] = {\n");
+
+ for (i = 0; i < s->n_apply; i++) {
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
+ fprintf(f, "\t.n_instructions = "
+ "sizeof(apply%u_initial_instructions) / "
+ "sizeof(apply%u_initial_instructions[0]),\n",
+ i,
+ i);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* pipeline. */
+ fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
+ fprintf(f, "\t.extobjs = extobjs,\n");
+ fprintf(f, "\t.structs = structs,\n");
+ fprintf(f, "\t.headers = headers,\n");
+ fprintf(f, "\t.metadata = metadata,\n");
+ fprintf(f, "\t.actions = actions,\n");
+ fprintf(f, "\t.tables = tables,\n");
+ fprintf(f, "\t.selectors = selectors,\n");
+ fprintf(f, "\t.learners = learners,\n");
+ fprintf(f, "\t.regarrays = regarrays,\n");
+ fprintf(f, "\t.metarrays = metarrays,\n");
+ fprintf(f, "\t.apply = apply,\n");
+ fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
+ fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
+ fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
+ fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
+ fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
+ fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
+ fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
+ fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
+ fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
+ fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
+ fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
+ fprintf(f, "};\n");
+}
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 4f3a0b5958..707b99ba09 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,6 +206,11 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s);
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 5/9] pipeline: add API for pipeline code generation
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (2 preceding siblings ...)
2022-07-18 13:25 ` [PATCH V2 4/9] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
@ 2022-07-18 13:25 ` Cristian Dumitrescu
2022-07-18 13:26 ` [PATCH V2 6/9] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
` (4 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:25 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the C code generation for the pipeline was hidden under
the hood; now, we make this an explicit API operation. Besides the
functions for the pipeline actions and the pipeline instructions,
the generated C source code now includes the pipeline specification
structure required for the pipeline configuration operations.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline.c | 94 +++++++++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline.h | 25 +++++++++
lib/pipeline/version.map | 3 ++
3 files changed, 122 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 3e1c6e9edb..52760111fd 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -18,6 +18,7 @@
#include <rte_swx_table_wm.h>
#include "rte_swx_pipeline_internal.h"
+#include "rte_swx_pipeline_spec.h"
#define CHECK(condition, err_code) \
do { \
@@ -13476,3 +13477,96 @@ pipeline_compile(struct rte_swx_pipeline *p)
return status;
}
+
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg)
+
+{
+ struct rte_swx_pipeline *p = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!spec_file || !code_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ status = rte_swx_pipeline_config(&p, 0);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline configuration error.";
+ goto free;
+ }
+
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto free;
+ }
+
+ /*
+ * Pipeline code generation.
+ */
+
+ /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
+ * but there is no need for the pipeline build to be done as well.
+ */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
+ goto free;
+ }
+
+ /* Header file inclusion. */
+ fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
+ fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
+
+ /* Code generation for the pipeline specification. */
+ pipeline_spec_codegen(code_file, s);
+ fprintf(code_file, "\n");
+
+ /* Code generation for the action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
+
+ action_data_codegen(a, code_file);
+ fprintf(code_file, "\n");
+
+ action_instr_codegen(a, code_file);
+ fprintf(code_file, "\n");
+ }
+
+ /* Code generation for the pipeline instructions. */
+ instruction_group_list_codegen(igl, p, code_file);
+
+free:
+ instruction_group_list_free(igl);
+ rte_swx_pipeline_free(p);
+ pipeline_spec_free(s);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index c41ca5cb15..2bd019b05f 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -941,6 +941,31 @@ __rte_experimental
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p);
+/**
+ * Pipeline C code generate based on input specification file
+ *
+ * @param[in] spec_file
+ * Pipeline specification file (.spec) provided as input.
+ * @param[in] code_file
+ * Pipeline C language file (.c) to be generated.
+ * @param[out] err_line
+ * In case of error and non-NULL, the line number within the *spec* file where
+ * the error occurred. The first line number in the file is 1.
+ * @param[out] err_msg
+ * In case of error and non-NULL, the error message.
+ * @return
+ * 0 on success or the following error codes otherwise:
+ * -EINVAL: Invalid argument;
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Resource with the same name already exists.
+ */
+__rte_experimental
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg);
+
/**
* Pipeline build from specification file
*
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8312307a7a..51165d48cf 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -145,4 +145,7 @@ EXPERIMENTAL {
rte_swx_ctl_pipeline_learner_timeout_get;
rte_swx_ctl_pipeline_learner_timeout_set;
rte_swx_pipeline_hash_func_register;
+
+ #added in 22.11
+ rte_swx_pipeline_codegen;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 6/9] pipeline: add API for shared library-based pipeline build
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (3 preceding siblings ...)
2022-07-18 13:25 ` [PATCH V2 5/9] pipeline: add API for pipeline code generation Cristian Dumitrescu
@ 2022-07-18 13:26 ` Cristian Dumitrescu
2022-07-18 13:26 ` [PATCH V2 7/9] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
` (3 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:26 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the pipeline build operation was done based on the
specification file (typically produced by the P4 compiler), then the C
code with optimized functions for the pipeline actions and
instructions was generated, built into a shared object library, loaded
and installed into the pipeline in a completely hardcoded and
non-customizable way.
Now, this process is split into three explicit stages:
i) code generation (specification file -> C file);
ii) code build (C file -> shared object library);
iii) code installation (library load into the pipeline).
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 20 +-
lib/pipeline/rte_swx_pipeline.c | 289 +++++++++------------------
lib/pipeline/rte_swx_pipeline.h | 22 +-
lib/pipeline/rte_swx_pipeline_spec.c | 51 -----
lib/pipeline/version.map | 2 +-
5 files changed, 108 insertions(+), 276 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ad553f19ab..1f75b5dc9d 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -984,7 +984,7 @@ cmd_pipeline_port_out(char **tokens,
}
static const char cmd_pipeline_build_help[] =
-"pipeline <pipeline_name> build <spec_file>\n";
+"pipeline <pipeline_name> build <lib_file>\n";
static void
cmd_pipeline_build(char **tokens,
@@ -994,9 +994,6 @@ cmd_pipeline_build(char **tokens,
void *obj)
{
struct pipeline *p = NULL;
- FILE *spec = NULL;
- uint32_t err_line;
- const char *err_msg;
int status;
if (n_tokens != 4) {
@@ -1010,20 +1007,9 @@ cmd_pipeline_build(char **tokens,
return;
}
- spec = fopen(tokens[3], "r");
- if (!spec) {
- snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
- return;
- }
-
- status = rte_swx_pipeline_build_from_spec(p->p,
- spec,
- &err_line,
- &err_msg);
- fclose(spec);
+ status = rte_swx_pipeline_build_from_lib(p->p, tokens[3]);
if (status) {
- snprintf(out, out_size, "Error %d at line %u: %s\n.",
- status, err_line, err_msg);
+ snprintf(out, out_size, "Pipeline build error (%d).", status);
return;
}
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 52760111fd..03414bfd1f 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9807,9 +9807,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
return 0;
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p);
-
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
{
@@ -9899,8 +9896,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
p->build_done = 1;
- pipeline_compile(p);
-
return 0;
error:
@@ -13222,160 +13217,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *
return n_custom_instr;
}
-static int
-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- FILE *f = NULL;
-
- /* Create the .c file. */
- f = fopen("/tmp/pipeline.c", "w");
- if (!f)
- return -EIO;
-
- /* Include the .h file. */
- fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
-
- /* Add the code for each action. */
- TAILQ_FOREACH(a, &p->actions, node) {
- fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
-
- action_data_codegen(a, f);
-
- fprintf(f, "\n");
-
- action_instr_codegen(a, f);
-
- fprintf(f, "\n");
- }
-
- /* Add the pipeline code. */
- instruction_group_list_codegen(igl, p, f);
-
- /* Close the .c file. */
- fclose(f);
-
- return 0;
-}
-
-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
-#endif
-
-static int
-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- struct instruction_group *g;
- char *dir_in, *buffer = NULL;
- const char *dir_out;
- int status = 0;
-
- /* Get the environment variables. */
- dir_in = getenv("RTE_INSTALL_DIR");
- if (!dir_in) {
- status = -EINVAL;
- goto free;
- }
-
- dir_out = "/tmp";
-
- /* Memory allocation for the command buffer. */
- buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
- if (!buffer) {
- status = -ENOMEM;
- goto free;
- }
-
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
- "-I %s/lib/pipeline "
- "-I %s/lib/eal/include "
- "-I %s/lib/eal/x86/include "
- "-I %s/lib/eal/include/generic "
- "-I %s/lib/meter "
- "-I %s/lib/port "
- "-I %s/lib/table "
- "-I %s/lib/pipeline "
- "-I %s/config "
- "-I %s/build "
- "-I %s/lib/eal/linux/include "
- ">%s/pipeline.log 2>&1 "
- "&& "
- "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
- ">>%s/pipeline.log 2>&1",
- dir_out,
- dir_out,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_out,
- dir_out,
- dir_out,
- dir_out);
-
- /* Build the shared object library. */
- status = system(buffer);
- if (status)
- goto free;
-
- /* Open library. */
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "%s/libpipeline.so",
- dir_out);
-
- p->lib = dlopen(buffer, RTLD_LAZY);
- if (!p->lib) {
- status = -EIO;
- goto free;
- }
-
- /* Get the action function symbols. */
- TAILQ_FOREACH(a, &p->actions, node) {
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
-
- p->action_funcs[a->id] = dlsym(p->lib, buffer);
- if (!p->action_funcs[a->id]) {
- status = -EINVAL;
- goto free;
- }
- }
-
- /* Get the pipeline function symbols. */
- TAILQ_FOREACH(g, igl, node) {
- if (g->first_instr_id == g->last_instr_id)
- continue;
-
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
-
- g->func = dlsym(p->lib, buffer);
- if (!g->func) {
- status = -EINVAL;
- goto free;
- }
- }
-
-free:
- if (status && p->lib) {
- dlclose(p->lib);
- p->lib = NULL;
- }
-
- free(buffer);
-
- return status;
-}
-
static int
pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
struct instruction_group_list *igl)
@@ -13443,41 +13284,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p)
-{
- struct instruction_group_list *igl = NULL;
- int status = 0;
-
- igl = instruction_group_list_create(p);
- if (!igl) {
- status = -ENOMEM;
- goto free;
- }
-
- /* Code generation. */
- status = pipeline_codegen(p, igl);
- if (status)
- goto free;
-
- /* Build and load the shared object library. */
- status = pipeline_libload(p, igl);
- if (status)
- goto free;
-
- /* Adjust instructions. */
- status = pipeline_adjust_check(p, igl);
- if (status)
- goto free;
-
- pipeline_adjust(p, igl);
-
-free:
- instruction_group_list_free(igl);
-
- return status;
-}
-
int
rte_swx_pipeline_codegen(FILE *spec_file,
FILE *code_file,
@@ -13570,3 +13376,98 @@ rte_swx_pipeline_codegen(FILE *spec_file,
return status;
}
+
+int
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline *p,
+ const char *lib_file_name)
+{
+ void *lib = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ struct instruction_group *g;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!p || p->build_done || !lib_file_name || !lib_file_name[0]) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Open the library. */
+ lib = dlopen(lib_file_name, RTLD_LAZY);
+ if (!lib) {
+ status = -EIO;
+ goto free;
+ }
+
+ /* Get the pipeline specification structure from the library. */
+ s = dlsym(lib, "pipeline_spec");
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration based on the specification structure. */
+ status = pipeline_spec_configure(p, s, NULL);
+ if (status)
+ goto free;
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status)
+ goto free;
+
+ /* Action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ snprintf(name, sizeof(name), "action_%s_run", a->name);
+
+ p->action_funcs[a->id] = dlsym(lib, name);
+ if (!p->action_funcs[a->id]) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ /* Pipeline instructions. */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ status = -ENOMEM;
+ goto free;
+ }
+
+ TAILQ_FOREACH(g, igl, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ if (g->first_instr_id == g->last_instr_id)
+ continue;
+
+ snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
+
+ g->func = dlsym(lib, name);
+ if (!g->func) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ status = pipeline_adjust_check(p, igl);
+ if (status)
+ goto free;
+
+ pipeline_adjust(p, igl);
+
+ p->lib = lib;
+
+free:
+ if (status && lib) {
+ dlclose(lib);
+ p->lib = NULL;
+ }
+
+ instruction_group_list_free(igl);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 2bd019b05f..cb834cd64d 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -967,30 +967,26 @@ rte_swx_pipeline_codegen(FILE *spec_file,
const char **err_msg);
/**
- * Pipeline build from specification file
+ * Pipeline build from shared object library
+ *
+ * The shared object library must be built from the C language source code file
+ * previously generated by the rte_swx_pipeline_codegen() API function.
*
* @param[in] p
* Pipeline handle.
- * @param[in] spec
- * Pipeline specification file.
- * @param[out] err_line
- * In case of error and non-NULL, the line number within the *spec* file where
- * the error occurred. The first line number in the file is 1.
- * @param[out] err_msg
- * In case of error and non-NULL, the error message.
+ * @param[in] lib_file_name
+ * Shared object library file name.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
- * -EEXIST: Resource with the same name already exists;
+ * -EEXIST: Pipeline was already built successfully;
* -ENODEV: Extern object or table creation error.
*/
__rte_experimental
int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg);
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline *p,
+ const char *lib_file_name);
/**
* Pipeline run
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index bf21fe17ba..d6650fcc80 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -3515,54 +3515,3 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,
return 0;
}
-
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec_file,
- uint32_t *err_line,
- const char **err_msg)
-{
- struct pipeline_spec *s = NULL;
- int status = 0;
-
- /* Check the input arguments. */
- if (!p || !spec_file) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Invalid input argument.";
- status = -EINVAL;
- goto error;
- }
-
- /* Spec file parse. */
- s = pipeline_spec_parse(spec_file, err_line, err_msg);
- if (!s) {
- status = -EINVAL;
- goto error;
- }
-
- /* Pipeline configure. */
- status = pipeline_spec_configure(p, s, err_msg);
- if (status) {
- if (err_line)
- *err_line = 0;
- goto error;
- }
-
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
-
-error:
- pipeline_spec_free(s);
- return status;
-}
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 51165d48cf..810cc56467 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -82,7 +82,6 @@ EXPERIMENTAL {
rte_swx_ctl_table_ops_get;
rte_swx_pipeline_action_config;
rte_swx_pipeline_build;
- rte_swx_pipeline_build_from_spec;
rte_swx_pipeline_config;
rte_swx_pipeline_extern_func_register;
rte_swx_pipeline_extern_object_config;
@@ -148,4 +147,5 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_pipeline_codegen;
+ rte_swx_pipeline_build_from_lib;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 7/9] examples/pipeline: add CLI command for pipeline code generation
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (4 preceding siblings ...)
2022-07-18 13:26 ` [PATCH V2 6/9] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
@ 2022-07-18 13:26 ` Cristian Dumitrescu
2022-07-18 13:26 ` [PATCH V2 8/9] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
` (2 subsequent siblings)
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:26 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the pipeline code generation operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 1f75b5dc9d..fdaf5dd16b 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -983,6 +983,53 @@ cmd_pipeline_port_out(char **tokens,
}
}
+static const char cmd_pipeline_codegen_help[] =
+"pipeline codegen <spec_file> <code_file>\n";
+
+static void
+cmd_pipeline_codegen(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ FILE *spec_file = NULL;
+ FILE *code_file = NULL;
+ uint32_t err_line;
+ const char *err_msg;
+ int status;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ spec_file = fopen(tokens[2], "r");
+ if (!spec_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+ return;
+ }
+
+ code_file = fopen(tokens[3], "w");
+ if (!code_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ return;
+ }
+
+ status = rte_swx_pipeline_codegen(spec_file,
+ code_file,
+ &err_line,
+ &err_msg);
+
+ fclose(spec_file);
+ fclose(code_file);
+
+ if (status) {
+ snprintf(out, out_size, "Error %d at line %u: %s\n.",
+ status, err_line, err_msg);
+ return;
+ }
+}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build <lib_file>\n";
@@ -2962,6 +3009,7 @@ cmd_help(char **tokens,
"\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
+ "\tpipeline codegen\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3031,6 +3079,12 @@ cmd_help(char **tokens,
}
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3309,6 +3363,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "codegen") == 0)) {
+ cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 8/9] examples/pipeline: add CLI command for shared library build
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (5 preceding siblings ...)
2022-07-18 13:26 ` [PATCH V2 7/9] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
@ 2022-07-18 13:26 ` Cristian Dumitrescu
2022-07-18 13:26 ` [PATCH V2 9/9] examples/pipeline: call CLI commands for code generation and build Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:26 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the shared object library build operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 147 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 143 insertions(+), 4 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index fdaf5dd16b..f1d2fbf52d 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_ethdev.h>
@@ -25,6 +26,10 @@
#define CMD_MAX_TOKENS 256
#endif
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
@@ -1030,6 +1035,130 @@ cmd_pipeline_codegen(char **tokens,
return;
}
}
+
+static const char cmd_pipeline_libbuild_help[] =
+"pipeline libbuild <code_file> <lib_file>\n";
+
+static void
+cmd_pipeline_libbuild(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+ char *install_dir, *buffer = NULL;
+ size_t length;
+ int status = 0;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ goto free;
+ }
+
+ install_dir = getenv("RTE_INSTALL_DIR");
+ if (!install_dir) {
+ snprintf(out, out_size, "Error: Environment variable RTE_INSTALL_DIR is not set.");
+ return;
+ }
+
+ snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+ out_size -= strlen(out);
+ out += strlen(out);
+
+ code_file = tokens[2];
+ length = strnlen(code_file, MAX_LINE_SIZE);
+ if ((length < 3) ||
+ (code_file[length - 2] != '.') ||
+ (code_file[length - 1] != 'c')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+ goto free;
+ }
+
+ lib_file = tokens[3];
+ length = strnlen(lib_file, MAX_LINE_SIZE);
+ if ((length < 4) ||
+ (lib_file[length - 3] != '.') ||
+ (lib_file[length - 2] != 's') ||
+ (lib_file[length - 1] != 'o')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+ goto free;
+ }
+
+ obj_file = malloc(length);
+ log_file = malloc(length + 2);
+ if (!obj_file || !log_file) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ memcpy(obj_file, lib_file, length - 2);
+ obj_file[length - 2] = 'o';
+ obj_file[length - 1] = 0;
+
+ memcpy(log_file, lib_file, length - 2);
+ log_file[length - 2] = 'l';
+ log_file[length - 1] = 'o';
+ log_file[length] = 'g';
+ log_file[length + 1] = 0;
+
+ buffer = malloc(MAX_LINE_SIZE);
+ if (!buffer) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ return;
+ }
+
+ snprintf(buffer,
+ MAX_LINE_SIZE,
+ "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+ "-I %s/lib/pipeline "
+ "-I %s/lib/eal/include "
+ "-I %s/lib/eal/x86/include "
+ "-I %s/lib/eal/include/generic "
+ "-I %s/lib/meter "
+ "-I %s/lib/port "
+ "-I %s/lib/table "
+ "-I %s/lib/pipeline "
+ "-I %s/config "
+ "-I %s/build "
+ "-I %s/lib/eal/linux/include "
+ ">%s 2>&1 "
+ "&& "
+ "gcc -shared %s -o %s "
+ ">>%s 2>&1",
+ obj_file,
+ code_file,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ log_file,
+ obj_file,
+ lib_file,
+ log_file);
+
+ status = system(buffer);
+ if (status) {
+ snprintf(out,
+ out_size,
+ "Library build failed, see file \"%s\" for details.\n",
+ log_file);
+ goto free;
+ }
+
+free:
+ free(obj_file);
+ free(log_file);
+ free(buffer);
+}
+
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build <lib_file>\n";
@@ -1080,10 +1209,6 @@ table_entry_free(struct rte_swx_table_entry *entry)
free(entry);
}
-#ifndef MAX_LINE_SIZE
-#define MAX_LINE_SIZE 2048
-#endif
-
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
@@ -3010,6 +3135,7 @@ cmd_help(char **tokens,
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
+ "\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3085,6 +3211,12 @@ cmd_help(char **tokens,
return;
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3370,6 +3502,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "libbuild") == 0)) {
+ cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V2 9/9] examples/pipeline: call CLI commands for code generation and build
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (6 preceding siblings ...)
2022-07-18 13:26 ` [PATCH V2 8/9] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
@ 2022-07-18 13:26 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
8 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-18 13:26 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Update the example CLI scripts with the commands for code generation
and shared object library build.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/examples/fib.cli | 8 +++++++-
examples/pipeline/examples/hash_func.cli | 8 +++++++-
examples/pipeline/examples/l2fwd.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_macswp.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_macswp_pcap.cli | 8 +++++++-
examples/pipeline/examples/l2fwd_pcap.cli | 8 +++++++-
examples/pipeline/examples/learner.cli | 8 +++++++-
examples/pipeline/examples/meter.cli | 8 +++++++-
examples/pipeline/examples/mirroring.cli | 8 +++++++-
examples/pipeline/examples/recirculation.cli | 8 +++++++-
examples/pipeline/examples/registers.cli | 8 +++++++-
examples/pipeline/examples/selector.cli | 8 +++++++-
examples/pipeline/examples/varbit.cli | 8 +++++++-
examples/pipeline/examples/vxlan.cli | 8 +++++++-
examples/pipeline/examples/vxlan_pcap.cli | 8 +++++++-
15 files changed, 105 insertions(+), 15 deletions(-)
diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli
index 93ab2b08f8..8b55175bf3 100644
--- a/examples/pipeline/examples/fib.cli
+++ b/examples/pipeline/examples/fib.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/fib.spec /tmp/fib.c
+pipeline libbuild /tmp/fib.c /tmp/fib.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/fib.spec
+pipeline PIPELINE0 build /tmp/fib.so
;
; Initial set of table entries.
diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli
index d65cd62d17..f7bb28b28b 100644
--- a/examples/pipeline/examples/hash_func.cli
+++ b/examples/pipeline/examples/hash_func.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/hash_func.spec /tmp/hash_func.c
+pipeline libbuild /tmp/hash_func.c /tmp/hash_func.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/hash_func.spec
+pipeline PIPELINE0 build /tmp/hash_func.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli
index d89caf2d0a..a71727309b 100644
--- a/examples/pipeline/examples/l2fwd.cli
+++ b/examples/pipeline/examples/l2fwd.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,6 +26,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+pipeline PIPELINE0 build /tmp/l2fwd.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli
index 0f2a89ac5b..d8f5f9f735 100644
--- a/examples/pipeline/examples/l2fwd_macswp.cli
+++ b/examples/pipeline/examples/l2fwd_macswp.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,6 +26,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+pipeline PIPELINE0 build /tmp/l2fwd_macswp.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
index e9656fe3c2..bd077876ff 100644
--- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,6 +21,6 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+pipeline PIPELINE0 build /tmp/l2fwd_macswp.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli
index 23fcb199f1..2e56a116af 100644
--- a/examples/pipeline/examples/l2fwd_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,6 +21,6 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+pipeline PIPELINE0 build /tmp/l2fwd.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli
index 688ce34f34..10eb2af417 100644
--- a/examples/pipeline/examples/learner.cli
+++ b/examples/pipeline/examples/learner.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/learner.spec /tmp/learner.c
+pipeline libbuild /tmp/learner.c /tmp/learner.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/learner.spec
+pipeline PIPELINE0 build /tmp/learner.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli
index b29ed24022..9c22014f46 100644
--- a/examples/pipeline/examples/meter.cli
+++ b/examples/pipeline/examples/meter.cli
@@ -4,6 +4,12 @@
; Example command line:
; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/meter.spec /tmp/meter.c
+pipeline libbuild /tmp/meter.c /tmp/meter.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -23,7 +29,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/meter.spec
+pipeline PIPELINE0 build /tmp/meter.so
pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli
index 46d57db4ec..9614f64d38 100644
--- a/examples/pipeline/examples/mirroring.cli
+++ b/examples/pipeline/examples/mirroring.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/mirroring.spec /tmp/mirroring.c
+pipeline libbuild /tmp/mirroring.c /tmp/mirroring.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -27,7 +33,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/mirroring.spec
+pipeline PIPELINE0 build /tmp/mirroring.so
;
; Packet mirroring sessions.
diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli
index f855c5c327..bd114e91cd 100644
--- a/examples/pipeline/examples/recirculation.cli
+++ b/examples/pipeline/examples/recirculation.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/recirculation.spec /tmp/recirculation.c
+pipeline libbuild /tmp/recirculation.c /tmp/recirculation.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/recirculation.spec
+pipeline PIPELINE0 build /tmp/recirculation.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli
index 8d026294cb..3d9eeb0d5c 100644
--- a/examples/pipeline/examples/registers.cli
+++ b/examples/pipeline/examples/registers.cli
@@ -4,6 +4,12 @@
; Example command line:
; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/registers.spec /tmp/registers.c
+pipeline libbuild /tmp/registers.c /tmp/registers.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -23,6 +29,6 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/registers.spec
+pipeline PIPELINE0 build /tmp/registers.so
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli
index 123782c57b..6c7d032b10 100644
--- a/examples/pipeline/examples/selector.cli
+++ b/examples/pipeline/examples/selector.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/selector.spec /tmp/selector.c
+pipeline libbuild /tmp/selector.c /tmp/selector.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,7 +26,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/selector.spec
+pipeline PIPELINE0 build /tmp/selector.so
pipeline PIPELINE0 selector s group add
pipeline PIPELINE0 selector s group member add ./examples/pipeline/examples/selector.txt
diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli
index 9caeb9ca26..545cde262e 100644
--- a/examples/pipeline/examples/varbit.cli
+++ b/examples/pipeline/examples/varbit.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/varbit.spec /tmp/varbit.c
+pipeline libbuild /tmp/varbit.c /tmp/varbit.so
+
;
; Customize the LINK parameters to match your setup.
;
@@ -26,7 +32,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/varbit.spec
+pipeline PIPELINE0 build /tmp/varbit.so
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli
index 444f3f7bd8..321a28ba44 100644
--- a/examples/pipeline/examples/vxlan.cli
+++ b/examples/pipeline/examples/vxlan.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
@@ -20,7 +26,7 @@ pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+pipeline PIPELINE0 build /tmp/vxlan.so
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli
index 83fca8d0d9..596169f933 100644
--- a/examples/pipeline/examples/vxlan_pcap.cli
+++ b/examples/pipeline/examples/vxlan_pcap.cli
@@ -1,6 +1,12 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+;
+; Pipeline code generation & shared object library build
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
+
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
pipeline PIPELINE0 create 0
@@ -15,7 +21,7 @@ pipeline PIPELINE0 port out 1 sink none
pipeline PIPELINE0 port out 2 sink none
pipeline PIPELINE0 port out 3 sink none
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+pipeline PIPELINE0 build /tmp/vxlan.so
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 01/17] pipeline: add pipeline name
2022-07-18 13:25 ` [PATCH V2 1/9] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (7 preceding siblings ...)
2022-07-18 13:26 ` [PATCH V2 9/9] examples/pipeline: call CLI commands for code generation and build Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (16 more replies)
8 siblings, 17 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add an unique name to every pipeline. This enables the library to
maintain a list of the existing pipeline objects, which can be
queried by the application.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/obj.c | 2 +-
lib/pipeline/rte_swx_ctl.c | 99 +++++++++++++++++++++
lib/pipeline/rte_swx_ctl.h | 15 ++++
lib/pipeline/rte_swx_pipeline.c | 107 ++++++++++++++++++++++-
lib/pipeline/rte_swx_pipeline.h | 18 +++-
lib/pipeline/rte_swx_pipeline_internal.h | 2 +
lib/pipeline/version.map | 4 +
7 files changed, 244 insertions(+), 3 deletions(-)
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index b79f044ac7..967342c580 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -533,7 +533,7 @@ pipeline_create(struct obj *obj, const char *name, int numa_node)
return NULL;
/* Resource create */
- status = rte_swx_pipeline_config(&p, numa_node);
+ status = rte_swx_pipeline_config(&p, name, numa_node);
if (status)
goto error;
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 710e89a46a..1b776fc543 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -9,6 +9,8 @@
#include <rte_common.h>
#include <rte_byteorder.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_swx_table_selector.h>
@@ -1157,12 +1159,103 @@ table_state_create(struct rte_swx_ctl_pipeline *ctl)
return status;
}
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_ctl_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_ctl_pipeline_tailq = {
+ .name = "RTE_SWX_CTL_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_ctl_pipeline_tailq)
+
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_CTL_NAME_SIZE) >= RTE_SWX_CTL_NAME_SIZE))
+ return NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(name, ctl->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_read_unlock();
+ return ctl;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+ctl_register(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl_crt = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(ctl->info.name, ctl_crt->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)ctl;
+ TAILQ_INSERT_TAIL(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+ctl_unregister(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ if (te->data == (void *)ctl) {
+ TAILQ_REMOVE(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_ctl_pipeline_free(struct rte_swx_ctl_pipeline *ctl)
{
if (!ctl)
return;
+ if (ctl->info.name[0])
+ ctl_unregister(ctl);
+
action_free(ctl);
table_state_free(ctl);
@@ -1441,6 +1534,12 @@ rte_swx_ctl_pipeline_create(struct rte_swx_pipeline *p)
if (status)
goto error;
+ if (ctl->info.name[0]) {
+ status = ctl_register(ctl);
+ if (status)
+ goto error;
+ }
+
return ctl;
error:
diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h
index d771389d26..63ee479e47 100644
--- a/lib/pipeline/rte_swx_ctl.h
+++ b/lib/pipeline/rte_swx_ctl.h
@@ -35,6 +35,9 @@ struct rte_swx_pipeline;
/** Pipeline info. */
struct rte_swx_ctl_pipeline_info {
+ /** Pipeline name. */
+ char name[RTE_SWX_CTL_NAME_SIZE];
+
/** Number of input ports. */
uint32_t n_ports_in;
@@ -812,6 +815,18 @@ rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
/** Pipeline control opaque data structure. */
struct rte_swx_ctl_pipeline;
+/**
+ * Pipeline control find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline control handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name);
+
/**
* Pipeline control create
*
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 3e1c6e9edb..c8ccded4f8 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -6,6 +6,8 @@
#include <errno.h>
#include <dlfcn.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_jhash.h>
#include <rte_hash_crc.h>
@@ -9578,6 +9580,95 @@ metarray_free(struct rte_swx_pipeline *p)
/*
* Pipeline.
*/
+
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_pipeline_tailq = {
+ .name = "RTE_SWX_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
+
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
+ return NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(name, p->name, sizeof(p->name))) {
+ rte_mcfg_tailq_read_unlock();
+ return p;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+pipeline_register(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)p;
+ TAILQ_INSERT_TAIL(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+pipeline_unregister(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ if (te->data == (void *)p) {
+ TAILQ_REMOVE(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_pipeline_free(struct rte_swx_pipeline *p)
{
@@ -9586,6 +9677,9 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
if (!p)
return;
+ if (p->name[0])
+ pipeline_unregister(p);
+
lib = p->lib;
free(p->instruction_data);
@@ -9720,13 +9814,14 @@ hash_funcs_register(struct rte_swx_pipeline *p)
}
int
-rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
+rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
{
struct rte_swx_pipeline *pipeline = NULL;
int status = 0;
/* Check input parameters. */
CHECK(p, EINVAL);
+ CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
/* Memory allocation. */
pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
@@ -9736,6 +9831,9 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
}
/* Initialization. */
+ if (name)
+ strcpy(pipeline->name, name);
+
TAILQ_INIT(&pipeline->struct_types);
TAILQ_INIT(&pipeline->port_in_types);
TAILQ_INIT(&pipeline->ports_in);
@@ -9776,6 +9874,12 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
if (status)
goto error;
+ if (pipeline->name[0]) {
+ status = pipeline_register(pipeline);
+ if (status)
+ goto error;
+ }
+
*p = pipeline;
return 0;
@@ -9966,6 +10070,7 @@ rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
TAILQ_FOREACH(table, &p->tables, node)
n_tables++;
+ strcpy(pipeline->name, p->name);
pipeline->n_ports_in = p->n_ports_in;
pipeline->n_ports_out = p->n_ports_out;
pipeline->n_mirroring_slots = p->n_mirroring_slots;
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index c41ca5cb15..ef50a0fa70 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -44,22 +44,38 @@ extern "C" {
/** Pipeline opaque data structure. */
struct rte_swx_pipeline;
+/**
+ * Pipeline find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name);
+
/**
* Pipeline configure
*
* @param[out] p
* Pipeline handle. Must point to valid memory. Contains valid pipeline handle
* when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
* @param[in] numa_node
* Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
- * -ENOMEM: Not enough space/cannot allocate memory.
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Pipeline with this name already exists.
*/
__rte_experimental
int
rte_swx_pipeline_config(struct rte_swx_pipeline **p,
+ const char *name,
int numa_node);
/*
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index a35635efb7..588cad62b5 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -1459,6 +1459,8 @@ instr_operand_nbo(struct thread *t, const struct instr_operand *x)
#endif
struct rte_swx_pipeline {
+ char name[RTE_SWX_NAME_SIZE];
+
struct struct_type_tailq struct_types;
struct port_in_type_tailq port_in_types;
struct port_in_tailq ports_in;
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8312307a7a..50029aadcf 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -145,4 +145,8 @@ EXPERIMENTAL {
rte_swx_ctl_pipeline_learner_timeout_get;
rte_swx_ctl_pipeline_learner_timeout_set;
rte_swx_pipeline_hash_func_register;
+
+ #added in 22.11
+ rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 02/17] pipeline: move specification data structures to internal header
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
` (15 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Move all the pipeline object specification data structures to an
internal header file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 126 +------------------
lib/pipeline/rte_swx_pipeline_spec.h | 176 +++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 125 deletions(-)
create mode 100644 lib/pipeline/rte_swx_pipeline_spec.h
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 904b9eb471..5e07b4f794 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,7 +9,7 @@
#include <rte_common.h>
-#include "rte_swx_pipeline.h"
+#include "rte_swx_pipeline_spec.h"
#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 2048
@@ -34,15 +34,7 @@
/*
* extobj.
- *
- * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
*/
-struct extobj_spec {
- char *name;
- char *extern_type_name;
- char *pragma;
-};
-
static void
extobj_spec_free(struct extobj_spec *s)
{
@@ -104,18 +96,7 @@ extobj_statement_parse(struct extobj_spec *s,
/*
* struct.
*
- * struct STRUCT_TYPE_NAME {
- * bit<SIZE> | varbit<SIZE> FIELD_NAME
- * ...
- * }
*/
-struct struct_spec {
- char *name;
- struct rte_swx_field_params *fields;
- uint32_t n_fields;
- int varbit;
-};
-
static void
struct_spec_free(struct struct_spec *s)
{
@@ -293,13 +274,7 @@ struct_block_parse(struct struct_spec *s,
/*
* header.
*
- * header HEADER_NAME instanceof STRUCT_TYPE_NAME
*/
-struct header_spec {
- char *name;
- char *struct_type_name;
-};
-
static void
header_spec_free(struct header_spec *s)
{
@@ -351,12 +326,7 @@ header_statement_parse(struct header_spec *s,
/*
* metadata.
*
- * metadata instanceof STRUCT_TYPE_NAME
*/
-struct metadata_spec {
- char *struct_type_name;
-};
-
static void
metadata_spec_free(struct metadata_spec *s)
{
@@ -400,18 +370,7 @@ metadata_statement_parse(struct metadata_spec *s,
/*
* action.
*
- * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
- * INSTRUCTION
- * ...
- * }
*/
-struct action_spec {
- char *name;
- char *args_struct_type_name;
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
action_spec_free(struct action_spec *s)
{
@@ -540,29 +499,7 @@ action_block_parse(struct action_spec *s,
/*
* table.
*
- * table TABLE_NAME {
- * key {
- * MATCH_FIELD_NAME exact | wildcard | lpm
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly ]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * instanceof TABLE_TYPE_NAME
- * pragma ARGS
- * size SIZE
- * }
*/
-struct table_spec {
- char *name;
- struct rte_swx_pipeline_table_params params;
- char *recommended_table_type_name;
- char *args;
- uint32_t size;
-};
-
static void
table_spec_free(struct table_spec *s)
{
@@ -1084,22 +1021,7 @@ table_block_parse(struct table_spec *s,
/*
* selector.
*
- * selector SELECTOR_NAME {
- * group_id FIELD_NAME
- * selector {
- * FIELD_NAME
- * ...
- * }
- * member_id FIELD_NAME
- * n_groups N_GROUPS
- * n_members_per_group N_MEMBERS_PER_GROUP
- * }
*/
-struct selector_spec {
- char *name;
- struct rte_swx_pipeline_selector_params params;
-};
-
static void
selector_spec_free(struct selector_spec *s)
{
@@ -1385,31 +1307,7 @@ selector_block_parse(struct selector_spec *s,
/*
* learner.
*
- * learner LEARNER_NAME {
- * key {
- * MATCH_FIELD_NAME
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * size SIZE
- * timeout {
- * TIMEOUT_IN_SECONDS
- * ...
- * }
- * }
*/
-struct learner_spec {
- char *name;
- struct rte_swx_pipeline_learner_params params;
- uint32_t size;
- uint32_t *timeout;
- uint32_t n_timeouts;
-};
-
static void
learner_spec_free(struct learner_spec *s)
{
@@ -1958,14 +1856,7 @@ learner_block_parse(struct learner_spec *s,
/*
* regarray.
*
- * regarray NAME size SIZE initval INITVAL
*/
-struct regarray_spec {
- char *name;
- uint64_t init_val;
- uint32_t size;
-};
-
static void
regarray_spec_free(struct regarray_spec *s)
{
@@ -2033,13 +1924,7 @@ regarray_statement_parse(struct regarray_spec *s,
/*
* metarray.
*
- * metarray NAME size SIZE
*/
-struct metarray_spec {
- char *name;
- uint32_t size;
-};
-
static void
metarray_spec_free(struct metarray_spec *s)
{
@@ -2095,16 +1980,7 @@ metarray_statement_parse(struct metarray_spec *s,
/*
* apply.
*
- * apply {
- * INSTRUCTION
- * ...
- * }
*/
-struct apply_spec {
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
apply_spec_free(struct apply_spec *s)
{
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
new file mode 100644
index 0000000000..8458de878a
--- /dev/null
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+
+#include <rte_swx_pipeline.h>
+
+/*
+ * extobj.
+ *
+ * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
+ */
+struct extobj_spec {
+ char *name;
+ char *extern_type_name;
+ char *pragma;
+};
+
+/*
+ * struct.
+ *
+ * struct STRUCT_TYPE_NAME {
+ * bit<SIZE> | varbit<SIZE> FIELD_NAME
+ * ...
+ * }
+ */
+struct struct_spec {
+ char *name;
+ struct rte_swx_field_params *fields;
+ uint32_t n_fields;
+ int varbit;
+};
+
+/*
+ * header.
+ *
+ * header HEADER_NAME instanceof STRUCT_TYPE_NAME
+ */
+struct header_spec {
+ char *name;
+ char *struct_type_name;
+};
+
+/*
+ * metadata.
+ *
+ * metadata instanceof STRUCT_TYPE_NAME
+ */
+struct metadata_spec {
+ char *struct_type_name;
+};
+
+/*
+ * action.
+ *
+ * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct action_spec {
+ char *name;
+ char *args_struct_type_name;
+ const char **instructions;
+ uint32_t n_instructions;
+};
+
+/*
+ * table.
+ *
+ * table TABLE_NAME {
+ * key {
+ * MATCH_FIELD_NAME exact | wildcard | lpm
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly ]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * instanceof TABLE_TYPE_NAME
+ * pragma ARGS
+ * size SIZE
+ * }
+ */
+struct table_spec {
+ char *name;
+ struct rte_swx_pipeline_table_params params;
+ char *recommended_table_type_name;
+ char *args;
+ uint32_t size;
+};
+
+/*
+ * selector.
+ *
+ * selector SELECTOR_NAME {
+ * group_id FIELD_NAME
+ * selector {
+ * FIELD_NAME
+ * ...
+ * }
+ * member_id FIELD_NAME
+ * n_groups N_GROUPS
+ * n_members_per_group N_MEMBERS_PER_GROUP
+ * }
+ */
+struct selector_spec {
+ char *name;
+ struct rte_swx_pipeline_selector_params params;
+};
+
+/*
+ * learner.
+ *
+ * learner LEARNER_NAME {
+ * key {
+ * MATCH_FIELD_NAME
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * size SIZE
+ * timeout {
+ * TIMEOUT_IN_SECONDS
+ * ...
+ * }
+ * }
+ */
+struct learner_spec {
+ char *name;
+ struct rte_swx_pipeline_learner_params params;
+ uint32_t size;
+ uint32_t *timeout;
+ uint32_t n_timeouts;
+};
+
+/*
+ * regarray.
+ *
+ * regarray NAME size SIZE initval INITVAL
+ */
+struct regarray_spec {
+ char *name;
+ uint64_t init_val;
+ uint32_t size;
+};
+
+/*
+ * metarray.
+ *
+ * metarray NAME size SIZE
+ */
+struct metarray_spec {
+ char *name;
+ uint32_t size;
+};
+
+/*
+ * apply.
+ *
+ * apply {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct apply_spec {
+ const char **instructions;
+ uint32_t n_instructions;
+};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 03/17] pipeline: add pipeline specification data structure
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
` (14 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure for the entire pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 21 ++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 32 ++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5e07b4f794..642091b678 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2082,6 +2082,27 @@ apply_block_parse(struct apply_spec *s,
/*
* Pipeline.
*/
+void
+pipeline_spec_free(struct pipeline_spec *s)
+{
+ if (!s)
+ return;
+
+ free(s->extobjs);
+ free(s->structs);
+ free(s->headers);
+ free(s->metadata);
+ free(s->actions);
+ free(s->tables);
+ free(s->selectors);
+ free(s->learners);
+ free(s->regarrays);
+ free(s->metarrays);
+ free(s->apply);
+
+ memset(s, 0, sizeof(struct pipeline_spec));
+}
+
int
rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
FILE *spec,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 8458de878a..e1170a33b1 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -174,3 +174,35 @@ struct apply_spec {
const char **instructions;
uint32_t n_instructions;
};
+
+/*
+ * Pipeline.
+ */
+struct pipeline_spec {
+ struct extobj_spec *extobjs;
+ struct struct_spec *structs;
+ struct header_spec *headers;
+ struct metadata_spec *metadata;
+ struct action_spec *actions;
+ struct table_spec *tables;
+ struct selector_spec *selectors;
+ struct learner_spec *learners;
+ struct regarray_spec *regarrays;
+ struct metarray_spec *metarrays;
+ struct apply_spec *apply;
+
+ uint32_t n_extobjs;
+ uint32_t n_structs;
+ uint32_t n_headers;
+ uint32_t n_metadata;
+ uint32_t n_actions;
+ uint32_t n_tables;
+ uint32_t n_selectors;
+ uint32_t n_learners;
+ uint32_t n_regarrays;
+ uint32_t n_metarrays;
+ uint32_t n_apply;
+};
+
+void
+pipeline_spec_free(struct pipeline_spec *s);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 04/17] pipeline: rework the specification file-based pipeline build
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
` (13 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the specification file-based pipeline build operation to first
parse the specification file into the previously introduced pipeline
specification data structure, then use this structure to configure
and build the pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 478 +++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline_spec.h | 9 +
2 files changed, 385 insertions(+), 102 deletions(-)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 642091b678..62929a9da6 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2103,11 +2103,10 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg)
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
{
struct extobj_spec extobj_spec = {0};
struct struct_spec struct_spec = {0};
@@ -2120,26 +2119,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0};
- uint32_t n_lines;
+ struct pipeline_spec *s = NULL;
+ uint32_t n_lines = 0;
uint32_t block_mask = 0;
- int status;
+ int status = 0;
/* Check the input arguments. */
- if (!p) {
+ if (!spec) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null pipeline argument.";
+ *err_msg = "Invalid input argument.";
status = -EINVAL;
goto error;
}
- if (!spec) {
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_spec), 1);
+ if (!s) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null specification file argument.";
- status = -EINVAL;
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
@@ -2200,6 +2202,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* struct block. */
if (block_mask & (1 << STRUCT_BLOCK)) {
+ struct struct_spec *new_structs;
+
status = struct_block_parse(&struct_spec,
&block_mask,
tokens,
@@ -2214,26 +2218,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_struct_type_register(p,
- struct_spec.name,
- struct_spec.fields,
- struct_spec.n_fields,
- struct_spec.varbit);
- if (status) {
+ new_structs = realloc(s->structs,
+ (s->n_structs + 1) * sizeof(struct struct_spec));
+ if (!new_structs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Struct registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- struct_spec_free(&struct_spec);
+ s->structs = new_structs;
+ memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
+ s->n_structs++;
+ memset(&struct_spec, 0, sizeof(struct struct_spec));
continue;
}
/* action block. */
if (block_mask & (1 << ACTION_BLOCK)) {
+ struct action_spec *new_actions;
+
status = action_block_parse(&action_spec,
&block_mask,
tokens,
@@ -2248,26 +2255,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_action_config(p,
- action_spec.name,
- action_spec.args_struct_type_name,
- action_spec.instructions,
- action_spec.n_instructions);
- if (status) {
+ new_actions = realloc(s->actions,
+ (s->n_actions + 1) * sizeof(struct action_spec));
+ if (!new_actions) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Action config error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- action_spec_free(&action_spec);
+ s->actions = new_actions;
+ memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
+ s->n_actions++;
+ memset(&action_spec, 0, sizeof(struct action_spec));
continue;
}
/* table block. */
if (block_mask & (1 << TABLE_BLOCK)) {
+ struct table_spec *new_tables;
+
status = table_block_parse(&table_spec,
&block_mask,
tokens,
@@ -2282,27 +2292,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_table_config(p,
- table_spec.name,
- &table_spec.params,
- table_spec.recommended_table_type_name,
- table_spec.args,
- table_spec.size);
- if (status) {
+ new_tables = realloc(s->tables,
+ (s->n_tables + 1) * sizeof(struct table_spec));
+ if (!new_tables) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- table_spec_free(&table_spec);
+ s->tables = new_tables;
+ memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
+ s->n_tables++;
+ memset(&table_spec, 0, sizeof(struct table_spec));
continue;
}
/* selector block. */
if (block_mask & (1 << SELECTOR_BLOCK)) {
+ struct selector_spec *new_selectors;
+
status = selector_block_parse(&selector_spec,
&block_mask,
tokens,
@@ -2317,24 +2329,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_selector_config(p,
- selector_spec.name,
- &selector_spec.params);
- if (status) {
+ new_selectors = realloc(s->selectors,
+ (s->n_selectors + 1) * sizeof(struct selector_spec));
+ if (!new_selectors) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Selector configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- selector_spec_free(&selector_spec);
+ s->selectors = new_selectors;
+ memcpy(&s->selectors[s->n_selectors],
+ &selector_spec,
+ sizeof(struct selector_spec));
+ s->n_selectors++;
+ memset(&selector_spec, 0, sizeof(struct selector_spec));
continue;
}
/* learner block. */
if (block_mask & (1 << LEARNER_BLOCK)) {
+ struct learner_spec *new_learners;
+
status = learner_block_parse(&learner_spec,
&block_mask,
tokens,
@@ -2349,27 +2368,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_learner_config(p,
- learner_spec.name,
- &learner_spec.params,
- learner_spec.size,
- learner_spec.timeout,
- learner_spec.n_timeouts);
- if (status) {
+ new_learners = realloc(s->learners,
+ (s->n_learners + 1) * sizeof(struct learner_spec));
+ if (!new_learners) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Learner table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- learner_spec_free(&learner_spec);
+ s->learners = new_learners;
+ memcpy(&s->learners[s->n_learners],
+ &learner_spec,
+ sizeof(struct learner_spec));
+ s->n_learners++;
+ memset(&learner_spec, 0, sizeof(struct learner_spec));
continue;
}
/* apply block. */
if (block_mask & (1 << APPLY_BLOCK)) {
+ struct apply_spec *new_apply;
+
status = apply_block_parse(&apply_spec,
&block_mask,
tokens,
@@ -2384,24 +2407,28 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_instructions_config(p,
- apply_spec.instructions,
- apply_spec.n_instructions);
- if (status) {
+ new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
+ if (!new_apply) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Pipeline instructions err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- apply_spec_free(&apply_spec);
+ s->apply = new_apply;
+ memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
+ s->n_apply++;
+ memset(&apply_spec, 0, sizeof(struct apply_spec));
continue;
}
/* extobj. */
if (!strcmp(tokens[0], "extobj")) {
+ struct extobj_spec *new_extobjs;
+
status = extobj_statement_parse(&extobj_spec,
tokens,
n_tokens,
@@ -2411,19 +2438,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_extern_object_config(p,
- extobj_spec.name,
- extobj_spec.extern_type_name,
- extobj_spec.pragma);
- if (status) {
+ new_extobjs = realloc(s->extobjs,
+ (s->n_extobjs + 1) * sizeof(struct extobj_spec));
+ if (!new_extobjs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Extern object config err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- extobj_spec_free(&extobj_spec);
+ s->extobjs = new_extobjs;
+ memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
+ s->n_extobjs++;
+ memset(&extobj_spec, 0, sizeof(struct extobj_spec));
continue;
}
@@ -2445,6 +2474,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* header. */
if (!strcmp(tokens[0], "header")) {
+ struct header_spec *new_headers;
+
status = header_statement_parse(&header_spec,
tokens,
n_tokens,
@@ -2454,24 +2485,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_header_register(p,
- header_spec.name,
- header_spec.struct_type_name);
- if (status) {
+ new_headers = realloc(s->headers,
+ (s->n_headers + 1) * sizeof(struct header_spec));
+ if (!new_headers) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Header registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- header_spec_free(&header_spec);
+ s->headers = new_headers;
+ memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
+ s->n_headers++;
+ memset(&header_spec, 0, sizeof(struct header_spec));
continue;
}
/* metadata. */
if (!strcmp(tokens[0], "metadata")) {
+ struct metadata_spec *new_metadata;
+
status = metadata_statement_parse(&metadata_spec,
tokens,
n_tokens,
@@ -2481,17 +2517,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_metadata_register(p,
- metadata_spec.struct_type_name);
- if (status) {
+ new_metadata = realloc(s->metadata,
+ (s->n_metadata + 1) * sizeof(struct metadata_spec));
+ if (!new_metadata) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meta-data reg err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metadata_spec_free(&metadata_spec);
+ s->metadata = new_metadata;
+ memcpy(&s->metadata[s->n_metadata],
+ &metadata_spec,
+ sizeof(struct metadata_spec));
+ s->n_metadata++;
+ memset(&metadata_spec, 0, sizeof(struct metadata_spec));
continue;
}
@@ -2558,6 +2600,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* regarray. */
if (!strcmp(tokens[0], "regarray")) {
+ struct regarray_spec *new_regarrays;
+
status = regarray_statement_parse(®array_spec,
tokens,
n_tokens,
@@ -2567,25 +2611,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_regarray_config(p,
- regarray_spec.name,
- regarray_spec.size,
- regarray_spec.init_val);
- if (status) {
+ new_regarrays = realloc(s->regarrays,
+ (s->n_regarrays + 1) * sizeof(struct regarray_spec));
+ if (!new_regarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Register array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- regarray_spec_free(®array_spec);
+ s->regarrays = new_regarrays;
+ memcpy(&s->regarrays[s->n_regarrays],
+ ®array_spec,
+ sizeof(struct regarray_spec));
+ s->n_regarrays++;
+ memset(®array_spec, 0, sizeof(struct regarray_spec));
continue;
}
/* metarray. */
if (!strcmp(tokens[0], "metarray")) {
+ struct metarray_spec *new_metarrays;
+
status = metarray_statement_parse(&metarray_spec,
tokens,
n_tokens,
@@ -2595,18 +2645,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_metarray_config(p,
- metarray_spec.name,
- metarray_spec.size);
- if (status) {
+ new_metarrays = realloc(s->metarrays,
+ (s->n_metarrays + 1) * sizeof(struct metarray_spec));
+ if (!new_metarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meter array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metarray_spec_free(&metarray_spec);
+ s->metarrays = new_metarrays;
+ memcpy(&s->metarrays[s->n_metarrays],
+ &metarray_spec,
+ sizeof(struct metarray_spec));
+ s->n_metarrays++;
+ memset(&metarray_spec, 0, sizeof(struct metarray_spec));
continue;
}
@@ -2644,17 +2699,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
goto error;
}
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
+ return s;
error:
extobj_spec_free(&extobj_spec);
@@ -2668,5 +2713,234 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
regarray_spec_free(®array_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec);
+ pipeline_spec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* extobj. */
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ status = rte_swx_pipeline_extern_object_config(p,
+ extobj_spec->name,
+ extobj_spec->extern_type_name,
+ extobj_spec->pragma);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Extern object configuration error.";
+ return status;
+ }
+ }
+
+ /* regarray. */
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ status = rte_swx_pipeline_regarray_config(p,
+ regarray_spec->name,
+ regarray_spec->size,
+ regarray_spec->init_val);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Register array configuration error.";
+ return status;
+ }
+ }
+
+ /* metarray. */
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ status = rte_swx_pipeline_metarray_config(p,
+ metarray_spec->name,
+ metarray_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meter array configuration error.";
+ return status;
+ }
+ }
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ status = rte_swx_pipeline_struct_type_register(p,
+ struct_spec->name,
+ struct_spec->fields,
+ struct_spec->n_fields,
+ struct_spec->varbit);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Struct type registration error.";
+ return status;
+ }
+ }
+
+ /* header. */
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ status = rte_swx_pipeline_packet_header_register(p,
+ header_spec->name,
+ header_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Header configuration error.";
+ return status;
+ }
+ }
+
+ /* metadata. */
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ status = rte_swx_pipeline_packet_metadata_register(p,
+ metadata_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meta-data registration error.";
+ return status;
+ }
+ }
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ status = rte_swx_pipeline_action_config(p,
+ action_spec->name,
+ action_spec->args_struct_type_name,
+ action_spec->instructions,
+ action_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Action configuration error.";
+ return status;
+ }
+ }
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ status = rte_swx_pipeline_table_config(p,
+ table_spec->name,
+ &table_spec->params,
+ table_spec->recommended_table_type_name,
+ table_spec->args,
+ table_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Table configuration error.";
+ return status;
+ }
+ }
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ status = rte_swx_pipeline_selector_config(p,
+ selector_spec->name,
+ &selector_spec->params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Selector table configuration error.";
+ return status;
+ }
+ }
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ status = rte_swx_pipeline_learner_config(p,
+ learner_spec->name,
+ &learner_spec->params,
+ learner_spec->size,
+ learner_spec->timeout,
+ learner_spec->n_timeouts);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Learner table configuration error.";
+ return status;
+ }
+ }
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+
+ status = rte_swx_pipeline_instructions_config(p,
+ apply_spec->instructions,
+ apply_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline instructions configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
+ FILE *spec_file,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_spec *s = NULL;
+ int status = 0;
+
+ /* Check the input arguments. */
+ if (!p || !spec_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Spec file parse. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Pipeline configure. */
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto error;
+ }
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline build error.";
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pipeline_spec_free(s);
return status;
}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index e1170a33b1..4f3a0b5958 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,3 +206,12 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 05/17] pipeline: generate the code for pipeline specification structure
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (2 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
` (12 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add support to export the pipeline specification data structure to a C
source code file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 622 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 5 +
2 files changed, 627 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 62929a9da6..bf21fe17ba 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2,6 +2,7 @@
* Copyright(c) 2020 Intel Corporation
*/
#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -2103,6 +2104,627 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
+static const char *
+match_type_string_get(enum rte_swx_table_match_type match_type)
+{
+ switch (match_type) {
+ case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
+ case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
+ case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
+ default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
+ }
+}
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s)
+{
+ uint32_t i;
+
+ /* Check the input arguments. */
+ if (!f || !s)
+ return;
+
+ /* extobj. */
+ fprintf(f, "static struct extobj_spec extobjs[] = {\n");
+
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
+ fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
+ if (extobj_spec->pragma)
+ fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
+ else
+ fprintf(f, "\t\t.pragma = NULL,\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* regarray. */
+ fprintf(f, "static struct regarray_spec regarrays[] = {\n");
+
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
+ fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
+ fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metarray. */
+ fprintf(f, "static struct metarray_spec metarrays[] = {\n");
+
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
+ fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+ uint32_t j;
+
+ fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
+ struct_spec->name);
+
+ for (j = 0; j < struct_spec->n_fields; j++) {
+ struct rte_swx_field_params *field = &struct_spec->fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct struct_spec structs[] = {\n");
+
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
+ fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
+ fprintf(f, "\t\t.n_fields = "
+ "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
+ struct_spec->name,
+ struct_spec->name);
+ fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* header. */
+ fprintf(f, "static struct header_spec headers[] = {\n");
+
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metadata. */
+ fprintf(f, "static struct metadata_spec metadata[] = {\n");
+
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
+ action_spec->name);
+
+ for (j = 0; j < action_spec->n_instructions; j++) {
+ const char *instr = action_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct action_spec actions[] = {\n");
+
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
+
+ if (action_spec->args_struct_type_name)
+ fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
+ action_spec->args_struct_type_name);
+ else
+ fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
+
+ fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
+ action_spec->name);
+ fprintf(f, "\t\t.n_instructions = "
+ "sizeof(action_%s_initial_instructions) / "
+ "sizeof(action_%s_initial_instructions[0]),\n",
+ action_spec->name,
+ action_spec->name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+ uint32_t j;
+
+ /* fields. */
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "static struct rte_swx_match_field_params "
+ "table_%s_fields[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_fields; j++) {
+ struct rte_swx_match_field_params *field =
+ &table_spec->params.fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.match_type = %s,\n",
+ match_type_string_get(field->match_type));
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (table_spec->params.action_names && table_spec->params.n_actions) {
+ fprintf(f, "static const char *table_%s_action_names[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ const char *action_name = table_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (table_spec->params.action_is_for_table_entries &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (table_spec->params.action_is_for_default_entry &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct table_spec tables[] = {\n");
+
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.fields = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (table_spec->params.action_names && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "table_%s_action_is_for_table_entries,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "table_%s_action_is_for_default_entry,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
+ "sizeof(table_%s_action_names[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = 0,\n");
+
+ if (table_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ table_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (table_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ table_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ table_spec->params.default_action_is_const);
+ fprintf(f, "\t\t},\n");
+
+ if (table_spec->recommended_table_type_name)
+ fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
+ table_spec->recommended_table_type_name);
+ else
+ fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
+
+ if (table_spec->args)
+ fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
+ else
+ fprintf(f, "\t\t.args = NULL,\n");
+
+ fprintf(f, "\t\t.size = %u,\n", table_spec->size);
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+ uint32_t j;
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "static const char *selector_%s_field_names[] = {\n",
+ selector_spec->name);
+
+ for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
+ const char *field_name =
+ selector_spec->params.selector_field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct selector_spec selectors[] = {\n");
+
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+
+ fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
+ fprintf(f, "\t\t.params = {\n");
+
+ if (selector_spec->params.group_id_field_name)
+ fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
+ selector_spec->params.group_id_field_name);
+ else
+ fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
+ selector_spec->name);
+ fprintf(f, "\t\t\t.n_selector_fields = "
+ "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
+ selector_spec->name,
+ selector_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
+ }
+
+ if (selector_spec->params.member_id_field_name)
+ fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
+ selector_spec->params.member_id_field_name);
+ else
+ fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
+
+ fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
+
+ fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
+ selector_spec->params.n_members_per_group_max);
+
+ fprintf(f, "\t\t},\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+ uint32_t j;
+
+ /* field_names. */
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "static const char *learner_%s_field_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_fields; j++) {
+ const char *field_name = learner_spec->params.field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (learner_spec->params.action_names && learner_spec->params.n_actions) {
+ fprintf(f, "static const char *learner_%s_action_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ const char *action_name = learner_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* timeout. */
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->n_timeouts; j++) {
+ uint32_t value = learner_spec->timeout[j];
+
+ fprintf(f, "\t[%d] = %u,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct learner_spec learners[] = {\n");
+
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
+ learner_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(learner_%s_field_names) / "
+ "sizeof(learner_%s_field_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "learner_%s_action_is_for_table_entries,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "learner_%s_action_is_for_default_entry,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = "
+ "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = NULL,\n");
+
+ if (learner_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ learner_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (learner_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ learner_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ learner_spec->params.default_action_is_const);
+
+ fprintf(f, "\t\t},\n");
+
+ fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
+
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
+ fprintf(f, "\t\t\t.n_timeouts = "
+ "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t.timeout = NULL,\n");
+ fprintf(f, "\t\t\t.n_timeouts = 0,\n");
+ }
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
+
+ for (j = 0; j < apply_spec->n_instructions; j++) {
+ const char *instr = apply_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct apply_spec apply[] = {\n");
+
+ for (i = 0; i < s->n_apply; i++) {
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
+ fprintf(f, "\t.n_instructions = "
+ "sizeof(apply%u_initial_instructions) / "
+ "sizeof(apply%u_initial_instructions[0]),\n",
+ i,
+ i);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* pipeline. */
+ fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
+ fprintf(f, "\t.extobjs = extobjs,\n");
+ fprintf(f, "\t.structs = structs,\n");
+ fprintf(f, "\t.headers = headers,\n");
+ fprintf(f, "\t.metadata = metadata,\n");
+ fprintf(f, "\t.actions = actions,\n");
+ fprintf(f, "\t.tables = tables,\n");
+ fprintf(f, "\t.selectors = selectors,\n");
+ fprintf(f, "\t.learners = learners,\n");
+ fprintf(f, "\t.regarrays = regarrays,\n");
+ fprintf(f, "\t.metarrays = metarrays,\n");
+ fprintf(f, "\t.apply = apply,\n");
+ fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
+ fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
+ fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
+ fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
+ fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
+ fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
+ fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
+ fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
+ fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
+ fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
+ fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
+ fprintf(f, "};\n");
+}
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 4f3a0b5958..707b99ba09 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,6 +206,11 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s);
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 06/17] pipeline: add support for pipeline I/O specification
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (3 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
` (11 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure and API for the pipeline I/O ports
and related pipeline configuration such as packet mirroring.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 852 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 58 ++
2 files changed, 910 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index bf21fe17ba..89cf194b19 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,6 +9,12 @@
#include <errno.h>
#include <rte_common.h>
+#include <rte_mempool.h>
+
+#include <rte_swx_port_ethdev.h>
+#include <rte_swx_port_ring.h>
+#include <rte_swx_port_source_sink.h>
+#include <rte_swx_port_fd.h>
#include "rte_swx_pipeline_spec.h"
@@ -3566,3 +3572,849 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
pipeline_spec_free(s);
return status;
}
+
+static void
+port_in_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "source")) {
+ struct rte_swx_port_source_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+static void
+port_out_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "sink")) {
+ struct rte_swx_port_sink_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s)
+{
+ uint32_t i;
+
+ if (!s)
+ return;
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ uintptr_t name = (uintptr_t)s->port_in_type[i];
+
+ port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_in_type);
+ free(s->port_in_params);
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ uintptr_t name = (uintptr_t)s->port_out_type[i];
+
+ port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_out_type);
+ free(s->port_out_params);
+
+ free(s);
+}
+
+static int
+mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
+ char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ char *token;
+
+ if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return -EINVAL;
+ }
+
+ /* <n_slots>. */
+ token = tokens[1];
+ p->n_slots = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_slots> parameter.";
+ return -EINVAL;
+ }
+
+ /* <n_sessions>. */
+ token = tokens[3];
+ p->n_sessions = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_sessions> parameter.";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void *
+port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_reader_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_reader_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_source_params *p = NULL;
+ struct rte_mempool *pool = NULL;
+ char *token, *file_name = NULL;
+ uint32_t n_loops, n_pkts_max;
+
+ if ((n_tokens != 8) ||
+ strcmp(tokens[0], "mempool") ||
+ strcmp(tokens[2], "file") ||
+ strcmp(tokens[4], "loop") ||
+ strcmp(tokens[6], "packets")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ pool = rte_mempool_lookup(tokens[1]);
+ if (!pool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <n_loops>. */
+ token = tokens[5];
+ n_loops = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_loops> parameter.";
+ return NULL;
+ }
+
+ /* <n_pkts_max>. */
+ token = tokens[7];
+ n_pkts_max = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_pkts_max> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ file_name = strdup(tokens[3]);
+ p = malloc(sizeof(struct rte_swx_port_source_params));
+ if (!file_name || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->pool = pool;
+ p->file_name = file_name;
+ p->n_loops = n_loops;
+ p->n_pkts_max = n_pkts_max;
+
+ return p;
+}
+
+static void *
+port_in_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_reader_params *p = NULL;
+ struct rte_mempool *mempool = NULL;
+ char *token;
+ uint32_t mtu, burst_size;
+ int fd;
+
+ if ((n_tokens != 7) ||
+ strcmp(tokens[1], "mtu") ||
+ strcmp(tokens[3], "mempool") ||
+ strcmp(tokens[5], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <mtu>. */
+ token = tokens[2];
+ mtu = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <mtu> parameter.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ mempool = rte_mempool_lookup(tokens[4]);
+ if (!mempool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[6];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->mtu = mtu;
+ p->mempool = mempool;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_writer_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_writer_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_sink_params *p = NULL;
+ char *file_name = NULL;
+ int file_name_valid = 0;
+
+ if ((n_tokens != 2) || strcmp(tokens[0], "file")){
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ if (strcmp(tokens[1], "none")) {
+ file_name_valid = 1;
+ file_name = strdup(tokens[1]);
+ }
+
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if ((file_name_valid && !file_name) || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->file_name = file_name;
+
+ return p;
+}
+
+static void *
+port_out_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_writer_params *p = NULL;
+ char *token;
+ uint32_t burst_size;
+ int fd;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_iospec *s = NULL;
+ uint32_t n_lines = 0;
+
+ /* Check the input arguments. */
+ if (!spec) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ goto error;
+ }
+
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_iospec), 1);
+ if (!s) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ /* Initialize with the defaut values. */
+ s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
+ s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
+
+ for (n_lines = 1; ; n_lines++) {
+ char line[MAX_LINE_LENGTH];
+ char *tokens[MAX_TOKENS], *ptr = line;
+ uint32_t n_tokens = 0;
+
+ /* Read next line. */
+ if (!fgets(line, sizeof(line), spec))
+ break;
+
+ /* Parse the line into tokens. */
+ for ( ; ; ) {
+ char *token;
+
+ /* Get token. */
+ token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
+ if (!token)
+ break;
+
+ /* Handle comments. */
+ if ((token[0] == '#') ||
+ (token[0] == ';') ||
+ ((token[0] == '/') && (token[1] == '/'))) {
+ break;
+ }
+
+ /* Handle excessively long lines. */
+ if (n_tokens >= RTE_DIM(tokens)) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Too many tokens.";
+ goto error;
+ }
+
+ /* Handle excessively long tokens. */
+ if (strnlen(token, RTE_SWX_NAME_SIZE) >=
+ RTE_SWX_NAME_SIZE) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Token too big.";
+ goto error;
+ }
+
+ /* Save token. */
+ tokens[n_tokens] = token;
+ n_tokens++;
+ }
+
+ /* Handle empty lines. */
+ if (!n_tokens)
+ continue;
+
+ /* mirroring. */
+ if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
+ int status = 0;
+
+ status = mirroring_parse(&s->mirroring_params,
+ &tokens[1],
+ n_tokens - 1,
+ err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ continue;
+ }
+
+ /* port in. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "source"))
+ p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_in_id,
+ (s->n_ports_in + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_in_type,
+ (s->n_ports_in + 1) * sizeof(char *));
+ new_params = realloc(s->port_in_params,
+ (s->n_ports_in + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_in_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_in_id = new_id;
+ s->port_in_type = new_type;
+ s->port_in_params = new_params;
+
+ s->port_in_id[s->n_ports_in] = port_id;
+ s->port_in_type[s->n_ports_in] = port_type;
+ s->port_in_params[s->n_ports_in] = p;
+ s->n_ports_in++;
+
+ continue;
+ }
+
+ /* port out. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "sink"))
+ p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_out_id,
+ (s->n_ports_out + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_out_type,
+ (s->n_ports_out + 1) * sizeof(char *));
+ new_params = realloc(s->port_out_params,
+ (s->n_ports_out + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_out_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_out_id = new_id;
+ s->port_out_type = new_type;
+ s->port_out_params = new_params;
+
+ s->port_out_id[s->n_ports_out] = port_id;
+ s->port_out_type[s->n_ports_out] = port_type;
+ s->port_out_params[s->n_ports_out] = p;
+ s->n_ports_out++;
+
+ continue;
+ }
+
+ /* Anything else. */
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Unknown I/O statement.";
+ goto error;
+ }
+
+ return s;
+
+error:
+ pipeline_iospec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!p || !s) {
+ if (err_msg)
+ *err_msg = "Invalid input argument";
+ return -EINVAL;
+ }
+
+ /* Mirroring. */
+ status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline mirroring configuration error.";
+ return status;
+ }
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ status = rte_swx_pipeline_port_in_config(p,
+ i,
+ s->port_in_type[i],
+ s->port_in_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline input port configuration error.";
+ return status;
+ }
+ }
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ status = rte_swx_pipeline_port_out_config(p,
+ i,
+ s->port_out_type[i],
+ s->port_out_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline output port configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 707b99ba09..62ac4ecfc4 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -1,6 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2022 Intel Corporation
*/
+#ifndef __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+#define __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include <stdio.h>
@@ -204,6 +211,38 @@ struct pipeline_spec {
uint32_t n_apply;
};
+/*
+ * Mirroring:
+ * mirroring slots <n_slots> sessions <n_sessions>
+ *
+ * Input ports:
+ * port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+ * port in <port_id> ring <ring_name> bsz <burst_size>
+ * port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops>
+ * packets <n_pkts_max>
+ * port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+ *
+ * Output ports:
+ * port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+ * port out <port_id> ring <ring_name> bsz <burst_size>
+ * port out <port_id> sink file <file_name> | none
+ * port out <port_id> fd <file_descriptor> bsz <burst_size>
+ */
+struct pipeline_iospec {
+ struct rte_swx_pipeline_mirroring_params mirroring_params;
+
+ uint32_t *port_in_id;
+ const char **port_in_type;
+ void **port_in_params;
+
+ uint32_t *port_out_id;
+ const char **port_out_type;
+ void **port_out_params;
+
+ uint32_t n_ports_in;
+ uint32_t n_ports_out;
+};
+
void
pipeline_spec_free(struct pipeline_spec *s);
@@ -220,3 +259,22 @@ int
pipeline_spec_configure(struct rte_swx_pipeline *p,
struct pipeline_spec *s,
const char **err_msg);
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s);
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 07/17] pipeline: add API for pipeline code generation
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (4 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
` (10 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the C code generation for the pipeline was hidden under
the hood; now, we make this an explicit API operation. Besides the
functions for the pipeline actions and the pipeline instructions,
the generated C source code now includes the pipeline specification
structure required for the pipeline configuration operations.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline.c | 94 +++++++++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline.h | 25 +++++++++
lib/pipeline/version.map | 1 +
3 files changed, 120 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index c8ccded4f8..dd5f7107fa 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -20,6 +20,7 @@
#include <rte_swx_table_wm.h>
#include "rte_swx_pipeline_internal.h"
+#include "rte_swx_pipeline_spec.h"
#define CHECK(condition, err_code) \
do { \
@@ -13581,3 +13582,96 @@ pipeline_compile(struct rte_swx_pipeline *p)
return status;
}
+
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg)
+
+{
+ struct rte_swx_pipeline *p = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!spec_file || !code_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ status = rte_swx_pipeline_config(&p, NULL, 0);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline configuration error.";
+ goto free;
+ }
+
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto free;
+ }
+
+ /*
+ * Pipeline code generation.
+ */
+
+ /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
+ * but there is no need for the pipeline build to be done as well.
+ */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
+ goto free;
+ }
+
+ /* Header file inclusion. */
+ fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
+ fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
+
+ /* Code generation for the pipeline specification. */
+ pipeline_spec_codegen(code_file, s);
+ fprintf(code_file, "\n");
+
+ /* Code generation for the action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
+
+ action_data_codegen(a, code_file);
+ fprintf(code_file, "\n");
+
+ action_instr_codegen(a, code_file);
+ fprintf(code_file, "\n");
+ }
+
+ /* Code generation for the pipeline instructions. */
+ instruction_group_list_codegen(igl, p, code_file);
+
+free:
+ instruction_group_list_free(igl);
+ rte_swx_pipeline_free(p);
+ pipeline_spec_free(s);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index ef50a0fa70..724607b87c 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -957,6 +957,31 @@ __rte_experimental
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p);
+/**
+ * Pipeline C code generate based on input specification file
+ *
+ * @param[in] spec_file
+ * Pipeline specification file (.spec) provided as input.
+ * @param[in] code_file
+ * Pipeline C language file (.c) to be generated.
+ * @param[out] err_line
+ * In case of error and non-NULL, the line number within the *spec* file where
+ * the error occurred. The first line number in the file is 1.
+ * @param[out] err_msg
+ * In case of error and non-NULL, the error message.
+ * @return
+ * 0 on success or the following error codes otherwise:
+ * -EINVAL: Invalid argument;
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Resource with the same name already exists.
+ */
+__rte_experimental
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg);
+
/**
* Pipeline build from specification file
*
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 50029aadcf..8d95005a5b 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -148,5 +148,6 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 08/17] pipeline: add API for shared library-based pipeline build
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (5 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
` (9 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the pipeline build operation was done based on the
specification file (typically produced by the P4 compiler), then the C
code with optimized functions for the pipeline actions and
instructions was generated, built into a shared object library, loaded
and installed into the pipeline in a completely hardcoded and
non-customizable way.
Now, this process is split into three explicit stages:
i) code generation (specification file -> C file);
ii) code build (C file -> shared object library);
iii) code installation (library load into the pipeline).
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 85 ++++---
lib/pipeline/rte_swx_pipeline.c | 319 +++++++++++----------------
lib/pipeline/rte_swx_pipeline.h | 38 ++--
lib/pipeline/rte_swx_pipeline_spec.c | 51 -----
lib/pipeline/version.map | 2 +-
5 files changed, 208 insertions(+), 287 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ad553f19ab..f0285675b3 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -984,55 +984,88 @@ cmd_pipeline_port_out(char **tokens,
}
static const char cmd_pipeline_build_help[] =
-"pipeline <pipeline_name> build <spec_file>\n";
+"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
static void
cmd_pipeline_build(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p = NULL;
- FILE *spec = NULL;
- uint32_t err_line;
- const char *err_msg;
- int status;
+ struct rte_swx_pipeline *p = NULL;
+ struct rte_swx_ctl_pipeline *ctl = NULL;
+ char *pipeline_name, *lib_file_name, *iospec_file_name;
+ FILE *iospec_file = NULL;
+ uint32_t numa_node = 0;
+ int status = 0;
- if (n_tokens != 4) {
+ /* Parsing. */
+ if (n_tokens != 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "build")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
return;
}
- spec = fopen(tokens[3], "r");
- if (!spec) {
- snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ if (strcmp(tokens[3], "lib")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
return;
}
- status = rte_swx_pipeline_build_from_spec(p->p,
- spec,
- &err_line,
- &err_msg);
- fclose(spec);
- if (status) {
- snprintf(out, out_size, "Error %d at line %u: %s\n.",
- status, err_line, err_msg);
+ lib_file_name = tokens[4];
+
+ if (strcmp(tokens[5], "io")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
return;
}
- p->ctl = rte_swx_ctl_pipeline_create(p->p);
- if (!p->ctl) {
- snprintf(out, out_size, "Pipeline control create failed.");
- rte_swx_pipeline_free(p->p);
+ iospec_file_name = tokens[6];
+
+ if (strcmp(tokens[7], "numa")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
return;
}
+
+ if (parser_read_uint32(&numa_node, tokens[8])) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+ return;
+ }
+
+ /* I/O spec file open. */
+ iospec_file = fopen(iospec_file_name, "r");
+ if (!iospec_file) {
+ snprintf(out, out_size, "Cannot open file \"%s\".\n", iospec_file_name);
+ return;
+ }
+
+ status = rte_swx_pipeline_build_from_lib(&p,
+ pipeline_name,
+ lib_file_name,
+ iospec_file,
+ (int)numa_node);
+ if (status) {
+ snprintf(out, out_size, "Pipeline build failed (%d).", status);
+ goto free;
+ }
+
+ ctl = rte_swx_ctl_pipeline_create(p);
+ if (!ctl) {
+ snprintf(out, out_size, "Pipeline control create failed.");
+ goto free;
+ }
+
+free:
+ if (status)
+ rte_swx_pipeline_free(p);
+
+ if (iospec_file)
+ fclose(iospec_file);
}
static void
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index dd5f7107fa..12e156b00b 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9911,9 +9911,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
return 0;
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p);
-
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
{
@@ -10003,8 +10000,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
p->build_done = 1;
- pipeline_compile(p);
-
return 0;
error:
@@ -13327,160 +13322,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *
return n_custom_instr;
}
-static int
-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- FILE *f = NULL;
-
- /* Create the .c file. */
- f = fopen("/tmp/pipeline.c", "w");
- if (!f)
- return -EIO;
-
- /* Include the .h file. */
- fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
-
- /* Add the code for each action. */
- TAILQ_FOREACH(a, &p->actions, node) {
- fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
-
- action_data_codegen(a, f);
-
- fprintf(f, "\n");
-
- action_instr_codegen(a, f);
-
- fprintf(f, "\n");
- }
-
- /* Add the pipeline code. */
- instruction_group_list_codegen(igl, p, f);
-
- /* Close the .c file. */
- fclose(f);
-
- return 0;
-}
-
-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
-#endif
-
-static int
-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- struct instruction_group *g;
- char *dir_in, *buffer = NULL;
- const char *dir_out;
- int status = 0;
-
- /* Get the environment variables. */
- dir_in = getenv("RTE_INSTALL_DIR");
- if (!dir_in) {
- status = -EINVAL;
- goto free;
- }
-
- dir_out = "/tmp";
-
- /* Memory allocation for the command buffer. */
- buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
- if (!buffer) {
- status = -ENOMEM;
- goto free;
- }
-
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
- "-I %s/lib/pipeline "
- "-I %s/lib/eal/include "
- "-I %s/lib/eal/x86/include "
- "-I %s/lib/eal/include/generic "
- "-I %s/lib/meter "
- "-I %s/lib/port "
- "-I %s/lib/table "
- "-I %s/lib/pipeline "
- "-I %s/config "
- "-I %s/build "
- "-I %s/lib/eal/linux/include "
- ">%s/pipeline.log 2>&1 "
- "&& "
- "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
- ">>%s/pipeline.log 2>&1",
- dir_out,
- dir_out,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_out,
- dir_out,
- dir_out,
- dir_out);
-
- /* Build the shared object library. */
- status = system(buffer);
- if (status)
- goto free;
-
- /* Open library. */
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "%s/libpipeline.so",
- dir_out);
-
- p->lib = dlopen(buffer, RTLD_LAZY);
- if (!p->lib) {
- status = -EIO;
- goto free;
- }
-
- /* Get the action function symbols. */
- TAILQ_FOREACH(a, &p->actions, node) {
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
-
- p->action_funcs[a->id] = dlsym(p->lib, buffer);
- if (!p->action_funcs[a->id]) {
- status = -EINVAL;
- goto free;
- }
- }
-
- /* Get the pipeline function symbols. */
- TAILQ_FOREACH(g, igl, node) {
- if (g->first_instr_id == g->last_instr_id)
- continue;
-
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
-
- g->func = dlsym(p->lib, buffer);
- if (!g->func) {
- status = -EINVAL;
- goto free;
- }
- }
-
-free:
- if (status && p->lib) {
- dlclose(p->lib);
- p->lib = NULL;
- }
-
- free(buffer);
-
- return status;
-}
-
static int
pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
struct instruction_group_list *igl)
@@ -13548,41 +13389,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p)
-{
- struct instruction_group_list *igl = NULL;
- int status = 0;
-
- igl = instruction_group_list_create(p);
- if (!igl) {
- status = -ENOMEM;
- goto free;
- }
-
- /* Code generation. */
- status = pipeline_codegen(p, igl);
- if (status)
- goto free;
-
- /* Build and load the shared object library. */
- status = pipeline_libload(p, igl);
- if (status)
- goto free;
-
- /* Adjust instructions. */
- status = pipeline_adjust_check(p, igl);
- if (status)
- goto free;
-
- pipeline_adjust(p, igl);
-
-free:
- instruction_group_list_free(igl);
-
- return status;
-}
-
int
rte_swx_pipeline_codegen(FILE *spec_file,
FILE *code_file,
@@ -13675,3 +13481,128 @@ rte_swx_pipeline_codegen(FILE *spec_file,
return status;
}
+
+int
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node)
+{
+ struct rte_swx_pipeline *p = NULL;
+ void *lib = NULL;
+ struct pipeline_iospec *sio = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ struct instruction_group *g;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!pipeline ||
+ !name ||
+ !name[0] ||
+ !lib_file_name ||
+ !lib_file_name[0] ||
+ !iospec_file) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Open the library. */
+ lib = dlopen(lib_file_name, RTLD_LAZY);
+ if (!lib) {
+ status = -EIO;
+ goto free;
+ }
+
+ /* Get the pipeline specification structures. */
+ s = dlsym(lib, "pipeline_spec");
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
+ if (!sio) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration based on the specification structures. */
+ status = rte_swx_pipeline_config(&p, name, numa_node);
+ if (status)
+ goto free;
+
+ status = pipeline_iospec_configure(p, sio, NULL);
+ if (status)
+ goto free;
+
+ status = pipeline_spec_configure(p, s, NULL);
+ if (status)
+ goto free;
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status)
+ goto free;
+
+ /* Action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ snprintf(name, sizeof(name), "action_%s_run", a->name);
+
+ p->action_funcs[a->id] = dlsym(lib, name);
+ if (!p->action_funcs[a->id]) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ /* Pipeline instructions. */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ status = -ENOMEM;
+ goto free;
+ }
+
+ TAILQ_FOREACH(g, igl, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ if (g->first_instr_id == g->last_instr_id)
+ continue;
+
+ snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
+
+ g->func = dlsym(lib, name);
+ if (!g->func) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ status = pipeline_adjust_check(p, igl);
+ if (status)
+ goto free;
+
+ pipeline_adjust(p, igl);
+
+ p->lib = lib;
+
+ *pipeline = p;
+
+free:
+ instruction_group_list_free(igl);
+
+ pipeline_iospec_free(sio);
+
+ if (status) {
+ rte_swx_pipeline_free(p);
+
+ if (lib)
+ dlclose(lib);
+ }
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 724607b87c..9c629d4118 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -983,30 +983,38 @@ rte_swx_pipeline_codegen(FILE *spec_file,
const char **err_msg);
/**
- * Pipeline build from specification file
+ * Pipeline build from shared object library
*
- * @param[in] p
- * Pipeline handle.
- * @param[in] spec
- * Pipeline specification file.
- * @param[out] err_line
- * In case of error and non-NULL, the line number within the *spec* file where
- * the error occurred. The first line number in the file is 1.
- * @param[out] err_msg
- * In case of error and non-NULL, the error message.
+ * The shared object library must be built from the C language source code file
+ * previously generated by the rte_swx_pipeline_codegen() API function.
+ *
+ * The pipeline I/O specification file defines the I/O ports of the pipeline.
+ *
+ * @param[out] p
+ * Pipeline handle. Must point to valid memory. Contains valid pipeline handle
+ * when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
+ * @param[in] lib_file_name
+ * Shared object library file name.
+ * @param[in] iospec_file
+ * Pipeline I/O specification file.
+ * @param[in] numa_node
+ * Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
- * -EEXIST: Resource with the same name already exists;
+ * -EEXIST: Pipeline with this name already exists;
* -ENODEV: Extern object or table creation error.
*/
__rte_experimental
int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg);
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **p,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node);
/**
* Pipeline run
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 89cf194b19..c0ca3dc131 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -3522,57 +3522,6 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,
return 0;
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec_file,
- uint32_t *err_line,
- const char **err_msg)
-{
- struct pipeline_spec *s = NULL;
- int status = 0;
-
- /* Check the input arguments. */
- if (!p || !spec_file) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Invalid input argument.";
- status = -EINVAL;
- goto error;
- }
-
- /* Spec file parse. */
- s = pipeline_spec_parse(spec_file, err_line, err_msg);
- if (!s) {
- status = -EINVAL;
- goto error;
- }
-
- /* Pipeline configure. */
- status = pipeline_spec_configure(p, s, err_msg);
- if (status) {
- if (err_line)
- *err_line = 0;
- goto error;
- }
-
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
-
-error:
- pipeline_spec_free(s);
- return status;
-}
-
static void
port_in_params_free(void *params, const char *port_type)
{
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8d95005a5b..16806e6802 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -82,7 +82,6 @@ EXPERIMENTAL {
rte_swx_ctl_table_ops_get;
rte_swx_pipeline_action_config;
rte_swx_pipeline_build;
- rte_swx_pipeline_build_from_spec;
rte_swx_pipeline_config;
rte_swx_pipeline_extern_func_register;
rte_swx_pipeline_extern_object_config;
@@ -148,6 +147,7 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_build_from_lib;
rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 09/17] examples/pipeline: add CLI command for pipeline code generation
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (6 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 10/17] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
` (8 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the pipeline code generation operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index f0285675b3..2b38977be1 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -983,6 +983,53 @@ cmd_pipeline_port_out(char **tokens,
}
}
+static const char cmd_pipeline_codegen_help[] =
+"pipeline codegen <spec_file> <code_file>\n";
+
+static void
+cmd_pipeline_codegen(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ FILE *spec_file = NULL;
+ FILE *code_file = NULL;
+ uint32_t err_line;
+ const char *err_msg;
+ int status;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ spec_file = fopen(tokens[2], "r");
+ if (!spec_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+ return;
+ }
+
+ code_file = fopen(tokens[3], "w");
+ if (!code_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ return;
+ }
+
+ status = rte_swx_pipeline_codegen(spec_file,
+ code_file,
+ &err_line,
+ &err_msg);
+
+ fclose(spec_file);
+ fclose(code_file);
+
+ if (status) {
+ snprintf(out, out_size, "Error %d at line %u: %s\n.",
+ status, err_line, err_msg);
+ return;
+ }
+}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -3009,6 +3056,7 @@ cmd_help(char **tokens,
"\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
+ "\tpipeline codegen\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3078,6 +3126,12 @@ cmd_help(char **tokens,
}
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3356,6 +3410,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "codegen") == 0)) {
+ cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 10/17] examples/pipeline: add CLI command for shared library build
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (7 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 11/17] examples/pipeline: remove the obsolete pipeline create CLI command Cristian Dumitrescu
` (7 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the shared object library build operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 157 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 153 insertions(+), 4 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 2b38977be1..28cf8d4178 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_ethdev.h>
@@ -25,6 +26,10 @@
#define CMD_MAX_TOKENS 256
#endif
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
@@ -1030,6 +1035,140 @@ cmd_pipeline_codegen(char **tokens,
return;
}
}
+
+static const char cmd_pipeline_libbuild_help[] =
+"pipeline libbuild <code_file> <lib_file>\n";
+
+static void
+cmd_pipeline_libbuild(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+ char *install_dir, *cwd = NULL, *buffer = NULL;
+ size_t length;
+ int status = 0;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ goto free;
+ }
+
+ install_dir = getenv("RTE_INSTALL_DIR");
+ if (!install_dir) {
+ cwd = malloc(MAX_LINE_SIZE);
+ if (!cwd) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ install_dir = getcwd(cwd, MAX_LINE_SIZE);
+ if (!install_dir) {
+ snprintf(out, out_size, "Error: Path too long.\n");
+ goto free;
+ }
+ }
+
+ snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+ out_size -= strlen(out);
+ out += strlen(out);
+
+ code_file = tokens[2];
+ length = strnlen(code_file, MAX_LINE_SIZE);
+ if ((length < 3) ||
+ (code_file[length - 2] != '.') ||
+ (code_file[length - 1] != 'c')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+ goto free;
+ }
+
+ lib_file = tokens[3];
+ length = strnlen(lib_file, MAX_LINE_SIZE);
+ if ((length < 4) ||
+ (lib_file[length - 3] != '.') ||
+ (lib_file[length - 2] != 's') ||
+ (lib_file[length - 1] != 'o')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+ goto free;
+ }
+
+ obj_file = malloc(length);
+ log_file = malloc(length + 2);
+ if (!obj_file || !log_file) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ memcpy(obj_file, lib_file, length - 2);
+ obj_file[length - 2] = 'o';
+ obj_file[length - 1] = 0;
+
+ memcpy(log_file, lib_file, length - 2);
+ log_file[length - 2] = 'l';
+ log_file[length - 1] = 'o';
+ log_file[length] = 'g';
+ log_file[length + 1] = 0;
+
+ buffer = malloc(MAX_LINE_SIZE);
+ if (!buffer) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ return;
+ }
+
+ snprintf(buffer,
+ MAX_LINE_SIZE,
+ "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+ "-I %s/lib/pipeline "
+ "-I %s/lib/eal/include "
+ "-I %s/lib/eal/x86/include "
+ "-I %s/lib/eal/include/generic "
+ "-I %s/lib/meter "
+ "-I %s/lib/port "
+ "-I %s/lib/table "
+ "-I %s/lib/pipeline "
+ "-I %s/config "
+ "-I %s/build "
+ "-I %s/lib/eal/linux/include "
+ ">%s 2>&1 "
+ "&& "
+ "gcc -shared %s -o %s "
+ ">>%s 2>&1",
+ obj_file,
+ code_file,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ log_file,
+ obj_file,
+ lib_file,
+ log_file);
+
+ status = system(buffer);
+ if (status) {
+ snprintf(out,
+ out_size,
+ "Library build failed, see file \"%s\" for details.\n",
+ log_file);
+ goto free;
+ }
+
+free:
+ free(cwd);
+ free(obj_file);
+ free(log_file);
+ free(buffer);
+}
+
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -1127,10 +1266,6 @@ table_entry_free(struct rte_swx_table_entry *entry)
free(entry);
}
-#ifndef MAX_LINE_SIZE
-#define MAX_LINE_SIZE 2048
-#endif
-
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
@@ -3057,6 +3192,7 @@ cmd_help(char **tokens,
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
+ "\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3132,6 +3268,12 @@ cmd_help(char **tokens,
return;
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3417,6 +3559,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "libbuild") == 0)) {
+ cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 11/17] examples/pipeline: remove the obsolete pipeline create CLI command
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (8 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 10/17] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 12/17] examples/pipeline: remove the obsolete port configuration CLI commands Cristian Dumitrescu
` (6 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline configuration is now done through the I/O specification
file, hence this CLI command is no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 47 -----------------------------------------
1 file changed, 47 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 28cf8d4178..7b725a9c27 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -523,39 +523,6 @@ cmd_tap(char **tokens,
}
}
-static const char cmd_pipeline_create_help[] =
-"pipeline <pipeline_name> create <numa_node>\n";
-
-static void
-cmd_pipeline_create(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- char *name;
- uint32_t numa_node;
-
- if (n_tokens != 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- name = tokens[1];
-
- if (parser_read_uint32(&numa_node, tokens[3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
- return;
- }
-
- p = pipeline_create(obj, name, (int)numa_node);
- if (!p) {
- snprintf(out, out_size, "pipeline create error.");
- return;
- }
-}
-
static const char cmd_pipeline_port_in_help[] =
"pipeline <pipeline_name> port in <port_id>\n"
" link <link_name> rxq <queue_id> bsz <burst_size>\n"
@@ -3188,7 +3155,6 @@ cmd_help(char **tokens,
"\tmempool\n"
"\tlink\n"
"\ttap\n"
- "\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
@@ -3241,12 +3207,6 @@ cmd_help(char **tokens,
return;
}
- if ((strcmp(tokens[0], "pipeline") == 0) &&
- (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) {
- snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
- return;
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
if (strcmp(tokens[2], "in") == 0) {
@@ -3529,13 +3489,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
}
if (strcmp(tokens[0], "pipeline") == 0) {
- if ((n_tokens >= 3) &&
- (strcmp(tokens[2], "create") == 0)) {
- cmd_pipeline_create(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
if ((n_tokens >= 4) &&
(strcmp(tokens[2], "port") == 0) &&
(strcmp(tokens[3], "in") == 0)) {
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 12/17] examples/pipeline: remove the obsolete port configuration CLI commands
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (9 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 11/17] examples/pipeline: remove the obsolete pipeline create CLI command Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command Cristian Dumitrescu
` (5 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline I/O ports configuration is now done through the I/O
specification file, hence these CLI commands are no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 465 ----------------------------------------
1 file changed, 465 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 7b725a9c27..b26e73c706 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -523,438 +523,6 @@ cmd_tap(char **tokens,
}
}
-static const char cmd_pipeline_port_in_help[] =
-"pipeline <pipeline_name> port in <port_id>\n"
-" link <link_name> rxq <queue_id> bsz <burst_size>\n"
-" ring <ring_name> bsz <burst_size>\n"
-" | source <mempool_name> <file_name> loop <n_loops>\n"
-" | tap <tap_name> mempool <mempool_name> mtu <mtu> bsz <burst_size>\n";
-
-static void
-cmd_pipeline_port_in(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- int status;
- uint32_t port_id = 0, t0;
-
- if (n_tokens < 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
-
- if (strcmp(tokens[3], "in") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
- return;
- }
-
- if (parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- t0 = 5;
-
- if (strcmp(tokens[t0], "link") == 0) {
- struct rte_swx_port_ethdev_reader_params params;
- struct link *link;
-
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in link");
- return;
- }
-
- link = link_find(obj, tokens[t0 + 1]);
- if (!link) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "link_name");
- return;
- }
- params.dev_name = link->dev_name;
-
- if (strcmp(tokens[t0 + 2], "rxq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
- return;
- }
-
- if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "queue_id");
- return;
- }
-
- if (strcmp(tokens[t0 + 4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 6;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "ethdev",
- ¶ms);
- } else if (strcmp(tokens[t0], "ring") == 0) {
- struct rte_swx_port_ring_reader_params params;
- struct ring *ring;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in ring");
- return;
- }
-
- ring = ring_find(obj, tokens[t0 + 1]);
- if (!ring) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "ring_name");
- return;
- }
- params.name = ring->name;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "ring",
- ¶ms);
- } else if (strcmp(tokens[t0], "source") == 0) {
- struct rte_swx_port_source_params params;
- struct mempool *mp;
-
- if (n_tokens < t0 + 5) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in source");
- return;
- }
-
- mp = mempool_find(obj, tokens[t0 + 1]);
- if (!mp) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "mempool_name");
- return;
- }
- params.pool = mp->m;
-
- params.file_name = tokens[t0 + 2];
-
- if (strcmp(tokens[t0 + 3], "loop") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "loop");
- return;
- }
-
- if (parser_read_uint64(¶ms.n_loops, tokens[t0 + 4])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "n_loops");
- return;
- }
-
- t0 += 5;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "source",
- ¶ms);
- } else if (strcmp(tokens[t0], "tap") == 0) {
- struct rte_swx_port_fd_reader_params params;
- struct tap *tap;
- struct mempool *mp;
-
- if (n_tokens < t0 + 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in tap");
- return;
- }
-
- tap = tap_find(obj, tokens[t0 + 1]);
- if (!tap) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "tap_name");
- return;
- }
- params.fd = tap->fd;
-
- if (strcmp(tokens[t0 + 2], "mempool") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mempool");
- return;
- }
-
- mp = mempool_find(obj, tokens[t0 + 3]);
- if (!mp) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "mempool_name");
- return;
- }
- params.mempool = mp->m;
-
- if (strcmp(tokens[t0 + 4], "mtu") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mtu");
- return;
- }
-
- if (parser_read_uint32(¶ms.mtu, tokens[t0 + 5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
- return;
- }
-
- if (strcmp(tokens[t0 + 6], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 7])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 8;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "fd",
- ¶ms);
-
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (status) {
- snprintf(out, out_size, "port in error.");
- return;
- }
-
- if (n_tokens != t0) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-}
-
-static const char cmd_pipeline_port_out_help[] =
-"pipeline <pipeline_name> port out <port_id>\n"
-" link <link_name> txq <txq_id> bsz <burst_size>\n"
-" ring <ring_name> bsz <burst_size>\n"
-" | sink <file_name> | none\n"
-" | tap <tap_name> bsz <burst_size>\n";
-
-static void
-cmd_pipeline_port_out(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- int status;
- uint32_t port_id = 0, t0;
-
- if (n_tokens < 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
-
- if (strcmp(tokens[3], "out") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
- return;
- }
-
- if (parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- t0 = 5;
-
- if (strcmp(tokens[t0], "link") == 0) {
- struct rte_swx_port_ethdev_writer_params params;
- struct link *link;
-
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out link");
- return;
- }
-
- link = link_find(obj, tokens[t0 + 1]);
- if (!link) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "link_name");
- return;
- }
- params.dev_name = link->dev_name;
-
- if (strcmp(tokens[t0 + 2], "txq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
- return;
- }
-
- if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "queue_id");
- return;
- }
-
- if (strcmp(tokens[t0 + 4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 6;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "ethdev",
- ¶ms);
- } else if (strcmp(tokens[t0], "ring") == 0) {
- struct rte_swx_port_ring_writer_params params;
- struct ring *ring;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out link");
- return;
- }
-
- ring = ring_find(obj, tokens[t0 + 1]);
- if (!ring) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "ring_name");
- return;
- }
- params.name = ring->name;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "ring",
- ¶ms);
- } else if (strcmp(tokens[t0], "sink") == 0) {
- struct rte_swx_port_sink_params params;
-
- params.file_name = strcmp(tokens[t0 + 1], "none") ?
- tokens[t0 + 1] : NULL;
-
- t0 += 2;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "sink",
- ¶ms);
- } else if (strcmp(tokens[t0], "tap") == 0) {
- struct rte_swx_port_fd_writer_params params;
- struct tap *tap;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out tap");
- return;
- }
-
- tap = tap_find(obj, tokens[t0 + 1]);
- if (!tap) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "tap_name");
- return;
- }
- params.fd = tap->fd;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "fd",
- ¶ms);
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (status) {
- snprintf(out, out_size, "port out error.");
- return;
- }
-
- if (n_tokens != t0) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-}
-
static const char cmd_pipeline_codegen_help[] =
"pipeline codegen <spec_file> <code_file>\n";
@@ -3155,8 +2723,6 @@ cmd_help(char **tokens,
"\tmempool\n"
"\tlink\n"
"\ttap\n"
- "\tpipeline port in\n"
- "\tpipeline port out\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
"\tpipeline build\n"
@@ -3207,21 +2773,6 @@ cmd_help(char **tokens,
return;
}
- if ((strcmp(tokens[0], "pipeline") == 0) &&
- (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
- if (strcmp(tokens[2], "in") == 0) {
- snprintf(out, out_size, "\n%s\n",
- cmd_pipeline_port_in_help);
- return;
- }
-
- if (strcmp(tokens[2], "out") == 0) {
- snprintf(out, out_size, "\n%s\n",
- cmd_pipeline_port_out_help);
- return;
- }
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
@@ -3489,22 +3040,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
}
if (strcmp(tokens[0], "pipeline") == 0) {
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "port") == 0) &&
- (strcmp(tokens[3], "in") == 0)) {
- cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "port") == 0) &&
- (strcmp(tokens[3], "out") == 0)) {
- cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "codegen") == 0)) {
cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (10 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 12/17] examples/pipeline: remove the obsolete port configuration CLI commands Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 14/17] examples/pipeline: use the pipeline name query API Cristian Dumitrescu
` (4 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline mirroring configuration is done through the I/O
specification file, so this CLI command is no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 76 -----------------------------------------
1 file changed, 76 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index b26e73c706..fa828c008b 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -2457,68 +2457,6 @@ cmd_pipeline_stats(char **tokens,
}
}
-static const char cmd_pipeline_mirror_help[] =
-"pipeline <pipeline_name> mirror slots <n_slots> sessions <n_sessions>\n";
-
-static void
-cmd_pipeline_mirror(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct rte_swx_pipeline_mirroring_params params;
- struct pipeline *p;
- int status;
-
- if (n_tokens != 7) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[0], "pipeline")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p) {
- snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
- return;
- }
-
- if (strcmp(tokens[2], "mirror")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
- return;
- }
-
- if (strcmp(tokens[3], "slots")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "slots");
- return;
- }
-
- if (parser_read_uint32(¶ms.n_slots, tokens[4])) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_slots");
- return;
- }
-
- if (strcmp(tokens[5], "sessions")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sessions");
- return;
- }
-
- if (parser_read_uint32(¶ms.n_sessions, tokens[6])) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_sessions");
- return;
- }
-
- status = rte_swx_pipeline_mirroring_config(p->p, ¶ms);
- if (status) {
- snprintf(out, out_size, "Command failed!\n");
- return;
- }
-}
-
static const char cmd_pipeline_mirror_session_help[] =
"pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow "
"truncate <truncation_length>\n";
@@ -2746,7 +2684,6 @@ cmd_help(char **tokens,
"\tpipeline meter set\n"
"\tpipeline meter stats\n"
"\tpipeline stats\n"
- "\tpipeline mirror\n"
"\tpipeline mirror session\n"
"\tthread pipeline enable\n"
"\tthread pipeline disable\n\n");
@@ -2958,12 +2895,6 @@ cmd_help(char **tokens,
return;
}
- if (!strcmp(tokens[0], "pipeline") &&
- (n_tokens == 2) && !strcmp(tokens[1], "mirror")) {
- snprintf(out, out_size, "\n%s\n", cmd_pipeline_mirror_help);
- return;
- }
-
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "mirror")
&& !strcmp(tokens[2], "session")) {
@@ -3217,13 +3148,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "mirror") == 0) &&
- (strcmp(tokens[3], "slots") == 0)) {
- cmd_pipeline_mirror(tokens, n_tokens, out, out_size, obj);
- return;
- }
-
if ((n_tokens >= 4) &&
(strcmp(tokens[2], "mirror") == 0) &&
(strcmp(tokens[3], "session") == 0)) {
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 14/17] examples/pipeline: use the pipeline name query API
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (11 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 15/17] examples/pipeline: rework the link CLI command Cristian Dumitrescu
` (3 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Convert the CLI commands to use the pipeline name query API and remove
the linked list of pipeline objects previously maintained by the
application.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 268 ++++++++++++++++++++-----------------
examples/pipeline/obj.c | 67 ----------
examples/pipeline/obj.h | 24 ----
examples/pipeline/thread.c | 65 ++++-----
examples/pipeline/thread.h | 9 +-
5 files changed, 175 insertions(+), 258 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index fa828c008b..f48ff326be 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -858,9 +858,9 @@ cmd_pipeline_table_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -872,8 +872,8 @@ cmd_pipeline_table_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -887,7 +887,7 @@ cmd_pipeline_table_add(char **tokens,
return;
}
- status = pipeline_table_entries_add(p->ctl,
+ status = pipeline_table_entries_add(ctl,
table_name,
file,
&file_line_number);
@@ -956,9 +956,9 @@ cmd_pipeline_table_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -970,8 +970,8 @@ cmd_pipeline_table_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -985,7 +985,7 @@ cmd_pipeline_table_delete(char **tokens,
return;
}
- status = pipeline_table_entries_delete(p->ctl,
+ status = pipeline_table_entries_delete(ctl,
table_name,
file,
&file_line_number);
@@ -1054,9 +1054,9 @@ cmd_pipeline_table_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1068,8 +1068,8 @@ cmd_pipeline_table_default(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1083,7 +1083,7 @@ cmd_pipeline_table_default(char **tokens,
return;
}
- status = pipeline_table_default_entry_add(p->ctl,
+ status = pipeline_table_default_entry_add(ctl,
table_name,
file,
&file_line_number);
@@ -1103,9 +1103,9 @@ cmd_pipeline_table_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name;
FILE *file = NULL;
int status;
@@ -1116,8 +1116,8 @@ cmd_pipeline_table_show(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1129,7 +1129,7 @@ cmd_pipeline_table_show(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
+ status = rte_swx_ctl_pipeline_table_fprintf(file, ctl, table_name);
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
@@ -1145,9 +1145,9 @@ cmd_pipeline_selector_group_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
@@ -1158,8 +1158,8 @@ cmd_pipeline_selector_group_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1177,7 +1177,7 @@ cmd_pipeline_selector_group_add(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
+ status = rte_swx_ctl_pipeline_selector_group_add(ctl,
selector_name,
&group_id);
if (status)
@@ -1194,9 +1194,9 @@ cmd_pipeline_selector_group_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
@@ -1207,8 +1207,8 @@ cmd_pipeline_selector_group_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1231,7 +1231,7 @@ cmd_pipeline_selector_group_delete(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
+ status = rte_swx_ctl_pipeline_selector_group_delete(ctl,
selector_name,
group_id);
if (status)
@@ -1402,9 +1402,9 @@ cmd_pipeline_selector_group_member_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1416,8 +1416,8 @@ cmd_pipeline_selector_group_member_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1443,7 +1443,7 @@ cmd_pipeline_selector_group_member_add(char **tokens,
return;
}
- status = pipeline_selector_group_members_add(p->ctl,
+ status = pipeline_selector_group_members_add(ctl,
selector_name,
file,
&file_line_number);
@@ -1512,9 +1512,9 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1526,8 +1526,8 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1553,7 +1553,7 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
return;
}
- status = pipeline_selector_group_members_delete(p->ctl,
+ status = pipeline_selector_group_members_delete(ctl,
selector_name,
file,
&file_line_number);
@@ -1573,9 +1573,9 @@ cmd_pipeline_selector_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
FILE *file = NULL;
int status;
@@ -1586,8 +1586,8 @@ cmd_pipeline_selector_show(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1600,7 +1600,7 @@ cmd_pipeline_selector_show(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
+ status = rte_swx_ctl_pipeline_selector_fprintf(file, ctl, selector_name);
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
@@ -1665,9 +1665,9 @@ cmd_pipeline_learner_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *learner_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1679,8 +1679,8 @@ cmd_pipeline_learner_default(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1694,7 +1694,7 @@ cmd_pipeline_learner_default(char **tokens,
return;
}
- status = pipeline_learner_default_entry_add(p->ctl,
+ status = pipeline_learner_default_entry_add(ctl,
learner_name,
file,
&file_line_number);
@@ -1714,9 +1714,9 @@ cmd_pipeline_commit(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
int status;
@@ -1726,13 +1726,13 @@ cmd_pipeline_commit(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
- status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
+ status = rte_swx_ctl_pipeline_commit(ctl, 1);
if (status)
snprintf(out, out_size, "Commit failed. "
"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
@@ -1746,9 +1746,9 @@ cmd_pipeline_abort(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
if (n_tokens != 3) {
@@ -1757,13 +1757,13 @@ cmd_pipeline_abort(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
- rte_swx_ctl_pipeline_abort(p->ctl);
+ rte_swx_ctl_pipeline_abort(ctl);
}
static const char cmd_pipeline_regrd_help[] =
@@ -1774,9 +1774,9 @@ cmd_pipeline_regrd(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint64_t value;
uint32_t idx;
@@ -1787,8 +1787,8 @@ cmd_pipeline_regrd(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1805,7 +1805,7 @@ cmd_pipeline_regrd(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
+ status = rte_swx_ctl_pipeline_regarray_read(p, name, idx, &value);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1822,9 +1822,9 @@ cmd_pipeline_regwr(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint64_t value;
uint32_t idx;
@@ -1835,8 +1835,8 @@ cmd_pipeline_regwr(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1858,7 +1858,7 @@ cmd_pipeline_regwr(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
+ status = rte_swx_ctl_pipeline_regarray_write(p, name, idx, value);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1874,10 +1874,10 @@ cmd_pipeline_meter_profile_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_meter_trtcm_params params;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *profile_name;
int status;
@@ -1886,8 +1886,8 @@ cmd_pipeline_meter_profile_add(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1949,7 +1949,7 @@ cmd_pipeline_meter_profile_add(char **tokens,
return;
}
- status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms);
+ status = rte_swx_ctl_meter_profile_add(p, profile_name, ¶ms);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1964,9 +1964,9 @@ cmd_pipeline_meter_profile_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *profile_name;
int status;
@@ -1975,8 +1975,8 @@ cmd_pipeline_meter_profile_delete(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1998,7 +1998,7 @@ cmd_pipeline_meter_profile_delete(char **tokens,
return;
}
- status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
+ status = rte_swx_ctl_meter_profile_delete(p, profile_name);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -2014,9 +2014,9 @@ cmd_pipeline_meter_reset(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2025,8 +2025,8 @@ cmd_pipeline_meter_reset(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2066,7 +2066,7 @@ cmd_pipeline_meter_reset(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_reset(p->p, name, idx0);
+ status = rte_swx_ctl_meter_reset(p, name, idx0);
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
@@ -2083,9 +2083,9 @@ cmd_pipeline_meter_set(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name, *profile_name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2094,8 +2094,8 @@ cmd_pipeline_meter_set(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2142,7 +2142,7 @@ cmd_pipeline_meter_set(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
+ status = rte_swx_ctl_meter_set(p, name, idx0, profile_name);
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
@@ -2159,10 +2159,10 @@ cmd_pipeline_meter_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_ctl_meter_stats stats;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2171,8 +2171,8 @@ cmd_pipeline_meter_stats(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2235,7 +2235,7 @@ cmd_pipeline_meter_stats(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
+ status = rte_swx_ctl_meter_stats_read(p, name, idx0, &stats);
if (status) {
snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
out_size -= strlen(out);
@@ -2265,10 +2265,10 @@ cmd_pipeline_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_ctl_pipeline_info info;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
uint32_t i;
int status;
@@ -2277,8 +2277,8 @@ cmd_pipeline_stats(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2288,7 +2288,7 @@ cmd_pipeline_stats(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_info_get(p->p, &info);
+ status = rte_swx_ctl_pipeline_info_get(p, &info);
if (status) {
snprintf(out, out_size, "Pipeline info get error.");
return;
@@ -2301,7 +2301,7 @@ cmd_pipeline_stats(char **tokens,
for (i = 0; i < info.n_ports_in; i++) {
struct rte_swx_port_in_stats stats;
- rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
+ rte_swx_ctl_pipeline_port_in_stats_read(p, i, &stats);
snprintf(out, out_size, "\tPort %u:"
" packets %" PRIu64
@@ -2319,7 +2319,7 @@ cmd_pipeline_stats(char **tokens,
for (i = 0; i < info.n_ports_out; i++) {
struct rte_swx_port_out_stats stats;
- rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
+ rte_swx_ctl_pipeline_port_out_stats_read(p, i, &stats);
if (i != info.n_ports_out - 1)
snprintf(out, out_size, "\tPort %u:", i);
@@ -2358,13 +2358,13 @@ cmd_pipeline_stats(char **tokens,
};
uint32_t j;
- status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+ status = rte_swx_ctl_table_info_get(p, i, &table_info);
if (status) {
snprintf(out, out_size, "Table info get error.");
return;
}
- status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+ status = rte_swx_ctl_pipeline_table_stats_read(p, table_info.name, &stats);
if (status) {
snprintf(out, out_size, "Table stats read error.");
return;
@@ -2382,7 +2382,7 @@ cmd_pipeline_stats(char **tokens,
for (j = 0; j < info.n_actions; j++) {
struct rte_swx_ctl_action_info action_info;
- status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+ status = rte_swx_ctl_action_info_get(p, j, &action_info);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
@@ -2410,13 +2410,13 @@ cmd_pipeline_stats(char **tokens,
};
uint32_t j;
- status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
+ status = rte_swx_ctl_learner_info_get(p, i, &learner_info);
if (status) {
snprintf(out, out_size, "Learner table info get error.");
return;
}
- status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
+ status = rte_swx_ctl_pipeline_learner_stats_read(p, learner_info.name, &stats);
if (status) {
snprintf(out, out_size, "Learner table stats read error.");
return;
@@ -2442,7 +2442,7 @@ cmd_pipeline_stats(char **tokens,
for (j = 0; j < info.n_actions; j++) {
struct rte_swx_ctl_action_info action_info;
- status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+ status = rte_swx_ctl_action_info_get(p, j, &action_info);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
@@ -2466,10 +2466,10 @@ cmd_pipeline_mirror_session(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_pipeline_mirroring_session_params params;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
uint32_t session_id = 0;
int status;
@@ -2483,8 +2483,8 @@ cmd_pipeline_mirror_session(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2538,7 +2538,7 @@ cmd_pipeline_mirror_session(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, ¶ms);
+ status = rte_swx_ctl_pipeline_mirroring_session_set(p, session_id, ¶ms);
if (status) {
snprintf(out, out_size, "Command failed!\n");
return;
@@ -2546,21 +2546,25 @@ cmd_pipeline_mirror_session(char **tokens,
}
static const char cmd_thread_pipeline_enable_help[] =
-"thread <thread_id> pipeline <pipeline_name> enable\n";
+"thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]\n";
+
+#ifndef TIMER_PERIOD_MS_DEFAULT
+#define TIMER_PERIOD_MS_DEFAULT 10
+#endif
static void
cmd_thread_pipeline_enable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
char *pipeline_name;
- struct pipeline *p;
- uint32_t thread_id;
+ struct rte_swx_pipeline *p;
+ uint32_t thread_id, timer_period_ms = TIMER_PERIOD_MS_DEFAULT;
int status;
- if (n_tokens != 5) {
+ if ((n_tokens != 5) && (n_tokens != 7)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
@@ -2576,8 +2580,8 @@ cmd_thread_pipeline_enable(char **tokens,
}
pipeline_name = tokens[3];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(pipeline_name);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2587,7 +2591,19 @@ cmd_thread_pipeline_enable(char **tokens,
return;
}
- status = thread_pipeline_enable(thread_id, obj, pipeline_name);
+ if (n_tokens == 7) {
+ if (strcmp(tokens[5], "period") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
+ return;
+ }
+
+ if (parser_read_uint32(&timer_period_ms, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
+ return;
+ }
+ }
+
+ status = thread_pipeline_enable(thread_id, p, timer_period_ms);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
return;
@@ -2602,9 +2618,9 @@ cmd_thread_pipeline_disable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
char *pipeline_name;
uint32_t thread_id;
int status;
@@ -2625,8 +2641,8 @@ cmd_thread_pipeline_disable(char **tokens,
}
pipeline_name = tokens[3];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(pipeline_name);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2636,7 +2652,7 @@ cmd_thread_pipeline_disable(char **tokens,
return;
}
- status = thread_pipeline_disable(thread_id, obj, pipeline_name);
+ status = thread_pipeline_disable(thread_id, p);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL,
"thread pipeline disable");
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index 967342c580..d1f519180e 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -16,7 +16,6 @@
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_ethdev.h>
-#include <rte_swx_pipeline.h>
#include <rte_swx_ctl.h>
#include "obj.h"
@@ -41,11 +40,6 @@ TAILQ_HEAD(ring_list, ring);
*/
TAILQ_HEAD(tap_list, tap);
-/*
- * pipeline
- */
-TAILQ_HEAD(pipeline_list, pipeline);
-
/*
* obj
*/
@@ -53,7 +47,6 @@ struct obj {
struct mempool_list mempool_list;
struct link_list link_list;
struct ring_list ring_list;
- struct pipeline_list pipeline_list;
struct tap_list tap_list;
};
@@ -513,65 +506,6 @@ tap_create(struct obj *obj, const char *name)
#endif
-/*
- * pipeline
- */
-#ifndef PIPELINE_MSGQ_SIZE
-#define PIPELINE_MSGQ_SIZE 64
-#endif
-
-struct pipeline *
-pipeline_create(struct obj *obj, const char *name, int numa_node)
-{
- struct pipeline *pipeline;
- struct rte_swx_pipeline *p = NULL;
- int status;
-
- /* Check input params */
- if ((name == NULL) ||
- pipeline_find(obj, name))
- return NULL;
-
- /* Resource create */
- status = rte_swx_pipeline_config(&p, name, numa_node);
- if (status)
- goto error;
-
- /* Node allocation */
- pipeline = calloc(1, sizeof(struct pipeline));
- if (pipeline == NULL)
- goto error;
-
- /* Node fill in */
- strlcpy(pipeline->name, name, sizeof(pipeline->name));
- pipeline->p = p;
- pipeline->timer_period_ms = 10;
-
- /* Node add to list */
- TAILQ_INSERT_TAIL(&obj->pipeline_list, pipeline, node);
-
- return pipeline;
-
-error:
- rte_swx_pipeline_free(p);
- return NULL;
-}
-
-struct pipeline *
-pipeline_find(struct obj *obj, const char *name)
-{
- struct pipeline *pipeline;
-
- if (!obj || !name)
- return NULL;
-
- TAILQ_FOREACH(pipeline, &obj->pipeline_list, node)
- if (strcmp(name, pipeline->name) == 0)
- return pipeline;
-
- return NULL;
-}
-
/*
* obj
*/
@@ -587,7 +521,6 @@ obj_init(void)
TAILQ_INIT(&obj->mempool_list);
TAILQ_INIT(&obj->link_list);
TAILQ_INIT(&obj->ring_list);
- TAILQ_INIT(&obj->pipeline_list);
TAILQ_INIT(&obj->tap_list);
return obj;
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index b921610554..e63a9c0e9a 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -143,28 +143,4 @@ tap_next(struct obj *obj, struct tap *tap);
struct tap *
tap_create(struct obj *obj, const char *name);
-/*
- * pipeline
- */
-struct pipeline {
- TAILQ_ENTRY(pipeline) node;
- char name[NAME_SIZE];
-
- struct rte_swx_pipeline *p;
- struct rte_swx_ctl_pipeline *ctl;
-
- uint32_t timer_period_ms;
- int enabled;
- uint32_t thread_id;
- uint32_t cpu_id;
-};
-
-struct pipeline *
-pipeline_create(struct obj *obj,
- const char *name,
- int numa_node);
-
-struct pipeline *
-pipeline_find(struct obj *obj, const char *name);
-
#endif /* _INCLUDE_OBJ_H_ */
diff --git a/examples/pipeline/thread.c b/examples/pipeline/thread.c
index 5fe7eae00e..6d15f51fb2 100644
--- a/examples/pipeline/thread.c
+++ b/examples/pipeline/thread.c
@@ -228,20 +228,33 @@ thread_msg_send_recv(uint32_t thread_id,
return rsp;
}
+static int
+thread_is_pipeline_enabled(uint32_t thread_id, struct rte_swx_pipeline *p)
+{
+ struct thread *t = &thread[thread_id];
+ struct thread_data *td = &thread_data[thread_id];
+ uint32_t i;
+
+ if (!t->enabled)
+ return 0; /* Pipeline NOT enabled on this thread. */
+
+ for (i = 0; i < td->n_pipelines; i++)
+ if (td->p[i] == p)
+ return 1; /* Pipeline enabled on this thread. */
+
+ return 0 /* Pipeline NOT enabled on this thread. */;
+}
+
int
-thread_pipeline_enable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name)
+thread_pipeline_enable(uint32_t thread_id, struct rte_swx_pipeline *p, uint32_t timer_period_ms)
{
- struct pipeline *p = pipeline_find(obj, pipeline_name);
struct thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
- (p == NULL))
+ if ((thread_id >= RTE_MAX_LCORE) || !p || !timer_period_ms)
return -1;
t = &thread[thread_id];
@@ -256,19 +269,14 @@ thread_pipeline_enable(uint32_t thread_id,
return -1;
/* Data plane thread */
- td->p[td->n_pipelines] = p->p;
+ td->p[td->n_pipelines] = p;
- tdp->p = p->p;
- tdp->timer_period =
- (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
+ tdp->p = p;
+ tdp->timer_period = (rte_get_tsc_hz() * timer_period_ms) / 1000;
tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
td->n_pipelines++;
- /* Pipeline */
- p->thread_id = thread_id;
- p->enabled = 1;
-
return 0;
}
@@ -279,8 +287,8 @@ thread_pipeline_enable(uint32_t thread_id,
/* Write request */
req->type = THREAD_REQ_PIPELINE_ENABLE;
- req->pipeline_enable.p = p->p;
- req->pipeline_enable.timer_period_ms = p->timer_period_ms;
+ req->pipeline_enable.p = p;
+ req->pipeline_enable.timer_period_ms = timer_period_ms;
/* Send request and wait for response */
rsp = thread_msg_send_recv(thread_id, req);
@@ -295,38 +303,28 @@ thread_pipeline_enable(uint32_t thread_id,
if (status)
return status;
- p->thread_id = thread_id;
- p->enabled = 1;
-
return 0;
}
int
-thread_pipeline_disable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name)
+thread_pipeline_disable(uint32_t thread_id, struct rte_swx_pipeline *p)
{
- struct pipeline *p = pipeline_find(obj, pipeline_name);
struct thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
- (p == NULL))
+ if ((thread_id >= RTE_MAX_LCORE) || !p)
return -1;
t = &thread[thread_id];
if (t->enabled == 0)
return -1;
- if (p->enabled == 0)
+ if (!thread_is_pipeline_enabled(thread_id, p))
return 0;
- if (p->thread_id != thread_id)
- return -1;
-
if (!thread_is_running(thread_id)) {
struct thread_data *td = &thread_data[thread_id];
uint32_t i;
@@ -334,7 +332,7 @@ thread_pipeline_disable(uint32_t thread_id,
for (i = 0; i < td->n_pipelines; i++) {
struct pipeline_data *tdp = &td->pipeline_data[i];
- if (tdp->p != p->p)
+ if (tdp->p != p)
continue;
/* Data plane thread */
@@ -350,9 +348,6 @@ thread_pipeline_disable(uint32_t thread_id,
td->n_pipelines--;
- /* Pipeline */
- p->enabled = 0;
-
break;
}
@@ -366,7 +361,7 @@ thread_pipeline_disable(uint32_t thread_id,
/* Write request */
req->type = THREAD_REQ_PIPELINE_DISABLE;
- req->pipeline_disable.p = p->p;
+ req->pipeline_disable.p = p;
/* Send request and wait for response */
rsp = thread_msg_send_recv(thread_id, req);
@@ -381,8 +376,6 @@ thread_pipeline_disable(uint32_t thread_id,
if (status)
return status;
- p->enabled = 0;
-
return 0;
}
diff --git a/examples/pipeline/thread.h b/examples/pipeline/thread.h
index d9d8645d4c..712cb25bbb 100644
--- a/examples/pipeline/thread.h
+++ b/examples/pipeline/thread.h
@@ -7,17 +7,16 @@
#include <stdint.h>
-#include "obj.h"
+#include <rte_swx_pipeline.h>
int
thread_pipeline_enable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name);
+ struct rte_swx_pipeline *p,
+ uint32_t timer_period_ms);
int
thread_pipeline_disable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name);
+ struct rte_swx_pipeline *p);
int
thread_init(void);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 15/17] examples/pipeline: rework the link CLI command
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (12 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 14/17] examples/pipeline: use the pipeline name query API Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 16/17] examples/pipelines: remove obsolete tap " Cristian Dumitrescu
` (2 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the link CLI command for better alignment with the naming
conventions used in the pipeline I/O specification file. Use the
library linked list of devices and remove the application list.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 81 +++++++++++++----------------------------
examples/pipeline/obj.c | 16 ++------
examples/pipeline/obj.h | 4 --
3 files changed, 29 insertions(+), 72 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index f48ff326be..d56a830fb7 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -106,22 +106,6 @@ parser_read_uint32(uint32_t *value, const char *p)
return 0;
}
-static int
-parser_read_uint16(uint16_t *value, const char *p)
-{
- uint64_t val = 0;
- int ret = parser_read_uint64(&val, p);
-
- if (ret < 0)
- return ret;
-
- if (val > UINT16_MAX)
- return -ERANGE;
-
- *value = val;
- return 0;
-}
-
#define PARSE_DELIMITER " \f\n\r\t\v"
static int
@@ -230,16 +214,15 @@ cmd_mempool(char **tokens,
}
}
-static const char cmd_link_help[] =
-"link <link_name>\n"
-" dev <device_name> | port <port_id>\n"
+static const char cmd_ethdev_help[] =
+"ethdev <ethdev_name>\n"
" rxq <n_queues> <queue_size> <mempool_name>\n"
" txq <n_queues> <queue_size>\n"
" promiscuous on | off\n"
" [rss <qid_0> ... <qid_n>]\n";
static void
-cmd_link(char **tokens,
+cmd_ethdev(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
@@ -252,65 +235,51 @@ cmd_link(char **tokens,
memset(&p, 0, sizeof(p));
- if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
+ if ((n_tokens < 11) || (n_tokens > 12 + LINK_RXQ_RSS_MAX)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
- if (strcmp(tokens[2], "dev") == 0)
- p.dev_name = tokens[3];
- else if (strcmp(tokens[2], "port") == 0) {
- p.dev_name = NULL;
-
- if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
- return;
- }
-
- if (strcmp(tokens[4], "rxq") != 0) {
+ if (strcmp(tokens[2], "rxq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
return;
}
- if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
+ if (parser_read_uint32(&p.rx.n_queues, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
- if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
+ if (parser_read_uint32(&p.rx.queue_size, tokens[4]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
- p.rx.mempool_name = tokens[7];
+ p.rx.mempool_name = tokens[5];
- if (strcmp(tokens[8], "txq") != 0) {
+ if (strcmp(tokens[6], "txq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
return;
}
- if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
+ if (parser_read_uint32(&p.tx.n_queues, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
- if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
+ if (parser_read_uint32(&p.tx.queue_size, tokens[8]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
- if (strcmp(tokens[11], "promiscuous") != 0) {
+ if (strcmp(tokens[9], "promiscuous") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
return;
}
- if (strcmp(tokens[12], "on") == 0)
+ if (strcmp(tokens[10], "on") == 0)
p.promiscuous = 1;
- else if (strcmp(tokens[12], "off") == 0)
+ else if (strcmp(tokens[10], "off") == 0)
p.promiscuous = 0;
else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
@@ -319,10 +288,10 @@ cmd_link(char **tokens,
/* RSS */
p.rx.rss = NULL;
- if (n_tokens > 13) {
+ if (n_tokens > 11) {
uint32_t queue_id, i;
- if (strcmp(tokens[13], "rss") != 0) {
+ if (strcmp(tokens[11], "rss") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
return;
}
@@ -330,7 +299,7 @@ cmd_link(char **tokens,
p.rx.rss = &rss;
rss.n_queues = 0;
- for (i = 14; i < n_tokens; i++) {
+ for (i = 12; i < n_tokens; i++) {
if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"queue_id");
@@ -406,10 +375,10 @@ print_link_info(struct link *link, char *out, size_t out_size)
}
/*
- * link show [<link_name>]
+ * ethdev show [<ethdev_name>]
*/
static void
-cmd_link_show(char **tokens,
+cmd_ethdev_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
@@ -2675,7 +2644,7 @@ cmd_help(char **tokens,
"Type 'help <command>' for command details.\n\n"
"List of commands:\n"
"\tmempool\n"
- "\tlink\n"
+ "\tethdev\n"
"\ttap\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
@@ -2711,8 +2680,8 @@ cmd_help(char **tokens,
return;
}
- if (strcmp(tokens[0], "link") == 0) {
- snprintf(out, out_size, "\n%s\n", cmd_link_help);
+ if (strcmp(tokens[0], "ethdev") == 0) {
+ snprintf(out, out_size, "\n%s\n", cmd_ethdev_help);
return;
}
@@ -2966,13 +2935,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if (strcmp(tokens[0], "link") == 0) {
+ if (strcmp(tokens[0], "ethdev") == 0) {
if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
- cmd_link_show(tokens, n_tokens, out, out_size, obj);
+ cmd_ethdev_show(tokens, n_tokens, out, out_size, obj);
return;
}
- cmd_link(tokens, n_tokens, out, out_size, obj);
+ cmd_ethdev(tokens, n_tokens, out, out_size, obj);
return;
}
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index d1f519180e..950ab831fb 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -181,7 +181,7 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
struct mempool *mempool;
uint32_t cpu_id, i;
int status;
- uint16_t port_id;
+ uint16_t port_id = 0;
/* Check input params */
if ((name == NULL) ||
@@ -193,16 +193,9 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
(params->tx.queue_size == 0))
return NULL;
- port_id = params->port_id;
- if (params->dev_name) {
- status = rte_eth_dev_get_port_by_name(params->dev_name,
- &port_id);
-
- if (status)
- return NULL;
- } else
- if (!rte_eth_dev_is_valid_port(port_id))
- return NULL;
+ status = rte_eth_dev_get_port_by_name(name, &port_id);
+ if (status)
+ return NULL;
if (rte_eth_dev_info_get(port_id, &port_info) != 0)
return NULL;
@@ -315,7 +308,6 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
/* Node fill in */
strlcpy(link->name, name, sizeof(link->name));
link->port_id = port_id;
- rte_eth_dev_get_name_by_port(port_id, link->dev_name);
link->n_rxq = params->rx.n_queues;
link->n_txq = params->tx.n_queues;
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index e63a9c0e9a..af270a8e57 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -63,9 +63,6 @@ struct link_params_rss {
};
struct link_params {
- const char *dev_name;
- uint16_t port_id; /**< Valid only when *dev_name* is NULL. */
-
struct {
uint32_t n_queues;
uint32_t queue_size;
@@ -84,7 +81,6 @@ struct link_params {
struct link {
TAILQ_ENTRY(link) node;
char name[NAME_SIZE];
- char dev_name[NAME_SIZE];
uint16_t port_id;
uint32_t n_rxq;
uint32_t n_txq;
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 16/17] examples/pipelines: remove obsolete tap CLI command
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (13 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 15/17] examples/pipeline: rework the link CLI command Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:36 ` [PATCH V3 17/17] examples/pipeline: call the code generation and build CLI commands Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Remove the tap CLI command, as the file descriptor I/O ports of the
pipeline are now configured trough the I/O specification file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 37 -----------------
examples/pipeline/obj.c | 89 -----------------------------------------
examples/pipeline/obj.h | 18 ---------
3 files changed, 144 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index d56a830fb7..75c32b9089 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -466,32 +466,6 @@ cmd_ring(char **tokens,
}
}
-static const char cmd_tap_help[] =
-"tap <tap_name>\n";
-
-static void
-cmd_tap(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct tap *tap;
- char *name;
-
- if (n_tokens < 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
- name = tokens[1];
-
- tap = tap_create(obj, name);
- if (tap == NULL) {
- snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- return;
- }
-}
-
static const char cmd_pipeline_codegen_help[] =
"pipeline codegen <spec_file> <code_file>\n";
@@ -2645,7 +2619,6 @@ cmd_help(char **tokens,
"List of commands:\n"
"\tmempool\n"
"\tethdev\n"
- "\ttap\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
"\tpipeline build\n"
@@ -2690,11 +2663,6 @@ cmd_help(char **tokens,
return;
}
- if (strcmp(tokens[0], "tap") == 0) {
- snprintf(out, out_size, "\n%s\n", cmd_tap_help);
- return;
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
@@ -2950,11 +2918,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if (strcmp(tokens[0], "tap") == 0) {
- cmd_tap(tokens, n_tokens, out, out_size, obj);
- return;
- }
-
if (strcmp(tokens[0], "pipeline") == 0) {
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "codegen") == 0)) {
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index 950ab831fb..b7e2316eec 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -35,11 +35,6 @@ TAILQ_HEAD(link_list, link);
*/
TAILQ_HEAD(ring_list, ring);
-/*
- * tap
- */
-TAILQ_HEAD(tap_list, tap);
-
/*
* obj
*/
@@ -47,7 +42,6 @@ struct obj {
struct mempool_list mempool_list;
struct link_list link_list;
struct ring_list ring_list;
- struct tap_list tap_list;
};
/*
@@ -416,88 +410,6 @@ ring_find(struct obj *obj, const char *name)
return NULL;
}
-/*
- * tap
- */
-#define TAP_DEV "/dev/net/tun"
-
-struct tap *
-tap_find(struct obj *obj, const char *name)
-{
- struct tap *tap;
-
- if (!obj || !name)
- return NULL;
-
- TAILQ_FOREACH(tap, &obj->tap_list, node)
- if (strcmp(tap->name, name) == 0)
- return tap;
-
- return NULL;
-}
-
-struct tap *
-tap_next(struct obj *obj, struct tap *tap)
-{
- return (tap == NULL) ?
- TAILQ_FIRST(&obj->tap_list) : TAILQ_NEXT(tap, node);
-}
-
-#ifndef RTE_EXEC_ENV_LINUX
-
-struct tap *
-tap_create(struct obj *obj __rte_unused, const char *name __rte_unused)
-{
- return NULL;
-}
-
-#else
-
-struct tap *
-tap_create(struct obj *obj, const char *name)
-{
- struct tap *tap;
- struct ifreq ifr;
- int fd, status;
-
- /* Check input params */
- if ((name == NULL) ||
- tap_find(obj, name))
- return NULL;
-
- /* Resource create */
- fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
- if (fd < 0)
- return NULL;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
- strlcpy(ifr.ifr_name, name, IFNAMSIZ);
-
- status = ioctl(fd, TUNSETIFF, (void *) &ifr);
- if (status < 0) {
- close(fd);
- return NULL;
- }
-
- /* Node allocation */
- tap = calloc(1, sizeof(struct tap));
- if (tap == NULL) {
- close(fd);
- return NULL;
- }
- /* Node fill in */
- strlcpy(tap->name, name, sizeof(tap->name));
- tap->fd = fd;
-
- /* Node add to list */
- TAILQ_INSERT_TAIL(&obj->tap_list, tap, node);
-
- return tap;
-}
-
-#endif
-
/*
* obj
*/
@@ -513,7 +425,6 @@ obj_init(void)
TAILQ_INIT(&obj->mempool_list);
TAILQ_INIT(&obj->link_list);
TAILQ_INIT(&obj->ring_list);
- TAILQ_INIT(&obj->tap_list);
return obj;
}
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index af270a8e57..8ea1c414c2 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -121,22 +121,4 @@ ring_create(struct obj *obj,
struct ring *
ring_find(struct obj *obj, const char *name);
-/*
- * tap
- */
-struct tap {
- TAILQ_ENTRY(tap) node;
- char name[NAME_SIZE];
- int fd;
-};
-
-struct tap *
-tap_find(struct obj *obj, const char *name);
-
-struct tap *
-tap_next(struct obj *obj, struct tap *tap);
-
-struct tap *
-tap_create(struct obj *obj, const char *name);
-
#endif /* _INCLUDE_OBJ_H_ */
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V3 17/17] examples/pipeline: call the code generation and build CLI commands
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (14 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 16/17] examples/pipelines: remove obsolete tap " Cristian Dumitrescu
@ 2022-07-27 22:36 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:36 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Update the example CLI scripts with the commands for code generation
and shared object library build.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/examples/ethdev.io | 27 +++++++++
examples/pipeline/examples/fib.cli | 44 +++++++-------
examples/pipeline/examples/hash_func.cli | 41 ++++++-------
examples/pipeline/examples/l2fwd.cli | 44 ++++++++------
examples/pipeline/examples/l2fwd_macswp.cli | 44 ++++++++------
.../pipeline/examples/l2fwd_macswp_pcap.cli | 35 +++++++----
examples/pipeline/examples/l2fwd_pcap.cli | 35 +++++++----
examples/pipeline/examples/learner.cli | 43 +++++++-------
examples/pipeline/examples/meter.cli | 58 +++++++++++--------
examples/pipeline/examples/mirroring.cli | 46 ++++++++-------
examples/pipeline/examples/pcap.io | 27 +++++++++
examples/pipeline/examples/recirculation.cli | 41 ++++++-------
examples/pipeline/examples/registers.cli | 53 +++++++++--------
examples/pipeline/examples/selector.cli | 55 +++++++++++-------
examples/pipeline/examples/varbit.cli | 41 ++++++-------
examples/pipeline/examples/vxlan.cli | 48 ++++++++++-----
examples/pipeline/examples/vxlan_pcap.cli | 39 +++++++++----
17 files changed, 444 insertions(+), 277 deletions(-)
create mode 100644 examples/pipeline/examples/ethdev.io
create mode 100644 examples/pipeline/examples/pcap.io
diff --git a/examples/pipeline/examples/ethdev.io b/examples/pipeline/examples/ethdev.io
new file mode 100644
index 0000000000..cf2f3e20bd
--- /dev/null
+++ b/examples/pipeline/examples/ethdev.io
@@ -0,0 +1,27 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline packet mirroring.
+;
+mirroring slots 4 sessions 64
+
+;
+; Pipeline input ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32
+port in 1 ethdev 0000:18:00.1 rxq 0 bsz 32
+port in 2 ethdev 0000:3b:00.0 rxq 0 bsz 32
+port in 3 ethdev 0000:3b:00.1 rxq 0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ethdev 0000:18:00.0 txq 0 bsz 32
+port out 1 ethdev 0000:18:00.1 txq 0 bsz 32
+port out 2 ethdev 0000:3b:00.0 txq 0 bsz 32
+port out 3 ethdev 0000:3b:00.1 txq 0 bsz 32
diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli
index 93ab2b08f8..4e30c1320f 100644
--- a/examples/pipeline/examples/fib.cli
+++ b/examples/pipeline/examples/fib.cli
@@ -1,38 +1,38 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/fib.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/fib.spec /tmp/fib.c
+pipeline libbuild /tmp/fib.c /tmp/fib.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/fib.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/fib.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Initial set of table entries.
;
-; The table entries can later be updated at run-time through the CLI commands. Once the application
-; has been successfully started, the command to get the CLI prompt is: telnet 0.0.0.0 8086.
+; The table entries can later be updated at run-time through the CLI commands.
;
pipeline PIPELINE0 table routing_table add ./examples/pipeline/examples/fib_routing_table.txt
pipeline PIPELINE0 selector nexthop_group_table group add
diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli
index d65cd62d17..b2e219e4c9 100644
--- a/examples/pipeline/examples/hash_func.cli
+++ b/examples/pipeline/examples/hash_func.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/hash_func.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/hash_func.spec /tmp/hash_func.c
+pipeline libbuild /tmp/hash_func.c /tmp/hash_func.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/hash_func.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/hash_func.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli
index d89caf2d0a..27e37021b9 100644
--- a/examples/pipeline/examples/l2fwd.cli
+++ b/examples/pipeline/examples/l2fwd.cli
@@ -1,25 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/ethdev.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli
index 0f2a89ac5b..11bb4543b9 100644
--- a/examples/pipeline/examples/l2fwd_macswp.cli
+++ b/examples/pipeline/examples/l2fwd_macswp.cli
@@ -1,25 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_macswp.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/examples/ethdev.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
index e9656fe3c2..8724dae3b0 100644
--- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
@@ -1,20 +1,31 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-pipeline PIPELINE0 create 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_macswp_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/examples/pcap.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli
index 23fcb199f1..4db0a0dc56 100644
--- a/examples/pipeline/examples/l2fwd_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_pcap.cli
@@ -1,20 +1,31 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-pipeline PIPELINE0 create 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/pcap.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli
index 688ce34f34..6c8aa3921e 100644
--- a/examples/pipeline/examples/learner.cli
+++ b/examples/pipeline/examples/learner.cli
@@ -1,36 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/learner.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/learner.spec /tmp/learner.c
+pipeline libbuild /tmp/learner.c /tmp/learner.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/learner.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/learner.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
;
thread 1 pipeline PIPELINE0 enable
-
-; Once the application has started, the command to get the CLI prompt is: telnet 0.0.0.0 8086
diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli
index b29ed24022..c1b88c882a 100644
--- a/examples/pipeline/examples/meter.cli
+++ b/examples/pipeline/examples/meter.cli
@@ -1,31 +1,43 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-; Example command line:
-; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
-
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/meter.spec /tmp/meter.c
+pipeline libbuild /tmp/meter.c /tmp/meter.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/meter.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/meter.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli
index 46d57db4ec..1d439e04d3 100644
--- a/examples/pipeline/examples/mirroring.cli
+++ b/examples/pipeline/examples/mirroring.cli
@@ -1,36 +1,38 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/mirroring.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/mirroring.spec /tmp/mirroring.c
+pipeline libbuild /tmp/mirroring.c /tmp/mirroring.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-pipeline PIPELINE0 mirror slots 4 sessions 16
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/mirroring.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/mirroring.so io ./examples/pipeline/examples/ethdev.io numa 0
;
-; Packet mirroring sessions.
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
;
pipeline PIPELINE0 mirror session 0 port 1 clone fast truncate 0
pipeline PIPELINE0 mirror session 1 port 2 clone slow truncate 0
diff --git a/examples/pipeline/examples/pcap.io b/examples/pipeline/examples/pcap.io
new file mode 100644
index 0000000000..111f61afae
--- /dev/null
+++ b/examples/pipeline/examples/pcap.io
@@ -0,0 +1,27 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline packet mirroring.
+;
+mirroring slots 4 sessions 64
+
+;
+; Pipeline input ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 1 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 2 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 3 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+
+;
+; Pipeline output ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 sink file none
+port out 1 sink file none
+port out 2 sink file none
+port out 3 sink file none
diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli
index f855c5c327..52d0894f12 100644
--- a/examples/pipeline/examples/recirculation.cli
+++ b/examples/pipeline/examples/recirculation.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/recirculation.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/recirculation.spec /tmp/recirculation.c
+pipeline libbuild /tmp/recirculation.c /tmp/recirculation.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/recirculation.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/recirculation.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli
index 8d026294cb..3516f76a5b 100644
--- a/examples/pipeline/examples/registers.cli
+++ b/examples/pipeline/examples/registers.cli
@@ -1,28 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-; Example command line:
-; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
-
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/registers.spec /tmp/registers.c
+pipeline libbuild /tmp/registers.c /tmp/registers.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/registers.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/registers.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli
index 123782c57b..f0e251b657 100644
--- a/examples/pipeline/examples/selector.cli
+++ b/examples/pipeline/examples/selector.cli
@@ -1,30 +1,45 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/selector.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/selector.spec /tmp/selector.c
+pipeline libbuild /tmp/selector.c /tmp/selector.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/selector.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/selector.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 selector s group add
pipeline PIPELINE0 selector s group member add ./examples/pipeline/examples/selector.txt
pipeline PIPELINE0 commit
pipeline PIPELINE0 selector s show
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli
index 9caeb9ca26..0f89990471 100644
--- a/examples/pipeline/examples/varbit.cli
+++ b/examples/pipeline/examples/varbit.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/varbit.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/varbit.spec /tmp/varbit.c
+pipeline libbuild /tmp/varbit.c /tmp/varbit.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/varbit.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/varbit.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli
index 444f3f7bd8..1fbd1be6e4 100644
--- a/examples/pipeline/examples/vxlan.cli
+++ b/examples/pipeline/examples/vxlan.cli
@@ -1,27 +1,43 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/vxlan.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/vxlan.so io ./examples/pipeline/examples/ethdev.io numa 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli
index 83fca8d0d9..adc7f73312 100644
--- a/examples/pipeline/examples/vxlan_pcap.cli
+++ b/examples/pipeline/examples/vxlan_pcap.cli
@@ -1,22 +1,39 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/vxlan_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/vxlan.so io ./examples/pipeline/examples/pcap.io numa 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 01/17] pipeline: add pipeline name
2022-07-27 22:36 ` [PATCH V3 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (15 preceding siblings ...)
2022-07-27 22:36 ` [PATCH V3 17/17] examples/pipeline: call the code generation and build CLI commands Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (16 more replies)
16 siblings, 17 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add an unique name to every pipeline. This enables the library to
maintain a list of the existing pipeline objects, which can be
queried by the application.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/obj.c | 2 +-
lib/pipeline/rte_swx_ctl.c | 99 +++++++++++++++++++++
lib/pipeline/rte_swx_ctl.h | 15 ++++
lib/pipeline/rte_swx_pipeline.c | 107 ++++++++++++++++++++++-
lib/pipeline/rte_swx_pipeline.h | 18 +++-
lib/pipeline/rte_swx_pipeline_internal.h | 2 +
lib/pipeline/version.map | 4 +
7 files changed, 244 insertions(+), 3 deletions(-)
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index b79f044ac7..967342c580 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -533,7 +533,7 @@ pipeline_create(struct obj *obj, const char *name, int numa_node)
return NULL;
/* Resource create */
- status = rte_swx_pipeline_config(&p, numa_node);
+ status = rte_swx_pipeline_config(&p, name, numa_node);
if (status)
goto error;
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 710e89a46a..1b776fc543 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -9,6 +9,8 @@
#include <rte_common.h>
#include <rte_byteorder.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_swx_table_selector.h>
@@ -1157,12 +1159,103 @@ table_state_create(struct rte_swx_ctl_pipeline *ctl)
return status;
}
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_ctl_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_ctl_pipeline_tailq = {
+ .name = "RTE_SWX_CTL_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_ctl_pipeline_tailq)
+
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_CTL_NAME_SIZE) >= RTE_SWX_CTL_NAME_SIZE))
+ return NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(name, ctl->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_read_unlock();
+ return ctl;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+ctl_register(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl_crt = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(ctl->info.name, ctl_crt->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)ctl;
+ TAILQ_INSERT_TAIL(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+ctl_unregister(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ if (te->data == (void *)ctl) {
+ TAILQ_REMOVE(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_ctl_pipeline_free(struct rte_swx_ctl_pipeline *ctl)
{
if (!ctl)
return;
+ if (ctl->info.name[0])
+ ctl_unregister(ctl);
+
action_free(ctl);
table_state_free(ctl);
@@ -1441,6 +1534,12 @@ rte_swx_ctl_pipeline_create(struct rte_swx_pipeline *p)
if (status)
goto error;
+ if (ctl->info.name[0]) {
+ status = ctl_register(ctl);
+ if (status)
+ goto error;
+ }
+
return ctl;
error:
diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h
index d771389d26..63ee479e47 100644
--- a/lib/pipeline/rte_swx_ctl.h
+++ b/lib/pipeline/rte_swx_ctl.h
@@ -35,6 +35,9 @@ struct rte_swx_pipeline;
/** Pipeline info. */
struct rte_swx_ctl_pipeline_info {
+ /** Pipeline name. */
+ char name[RTE_SWX_CTL_NAME_SIZE];
+
/** Number of input ports. */
uint32_t n_ports_in;
@@ -812,6 +815,18 @@ rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
/** Pipeline control opaque data structure. */
struct rte_swx_ctl_pipeline;
+/**
+ * Pipeline control find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline control handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name);
+
/**
* Pipeline control create
*
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 3e1c6e9edb..c8ccded4f8 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -6,6 +6,8 @@
#include <errno.h>
#include <dlfcn.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_jhash.h>
#include <rte_hash_crc.h>
@@ -9578,6 +9580,95 @@ metarray_free(struct rte_swx_pipeline *p)
/*
* Pipeline.
*/
+
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_pipeline_tailq = {
+ .name = "RTE_SWX_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
+
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
+ return NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(name, p->name, sizeof(p->name))) {
+ rte_mcfg_tailq_read_unlock();
+ return p;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+pipeline_register(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)p;
+ TAILQ_INSERT_TAIL(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+pipeline_unregister(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ if (te->data == (void *)p) {
+ TAILQ_REMOVE(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_pipeline_free(struct rte_swx_pipeline *p)
{
@@ -9586,6 +9677,9 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
if (!p)
return;
+ if (p->name[0])
+ pipeline_unregister(p);
+
lib = p->lib;
free(p->instruction_data);
@@ -9720,13 +9814,14 @@ hash_funcs_register(struct rte_swx_pipeline *p)
}
int
-rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
+rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
{
struct rte_swx_pipeline *pipeline = NULL;
int status = 0;
/* Check input parameters. */
CHECK(p, EINVAL);
+ CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
/* Memory allocation. */
pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
@@ -9736,6 +9831,9 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
}
/* Initialization. */
+ if (name)
+ strcpy(pipeline->name, name);
+
TAILQ_INIT(&pipeline->struct_types);
TAILQ_INIT(&pipeline->port_in_types);
TAILQ_INIT(&pipeline->ports_in);
@@ -9776,6 +9874,12 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
if (status)
goto error;
+ if (pipeline->name[0]) {
+ status = pipeline_register(pipeline);
+ if (status)
+ goto error;
+ }
+
*p = pipeline;
return 0;
@@ -9966,6 +10070,7 @@ rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
TAILQ_FOREACH(table, &p->tables, node)
n_tables++;
+ strcpy(pipeline->name, p->name);
pipeline->n_ports_in = p->n_ports_in;
pipeline->n_ports_out = p->n_ports_out;
pipeline->n_mirroring_slots = p->n_mirroring_slots;
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index c41ca5cb15..ef50a0fa70 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -44,22 +44,38 @@ extern "C" {
/** Pipeline opaque data structure. */
struct rte_swx_pipeline;
+/**
+ * Pipeline find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name);
+
/**
* Pipeline configure
*
* @param[out] p
* Pipeline handle. Must point to valid memory. Contains valid pipeline handle
* when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
* @param[in] numa_node
* Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
- * -ENOMEM: Not enough space/cannot allocate memory.
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Pipeline with this name already exists.
*/
__rte_experimental
int
rte_swx_pipeline_config(struct rte_swx_pipeline **p,
+ const char *name,
int numa_node);
/*
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index a35635efb7..588cad62b5 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -1459,6 +1459,8 @@ instr_operand_nbo(struct thread *t, const struct instr_operand *x)
#endif
struct rte_swx_pipeline {
+ char name[RTE_SWX_NAME_SIZE];
+
struct struct_type_tailq struct_types;
struct port_in_type_tailq port_in_types;
struct port_in_tailq ports_in;
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8312307a7a..50029aadcf 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -145,4 +145,8 @@ EXPERIMENTAL {
rte_swx_ctl_pipeline_learner_timeout_get;
rte_swx_ctl_pipeline_learner_timeout_set;
rte_swx_pipeline_hash_func_register;
+
+ #added in 22.11
+ rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 02/17] pipeline: move specification data structures to internal header
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
` (15 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Move all the pipeline object specification data structures to an
internal header file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 126 +------------------
lib/pipeline/rte_swx_pipeline_spec.h | 176 +++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 125 deletions(-)
create mode 100644 lib/pipeline/rte_swx_pipeline_spec.h
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 904b9eb471..5e07b4f794 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,7 +9,7 @@
#include <rte_common.h>
-#include "rte_swx_pipeline.h"
+#include "rte_swx_pipeline_spec.h"
#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 2048
@@ -34,15 +34,7 @@
/*
* extobj.
- *
- * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
*/
-struct extobj_spec {
- char *name;
- char *extern_type_name;
- char *pragma;
-};
-
static void
extobj_spec_free(struct extobj_spec *s)
{
@@ -104,18 +96,7 @@ extobj_statement_parse(struct extobj_spec *s,
/*
* struct.
*
- * struct STRUCT_TYPE_NAME {
- * bit<SIZE> | varbit<SIZE> FIELD_NAME
- * ...
- * }
*/
-struct struct_spec {
- char *name;
- struct rte_swx_field_params *fields;
- uint32_t n_fields;
- int varbit;
-};
-
static void
struct_spec_free(struct struct_spec *s)
{
@@ -293,13 +274,7 @@ struct_block_parse(struct struct_spec *s,
/*
* header.
*
- * header HEADER_NAME instanceof STRUCT_TYPE_NAME
*/
-struct header_spec {
- char *name;
- char *struct_type_name;
-};
-
static void
header_spec_free(struct header_spec *s)
{
@@ -351,12 +326,7 @@ header_statement_parse(struct header_spec *s,
/*
* metadata.
*
- * metadata instanceof STRUCT_TYPE_NAME
*/
-struct metadata_spec {
- char *struct_type_name;
-};
-
static void
metadata_spec_free(struct metadata_spec *s)
{
@@ -400,18 +370,7 @@ metadata_statement_parse(struct metadata_spec *s,
/*
* action.
*
- * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
- * INSTRUCTION
- * ...
- * }
*/
-struct action_spec {
- char *name;
- char *args_struct_type_name;
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
action_spec_free(struct action_spec *s)
{
@@ -540,29 +499,7 @@ action_block_parse(struct action_spec *s,
/*
* table.
*
- * table TABLE_NAME {
- * key {
- * MATCH_FIELD_NAME exact | wildcard | lpm
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly ]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * instanceof TABLE_TYPE_NAME
- * pragma ARGS
- * size SIZE
- * }
*/
-struct table_spec {
- char *name;
- struct rte_swx_pipeline_table_params params;
- char *recommended_table_type_name;
- char *args;
- uint32_t size;
-};
-
static void
table_spec_free(struct table_spec *s)
{
@@ -1084,22 +1021,7 @@ table_block_parse(struct table_spec *s,
/*
* selector.
*
- * selector SELECTOR_NAME {
- * group_id FIELD_NAME
- * selector {
- * FIELD_NAME
- * ...
- * }
- * member_id FIELD_NAME
- * n_groups N_GROUPS
- * n_members_per_group N_MEMBERS_PER_GROUP
- * }
*/
-struct selector_spec {
- char *name;
- struct rte_swx_pipeline_selector_params params;
-};
-
static void
selector_spec_free(struct selector_spec *s)
{
@@ -1385,31 +1307,7 @@ selector_block_parse(struct selector_spec *s,
/*
* learner.
*
- * learner LEARNER_NAME {
- * key {
- * MATCH_FIELD_NAME
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * size SIZE
- * timeout {
- * TIMEOUT_IN_SECONDS
- * ...
- * }
- * }
*/
-struct learner_spec {
- char *name;
- struct rte_swx_pipeline_learner_params params;
- uint32_t size;
- uint32_t *timeout;
- uint32_t n_timeouts;
-};
-
static void
learner_spec_free(struct learner_spec *s)
{
@@ -1958,14 +1856,7 @@ learner_block_parse(struct learner_spec *s,
/*
* regarray.
*
- * regarray NAME size SIZE initval INITVAL
*/
-struct regarray_spec {
- char *name;
- uint64_t init_val;
- uint32_t size;
-};
-
static void
regarray_spec_free(struct regarray_spec *s)
{
@@ -2033,13 +1924,7 @@ regarray_statement_parse(struct regarray_spec *s,
/*
* metarray.
*
- * metarray NAME size SIZE
*/
-struct metarray_spec {
- char *name;
- uint32_t size;
-};
-
static void
metarray_spec_free(struct metarray_spec *s)
{
@@ -2095,16 +1980,7 @@ metarray_statement_parse(struct metarray_spec *s,
/*
* apply.
*
- * apply {
- * INSTRUCTION
- * ...
- * }
*/
-struct apply_spec {
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
apply_spec_free(struct apply_spec *s)
{
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
new file mode 100644
index 0000000000..8458de878a
--- /dev/null
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+
+#include <rte_swx_pipeline.h>
+
+/*
+ * extobj.
+ *
+ * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
+ */
+struct extobj_spec {
+ char *name;
+ char *extern_type_name;
+ char *pragma;
+};
+
+/*
+ * struct.
+ *
+ * struct STRUCT_TYPE_NAME {
+ * bit<SIZE> | varbit<SIZE> FIELD_NAME
+ * ...
+ * }
+ */
+struct struct_spec {
+ char *name;
+ struct rte_swx_field_params *fields;
+ uint32_t n_fields;
+ int varbit;
+};
+
+/*
+ * header.
+ *
+ * header HEADER_NAME instanceof STRUCT_TYPE_NAME
+ */
+struct header_spec {
+ char *name;
+ char *struct_type_name;
+};
+
+/*
+ * metadata.
+ *
+ * metadata instanceof STRUCT_TYPE_NAME
+ */
+struct metadata_spec {
+ char *struct_type_name;
+};
+
+/*
+ * action.
+ *
+ * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct action_spec {
+ char *name;
+ char *args_struct_type_name;
+ const char **instructions;
+ uint32_t n_instructions;
+};
+
+/*
+ * table.
+ *
+ * table TABLE_NAME {
+ * key {
+ * MATCH_FIELD_NAME exact | wildcard | lpm
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly ]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * instanceof TABLE_TYPE_NAME
+ * pragma ARGS
+ * size SIZE
+ * }
+ */
+struct table_spec {
+ char *name;
+ struct rte_swx_pipeline_table_params params;
+ char *recommended_table_type_name;
+ char *args;
+ uint32_t size;
+};
+
+/*
+ * selector.
+ *
+ * selector SELECTOR_NAME {
+ * group_id FIELD_NAME
+ * selector {
+ * FIELD_NAME
+ * ...
+ * }
+ * member_id FIELD_NAME
+ * n_groups N_GROUPS
+ * n_members_per_group N_MEMBERS_PER_GROUP
+ * }
+ */
+struct selector_spec {
+ char *name;
+ struct rte_swx_pipeline_selector_params params;
+};
+
+/*
+ * learner.
+ *
+ * learner LEARNER_NAME {
+ * key {
+ * MATCH_FIELD_NAME
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * size SIZE
+ * timeout {
+ * TIMEOUT_IN_SECONDS
+ * ...
+ * }
+ * }
+ */
+struct learner_spec {
+ char *name;
+ struct rte_swx_pipeline_learner_params params;
+ uint32_t size;
+ uint32_t *timeout;
+ uint32_t n_timeouts;
+};
+
+/*
+ * regarray.
+ *
+ * regarray NAME size SIZE initval INITVAL
+ */
+struct regarray_spec {
+ char *name;
+ uint64_t init_val;
+ uint32_t size;
+};
+
+/*
+ * metarray.
+ *
+ * metarray NAME size SIZE
+ */
+struct metarray_spec {
+ char *name;
+ uint32_t size;
+};
+
+/*
+ * apply.
+ *
+ * apply {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct apply_spec {
+ const char **instructions;
+ uint32_t n_instructions;
+};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 03/17] pipeline: add pipeline specification data structure
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
` (14 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure for the entire pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 21 ++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 32 ++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5e07b4f794..642091b678 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2082,6 +2082,27 @@ apply_block_parse(struct apply_spec *s,
/*
* Pipeline.
*/
+void
+pipeline_spec_free(struct pipeline_spec *s)
+{
+ if (!s)
+ return;
+
+ free(s->extobjs);
+ free(s->structs);
+ free(s->headers);
+ free(s->metadata);
+ free(s->actions);
+ free(s->tables);
+ free(s->selectors);
+ free(s->learners);
+ free(s->regarrays);
+ free(s->metarrays);
+ free(s->apply);
+
+ memset(s, 0, sizeof(struct pipeline_spec));
+}
+
int
rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
FILE *spec,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 8458de878a..e1170a33b1 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -174,3 +174,35 @@ struct apply_spec {
const char **instructions;
uint32_t n_instructions;
};
+
+/*
+ * Pipeline.
+ */
+struct pipeline_spec {
+ struct extobj_spec *extobjs;
+ struct struct_spec *structs;
+ struct header_spec *headers;
+ struct metadata_spec *metadata;
+ struct action_spec *actions;
+ struct table_spec *tables;
+ struct selector_spec *selectors;
+ struct learner_spec *learners;
+ struct regarray_spec *regarrays;
+ struct metarray_spec *metarrays;
+ struct apply_spec *apply;
+
+ uint32_t n_extobjs;
+ uint32_t n_structs;
+ uint32_t n_headers;
+ uint32_t n_metadata;
+ uint32_t n_actions;
+ uint32_t n_tables;
+ uint32_t n_selectors;
+ uint32_t n_learners;
+ uint32_t n_regarrays;
+ uint32_t n_metarrays;
+ uint32_t n_apply;
+};
+
+void
+pipeline_spec_free(struct pipeline_spec *s);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 04/17] pipeline: rework the specification file-based pipeline build
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
` (13 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the specification file-based pipeline build operation to first
parse the specification file into the previously introduced pipeline
specification data structure, then use this structure to configure
and build the pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 478 +++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline_spec.h | 9 +
2 files changed, 385 insertions(+), 102 deletions(-)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 642091b678..62929a9da6 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2103,11 +2103,10 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg)
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
{
struct extobj_spec extobj_spec = {0};
struct struct_spec struct_spec = {0};
@@ -2120,26 +2119,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0};
- uint32_t n_lines;
+ struct pipeline_spec *s = NULL;
+ uint32_t n_lines = 0;
uint32_t block_mask = 0;
- int status;
+ int status = 0;
/* Check the input arguments. */
- if (!p) {
+ if (!spec) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null pipeline argument.";
+ *err_msg = "Invalid input argument.";
status = -EINVAL;
goto error;
}
- if (!spec) {
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_spec), 1);
+ if (!s) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null specification file argument.";
- status = -EINVAL;
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
@@ -2200,6 +2202,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* struct block. */
if (block_mask & (1 << STRUCT_BLOCK)) {
+ struct struct_spec *new_structs;
+
status = struct_block_parse(&struct_spec,
&block_mask,
tokens,
@@ -2214,26 +2218,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_struct_type_register(p,
- struct_spec.name,
- struct_spec.fields,
- struct_spec.n_fields,
- struct_spec.varbit);
- if (status) {
+ new_structs = realloc(s->structs,
+ (s->n_structs + 1) * sizeof(struct struct_spec));
+ if (!new_structs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Struct registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- struct_spec_free(&struct_spec);
+ s->structs = new_structs;
+ memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
+ s->n_structs++;
+ memset(&struct_spec, 0, sizeof(struct struct_spec));
continue;
}
/* action block. */
if (block_mask & (1 << ACTION_BLOCK)) {
+ struct action_spec *new_actions;
+
status = action_block_parse(&action_spec,
&block_mask,
tokens,
@@ -2248,26 +2255,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_action_config(p,
- action_spec.name,
- action_spec.args_struct_type_name,
- action_spec.instructions,
- action_spec.n_instructions);
- if (status) {
+ new_actions = realloc(s->actions,
+ (s->n_actions + 1) * sizeof(struct action_spec));
+ if (!new_actions) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Action config error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- action_spec_free(&action_spec);
+ s->actions = new_actions;
+ memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
+ s->n_actions++;
+ memset(&action_spec, 0, sizeof(struct action_spec));
continue;
}
/* table block. */
if (block_mask & (1 << TABLE_BLOCK)) {
+ struct table_spec *new_tables;
+
status = table_block_parse(&table_spec,
&block_mask,
tokens,
@@ -2282,27 +2292,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_table_config(p,
- table_spec.name,
- &table_spec.params,
- table_spec.recommended_table_type_name,
- table_spec.args,
- table_spec.size);
- if (status) {
+ new_tables = realloc(s->tables,
+ (s->n_tables + 1) * sizeof(struct table_spec));
+ if (!new_tables) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- table_spec_free(&table_spec);
+ s->tables = new_tables;
+ memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
+ s->n_tables++;
+ memset(&table_spec, 0, sizeof(struct table_spec));
continue;
}
/* selector block. */
if (block_mask & (1 << SELECTOR_BLOCK)) {
+ struct selector_spec *new_selectors;
+
status = selector_block_parse(&selector_spec,
&block_mask,
tokens,
@@ -2317,24 +2329,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_selector_config(p,
- selector_spec.name,
- &selector_spec.params);
- if (status) {
+ new_selectors = realloc(s->selectors,
+ (s->n_selectors + 1) * sizeof(struct selector_spec));
+ if (!new_selectors) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Selector configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- selector_spec_free(&selector_spec);
+ s->selectors = new_selectors;
+ memcpy(&s->selectors[s->n_selectors],
+ &selector_spec,
+ sizeof(struct selector_spec));
+ s->n_selectors++;
+ memset(&selector_spec, 0, sizeof(struct selector_spec));
continue;
}
/* learner block. */
if (block_mask & (1 << LEARNER_BLOCK)) {
+ struct learner_spec *new_learners;
+
status = learner_block_parse(&learner_spec,
&block_mask,
tokens,
@@ -2349,27 +2368,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_learner_config(p,
- learner_spec.name,
- &learner_spec.params,
- learner_spec.size,
- learner_spec.timeout,
- learner_spec.n_timeouts);
- if (status) {
+ new_learners = realloc(s->learners,
+ (s->n_learners + 1) * sizeof(struct learner_spec));
+ if (!new_learners) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Learner table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- learner_spec_free(&learner_spec);
+ s->learners = new_learners;
+ memcpy(&s->learners[s->n_learners],
+ &learner_spec,
+ sizeof(struct learner_spec));
+ s->n_learners++;
+ memset(&learner_spec, 0, sizeof(struct learner_spec));
continue;
}
/* apply block. */
if (block_mask & (1 << APPLY_BLOCK)) {
+ struct apply_spec *new_apply;
+
status = apply_block_parse(&apply_spec,
&block_mask,
tokens,
@@ -2384,24 +2407,28 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_instructions_config(p,
- apply_spec.instructions,
- apply_spec.n_instructions);
- if (status) {
+ new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
+ if (!new_apply) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Pipeline instructions err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- apply_spec_free(&apply_spec);
+ s->apply = new_apply;
+ memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
+ s->n_apply++;
+ memset(&apply_spec, 0, sizeof(struct apply_spec));
continue;
}
/* extobj. */
if (!strcmp(tokens[0], "extobj")) {
+ struct extobj_spec *new_extobjs;
+
status = extobj_statement_parse(&extobj_spec,
tokens,
n_tokens,
@@ -2411,19 +2438,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_extern_object_config(p,
- extobj_spec.name,
- extobj_spec.extern_type_name,
- extobj_spec.pragma);
- if (status) {
+ new_extobjs = realloc(s->extobjs,
+ (s->n_extobjs + 1) * sizeof(struct extobj_spec));
+ if (!new_extobjs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Extern object config err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- extobj_spec_free(&extobj_spec);
+ s->extobjs = new_extobjs;
+ memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
+ s->n_extobjs++;
+ memset(&extobj_spec, 0, sizeof(struct extobj_spec));
continue;
}
@@ -2445,6 +2474,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* header. */
if (!strcmp(tokens[0], "header")) {
+ struct header_spec *new_headers;
+
status = header_statement_parse(&header_spec,
tokens,
n_tokens,
@@ -2454,24 +2485,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_header_register(p,
- header_spec.name,
- header_spec.struct_type_name);
- if (status) {
+ new_headers = realloc(s->headers,
+ (s->n_headers + 1) * sizeof(struct header_spec));
+ if (!new_headers) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Header registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- header_spec_free(&header_spec);
+ s->headers = new_headers;
+ memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
+ s->n_headers++;
+ memset(&header_spec, 0, sizeof(struct header_spec));
continue;
}
/* metadata. */
if (!strcmp(tokens[0], "metadata")) {
+ struct metadata_spec *new_metadata;
+
status = metadata_statement_parse(&metadata_spec,
tokens,
n_tokens,
@@ -2481,17 +2517,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_metadata_register(p,
- metadata_spec.struct_type_name);
- if (status) {
+ new_metadata = realloc(s->metadata,
+ (s->n_metadata + 1) * sizeof(struct metadata_spec));
+ if (!new_metadata) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meta-data reg err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metadata_spec_free(&metadata_spec);
+ s->metadata = new_metadata;
+ memcpy(&s->metadata[s->n_metadata],
+ &metadata_spec,
+ sizeof(struct metadata_spec));
+ s->n_metadata++;
+ memset(&metadata_spec, 0, sizeof(struct metadata_spec));
continue;
}
@@ -2558,6 +2600,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* regarray. */
if (!strcmp(tokens[0], "regarray")) {
+ struct regarray_spec *new_regarrays;
+
status = regarray_statement_parse(®array_spec,
tokens,
n_tokens,
@@ -2567,25 +2611,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_regarray_config(p,
- regarray_spec.name,
- regarray_spec.size,
- regarray_spec.init_val);
- if (status) {
+ new_regarrays = realloc(s->regarrays,
+ (s->n_regarrays + 1) * sizeof(struct regarray_spec));
+ if (!new_regarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Register array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- regarray_spec_free(®array_spec);
+ s->regarrays = new_regarrays;
+ memcpy(&s->regarrays[s->n_regarrays],
+ ®array_spec,
+ sizeof(struct regarray_spec));
+ s->n_regarrays++;
+ memset(®array_spec, 0, sizeof(struct regarray_spec));
continue;
}
/* metarray. */
if (!strcmp(tokens[0], "metarray")) {
+ struct metarray_spec *new_metarrays;
+
status = metarray_statement_parse(&metarray_spec,
tokens,
n_tokens,
@@ -2595,18 +2645,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_metarray_config(p,
- metarray_spec.name,
- metarray_spec.size);
- if (status) {
+ new_metarrays = realloc(s->metarrays,
+ (s->n_metarrays + 1) * sizeof(struct metarray_spec));
+ if (!new_metarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meter array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metarray_spec_free(&metarray_spec);
+ s->metarrays = new_metarrays;
+ memcpy(&s->metarrays[s->n_metarrays],
+ &metarray_spec,
+ sizeof(struct metarray_spec));
+ s->n_metarrays++;
+ memset(&metarray_spec, 0, sizeof(struct metarray_spec));
continue;
}
@@ -2644,17 +2699,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
goto error;
}
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
+ return s;
error:
extobj_spec_free(&extobj_spec);
@@ -2668,5 +2713,234 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
regarray_spec_free(®array_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec);
+ pipeline_spec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* extobj. */
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ status = rte_swx_pipeline_extern_object_config(p,
+ extobj_spec->name,
+ extobj_spec->extern_type_name,
+ extobj_spec->pragma);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Extern object configuration error.";
+ return status;
+ }
+ }
+
+ /* regarray. */
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ status = rte_swx_pipeline_regarray_config(p,
+ regarray_spec->name,
+ regarray_spec->size,
+ regarray_spec->init_val);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Register array configuration error.";
+ return status;
+ }
+ }
+
+ /* metarray. */
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ status = rte_swx_pipeline_metarray_config(p,
+ metarray_spec->name,
+ metarray_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meter array configuration error.";
+ return status;
+ }
+ }
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ status = rte_swx_pipeline_struct_type_register(p,
+ struct_spec->name,
+ struct_spec->fields,
+ struct_spec->n_fields,
+ struct_spec->varbit);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Struct type registration error.";
+ return status;
+ }
+ }
+
+ /* header. */
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ status = rte_swx_pipeline_packet_header_register(p,
+ header_spec->name,
+ header_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Header configuration error.";
+ return status;
+ }
+ }
+
+ /* metadata. */
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ status = rte_swx_pipeline_packet_metadata_register(p,
+ metadata_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meta-data registration error.";
+ return status;
+ }
+ }
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ status = rte_swx_pipeline_action_config(p,
+ action_spec->name,
+ action_spec->args_struct_type_name,
+ action_spec->instructions,
+ action_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Action configuration error.";
+ return status;
+ }
+ }
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ status = rte_swx_pipeline_table_config(p,
+ table_spec->name,
+ &table_spec->params,
+ table_spec->recommended_table_type_name,
+ table_spec->args,
+ table_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Table configuration error.";
+ return status;
+ }
+ }
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ status = rte_swx_pipeline_selector_config(p,
+ selector_spec->name,
+ &selector_spec->params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Selector table configuration error.";
+ return status;
+ }
+ }
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ status = rte_swx_pipeline_learner_config(p,
+ learner_spec->name,
+ &learner_spec->params,
+ learner_spec->size,
+ learner_spec->timeout,
+ learner_spec->n_timeouts);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Learner table configuration error.";
+ return status;
+ }
+ }
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+
+ status = rte_swx_pipeline_instructions_config(p,
+ apply_spec->instructions,
+ apply_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline instructions configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
+ FILE *spec_file,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_spec *s = NULL;
+ int status = 0;
+
+ /* Check the input arguments. */
+ if (!p || !spec_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Spec file parse. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Pipeline configure. */
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto error;
+ }
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline build error.";
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pipeline_spec_free(s);
return status;
}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index e1170a33b1..4f3a0b5958 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,3 +206,12 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 05/17] pipeline: generate the code for pipeline specification structure
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (2 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
` (12 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add support to export the pipeline specification data structure to a C
source code file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 622 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 5 +
2 files changed, 627 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 62929a9da6..bf21fe17ba 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2,6 +2,7 @@
* Copyright(c) 2020 Intel Corporation
*/
#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -2103,6 +2104,627 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
+static const char *
+match_type_string_get(enum rte_swx_table_match_type match_type)
+{
+ switch (match_type) {
+ case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
+ case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
+ case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
+ default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
+ }
+}
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s)
+{
+ uint32_t i;
+
+ /* Check the input arguments. */
+ if (!f || !s)
+ return;
+
+ /* extobj. */
+ fprintf(f, "static struct extobj_spec extobjs[] = {\n");
+
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
+ fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
+ if (extobj_spec->pragma)
+ fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
+ else
+ fprintf(f, "\t\t.pragma = NULL,\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* regarray. */
+ fprintf(f, "static struct regarray_spec regarrays[] = {\n");
+
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
+ fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
+ fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metarray. */
+ fprintf(f, "static struct metarray_spec metarrays[] = {\n");
+
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
+ fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+ uint32_t j;
+
+ fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
+ struct_spec->name);
+
+ for (j = 0; j < struct_spec->n_fields; j++) {
+ struct rte_swx_field_params *field = &struct_spec->fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct struct_spec structs[] = {\n");
+
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
+ fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
+ fprintf(f, "\t\t.n_fields = "
+ "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
+ struct_spec->name,
+ struct_spec->name);
+ fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* header. */
+ fprintf(f, "static struct header_spec headers[] = {\n");
+
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metadata. */
+ fprintf(f, "static struct metadata_spec metadata[] = {\n");
+
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
+ action_spec->name);
+
+ for (j = 0; j < action_spec->n_instructions; j++) {
+ const char *instr = action_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct action_spec actions[] = {\n");
+
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
+
+ if (action_spec->args_struct_type_name)
+ fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
+ action_spec->args_struct_type_name);
+ else
+ fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
+
+ fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
+ action_spec->name);
+ fprintf(f, "\t\t.n_instructions = "
+ "sizeof(action_%s_initial_instructions) / "
+ "sizeof(action_%s_initial_instructions[0]),\n",
+ action_spec->name,
+ action_spec->name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+ uint32_t j;
+
+ /* fields. */
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "static struct rte_swx_match_field_params "
+ "table_%s_fields[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_fields; j++) {
+ struct rte_swx_match_field_params *field =
+ &table_spec->params.fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.match_type = %s,\n",
+ match_type_string_get(field->match_type));
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (table_spec->params.action_names && table_spec->params.n_actions) {
+ fprintf(f, "static const char *table_%s_action_names[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ const char *action_name = table_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (table_spec->params.action_is_for_table_entries &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (table_spec->params.action_is_for_default_entry &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct table_spec tables[] = {\n");
+
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.fields = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (table_spec->params.action_names && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "table_%s_action_is_for_table_entries,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "table_%s_action_is_for_default_entry,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
+ "sizeof(table_%s_action_names[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = 0,\n");
+
+ if (table_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ table_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (table_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ table_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ table_spec->params.default_action_is_const);
+ fprintf(f, "\t\t},\n");
+
+ if (table_spec->recommended_table_type_name)
+ fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
+ table_spec->recommended_table_type_name);
+ else
+ fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
+
+ if (table_spec->args)
+ fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
+ else
+ fprintf(f, "\t\t.args = NULL,\n");
+
+ fprintf(f, "\t\t.size = %u,\n", table_spec->size);
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+ uint32_t j;
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "static const char *selector_%s_field_names[] = {\n",
+ selector_spec->name);
+
+ for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
+ const char *field_name =
+ selector_spec->params.selector_field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct selector_spec selectors[] = {\n");
+
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+
+ fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
+ fprintf(f, "\t\t.params = {\n");
+
+ if (selector_spec->params.group_id_field_name)
+ fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
+ selector_spec->params.group_id_field_name);
+ else
+ fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
+ selector_spec->name);
+ fprintf(f, "\t\t\t.n_selector_fields = "
+ "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
+ selector_spec->name,
+ selector_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
+ }
+
+ if (selector_spec->params.member_id_field_name)
+ fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
+ selector_spec->params.member_id_field_name);
+ else
+ fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
+
+ fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
+
+ fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
+ selector_spec->params.n_members_per_group_max);
+
+ fprintf(f, "\t\t},\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+ uint32_t j;
+
+ /* field_names. */
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "static const char *learner_%s_field_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_fields; j++) {
+ const char *field_name = learner_spec->params.field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (learner_spec->params.action_names && learner_spec->params.n_actions) {
+ fprintf(f, "static const char *learner_%s_action_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ const char *action_name = learner_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* timeout. */
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->n_timeouts; j++) {
+ uint32_t value = learner_spec->timeout[j];
+
+ fprintf(f, "\t[%d] = %u,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct learner_spec learners[] = {\n");
+
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
+ learner_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(learner_%s_field_names) / "
+ "sizeof(learner_%s_field_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "learner_%s_action_is_for_table_entries,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "learner_%s_action_is_for_default_entry,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = "
+ "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = NULL,\n");
+
+ if (learner_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ learner_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (learner_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ learner_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ learner_spec->params.default_action_is_const);
+
+ fprintf(f, "\t\t},\n");
+
+ fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
+
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
+ fprintf(f, "\t\t\t.n_timeouts = "
+ "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t.timeout = NULL,\n");
+ fprintf(f, "\t\t\t.n_timeouts = 0,\n");
+ }
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
+
+ for (j = 0; j < apply_spec->n_instructions; j++) {
+ const char *instr = apply_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct apply_spec apply[] = {\n");
+
+ for (i = 0; i < s->n_apply; i++) {
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
+ fprintf(f, "\t.n_instructions = "
+ "sizeof(apply%u_initial_instructions) / "
+ "sizeof(apply%u_initial_instructions[0]),\n",
+ i,
+ i);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* pipeline. */
+ fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
+ fprintf(f, "\t.extobjs = extobjs,\n");
+ fprintf(f, "\t.structs = structs,\n");
+ fprintf(f, "\t.headers = headers,\n");
+ fprintf(f, "\t.metadata = metadata,\n");
+ fprintf(f, "\t.actions = actions,\n");
+ fprintf(f, "\t.tables = tables,\n");
+ fprintf(f, "\t.selectors = selectors,\n");
+ fprintf(f, "\t.learners = learners,\n");
+ fprintf(f, "\t.regarrays = regarrays,\n");
+ fprintf(f, "\t.metarrays = metarrays,\n");
+ fprintf(f, "\t.apply = apply,\n");
+ fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
+ fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
+ fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
+ fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
+ fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
+ fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
+ fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
+ fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
+ fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
+ fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
+ fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
+ fprintf(f, "};\n");
+}
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 4f3a0b5958..707b99ba09 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,6 +206,11 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s);
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 06/17] pipeline: add support for pipeline I/O specification
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (3 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
` (11 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure and API for the pipeline I/O ports
and related pipeline configuration such as packet mirroring.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 852 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 58 ++
2 files changed, 910 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index bf21fe17ba..aea69b500b 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,6 +9,12 @@
#include <errno.h>
#include <rte_common.h>
+#include <rte_mempool.h>
+
+#include <rte_swx_port_ethdev.h>
+#include <rte_swx_port_ring.h>
+#include <rte_swx_port_source_sink.h>
+#include <rte_swx_port_fd.h>
#include "rte_swx_pipeline_spec.h"
@@ -3566,3 +3572,849 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
pipeline_spec_free(s);
return status;
}
+
+static void
+port_in_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "source")) {
+ struct rte_swx_port_source_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+static void
+port_out_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "sink")) {
+ struct rte_swx_port_sink_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s)
+{
+ uint32_t i;
+
+ if (!s)
+ return;
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ uintptr_t name = (uintptr_t)s->port_in_type[i];
+
+ port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_in_type);
+ free(s->port_in_params);
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ uintptr_t name = (uintptr_t)s->port_out_type[i];
+
+ port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_out_type);
+ free(s->port_out_params);
+
+ free(s);
+}
+
+static int
+mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
+ char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ char *token;
+
+ if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return -EINVAL;
+ }
+
+ /* <n_slots>. */
+ token = tokens[1];
+ p->n_slots = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_slots> parameter.";
+ return -EINVAL;
+ }
+
+ /* <n_sessions>. */
+ token = tokens[3];
+ p->n_sessions = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_sessions> parameter.";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void *
+port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_reader_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_reader_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_source_params *p = NULL;
+ struct rte_mempool *pool = NULL;
+ char *token, *file_name = NULL;
+ uint32_t n_loops, n_pkts_max;
+
+ if ((n_tokens != 8) ||
+ strcmp(tokens[0], "mempool") ||
+ strcmp(tokens[2], "file") ||
+ strcmp(tokens[4], "loop") ||
+ strcmp(tokens[6], "packets")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ pool = rte_mempool_lookup(tokens[1]);
+ if (!pool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <n_loops>. */
+ token = tokens[5];
+ n_loops = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_loops> parameter.";
+ return NULL;
+ }
+
+ /* <n_pkts_max>. */
+ token = tokens[7];
+ n_pkts_max = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_pkts_max> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ file_name = strdup(tokens[3]);
+ p = malloc(sizeof(struct rte_swx_port_source_params));
+ if (!file_name || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->pool = pool;
+ p->file_name = file_name;
+ p->n_loops = n_loops;
+ p->n_pkts_max = n_pkts_max;
+
+ return p;
+}
+
+static void *
+port_in_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_reader_params *p = NULL;
+ struct rte_mempool *mempool = NULL;
+ char *token;
+ uint32_t mtu, burst_size;
+ int fd;
+
+ if ((n_tokens != 7) ||
+ strcmp(tokens[1], "mtu") ||
+ strcmp(tokens[3], "mempool") ||
+ strcmp(tokens[5], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <mtu>. */
+ token = tokens[2];
+ mtu = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <mtu> parameter.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ mempool = rte_mempool_lookup(tokens[4]);
+ if (!mempool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[6];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->mtu = mtu;
+ p->mempool = mempool;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_writer_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_writer_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_sink_params *p = NULL;
+ char *file_name = NULL;
+ int file_name_valid = 0;
+
+ if ((n_tokens != 2) || strcmp(tokens[0], "file")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ if (strcmp(tokens[1], "none")) {
+ file_name_valid = 1;
+ file_name = strdup(tokens[1]);
+ }
+
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if ((file_name_valid && !file_name) || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->file_name = file_name;
+
+ return p;
+}
+
+static void *
+port_out_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_writer_params *p = NULL;
+ char *token;
+ uint32_t burst_size;
+ int fd;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_iospec *s = NULL;
+ uint32_t n_lines = 0;
+
+ /* Check the input arguments. */
+ if (!spec) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ goto error;
+ }
+
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_iospec), 1);
+ if (!s) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ /* Initialize with the defaut values. */
+ s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
+ s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
+
+ for (n_lines = 1; ; n_lines++) {
+ char line[MAX_LINE_LENGTH];
+ char *tokens[MAX_TOKENS], *ptr = line;
+ uint32_t n_tokens = 0;
+
+ /* Read next line. */
+ if (!fgets(line, sizeof(line), spec))
+ break;
+
+ /* Parse the line into tokens. */
+ for ( ; ; ) {
+ char *token;
+
+ /* Get token. */
+ token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
+ if (!token)
+ break;
+
+ /* Handle comments. */
+ if ((token[0] == '#') ||
+ (token[0] == ';') ||
+ ((token[0] == '/') && (token[1] == '/'))) {
+ break;
+ }
+
+ /* Handle excessively long lines. */
+ if (n_tokens >= RTE_DIM(tokens)) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Too many tokens.";
+ goto error;
+ }
+
+ /* Handle excessively long tokens. */
+ if (strnlen(token, RTE_SWX_NAME_SIZE) >=
+ RTE_SWX_NAME_SIZE) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Token too big.";
+ goto error;
+ }
+
+ /* Save token. */
+ tokens[n_tokens] = token;
+ n_tokens++;
+ }
+
+ /* Handle empty lines. */
+ if (!n_tokens)
+ continue;
+
+ /* mirroring. */
+ if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
+ int status = 0;
+
+ status = mirroring_parse(&s->mirroring_params,
+ &tokens[1],
+ n_tokens - 1,
+ err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ continue;
+ }
+
+ /* port in. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "source"))
+ p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_in_id,
+ (s->n_ports_in + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_in_type,
+ (s->n_ports_in + 1) * sizeof(char *));
+ new_params = realloc(s->port_in_params,
+ (s->n_ports_in + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_in_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_in_id = new_id;
+ s->port_in_type = new_type;
+ s->port_in_params = new_params;
+
+ s->port_in_id[s->n_ports_in] = port_id;
+ s->port_in_type[s->n_ports_in] = port_type;
+ s->port_in_params[s->n_ports_in] = p;
+ s->n_ports_in++;
+
+ continue;
+ }
+
+ /* port out. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "sink"))
+ p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_out_id,
+ (s->n_ports_out + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_out_type,
+ (s->n_ports_out + 1) * sizeof(char *));
+ new_params = realloc(s->port_out_params,
+ (s->n_ports_out + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_out_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_out_id = new_id;
+ s->port_out_type = new_type;
+ s->port_out_params = new_params;
+
+ s->port_out_id[s->n_ports_out] = port_id;
+ s->port_out_type[s->n_ports_out] = port_type;
+ s->port_out_params[s->n_ports_out] = p;
+ s->n_ports_out++;
+
+ continue;
+ }
+
+ /* Anything else. */
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Unknown I/O statement.";
+ goto error;
+ }
+
+ return s;
+
+error:
+ pipeline_iospec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!p || !s) {
+ if (err_msg)
+ *err_msg = "Invalid input argument";
+ return -EINVAL;
+ }
+
+ /* Mirroring. */
+ status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline mirroring configuration error.";
+ return status;
+ }
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ status = rte_swx_pipeline_port_in_config(p,
+ i,
+ s->port_in_type[i],
+ s->port_in_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline input port configuration error.";
+ return status;
+ }
+ }
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ status = rte_swx_pipeline_port_out_config(p,
+ i,
+ s->port_out_type[i],
+ s->port_out_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline output port configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 707b99ba09..62ac4ecfc4 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -1,6 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2022 Intel Corporation
*/
+#ifndef __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+#define __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include <stdio.h>
@@ -204,6 +211,38 @@ struct pipeline_spec {
uint32_t n_apply;
};
+/*
+ * Mirroring:
+ * mirroring slots <n_slots> sessions <n_sessions>
+ *
+ * Input ports:
+ * port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+ * port in <port_id> ring <ring_name> bsz <burst_size>
+ * port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops>
+ * packets <n_pkts_max>
+ * port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+ *
+ * Output ports:
+ * port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+ * port out <port_id> ring <ring_name> bsz <burst_size>
+ * port out <port_id> sink file <file_name> | none
+ * port out <port_id> fd <file_descriptor> bsz <burst_size>
+ */
+struct pipeline_iospec {
+ struct rte_swx_pipeline_mirroring_params mirroring_params;
+
+ uint32_t *port_in_id;
+ const char **port_in_type;
+ void **port_in_params;
+
+ uint32_t *port_out_id;
+ const char **port_out_type;
+ void **port_out_params;
+
+ uint32_t n_ports_in;
+ uint32_t n_ports_out;
+};
+
void
pipeline_spec_free(struct pipeline_spec *s);
@@ -220,3 +259,22 @@ int
pipeline_spec_configure(struct rte_swx_pipeline *p,
struct pipeline_spec *s,
const char **err_msg);
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s);
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 07/17] pipeline: add API for pipeline code generation
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (4 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
` (10 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the C code generation for the pipeline was hidden under
the hood; now, we make this an explicit API operation. Besides the
functions for the pipeline actions and the pipeline instructions,
the generated C source code now includes the pipeline specification
structure required for the pipeline configuration operations.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline.c | 94 +++++++++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline.h | 25 +++++++++
lib/pipeline/version.map | 1 +
3 files changed, 120 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index c8ccded4f8..dd5f7107fa 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -20,6 +20,7 @@
#include <rte_swx_table_wm.h>
#include "rte_swx_pipeline_internal.h"
+#include "rte_swx_pipeline_spec.h"
#define CHECK(condition, err_code) \
do { \
@@ -13581,3 +13582,96 @@ pipeline_compile(struct rte_swx_pipeline *p)
return status;
}
+
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg)
+
+{
+ struct rte_swx_pipeline *p = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!spec_file || !code_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ status = rte_swx_pipeline_config(&p, NULL, 0);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline configuration error.";
+ goto free;
+ }
+
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto free;
+ }
+
+ /*
+ * Pipeline code generation.
+ */
+
+ /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
+ * but there is no need for the pipeline build to be done as well.
+ */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
+ goto free;
+ }
+
+ /* Header file inclusion. */
+ fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
+ fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
+
+ /* Code generation for the pipeline specification. */
+ pipeline_spec_codegen(code_file, s);
+ fprintf(code_file, "\n");
+
+ /* Code generation for the action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
+
+ action_data_codegen(a, code_file);
+ fprintf(code_file, "\n");
+
+ action_instr_codegen(a, code_file);
+ fprintf(code_file, "\n");
+ }
+
+ /* Code generation for the pipeline instructions. */
+ instruction_group_list_codegen(igl, p, code_file);
+
+free:
+ instruction_group_list_free(igl);
+ rte_swx_pipeline_free(p);
+ pipeline_spec_free(s);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index ef50a0fa70..724607b87c 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -957,6 +957,31 @@ __rte_experimental
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p);
+/**
+ * Pipeline C code generate based on input specification file
+ *
+ * @param[in] spec_file
+ * Pipeline specification file (.spec) provided as input.
+ * @param[in] code_file
+ * Pipeline C language file (.c) to be generated.
+ * @param[out] err_line
+ * In case of error and non-NULL, the line number within the *spec* file where
+ * the error occurred. The first line number in the file is 1.
+ * @param[out] err_msg
+ * In case of error and non-NULL, the error message.
+ * @return
+ * 0 on success or the following error codes otherwise:
+ * -EINVAL: Invalid argument;
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Resource with the same name already exists.
+ */
+__rte_experimental
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg);
+
/**
* Pipeline build from specification file
*
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 50029aadcf..8d95005a5b 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -148,5 +148,6 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 08/17] pipeline: add API for shared library-based pipeline build
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (5 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
` (9 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the pipeline build operation was done based on the
specification file (typically produced by the P4 compiler), then the C
code with optimized functions for the pipeline actions and
instructions was generated, built into a shared object library, loaded
and installed into the pipeline in a completely hardcoded and
non-customizable way.
Now, this process is split into three explicit stages:
i) code generation (specification file -> C file);
ii) code build (C file -> shared object library);
iii) code installation (library load into the pipeline).
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 85 ++++---
lib/pipeline/rte_swx_pipeline.c | 319 +++++++++++----------------
lib/pipeline/rte_swx_pipeline.h | 38 ++--
lib/pipeline/rte_swx_pipeline_spec.c | 51 -----
lib/pipeline/version.map | 2 +-
5 files changed, 208 insertions(+), 287 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ad553f19ab..f0285675b3 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -984,55 +984,88 @@ cmd_pipeline_port_out(char **tokens,
}
static const char cmd_pipeline_build_help[] =
-"pipeline <pipeline_name> build <spec_file>\n";
+"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
static void
cmd_pipeline_build(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p = NULL;
- FILE *spec = NULL;
- uint32_t err_line;
- const char *err_msg;
- int status;
+ struct rte_swx_pipeline *p = NULL;
+ struct rte_swx_ctl_pipeline *ctl = NULL;
+ char *pipeline_name, *lib_file_name, *iospec_file_name;
+ FILE *iospec_file = NULL;
+ uint32_t numa_node = 0;
+ int status = 0;
- if (n_tokens != 4) {
+ /* Parsing. */
+ if (n_tokens != 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "build")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
return;
}
- spec = fopen(tokens[3], "r");
- if (!spec) {
- snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ if (strcmp(tokens[3], "lib")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
return;
}
- status = rte_swx_pipeline_build_from_spec(p->p,
- spec,
- &err_line,
- &err_msg);
- fclose(spec);
- if (status) {
- snprintf(out, out_size, "Error %d at line %u: %s\n.",
- status, err_line, err_msg);
+ lib_file_name = tokens[4];
+
+ if (strcmp(tokens[5], "io")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
return;
}
- p->ctl = rte_swx_ctl_pipeline_create(p->p);
- if (!p->ctl) {
- snprintf(out, out_size, "Pipeline control create failed.");
- rte_swx_pipeline_free(p->p);
+ iospec_file_name = tokens[6];
+
+ if (strcmp(tokens[7], "numa")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
return;
}
+
+ if (parser_read_uint32(&numa_node, tokens[8])) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+ return;
+ }
+
+ /* I/O spec file open. */
+ iospec_file = fopen(iospec_file_name, "r");
+ if (!iospec_file) {
+ snprintf(out, out_size, "Cannot open file \"%s\".\n", iospec_file_name);
+ return;
+ }
+
+ status = rte_swx_pipeline_build_from_lib(&p,
+ pipeline_name,
+ lib_file_name,
+ iospec_file,
+ (int)numa_node);
+ if (status) {
+ snprintf(out, out_size, "Pipeline build failed (%d).", status);
+ goto free;
+ }
+
+ ctl = rte_swx_ctl_pipeline_create(p);
+ if (!ctl) {
+ snprintf(out, out_size, "Pipeline control create failed.");
+ goto free;
+ }
+
+free:
+ if (status)
+ rte_swx_pipeline_free(p);
+
+ if (iospec_file)
+ fclose(iospec_file);
}
static void
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index dd5f7107fa..12e156b00b 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9911,9 +9911,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
return 0;
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p);
-
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
{
@@ -10003,8 +10000,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
p->build_done = 1;
- pipeline_compile(p);
-
return 0;
error:
@@ -13327,160 +13322,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *
return n_custom_instr;
}
-static int
-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- FILE *f = NULL;
-
- /* Create the .c file. */
- f = fopen("/tmp/pipeline.c", "w");
- if (!f)
- return -EIO;
-
- /* Include the .h file. */
- fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
-
- /* Add the code for each action. */
- TAILQ_FOREACH(a, &p->actions, node) {
- fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
-
- action_data_codegen(a, f);
-
- fprintf(f, "\n");
-
- action_instr_codegen(a, f);
-
- fprintf(f, "\n");
- }
-
- /* Add the pipeline code. */
- instruction_group_list_codegen(igl, p, f);
-
- /* Close the .c file. */
- fclose(f);
-
- return 0;
-}
-
-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
-#endif
-
-static int
-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- struct instruction_group *g;
- char *dir_in, *buffer = NULL;
- const char *dir_out;
- int status = 0;
-
- /* Get the environment variables. */
- dir_in = getenv("RTE_INSTALL_DIR");
- if (!dir_in) {
- status = -EINVAL;
- goto free;
- }
-
- dir_out = "/tmp";
-
- /* Memory allocation for the command buffer. */
- buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
- if (!buffer) {
- status = -ENOMEM;
- goto free;
- }
-
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
- "-I %s/lib/pipeline "
- "-I %s/lib/eal/include "
- "-I %s/lib/eal/x86/include "
- "-I %s/lib/eal/include/generic "
- "-I %s/lib/meter "
- "-I %s/lib/port "
- "-I %s/lib/table "
- "-I %s/lib/pipeline "
- "-I %s/config "
- "-I %s/build "
- "-I %s/lib/eal/linux/include "
- ">%s/pipeline.log 2>&1 "
- "&& "
- "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
- ">>%s/pipeline.log 2>&1",
- dir_out,
- dir_out,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_out,
- dir_out,
- dir_out,
- dir_out);
-
- /* Build the shared object library. */
- status = system(buffer);
- if (status)
- goto free;
-
- /* Open library. */
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "%s/libpipeline.so",
- dir_out);
-
- p->lib = dlopen(buffer, RTLD_LAZY);
- if (!p->lib) {
- status = -EIO;
- goto free;
- }
-
- /* Get the action function symbols. */
- TAILQ_FOREACH(a, &p->actions, node) {
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
-
- p->action_funcs[a->id] = dlsym(p->lib, buffer);
- if (!p->action_funcs[a->id]) {
- status = -EINVAL;
- goto free;
- }
- }
-
- /* Get the pipeline function symbols. */
- TAILQ_FOREACH(g, igl, node) {
- if (g->first_instr_id == g->last_instr_id)
- continue;
-
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
-
- g->func = dlsym(p->lib, buffer);
- if (!g->func) {
- status = -EINVAL;
- goto free;
- }
- }
-
-free:
- if (status && p->lib) {
- dlclose(p->lib);
- p->lib = NULL;
- }
-
- free(buffer);
-
- return status;
-}
-
static int
pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
struct instruction_group_list *igl)
@@ -13548,41 +13389,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p)
-{
- struct instruction_group_list *igl = NULL;
- int status = 0;
-
- igl = instruction_group_list_create(p);
- if (!igl) {
- status = -ENOMEM;
- goto free;
- }
-
- /* Code generation. */
- status = pipeline_codegen(p, igl);
- if (status)
- goto free;
-
- /* Build and load the shared object library. */
- status = pipeline_libload(p, igl);
- if (status)
- goto free;
-
- /* Adjust instructions. */
- status = pipeline_adjust_check(p, igl);
- if (status)
- goto free;
-
- pipeline_adjust(p, igl);
-
-free:
- instruction_group_list_free(igl);
-
- return status;
-}
-
int
rte_swx_pipeline_codegen(FILE *spec_file,
FILE *code_file,
@@ -13675,3 +13481,128 @@ rte_swx_pipeline_codegen(FILE *spec_file,
return status;
}
+
+int
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node)
+{
+ struct rte_swx_pipeline *p = NULL;
+ void *lib = NULL;
+ struct pipeline_iospec *sio = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ struct instruction_group *g;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!pipeline ||
+ !name ||
+ !name[0] ||
+ !lib_file_name ||
+ !lib_file_name[0] ||
+ !iospec_file) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Open the library. */
+ lib = dlopen(lib_file_name, RTLD_LAZY);
+ if (!lib) {
+ status = -EIO;
+ goto free;
+ }
+
+ /* Get the pipeline specification structures. */
+ s = dlsym(lib, "pipeline_spec");
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
+ if (!sio) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration based on the specification structures. */
+ status = rte_swx_pipeline_config(&p, name, numa_node);
+ if (status)
+ goto free;
+
+ status = pipeline_iospec_configure(p, sio, NULL);
+ if (status)
+ goto free;
+
+ status = pipeline_spec_configure(p, s, NULL);
+ if (status)
+ goto free;
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status)
+ goto free;
+
+ /* Action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ snprintf(name, sizeof(name), "action_%s_run", a->name);
+
+ p->action_funcs[a->id] = dlsym(lib, name);
+ if (!p->action_funcs[a->id]) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ /* Pipeline instructions. */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ status = -ENOMEM;
+ goto free;
+ }
+
+ TAILQ_FOREACH(g, igl, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ if (g->first_instr_id == g->last_instr_id)
+ continue;
+
+ snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
+
+ g->func = dlsym(lib, name);
+ if (!g->func) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ status = pipeline_adjust_check(p, igl);
+ if (status)
+ goto free;
+
+ pipeline_adjust(p, igl);
+
+ p->lib = lib;
+
+ *pipeline = p;
+
+free:
+ instruction_group_list_free(igl);
+
+ pipeline_iospec_free(sio);
+
+ if (status) {
+ rte_swx_pipeline_free(p);
+
+ if (lib)
+ dlclose(lib);
+ }
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 724607b87c..9c629d4118 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -983,30 +983,38 @@ rte_swx_pipeline_codegen(FILE *spec_file,
const char **err_msg);
/**
- * Pipeline build from specification file
+ * Pipeline build from shared object library
*
- * @param[in] p
- * Pipeline handle.
- * @param[in] spec
- * Pipeline specification file.
- * @param[out] err_line
- * In case of error and non-NULL, the line number within the *spec* file where
- * the error occurred. The first line number in the file is 1.
- * @param[out] err_msg
- * In case of error and non-NULL, the error message.
+ * The shared object library must be built from the C language source code file
+ * previously generated by the rte_swx_pipeline_codegen() API function.
+ *
+ * The pipeline I/O specification file defines the I/O ports of the pipeline.
+ *
+ * @param[out] p
+ * Pipeline handle. Must point to valid memory. Contains valid pipeline handle
+ * when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
+ * @param[in] lib_file_name
+ * Shared object library file name.
+ * @param[in] iospec_file
+ * Pipeline I/O specification file.
+ * @param[in] numa_node
+ * Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
- * -EEXIST: Resource with the same name already exists;
+ * -EEXIST: Pipeline with this name already exists;
* -ENODEV: Extern object or table creation error.
*/
__rte_experimental
int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg);
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **p,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node);
/**
* Pipeline run
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index aea69b500b..63c919d16e 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -3522,57 +3522,6 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,
return 0;
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec_file,
- uint32_t *err_line,
- const char **err_msg)
-{
- struct pipeline_spec *s = NULL;
- int status = 0;
-
- /* Check the input arguments. */
- if (!p || !spec_file) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Invalid input argument.";
- status = -EINVAL;
- goto error;
- }
-
- /* Spec file parse. */
- s = pipeline_spec_parse(spec_file, err_line, err_msg);
- if (!s) {
- status = -EINVAL;
- goto error;
- }
-
- /* Pipeline configure. */
- status = pipeline_spec_configure(p, s, err_msg);
- if (status) {
- if (err_line)
- *err_line = 0;
- goto error;
- }
-
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
-
-error:
- pipeline_spec_free(s);
- return status;
-}
-
static void
port_in_params_free(void *params, const char *port_type)
{
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8d95005a5b..16806e6802 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -82,7 +82,6 @@ EXPERIMENTAL {
rte_swx_ctl_table_ops_get;
rte_swx_pipeline_action_config;
rte_swx_pipeline_build;
- rte_swx_pipeline_build_from_spec;
rte_swx_pipeline_config;
rte_swx_pipeline_extern_func_register;
rte_swx_pipeline_extern_object_config;
@@ -148,6 +147,7 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_build_from_lib;
rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 09/17] examples/pipeline: add CLI command for pipeline code generation
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (6 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 10/17] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
` (8 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the pipeline code generation operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index f0285675b3..2b38977be1 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -983,6 +983,53 @@ cmd_pipeline_port_out(char **tokens,
}
}
+static const char cmd_pipeline_codegen_help[] =
+"pipeline codegen <spec_file> <code_file>\n";
+
+static void
+cmd_pipeline_codegen(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ FILE *spec_file = NULL;
+ FILE *code_file = NULL;
+ uint32_t err_line;
+ const char *err_msg;
+ int status;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ spec_file = fopen(tokens[2], "r");
+ if (!spec_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+ return;
+ }
+
+ code_file = fopen(tokens[3], "w");
+ if (!code_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ return;
+ }
+
+ status = rte_swx_pipeline_codegen(spec_file,
+ code_file,
+ &err_line,
+ &err_msg);
+
+ fclose(spec_file);
+ fclose(code_file);
+
+ if (status) {
+ snprintf(out, out_size, "Error %d at line %u: %s\n.",
+ status, err_line, err_msg);
+ return;
+ }
+}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -3009,6 +3056,7 @@ cmd_help(char **tokens,
"\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
+ "\tpipeline codegen\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3078,6 +3126,12 @@ cmd_help(char **tokens,
}
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3356,6 +3410,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "codegen") == 0)) {
+ cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 10/17] examples/pipeline: add CLI command for shared library build
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (7 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 11/17] examples/pipeline: remove the obsolete pipeline create CLI command Cristian Dumitrescu
` (7 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the shared object library build operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 157 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 153 insertions(+), 4 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 2b38977be1..28cf8d4178 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_ethdev.h>
@@ -25,6 +26,10 @@
#define CMD_MAX_TOKENS 256
#endif
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
@@ -1030,6 +1035,140 @@ cmd_pipeline_codegen(char **tokens,
return;
}
}
+
+static const char cmd_pipeline_libbuild_help[] =
+"pipeline libbuild <code_file> <lib_file>\n";
+
+static void
+cmd_pipeline_libbuild(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+ char *install_dir, *cwd = NULL, *buffer = NULL;
+ size_t length;
+ int status = 0;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ goto free;
+ }
+
+ install_dir = getenv("RTE_INSTALL_DIR");
+ if (!install_dir) {
+ cwd = malloc(MAX_LINE_SIZE);
+ if (!cwd) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ install_dir = getcwd(cwd, MAX_LINE_SIZE);
+ if (!install_dir) {
+ snprintf(out, out_size, "Error: Path too long.\n");
+ goto free;
+ }
+ }
+
+ snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+ out_size -= strlen(out);
+ out += strlen(out);
+
+ code_file = tokens[2];
+ length = strnlen(code_file, MAX_LINE_SIZE);
+ if ((length < 3) ||
+ (code_file[length - 2] != '.') ||
+ (code_file[length - 1] != 'c')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+ goto free;
+ }
+
+ lib_file = tokens[3];
+ length = strnlen(lib_file, MAX_LINE_SIZE);
+ if ((length < 4) ||
+ (lib_file[length - 3] != '.') ||
+ (lib_file[length - 2] != 's') ||
+ (lib_file[length - 1] != 'o')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+ goto free;
+ }
+
+ obj_file = malloc(length);
+ log_file = malloc(length + 2);
+ if (!obj_file || !log_file) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ memcpy(obj_file, lib_file, length - 2);
+ obj_file[length - 2] = 'o';
+ obj_file[length - 1] = 0;
+
+ memcpy(log_file, lib_file, length - 2);
+ log_file[length - 2] = 'l';
+ log_file[length - 1] = 'o';
+ log_file[length] = 'g';
+ log_file[length + 1] = 0;
+
+ buffer = malloc(MAX_LINE_SIZE);
+ if (!buffer) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ return;
+ }
+
+ snprintf(buffer,
+ MAX_LINE_SIZE,
+ "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+ "-I %s/lib/pipeline "
+ "-I %s/lib/eal/include "
+ "-I %s/lib/eal/x86/include "
+ "-I %s/lib/eal/include/generic "
+ "-I %s/lib/meter "
+ "-I %s/lib/port "
+ "-I %s/lib/table "
+ "-I %s/lib/pipeline "
+ "-I %s/config "
+ "-I %s/build "
+ "-I %s/lib/eal/linux/include "
+ ">%s 2>&1 "
+ "&& "
+ "gcc -shared %s -o %s "
+ ">>%s 2>&1",
+ obj_file,
+ code_file,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ log_file,
+ obj_file,
+ lib_file,
+ log_file);
+
+ status = system(buffer);
+ if (status) {
+ snprintf(out,
+ out_size,
+ "Library build failed, see file \"%s\" for details.\n",
+ log_file);
+ goto free;
+ }
+
+free:
+ free(cwd);
+ free(obj_file);
+ free(log_file);
+ free(buffer);
+}
+
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -1127,10 +1266,6 @@ table_entry_free(struct rte_swx_table_entry *entry)
free(entry);
}
-#ifndef MAX_LINE_SIZE
-#define MAX_LINE_SIZE 2048
-#endif
-
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
@@ -3057,6 +3192,7 @@ cmd_help(char **tokens,
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
+ "\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3132,6 +3268,12 @@ cmd_help(char **tokens,
return;
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3417,6 +3559,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "libbuild") == 0)) {
+ cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 11/17] examples/pipeline: remove the obsolete pipeline create CLI command
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (8 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 10/17] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 12/17] examples/pipeline: remove the obsolete port configuration CLI commands Cristian Dumitrescu
` (6 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline configuration is now done through the I/O specification
file, hence this CLI command is no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 47 -----------------------------------------
1 file changed, 47 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 28cf8d4178..7b725a9c27 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -523,39 +523,6 @@ cmd_tap(char **tokens,
}
}
-static const char cmd_pipeline_create_help[] =
-"pipeline <pipeline_name> create <numa_node>\n";
-
-static void
-cmd_pipeline_create(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- char *name;
- uint32_t numa_node;
-
- if (n_tokens != 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- name = tokens[1];
-
- if (parser_read_uint32(&numa_node, tokens[3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
- return;
- }
-
- p = pipeline_create(obj, name, (int)numa_node);
- if (!p) {
- snprintf(out, out_size, "pipeline create error.");
- return;
- }
-}
-
static const char cmd_pipeline_port_in_help[] =
"pipeline <pipeline_name> port in <port_id>\n"
" link <link_name> rxq <queue_id> bsz <burst_size>\n"
@@ -3188,7 +3155,6 @@ cmd_help(char **tokens,
"\tmempool\n"
"\tlink\n"
"\ttap\n"
- "\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
@@ -3241,12 +3207,6 @@ cmd_help(char **tokens,
return;
}
- if ((strcmp(tokens[0], "pipeline") == 0) &&
- (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) {
- snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
- return;
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
if (strcmp(tokens[2], "in") == 0) {
@@ -3529,13 +3489,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
}
if (strcmp(tokens[0], "pipeline") == 0) {
- if ((n_tokens >= 3) &&
- (strcmp(tokens[2], "create") == 0)) {
- cmd_pipeline_create(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
if ((n_tokens >= 4) &&
(strcmp(tokens[2], "port") == 0) &&
(strcmp(tokens[3], "in") == 0)) {
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 12/17] examples/pipeline: remove the obsolete port configuration CLI commands
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (9 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 11/17] examples/pipeline: remove the obsolete pipeline create CLI command Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command Cristian Dumitrescu
` (5 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline I/O ports configuration is now done through the I/O
specification file, hence these CLI commands are no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 465 ----------------------------------------
1 file changed, 465 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 7b725a9c27..b26e73c706 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -523,438 +523,6 @@ cmd_tap(char **tokens,
}
}
-static const char cmd_pipeline_port_in_help[] =
-"pipeline <pipeline_name> port in <port_id>\n"
-" link <link_name> rxq <queue_id> bsz <burst_size>\n"
-" ring <ring_name> bsz <burst_size>\n"
-" | source <mempool_name> <file_name> loop <n_loops>\n"
-" | tap <tap_name> mempool <mempool_name> mtu <mtu> bsz <burst_size>\n";
-
-static void
-cmd_pipeline_port_in(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- int status;
- uint32_t port_id = 0, t0;
-
- if (n_tokens < 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
-
- if (strcmp(tokens[3], "in") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
- return;
- }
-
- if (parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- t0 = 5;
-
- if (strcmp(tokens[t0], "link") == 0) {
- struct rte_swx_port_ethdev_reader_params params;
- struct link *link;
-
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in link");
- return;
- }
-
- link = link_find(obj, tokens[t0 + 1]);
- if (!link) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "link_name");
- return;
- }
- params.dev_name = link->dev_name;
-
- if (strcmp(tokens[t0 + 2], "rxq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
- return;
- }
-
- if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "queue_id");
- return;
- }
-
- if (strcmp(tokens[t0 + 4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 6;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "ethdev",
- ¶ms);
- } else if (strcmp(tokens[t0], "ring") == 0) {
- struct rte_swx_port_ring_reader_params params;
- struct ring *ring;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in ring");
- return;
- }
-
- ring = ring_find(obj, tokens[t0 + 1]);
- if (!ring) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "ring_name");
- return;
- }
- params.name = ring->name;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "ring",
- ¶ms);
- } else if (strcmp(tokens[t0], "source") == 0) {
- struct rte_swx_port_source_params params;
- struct mempool *mp;
-
- if (n_tokens < t0 + 5) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in source");
- return;
- }
-
- mp = mempool_find(obj, tokens[t0 + 1]);
- if (!mp) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "mempool_name");
- return;
- }
- params.pool = mp->m;
-
- params.file_name = tokens[t0 + 2];
-
- if (strcmp(tokens[t0 + 3], "loop") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "loop");
- return;
- }
-
- if (parser_read_uint64(¶ms.n_loops, tokens[t0 + 4])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "n_loops");
- return;
- }
-
- t0 += 5;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "source",
- ¶ms);
- } else if (strcmp(tokens[t0], "tap") == 0) {
- struct rte_swx_port_fd_reader_params params;
- struct tap *tap;
- struct mempool *mp;
-
- if (n_tokens < t0 + 8) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port in tap");
- return;
- }
-
- tap = tap_find(obj, tokens[t0 + 1]);
- if (!tap) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "tap_name");
- return;
- }
- params.fd = tap->fd;
-
- if (strcmp(tokens[t0 + 2], "mempool") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mempool");
- return;
- }
-
- mp = mempool_find(obj, tokens[t0 + 3]);
- if (!mp) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "mempool_name");
- return;
- }
- params.mempool = mp->m;
-
- if (strcmp(tokens[t0 + 4], "mtu") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND,
- "mtu");
- return;
- }
-
- if (parser_read_uint32(¶ms.mtu, tokens[t0 + 5]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
- return;
- }
-
- if (strcmp(tokens[t0 + 6], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 7])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 8;
-
- status = rte_swx_pipeline_port_in_config(p->p,
- port_id,
- "fd",
- ¶ms);
-
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (status) {
- snprintf(out, out_size, "port in error.");
- return;
- }
-
- if (n_tokens != t0) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-}
-
-static const char cmd_pipeline_port_out_help[] =
-"pipeline <pipeline_name> port out <port_id>\n"
-" link <link_name> txq <txq_id> bsz <burst_size>\n"
-" ring <ring_name> bsz <burst_size>\n"
-" | sink <file_name> | none\n"
-" | tap <tap_name> bsz <burst_size>\n";
-
-static void
-cmd_pipeline_port_out(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct pipeline *p;
- int status;
- uint32_t port_id = 0, t0;
-
- if (n_tokens < 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[2], "port") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
- return;
- }
-
- if (strcmp(tokens[3], "out") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
- return;
- }
-
- if (parser_read_uint32(&port_id, tokens[4]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
-
- t0 = 5;
-
- if (strcmp(tokens[t0], "link") == 0) {
- struct rte_swx_port_ethdev_writer_params params;
- struct link *link;
-
- if (n_tokens < t0 + 6) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out link");
- return;
- }
-
- link = link_find(obj, tokens[t0 + 1]);
- if (!link) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "link_name");
- return;
- }
- params.dev_name = link->dev_name;
-
- if (strcmp(tokens[t0 + 2], "txq") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
- return;
- }
-
- if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "queue_id");
- return;
- }
-
- if (strcmp(tokens[t0 + 4], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 6;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "ethdev",
- ¶ms);
- } else if (strcmp(tokens[t0], "ring") == 0) {
- struct rte_swx_port_ring_writer_params params;
- struct ring *ring;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out link");
- return;
- }
-
- ring = ring_find(obj, tokens[t0 + 1]);
- if (!ring) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "ring_name");
- return;
- }
- params.name = ring->name;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "ring",
- ¶ms);
- } else if (strcmp(tokens[t0], "sink") == 0) {
- struct rte_swx_port_sink_params params;
-
- params.file_name = strcmp(tokens[t0 + 1], "none") ?
- tokens[t0 + 1] : NULL;
-
- t0 += 2;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "sink",
- ¶ms);
- } else if (strcmp(tokens[t0], "tap") == 0) {
- struct rte_swx_port_fd_writer_params params;
- struct tap *tap;
-
- if (n_tokens < t0 + 4) {
- snprintf(out, out_size, MSG_ARG_MISMATCH,
- "pipeline port out tap");
- return;
- }
-
- tap = tap_find(obj, tokens[t0 + 1]);
- if (!tap) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "tap_name");
- return;
- }
- params.fd = tap->fd;
-
- if (strcmp(tokens[t0 + 2], "bsz") != 0) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
- return;
- }
-
- if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
- snprintf(out, out_size, MSG_ARG_INVALID,
- "burst_size");
- return;
- }
-
- t0 += 4;
-
- status = rte_swx_pipeline_port_out_config(p->p,
- port_id,
- "fd",
- ¶ms);
- } else {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
- return;
- }
-
- if (status) {
- snprintf(out, out_size, "port out error.");
- return;
- }
-
- if (n_tokens != t0) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-}
-
static const char cmd_pipeline_codegen_help[] =
"pipeline codegen <spec_file> <code_file>\n";
@@ -3155,8 +2723,6 @@ cmd_help(char **tokens,
"\tmempool\n"
"\tlink\n"
"\ttap\n"
- "\tpipeline port in\n"
- "\tpipeline port out\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
"\tpipeline build\n"
@@ -3207,21 +2773,6 @@ cmd_help(char **tokens,
return;
}
- if ((strcmp(tokens[0], "pipeline") == 0) &&
- (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
- if (strcmp(tokens[2], "in") == 0) {
- snprintf(out, out_size, "\n%s\n",
- cmd_pipeline_port_in_help);
- return;
- }
-
- if (strcmp(tokens[2], "out") == 0) {
- snprintf(out, out_size, "\n%s\n",
- cmd_pipeline_port_out_help);
- return;
- }
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
@@ -3489,22 +3040,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
}
if (strcmp(tokens[0], "pipeline") == 0) {
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "port") == 0) &&
- (strcmp(tokens[3], "in") == 0)) {
- cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "port") == 0) &&
- (strcmp(tokens[3], "out") == 0)) {
- cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
- obj);
- return;
- }
-
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "codegen") == 0)) {
cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (10 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 12/17] examples/pipeline: remove the obsolete port configuration CLI commands Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 14/17] examples/pipeline: use the pipeline name query API Cristian Dumitrescu
` (4 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
The pipeline mirroring configuration is done through the I/O
specification file, so this CLI command is no longer needed.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 76 -----------------------------------------
1 file changed, 76 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index b26e73c706..fa828c008b 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -2457,68 +2457,6 @@ cmd_pipeline_stats(char **tokens,
}
}
-static const char cmd_pipeline_mirror_help[] =
-"pipeline <pipeline_name> mirror slots <n_slots> sessions <n_sessions>\n";
-
-static void
-cmd_pipeline_mirror(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct rte_swx_pipeline_mirroring_params params;
- struct pipeline *p;
- int status;
-
- if (n_tokens != 7) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
-
- if (strcmp(tokens[0], "pipeline")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
- return;
- }
-
- p = pipeline_find(obj, tokens[1]);
- if (!p) {
- snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
- return;
- }
-
- if (strcmp(tokens[2], "mirror")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
- return;
- }
-
- if (strcmp(tokens[3], "slots")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "slots");
- return;
- }
-
- if (parser_read_uint32(¶ms.n_slots, tokens[4])) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_slots");
- return;
- }
-
- if (strcmp(tokens[5], "sessions")) {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "sessions");
- return;
- }
-
- if (parser_read_uint32(¶ms.n_sessions, tokens[6])) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_sessions");
- return;
- }
-
- status = rte_swx_pipeline_mirroring_config(p->p, ¶ms);
- if (status) {
- snprintf(out, out_size, "Command failed!\n");
- return;
- }
-}
-
static const char cmd_pipeline_mirror_session_help[] =
"pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow "
"truncate <truncation_length>\n";
@@ -2746,7 +2684,6 @@ cmd_help(char **tokens,
"\tpipeline meter set\n"
"\tpipeline meter stats\n"
"\tpipeline stats\n"
- "\tpipeline mirror\n"
"\tpipeline mirror session\n"
"\tthread pipeline enable\n"
"\tthread pipeline disable\n\n");
@@ -2958,12 +2895,6 @@ cmd_help(char **tokens,
return;
}
- if (!strcmp(tokens[0], "pipeline") &&
- (n_tokens == 2) && !strcmp(tokens[1], "mirror")) {
- snprintf(out, out_size, "\n%s\n", cmd_pipeline_mirror_help);
- return;
- }
-
if (!strcmp(tokens[0], "pipeline") &&
(n_tokens == 3) && !strcmp(tokens[1], "mirror")
&& !strcmp(tokens[2], "session")) {
@@ -3217,13 +3148,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if ((n_tokens >= 4) &&
- (strcmp(tokens[2], "mirror") == 0) &&
- (strcmp(tokens[3], "slots") == 0)) {
- cmd_pipeline_mirror(tokens, n_tokens, out, out_size, obj);
- return;
- }
-
if ((n_tokens >= 4) &&
(strcmp(tokens[2], "mirror") == 0) &&
(strcmp(tokens[3], "session") == 0)) {
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 14/17] examples/pipeline: use the pipeline name query API
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (11 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 13/17] examples/pipeline: remove the obsolete mirroring configuration CLI command Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 15/17] examples/pipeline: rework the link CLI command Cristian Dumitrescu
` (3 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Convert the CLI commands to use the pipeline name query API and remove
the linked list of pipeline objects previously maintained by the
application.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 268 ++++++++++++++++++++-----------------
examples/pipeline/obj.c | 67 ----------
examples/pipeline/obj.h | 24 ----
examples/pipeline/thread.c | 65 ++++-----
examples/pipeline/thread.h | 9 +-
5 files changed, 175 insertions(+), 258 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index fa828c008b..f48ff326be 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -858,9 +858,9 @@ cmd_pipeline_table_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -872,8 +872,8 @@ cmd_pipeline_table_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -887,7 +887,7 @@ cmd_pipeline_table_add(char **tokens,
return;
}
- status = pipeline_table_entries_add(p->ctl,
+ status = pipeline_table_entries_add(ctl,
table_name,
file,
&file_line_number);
@@ -956,9 +956,9 @@ cmd_pipeline_table_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -970,8 +970,8 @@ cmd_pipeline_table_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -985,7 +985,7 @@ cmd_pipeline_table_delete(char **tokens,
return;
}
- status = pipeline_table_entries_delete(p->ctl,
+ status = pipeline_table_entries_delete(ctl,
table_name,
file,
&file_line_number);
@@ -1054,9 +1054,9 @@ cmd_pipeline_table_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1068,8 +1068,8 @@ cmd_pipeline_table_default(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1083,7 +1083,7 @@ cmd_pipeline_table_default(char **tokens,
return;
}
- status = pipeline_table_default_entry_add(p->ctl,
+ status = pipeline_table_default_entry_add(ctl,
table_name,
file,
&file_line_number);
@@ -1103,9 +1103,9 @@ cmd_pipeline_table_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *table_name;
FILE *file = NULL;
int status;
@@ -1116,8 +1116,8 @@ cmd_pipeline_table_show(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1129,7 +1129,7 @@ cmd_pipeline_table_show(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
+ status = rte_swx_ctl_pipeline_table_fprintf(file, ctl, table_name);
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
@@ -1145,9 +1145,9 @@ cmd_pipeline_selector_group_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
@@ -1158,8 +1158,8 @@ cmd_pipeline_selector_group_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1177,7 +1177,7 @@ cmd_pipeline_selector_group_add(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
+ status = rte_swx_ctl_pipeline_selector_group_add(ctl,
selector_name,
&group_id);
if (status)
@@ -1194,9 +1194,9 @@ cmd_pipeline_selector_group_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
uint32_t group_id;
int status;
@@ -1207,8 +1207,8 @@ cmd_pipeline_selector_group_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1231,7 +1231,7 @@ cmd_pipeline_selector_group_delete(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
+ status = rte_swx_ctl_pipeline_selector_group_delete(ctl,
selector_name,
group_id);
if (status)
@@ -1402,9 +1402,9 @@ cmd_pipeline_selector_group_member_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1416,8 +1416,8 @@ cmd_pipeline_selector_group_member_add(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1443,7 +1443,7 @@ cmd_pipeline_selector_group_member_add(char **tokens,
return;
}
- status = pipeline_selector_group_members_add(p->ctl,
+ status = pipeline_selector_group_members_add(ctl,
selector_name,
file,
&file_line_number);
@@ -1512,9 +1512,9 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1526,8 +1526,8 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1553,7 +1553,7 @@ cmd_pipeline_selector_group_member_delete(char **tokens,
return;
}
- status = pipeline_selector_group_members_delete(p->ctl,
+ status = pipeline_selector_group_members_delete(ctl,
selector_name,
file,
&file_line_number);
@@ -1573,9 +1573,9 @@ cmd_pipeline_selector_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *selector_name;
FILE *file = NULL;
int status;
@@ -1586,8 +1586,8 @@ cmd_pipeline_selector_show(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1600,7 +1600,7 @@ cmd_pipeline_selector_show(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
+ status = rte_swx_ctl_pipeline_selector_fprintf(file, ctl, selector_name);
if (status)
snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
@@ -1665,9 +1665,9 @@ cmd_pipeline_learner_default(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name, *learner_name, *file_name;
FILE *file = NULL;
uint32_t file_line_number = 0;
@@ -1679,8 +1679,8 @@ cmd_pipeline_learner_default(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1694,7 +1694,7 @@ cmd_pipeline_learner_default(char **tokens,
return;
}
- status = pipeline_learner_default_entry_add(p->ctl,
+ status = pipeline_learner_default_entry_add(ctl,
learner_name,
file,
&file_line_number);
@@ -1714,9 +1714,9 @@ cmd_pipeline_commit(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
int status;
@@ -1726,13 +1726,13 @@ cmd_pipeline_commit(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
- status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
+ status = rte_swx_ctl_pipeline_commit(ctl, 1);
if (status)
snprintf(out, out_size, "Commit failed. "
"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
@@ -1746,9 +1746,9 @@ cmd_pipeline_abort(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_ctl_pipeline *ctl;
char *pipeline_name;
if (n_tokens != 3) {
@@ -1757,13 +1757,13 @@ cmd_pipeline_abort(char **tokens,
}
pipeline_name = tokens[1];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ ctl = rte_swx_ctl_pipeline_find(pipeline_name);
+ if (!ctl) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
- rte_swx_ctl_pipeline_abort(p->ctl);
+ rte_swx_ctl_pipeline_abort(ctl);
}
static const char cmd_pipeline_regrd_help[] =
@@ -1774,9 +1774,9 @@ cmd_pipeline_regrd(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint64_t value;
uint32_t idx;
@@ -1787,8 +1787,8 @@ cmd_pipeline_regrd(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1805,7 +1805,7 @@ cmd_pipeline_regrd(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
+ status = rte_swx_ctl_pipeline_regarray_read(p, name, idx, &value);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1822,9 +1822,9 @@ cmd_pipeline_regwr(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint64_t value;
uint32_t idx;
@@ -1835,8 +1835,8 @@ cmd_pipeline_regwr(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1858,7 +1858,7 @@ cmd_pipeline_regwr(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
+ status = rte_swx_ctl_pipeline_regarray_write(p, name, idx, value);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1874,10 +1874,10 @@ cmd_pipeline_meter_profile_add(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_meter_trtcm_params params;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *profile_name;
int status;
@@ -1886,8 +1886,8 @@ cmd_pipeline_meter_profile_add(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1949,7 +1949,7 @@ cmd_pipeline_meter_profile_add(char **tokens,
return;
}
- status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms);
+ status = rte_swx_ctl_meter_profile_add(p, profile_name, ¶ms);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -1964,9 +1964,9 @@ cmd_pipeline_meter_profile_delete(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *profile_name;
int status;
@@ -1975,8 +1975,8 @@ cmd_pipeline_meter_profile_delete(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -1998,7 +1998,7 @@ cmd_pipeline_meter_profile_delete(char **tokens,
return;
}
- status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
+ status = rte_swx_ctl_meter_profile_delete(p, profile_name);
if (status) {
snprintf(out, out_size, "Command failed.\n");
return;
@@ -2014,9 +2014,9 @@ cmd_pipeline_meter_reset(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2025,8 +2025,8 @@ cmd_pipeline_meter_reset(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2066,7 +2066,7 @@ cmd_pipeline_meter_reset(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_reset(p->p, name, idx0);
+ status = rte_swx_ctl_meter_reset(p, name, idx0);
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
@@ -2083,9 +2083,9 @@ cmd_pipeline_meter_set(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name, *profile_name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2094,8 +2094,8 @@ cmd_pipeline_meter_set(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2142,7 +2142,7 @@ cmd_pipeline_meter_set(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
+ status = rte_swx_ctl_meter_set(p, name, idx0, profile_name);
if (status) {
snprintf(out, out_size, "Command failed for index %u.\n", idx0);
return;
@@ -2159,10 +2159,10 @@ cmd_pipeline_meter_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_ctl_meter_stats stats;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
const char *name;
uint32_t idx0 = 0, idx1 = 0;
@@ -2171,8 +2171,8 @@ cmd_pipeline_meter_stats(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2235,7 +2235,7 @@ cmd_pipeline_meter_stats(char **tokens,
for ( ; idx0 <= idx1; idx0++) {
int status;
- status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
+ status = rte_swx_ctl_meter_stats_read(p, name, idx0, &stats);
if (status) {
snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
out_size -= strlen(out);
@@ -2265,10 +2265,10 @@ cmd_pipeline_stats(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_ctl_pipeline_info info;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
uint32_t i;
int status;
@@ -2277,8 +2277,8 @@ cmd_pipeline_stats(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2288,7 +2288,7 @@ cmd_pipeline_stats(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_info_get(p->p, &info);
+ status = rte_swx_ctl_pipeline_info_get(p, &info);
if (status) {
snprintf(out, out_size, "Pipeline info get error.");
return;
@@ -2301,7 +2301,7 @@ cmd_pipeline_stats(char **tokens,
for (i = 0; i < info.n_ports_in; i++) {
struct rte_swx_port_in_stats stats;
- rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
+ rte_swx_ctl_pipeline_port_in_stats_read(p, i, &stats);
snprintf(out, out_size, "\tPort %u:"
" packets %" PRIu64
@@ -2319,7 +2319,7 @@ cmd_pipeline_stats(char **tokens,
for (i = 0; i < info.n_ports_out; i++) {
struct rte_swx_port_out_stats stats;
- rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
+ rte_swx_ctl_pipeline_port_out_stats_read(p, i, &stats);
if (i != info.n_ports_out - 1)
snprintf(out, out_size, "\tPort %u:", i);
@@ -2358,13 +2358,13 @@ cmd_pipeline_stats(char **tokens,
};
uint32_t j;
- status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+ status = rte_swx_ctl_table_info_get(p, i, &table_info);
if (status) {
snprintf(out, out_size, "Table info get error.");
return;
}
- status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+ status = rte_swx_ctl_pipeline_table_stats_read(p, table_info.name, &stats);
if (status) {
snprintf(out, out_size, "Table stats read error.");
return;
@@ -2382,7 +2382,7 @@ cmd_pipeline_stats(char **tokens,
for (j = 0; j < info.n_actions; j++) {
struct rte_swx_ctl_action_info action_info;
- status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+ status = rte_swx_ctl_action_info_get(p, j, &action_info);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
@@ -2410,13 +2410,13 @@ cmd_pipeline_stats(char **tokens,
};
uint32_t j;
- status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
+ status = rte_swx_ctl_learner_info_get(p, i, &learner_info);
if (status) {
snprintf(out, out_size, "Learner table info get error.");
return;
}
- status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
+ status = rte_swx_ctl_pipeline_learner_stats_read(p, learner_info.name, &stats);
if (status) {
snprintf(out, out_size, "Learner table stats read error.");
return;
@@ -2442,7 +2442,7 @@ cmd_pipeline_stats(char **tokens,
for (j = 0; j < info.n_actions; j++) {
struct rte_swx_ctl_action_info action_info;
- status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+ status = rte_swx_ctl_action_info_get(p, j, &action_info);
if (status) {
snprintf(out, out_size, "Action info get error.");
return;
@@ -2466,10 +2466,10 @@ cmd_pipeline_mirror_session(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
struct rte_swx_pipeline_mirroring_session_params params;
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
uint32_t session_id = 0;
int status;
@@ -2483,8 +2483,8 @@ cmd_pipeline_mirror_session(char **tokens,
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(tokens[1]);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2538,7 +2538,7 @@ cmd_pipeline_mirror_session(char **tokens,
return;
}
- status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, ¶ms);
+ status = rte_swx_ctl_pipeline_mirroring_session_set(p, session_id, ¶ms);
if (status) {
snprintf(out, out_size, "Command failed!\n");
return;
@@ -2546,21 +2546,25 @@ cmd_pipeline_mirror_session(char **tokens,
}
static const char cmd_thread_pipeline_enable_help[] =
-"thread <thread_id> pipeline <pipeline_name> enable\n";
+"thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]\n";
+
+#ifndef TIMER_PERIOD_MS_DEFAULT
+#define TIMER_PERIOD_MS_DEFAULT 10
+#endif
static void
cmd_thread_pipeline_enable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
char *pipeline_name;
- struct pipeline *p;
- uint32_t thread_id;
+ struct rte_swx_pipeline *p;
+ uint32_t thread_id, timer_period_ms = TIMER_PERIOD_MS_DEFAULT;
int status;
- if (n_tokens != 5) {
+ if ((n_tokens != 5) && (n_tokens != 7)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
@@ -2576,8 +2580,8 @@ cmd_thread_pipeline_enable(char **tokens,
}
pipeline_name = tokens[3];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(pipeline_name);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2587,7 +2591,19 @@ cmd_thread_pipeline_enable(char **tokens,
return;
}
- status = thread_pipeline_enable(thread_id, obj, pipeline_name);
+ if (n_tokens == 7) {
+ if (strcmp(tokens[5], "period") != 0) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
+ return;
+ }
+
+ if (parser_read_uint32(&timer_period_ms, tokens[6]) != 0) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
+ return;
+ }
+ }
+
+ status = thread_pipeline_enable(thread_id, p, timer_period_ms);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
return;
@@ -2602,9 +2618,9 @@ cmd_thread_pipeline_disable(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p;
+ struct rte_swx_pipeline *p;
char *pipeline_name;
uint32_t thread_id;
int status;
@@ -2625,8 +2641,8 @@ cmd_thread_pipeline_disable(char **tokens,
}
pipeline_name = tokens[3];
- p = pipeline_find(obj, pipeline_name);
- if (!p || !p->ctl) {
+ p = rte_swx_pipeline_find(pipeline_name);
+ if (!p) {
snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
return;
}
@@ -2636,7 +2652,7 @@ cmd_thread_pipeline_disable(char **tokens,
return;
}
- status = thread_pipeline_disable(thread_id, obj, pipeline_name);
+ status = thread_pipeline_disable(thread_id, p);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL,
"thread pipeline disable");
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index 967342c580..d1f519180e 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -16,7 +16,6 @@
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_ethdev.h>
-#include <rte_swx_pipeline.h>
#include <rte_swx_ctl.h>
#include "obj.h"
@@ -41,11 +40,6 @@ TAILQ_HEAD(ring_list, ring);
*/
TAILQ_HEAD(tap_list, tap);
-/*
- * pipeline
- */
-TAILQ_HEAD(pipeline_list, pipeline);
-
/*
* obj
*/
@@ -53,7 +47,6 @@ struct obj {
struct mempool_list mempool_list;
struct link_list link_list;
struct ring_list ring_list;
- struct pipeline_list pipeline_list;
struct tap_list tap_list;
};
@@ -513,65 +506,6 @@ tap_create(struct obj *obj, const char *name)
#endif
-/*
- * pipeline
- */
-#ifndef PIPELINE_MSGQ_SIZE
-#define PIPELINE_MSGQ_SIZE 64
-#endif
-
-struct pipeline *
-pipeline_create(struct obj *obj, const char *name, int numa_node)
-{
- struct pipeline *pipeline;
- struct rte_swx_pipeline *p = NULL;
- int status;
-
- /* Check input params */
- if ((name == NULL) ||
- pipeline_find(obj, name))
- return NULL;
-
- /* Resource create */
- status = rte_swx_pipeline_config(&p, name, numa_node);
- if (status)
- goto error;
-
- /* Node allocation */
- pipeline = calloc(1, sizeof(struct pipeline));
- if (pipeline == NULL)
- goto error;
-
- /* Node fill in */
- strlcpy(pipeline->name, name, sizeof(pipeline->name));
- pipeline->p = p;
- pipeline->timer_period_ms = 10;
-
- /* Node add to list */
- TAILQ_INSERT_TAIL(&obj->pipeline_list, pipeline, node);
-
- return pipeline;
-
-error:
- rte_swx_pipeline_free(p);
- return NULL;
-}
-
-struct pipeline *
-pipeline_find(struct obj *obj, const char *name)
-{
- struct pipeline *pipeline;
-
- if (!obj || !name)
- return NULL;
-
- TAILQ_FOREACH(pipeline, &obj->pipeline_list, node)
- if (strcmp(name, pipeline->name) == 0)
- return pipeline;
-
- return NULL;
-}
-
/*
* obj
*/
@@ -587,7 +521,6 @@ obj_init(void)
TAILQ_INIT(&obj->mempool_list);
TAILQ_INIT(&obj->link_list);
TAILQ_INIT(&obj->ring_list);
- TAILQ_INIT(&obj->pipeline_list);
TAILQ_INIT(&obj->tap_list);
return obj;
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index b921610554..e63a9c0e9a 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -143,28 +143,4 @@ tap_next(struct obj *obj, struct tap *tap);
struct tap *
tap_create(struct obj *obj, const char *name);
-/*
- * pipeline
- */
-struct pipeline {
- TAILQ_ENTRY(pipeline) node;
- char name[NAME_SIZE];
-
- struct rte_swx_pipeline *p;
- struct rte_swx_ctl_pipeline *ctl;
-
- uint32_t timer_period_ms;
- int enabled;
- uint32_t thread_id;
- uint32_t cpu_id;
-};
-
-struct pipeline *
-pipeline_create(struct obj *obj,
- const char *name,
- int numa_node);
-
-struct pipeline *
-pipeline_find(struct obj *obj, const char *name);
-
#endif /* _INCLUDE_OBJ_H_ */
diff --git a/examples/pipeline/thread.c b/examples/pipeline/thread.c
index 5fe7eae00e..6d15f51fb2 100644
--- a/examples/pipeline/thread.c
+++ b/examples/pipeline/thread.c
@@ -228,20 +228,33 @@ thread_msg_send_recv(uint32_t thread_id,
return rsp;
}
+static int
+thread_is_pipeline_enabled(uint32_t thread_id, struct rte_swx_pipeline *p)
+{
+ struct thread *t = &thread[thread_id];
+ struct thread_data *td = &thread_data[thread_id];
+ uint32_t i;
+
+ if (!t->enabled)
+ return 0; /* Pipeline NOT enabled on this thread. */
+
+ for (i = 0; i < td->n_pipelines; i++)
+ if (td->p[i] == p)
+ return 1; /* Pipeline enabled on this thread. */
+
+ return 0 /* Pipeline NOT enabled on this thread. */;
+}
+
int
-thread_pipeline_enable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name)
+thread_pipeline_enable(uint32_t thread_id, struct rte_swx_pipeline *p, uint32_t timer_period_ms)
{
- struct pipeline *p = pipeline_find(obj, pipeline_name);
struct thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
- (p == NULL))
+ if ((thread_id >= RTE_MAX_LCORE) || !p || !timer_period_ms)
return -1;
t = &thread[thread_id];
@@ -256,19 +269,14 @@ thread_pipeline_enable(uint32_t thread_id,
return -1;
/* Data plane thread */
- td->p[td->n_pipelines] = p->p;
+ td->p[td->n_pipelines] = p;
- tdp->p = p->p;
- tdp->timer_period =
- (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
+ tdp->p = p;
+ tdp->timer_period = (rte_get_tsc_hz() * timer_period_ms) / 1000;
tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
td->n_pipelines++;
- /* Pipeline */
- p->thread_id = thread_id;
- p->enabled = 1;
-
return 0;
}
@@ -279,8 +287,8 @@ thread_pipeline_enable(uint32_t thread_id,
/* Write request */
req->type = THREAD_REQ_PIPELINE_ENABLE;
- req->pipeline_enable.p = p->p;
- req->pipeline_enable.timer_period_ms = p->timer_period_ms;
+ req->pipeline_enable.p = p;
+ req->pipeline_enable.timer_period_ms = timer_period_ms;
/* Send request and wait for response */
rsp = thread_msg_send_recv(thread_id, req);
@@ -295,38 +303,28 @@ thread_pipeline_enable(uint32_t thread_id,
if (status)
return status;
- p->thread_id = thread_id;
- p->enabled = 1;
-
return 0;
}
int
-thread_pipeline_disable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name)
+thread_pipeline_disable(uint32_t thread_id, struct rte_swx_pipeline *p)
{
- struct pipeline *p = pipeline_find(obj, pipeline_name);
struct thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
- (p == NULL))
+ if ((thread_id >= RTE_MAX_LCORE) || !p)
return -1;
t = &thread[thread_id];
if (t->enabled == 0)
return -1;
- if (p->enabled == 0)
+ if (!thread_is_pipeline_enabled(thread_id, p))
return 0;
- if (p->thread_id != thread_id)
- return -1;
-
if (!thread_is_running(thread_id)) {
struct thread_data *td = &thread_data[thread_id];
uint32_t i;
@@ -334,7 +332,7 @@ thread_pipeline_disable(uint32_t thread_id,
for (i = 0; i < td->n_pipelines; i++) {
struct pipeline_data *tdp = &td->pipeline_data[i];
- if (tdp->p != p->p)
+ if (tdp->p != p)
continue;
/* Data plane thread */
@@ -350,9 +348,6 @@ thread_pipeline_disable(uint32_t thread_id,
td->n_pipelines--;
- /* Pipeline */
- p->enabled = 0;
-
break;
}
@@ -366,7 +361,7 @@ thread_pipeline_disable(uint32_t thread_id,
/* Write request */
req->type = THREAD_REQ_PIPELINE_DISABLE;
- req->pipeline_disable.p = p->p;
+ req->pipeline_disable.p = p;
/* Send request and wait for response */
rsp = thread_msg_send_recv(thread_id, req);
@@ -381,8 +376,6 @@ thread_pipeline_disable(uint32_t thread_id,
if (status)
return status;
- p->enabled = 0;
-
return 0;
}
diff --git a/examples/pipeline/thread.h b/examples/pipeline/thread.h
index d9d8645d4c..712cb25bbb 100644
--- a/examples/pipeline/thread.h
+++ b/examples/pipeline/thread.h
@@ -7,17 +7,16 @@
#include <stdint.h>
-#include "obj.h"
+#include <rte_swx_pipeline.h>
int
thread_pipeline_enable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name);
+ struct rte_swx_pipeline *p,
+ uint32_t timer_period_ms);
int
thread_pipeline_disable(uint32_t thread_id,
- struct obj *obj,
- const char *pipeline_name);
+ struct rte_swx_pipeline *p);
int
thread_init(void);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 15/17] examples/pipeline: rework the link CLI command
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (12 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 14/17] examples/pipeline: use the pipeline name query API Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 16/17] examples/pipelines: remove obsolete tap " Cristian Dumitrescu
` (2 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the link CLI command for better alignment with the naming
conventions used in the pipeline I/O specification file. Use the
library linked list of devices and remove the application list.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 81 +++++++++++++----------------------------
examples/pipeline/obj.c | 16 ++------
examples/pipeline/obj.h | 4 --
3 files changed, 29 insertions(+), 72 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index f48ff326be..d56a830fb7 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -106,22 +106,6 @@ parser_read_uint32(uint32_t *value, const char *p)
return 0;
}
-static int
-parser_read_uint16(uint16_t *value, const char *p)
-{
- uint64_t val = 0;
- int ret = parser_read_uint64(&val, p);
-
- if (ret < 0)
- return ret;
-
- if (val > UINT16_MAX)
- return -ERANGE;
-
- *value = val;
- return 0;
-}
-
#define PARSE_DELIMITER " \f\n\r\t\v"
static int
@@ -230,16 +214,15 @@ cmd_mempool(char **tokens,
}
}
-static const char cmd_link_help[] =
-"link <link_name>\n"
-" dev <device_name> | port <port_id>\n"
+static const char cmd_ethdev_help[] =
+"ethdev <ethdev_name>\n"
" rxq <n_queues> <queue_size> <mempool_name>\n"
" txq <n_queues> <queue_size>\n"
" promiscuous on | off\n"
" [rss <qid_0> ... <qid_n>]\n";
static void
-cmd_link(char **tokens,
+cmd_ethdev(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
@@ -252,65 +235,51 @@ cmd_link(char **tokens,
memset(&p, 0, sizeof(p));
- if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
+ if ((n_tokens < 11) || (n_tokens > 12 + LINK_RXQ_RSS_MAX)) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
name = tokens[1];
- if (strcmp(tokens[2], "dev") == 0)
- p.dev_name = tokens[3];
- else if (strcmp(tokens[2], "port") == 0) {
- p.dev_name = NULL;
-
- if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
- snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
- return;
- }
- } else {
- snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
- return;
- }
-
- if (strcmp(tokens[4], "rxq") != 0) {
+ if (strcmp(tokens[2], "rxq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
return;
}
- if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
+ if (parser_read_uint32(&p.rx.n_queues, tokens[3]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
- if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
+ if (parser_read_uint32(&p.rx.queue_size, tokens[4]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
- p.rx.mempool_name = tokens[7];
+ p.rx.mempool_name = tokens[5];
- if (strcmp(tokens[8], "txq") != 0) {
+ if (strcmp(tokens[6], "txq") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
return;
}
- if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
+ if (parser_read_uint32(&p.tx.n_queues, tokens[7]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
return;
}
- if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
+ if (parser_read_uint32(&p.tx.queue_size, tokens[8]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
return;
}
- if (strcmp(tokens[11], "promiscuous") != 0) {
+ if (strcmp(tokens[9], "promiscuous") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
return;
}
- if (strcmp(tokens[12], "on") == 0)
+ if (strcmp(tokens[10], "on") == 0)
p.promiscuous = 1;
- else if (strcmp(tokens[12], "off") == 0)
+ else if (strcmp(tokens[10], "off") == 0)
p.promiscuous = 0;
else {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
@@ -319,10 +288,10 @@ cmd_link(char **tokens,
/* RSS */
p.rx.rss = NULL;
- if (n_tokens > 13) {
+ if (n_tokens > 11) {
uint32_t queue_id, i;
- if (strcmp(tokens[13], "rss") != 0) {
+ if (strcmp(tokens[11], "rss") != 0) {
snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
return;
}
@@ -330,7 +299,7 @@ cmd_link(char **tokens,
p.rx.rss = &rss;
rss.n_queues = 0;
- for (i = 14; i < n_tokens; i++) {
+ for (i = 12; i < n_tokens; i++) {
if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
snprintf(out, out_size, MSG_ARG_INVALID,
"queue_id");
@@ -406,10 +375,10 @@ print_link_info(struct link *link, char *out, size_t out_size)
}
/*
- * link show [<link_name>]
+ * ethdev show [<ethdev_name>]
*/
static void
-cmd_link_show(char **tokens,
+cmd_ethdev_show(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
@@ -2675,7 +2644,7 @@ cmd_help(char **tokens,
"Type 'help <command>' for command details.\n\n"
"List of commands:\n"
"\tmempool\n"
- "\tlink\n"
+ "\tethdev\n"
"\ttap\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
@@ -2711,8 +2680,8 @@ cmd_help(char **tokens,
return;
}
- if (strcmp(tokens[0], "link") == 0) {
- snprintf(out, out_size, "\n%s\n", cmd_link_help);
+ if (strcmp(tokens[0], "ethdev") == 0) {
+ snprintf(out, out_size, "\n%s\n", cmd_ethdev_help);
return;
}
@@ -2966,13 +2935,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if (strcmp(tokens[0], "link") == 0) {
+ if (strcmp(tokens[0], "ethdev") == 0) {
if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
- cmd_link_show(tokens, n_tokens, out, out_size, obj);
+ cmd_ethdev_show(tokens, n_tokens, out, out_size, obj);
return;
}
- cmd_link(tokens, n_tokens, out, out_size, obj);
+ cmd_ethdev(tokens, n_tokens, out, out_size, obj);
return;
}
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index d1f519180e..950ab831fb 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -181,7 +181,7 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
struct mempool *mempool;
uint32_t cpu_id, i;
int status;
- uint16_t port_id;
+ uint16_t port_id = 0;
/* Check input params */
if ((name == NULL) ||
@@ -193,16 +193,9 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
(params->tx.queue_size == 0))
return NULL;
- port_id = params->port_id;
- if (params->dev_name) {
- status = rte_eth_dev_get_port_by_name(params->dev_name,
- &port_id);
-
- if (status)
- return NULL;
- } else
- if (!rte_eth_dev_is_valid_port(port_id))
- return NULL;
+ status = rte_eth_dev_get_port_by_name(name, &port_id);
+ if (status)
+ return NULL;
if (rte_eth_dev_info_get(port_id, &port_info) != 0)
return NULL;
@@ -315,7 +308,6 @@ link_create(struct obj *obj, const char *name, struct link_params *params)
/* Node fill in */
strlcpy(link->name, name, sizeof(link->name));
link->port_id = port_id;
- rte_eth_dev_get_name_by_port(port_id, link->dev_name);
link->n_rxq = params->rx.n_queues;
link->n_txq = params->tx.n_queues;
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index e63a9c0e9a..af270a8e57 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -63,9 +63,6 @@ struct link_params_rss {
};
struct link_params {
- const char *dev_name;
- uint16_t port_id; /**< Valid only when *dev_name* is NULL. */
-
struct {
uint32_t n_queues;
uint32_t queue_size;
@@ -84,7 +81,6 @@ struct link_params {
struct link {
TAILQ_ENTRY(link) node;
char name[NAME_SIZE];
- char dev_name[NAME_SIZE];
uint16_t port_id;
uint32_t n_rxq;
uint32_t n_txq;
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 16/17] examples/pipelines: remove obsolete tap CLI command
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (13 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 15/17] examples/pipeline: rework the link CLI command Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 22:54 ` [PATCH V4 17/17] examples/pipeline: call the code generation and build CLI commands Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Remove the tap CLI command, as the file descriptor I/O ports of the
pipeline are now configured trough the I/O specification file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 37 -----------------
examples/pipeline/obj.c | 89 -----------------------------------------
examples/pipeline/obj.h | 18 ---------
3 files changed, 144 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index d56a830fb7..75c32b9089 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -466,32 +466,6 @@ cmd_ring(char **tokens,
}
}
-static const char cmd_tap_help[] =
-"tap <tap_name>\n";
-
-static void
-cmd_tap(char **tokens,
- uint32_t n_tokens,
- char *out,
- size_t out_size,
- void *obj)
-{
- struct tap *tap;
- char *name;
-
- if (n_tokens < 2) {
- snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
- return;
- }
- name = tokens[1];
-
- tap = tap_create(obj, name);
- if (tap == NULL) {
- snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- return;
- }
-}
-
static const char cmd_pipeline_codegen_help[] =
"pipeline codegen <spec_file> <code_file>\n";
@@ -2645,7 +2619,6 @@ cmd_help(char **tokens,
"List of commands:\n"
"\tmempool\n"
"\tethdev\n"
- "\ttap\n"
"\tpipeline codegen\n"
"\tpipeline libbuild\n"
"\tpipeline build\n"
@@ -2690,11 +2663,6 @@ cmd_help(char **tokens,
return;
}
- if (strcmp(tokens[0], "tap") == 0) {
- snprintf(out, out_size, "\n%s\n", cmd_tap_help);
- return;
- }
-
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
@@ -2950,11 +2918,6 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
- if (strcmp(tokens[0], "tap") == 0) {
- cmd_tap(tokens, n_tokens, out, out_size, obj);
- return;
- }
-
if (strcmp(tokens[0], "pipeline") == 0) {
if ((n_tokens >= 3) &&
(strcmp(tokens[1], "codegen") == 0)) {
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index 950ab831fb..b7e2316eec 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -35,11 +35,6 @@ TAILQ_HEAD(link_list, link);
*/
TAILQ_HEAD(ring_list, ring);
-/*
- * tap
- */
-TAILQ_HEAD(tap_list, tap);
-
/*
* obj
*/
@@ -47,7 +42,6 @@ struct obj {
struct mempool_list mempool_list;
struct link_list link_list;
struct ring_list ring_list;
- struct tap_list tap_list;
};
/*
@@ -416,88 +410,6 @@ ring_find(struct obj *obj, const char *name)
return NULL;
}
-/*
- * tap
- */
-#define TAP_DEV "/dev/net/tun"
-
-struct tap *
-tap_find(struct obj *obj, const char *name)
-{
- struct tap *tap;
-
- if (!obj || !name)
- return NULL;
-
- TAILQ_FOREACH(tap, &obj->tap_list, node)
- if (strcmp(tap->name, name) == 0)
- return tap;
-
- return NULL;
-}
-
-struct tap *
-tap_next(struct obj *obj, struct tap *tap)
-{
- return (tap == NULL) ?
- TAILQ_FIRST(&obj->tap_list) : TAILQ_NEXT(tap, node);
-}
-
-#ifndef RTE_EXEC_ENV_LINUX
-
-struct tap *
-tap_create(struct obj *obj __rte_unused, const char *name __rte_unused)
-{
- return NULL;
-}
-
-#else
-
-struct tap *
-tap_create(struct obj *obj, const char *name)
-{
- struct tap *tap;
- struct ifreq ifr;
- int fd, status;
-
- /* Check input params */
- if ((name == NULL) ||
- tap_find(obj, name))
- return NULL;
-
- /* Resource create */
- fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
- if (fd < 0)
- return NULL;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
- strlcpy(ifr.ifr_name, name, IFNAMSIZ);
-
- status = ioctl(fd, TUNSETIFF, (void *) &ifr);
- if (status < 0) {
- close(fd);
- return NULL;
- }
-
- /* Node allocation */
- tap = calloc(1, sizeof(struct tap));
- if (tap == NULL) {
- close(fd);
- return NULL;
- }
- /* Node fill in */
- strlcpy(tap->name, name, sizeof(tap->name));
- tap->fd = fd;
-
- /* Node add to list */
- TAILQ_INSERT_TAIL(&obj->tap_list, tap, node);
-
- return tap;
-}
-
-#endif
-
/*
* obj
*/
@@ -513,7 +425,6 @@ obj_init(void)
TAILQ_INIT(&obj->mempool_list);
TAILQ_INIT(&obj->link_list);
TAILQ_INIT(&obj->ring_list);
- TAILQ_INIT(&obj->tap_list);
return obj;
}
diff --git a/examples/pipeline/obj.h b/examples/pipeline/obj.h
index af270a8e57..8ea1c414c2 100644
--- a/examples/pipeline/obj.h
+++ b/examples/pipeline/obj.h
@@ -121,22 +121,4 @@ ring_create(struct obj *obj,
struct ring *
ring_find(struct obj *obj, const char *name);
-/*
- * tap
- */
-struct tap {
- TAILQ_ENTRY(tap) node;
- char name[NAME_SIZE];
- int fd;
-};
-
-struct tap *
-tap_find(struct obj *obj, const char *name);
-
-struct tap *
-tap_next(struct obj *obj, struct tap *tap);
-
-struct tap *
-tap_create(struct obj *obj, const char *name);
-
#endif /* _INCLUDE_OBJ_H_ */
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V4 17/17] examples/pipeline: call the code generation and build CLI commands
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (14 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 16/17] examples/pipelines: remove obsolete tap " Cristian Dumitrescu
@ 2022-07-27 22:54 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 22:54 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Update the example CLI scripts with the commands for code generation
and shared object library build.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/examples/ethdev.io | 27 +++++++++
examples/pipeline/examples/fib.cli | 44 +++++++-------
examples/pipeline/examples/hash_func.cli | 41 ++++++-------
examples/pipeline/examples/l2fwd.cli | 44 ++++++++------
examples/pipeline/examples/l2fwd_macswp.cli | 44 ++++++++------
.../pipeline/examples/l2fwd_macswp_pcap.cli | 35 +++++++----
examples/pipeline/examples/l2fwd_pcap.cli | 35 +++++++----
examples/pipeline/examples/learner.cli | 43 +++++++-------
examples/pipeline/examples/meter.cli | 58 +++++++++++--------
examples/pipeline/examples/mirroring.cli | 46 ++++++++-------
examples/pipeline/examples/pcap.io | 27 +++++++++
examples/pipeline/examples/recirculation.cli | 41 ++++++-------
examples/pipeline/examples/registers.cli | 53 +++++++++--------
examples/pipeline/examples/selector.cli | 55 +++++++++++-------
examples/pipeline/examples/varbit.cli | 41 ++++++-------
examples/pipeline/examples/vxlan.cli | 48 ++++++++++-----
examples/pipeline/examples/vxlan_pcap.cli | 39 +++++++++----
17 files changed, 444 insertions(+), 277 deletions(-)
create mode 100644 examples/pipeline/examples/ethdev.io
create mode 100644 examples/pipeline/examples/pcap.io
diff --git a/examples/pipeline/examples/ethdev.io b/examples/pipeline/examples/ethdev.io
new file mode 100644
index 0000000000..cf2f3e20bd
--- /dev/null
+++ b/examples/pipeline/examples/ethdev.io
@@ -0,0 +1,27 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline packet mirroring.
+;
+mirroring slots 4 sessions 64
+
+;
+; Pipeline input ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32
+port in 1 ethdev 0000:18:00.1 rxq 0 bsz 32
+port in 2 ethdev 0000:3b:00.0 rxq 0 bsz 32
+port in 3 ethdev 0000:3b:00.1 rxq 0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ethdev 0000:18:00.0 txq 0 bsz 32
+port out 1 ethdev 0000:18:00.1 txq 0 bsz 32
+port out 2 ethdev 0000:3b:00.0 txq 0 bsz 32
+port out 3 ethdev 0000:3b:00.1 txq 0 bsz 32
diff --git a/examples/pipeline/examples/fib.cli b/examples/pipeline/examples/fib.cli
index 93ab2b08f8..4e30c1320f 100644
--- a/examples/pipeline/examples/fib.cli
+++ b/examples/pipeline/examples/fib.cli
@@ -1,38 +1,38 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/fib.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/fib.spec /tmp/fib.c
+pipeline libbuild /tmp/fib.c /tmp/fib.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/fib.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/fib.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Initial set of table entries.
;
-; The table entries can later be updated at run-time through the CLI commands. Once the application
-; has been successfully started, the command to get the CLI prompt is: telnet 0.0.0.0 8086.
+; The table entries can later be updated at run-time through the CLI commands.
;
pipeline PIPELINE0 table routing_table add ./examples/pipeline/examples/fib_routing_table.txt
pipeline PIPELINE0 selector nexthop_group_table group add
diff --git a/examples/pipeline/examples/hash_func.cli b/examples/pipeline/examples/hash_func.cli
index d65cd62d17..b2e219e4c9 100644
--- a/examples/pipeline/examples/hash_func.cli
+++ b/examples/pipeline/examples/hash_func.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/hash_func.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/hash_func.spec /tmp/hash_func.c
+pipeline libbuild /tmp/hash_func.c /tmp/hash_func.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/hash_func.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/hash_func.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/l2fwd.cli b/examples/pipeline/examples/l2fwd.cli
index d89caf2d0a..27e37021b9 100644
--- a/examples/pipeline/examples/l2fwd.cli
+++ b/examples/pipeline/examples/l2fwd.cli
@@ -1,25 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/ethdev.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp.cli b/examples/pipeline/examples/l2fwd_macswp.cli
index 0f2a89ac5b..11bb4543b9 100644
--- a/examples/pipeline/examples/l2fwd_macswp.cli
+++ b/examples/pipeline/examples/l2fwd_macswp.cli
@@ -1,25 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_macswp.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/examples/ethdev.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_macswp_pcap.cli b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
index e9656fe3c2..8724dae3b0 100644
--- a/examples/pipeline/examples/l2fwd_macswp_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_macswp_pcap.cli
@@ -1,20 +1,31 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-pipeline PIPELINE0 create 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_macswp_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd_macswp.spec /tmp/l2fwd_macswp.c
+pipeline libbuild /tmp/l2fwd_macswp.c /tmp/l2fwd_macswp.so
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd_macswp.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd_macswp.so io ./examples/pipeline/examples/pcap.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/l2fwd_pcap.cli b/examples/pipeline/examples/l2fwd_pcap.cli
index 23fcb199f1..4db0a0dc56 100644
--- a/examples/pipeline/examples/l2fwd_pcap.cli
+++ b/examples/pipeline/examples/l2fwd_pcap.cli
@@ -1,20 +1,31 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-pipeline PIPELINE0 create 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/l2fwd_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/l2fwd.spec /tmp/l2fwd.c
+pipeline libbuild /tmp/l2fwd.c /tmp/l2fwd.so
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/l2fwd.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/l2fwd.so io ./examples/pipeline/examples/pcap.io numa 0
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/learner.cli b/examples/pipeline/examples/learner.cli
index 688ce34f34..6c8aa3921e 100644
--- a/examples/pipeline/examples/learner.cli
+++ b/examples/pipeline/examples/learner.cli
@@ -1,36 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/learner.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/learner.spec /tmp/learner.c
+pipeline libbuild /tmp/learner.c /tmp/learner.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/learner.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/learner.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
;
thread 1 pipeline PIPELINE0 enable
-
-; Once the application has started, the command to get the CLI prompt is: telnet 0.0.0.0 8086
diff --git a/examples/pipeline/examples/meter.cli b/examples/pipeline/examples/meter.cli
index b29ed24022..c1b88c882a 100644
--- a/examples/pipeline/examples/meter.cli
+++ b/examples/pipeline/examples/meter.cli
@@ -1,31 +1,43 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-; Example command line:
-; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
-
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/meter.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/meter.spec /tmp/meter.c
+pipeline libbuild /tmp/meter.c /tmp/meter.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/meter.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/meter.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 meter profile platinum add cir 46000000 pir 138000000 cbs 1000000 pbs 1000000
pipeline PIPELINE0 meter meters from 0 to 15 set profile platinum
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/mirroring.cli b/examples/pipeline/examples/mirroring.cli
index 46d57db4ec..1d439e04d3 100644
--- a/examples/pipeline/examples/mirroring.cli
+++ b/examples/pipeline/examples/mirroring.cli
@@ -1,36 +1,38 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/mirroring.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/mirroring.spec /tmp/mirroring.c
+pipeline libbuild /tmp/mirroring.c /tmp/mirroring.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-pipeline PIPELINE0 mirror slots 4 sessions 16
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/mirroring.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/mirroring.so io ./examples/pipeline/examples/ethdev.io numa 0
;
-; Packet mirroring sessions.
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
;
pipeline PIPELINE0 mirror session 0 port 1 clone fast truncate 0
pipeline PIPELINE0 mirror session 1 port 2 clone slow truncate 0
diff --git a/examples/pipeline/examples/pcap.io b/examples/pipeline/examples/pcap.io
new file mode 100644
index 0000000000..111f61afae
--- /dev/null
+++ b/examples/pipeline/examples/pcap.io
@@ -0,0 +1,27 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline packet mirroring.
+;
+mirroring slots 4 sessions 64
+
+;
+; Pipeline input ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 1 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 2 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+port in 3 source mempool MEMPOOL0 file ./examples/pipeline/examples/packet.pcap loop 1 packets 0
+
+;
+; Pipeline output ports.
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 sink file none
+port out 1 sink file none
+port out 2 sink file none
+port out 3 sink file none
diff --git a/examples/pipeline/examples/recirculation.cli b/examples/pipeline/examples/recirculation.cli
index f855c5c327..52d0894f12 100644
--- a/examples/pipeline/examples/recirculation.cli
+++ b/examples/pipeline/examples/recirculation.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2022 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/recirculation.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/recirculation.spec /tmp/recirculation.c
+pipeline libbuild /tmp/recirculation.c /tmp/recirculation.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/recirculation.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/recirculation.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/registers.cli b/examples/pipeline/examples/registers.cli
index 8d026294cb..3516f76a5b 100644
--- a/examples/pipeline/examples/registers.cli
+++ b/examples/pipeline/examples/registers.cli
@@ -1,28 +1,35 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-; Example command line:
-; ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
-
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/registers.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/registers.spec /tmp/registers.c
+pipeline libbuild /tmp/registers.c /tmp/registers.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/registers.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/registers.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/selector.cli b/examples/pipeline/examples/selector.cli
index 123782c57b..f0e251b657 100644
--- a/examples/pipeline/examples/selector.cli
+++ b/examples/pipeline/examples/selector.cli
@@ -1,30 +1,45 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/selector.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/selector.spec /tmp/selector.c
+pipeline libbuild /tmp/selector.c /tmp/selector.so
+
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
-
-pipeline PIPELINE0 build ./examples/pipeline/examples/selector.spec
-
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/selector.so io ./examples/pipeline/examples/ethdev.io numa 0
+
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 selector s group add
pipeline PIPELINE0 selector s group member add ./examples/pipeline/examples/selector.txt
pipeline PIPELINE0 commit
pipeline PIPELINE0 selector s show
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/varbit.cli b/examples/pipeline/examples/varbit.cli
index 9caeb9ca26..0f89990471 100644
--- a/examples/pipeline/examples/varbit.cli
+++ b/examples/pipeline/examples/varbit.cli
@@ -1,32 +1,33 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/varbit.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
+
;
-; Customize the LINK parameters to match your setup.
+; Pipeline code generation & shared object library build.
;
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+pipeline codegen ./examples/pipeline/examples/varbit.spec /tmp/varbit.c
+pipeline libbuild /tmp/varbit.c /tmp/varbit.so
;
-; PIPELINE0 setup.
+; List of DPDK devices.
;
-pipeline PIPELINE0 create 0
-
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
-
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 build ./examples/pipeline/examples/varbit.spec
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/varbit.so io ./examples/pipeline/examples/ethdev.io numa 0
;
; Pipelines-to-threads mapping.
diff --git a/examples/pipeline/examples/vxlan.cli b/examples/pipeline/examples/vxlan.cli
index 444f3f7bd8..1fbd1be6e4 100644
--- a/examples/pipeline/examples/vxlan.cli
+++ b/examples/pipeline/examples/vxlan.cli
@@ -1,27 +1,43 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-
-link LINK0 dev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK1 dev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK2 dev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-link LINK3 dev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/vxlan.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
-pipeline PIPELINE0 port in 0 link LINK0 rxq 0 bsz 32
-pipeline PIPELINE0 port in 1 link LINK1 rxq 0 bsz 32
-pipeline PIPELINE0 port in 2 link LINK2 rxq 0 bsz 32
-pipeline PIPELINE0 port in 3 link LINK3 rxq 0 bsz 32
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+ethdev 0000:18:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:18:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
+ethdev 0000:3b:00.1 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
-pipeline PIPELINE0 port out 0 link LINK0 txq 0 bsz 32
-pipeline PIPELINE0 port out 1 link LINK1 txq 0 bsz 32
-pipeline PIPELINE0 port out 2 link LINK2 txq 0 bsz 32
-pipeline PIPELINE0 port out 3 link LINK3 txq 0 bsz 32
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/vxlan.so io ./examples/pipeline/examples/ethdev.io numa 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
diff --git a/examples/pipeline/examples/vxlan_pcap.cli b/examples/pipeline/examples/vxlan_pcap.cli
index 83fca8d0d9..adc7f73312 100644
--- a/examples/pipeline/examples/vxlan_pcap.cli
+++ b/examples/pipeline/examples/vxlan_pcap.cli
@@ -1,22 +1,39 @@
; SPDX-License-Identifier: BSD-3-Clause
; Copyright(c) 2020 Intel Corporation
-mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
+# Example command line:
+# ./build/examples/dpdk-pipeline -l0-1 -- -s ./examples/pipeline/examples/vxlan_pcap.cli
+#
+# Once the application has started, the command to get the CLI prompt is:
+# telnet 0.0.0.0 8086
-pipeline PIPELINE0 create 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./examples/pipeline/examples/vxlan.spec /tmp/vxlan.c
+pipeline libbuild /tmp/vxlan.c /tmp/vxlan.so
-pipeline PIPELINE0 port in 0 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 1 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 2 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
-pipeline PIPELINE0 port in 3 source MEMPOOL0 ./examples/pipeline/examples/packet.pcap loop 1
+;
+; List of DPDK devices.
+;
+; Note: Customize the parameters below to match your setup.
+;
+mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0
-pipeline PIPELINE0 port out 0 sink none
-pipeline PIPELINE0 port out 1 sink none
-pipeline PIPELINE0 port out 2 sink none
-pipeline PIPELINE0 port out 3 sink none
+;
+; List of pipelines.
+;
+pipeline PIPELINE0 build lib /tmp/vxlan.so io ./examples/pipeline/examples/pcap.io numa 0
-pipeline PIPELINE0 build ./examples/pipeline/examples/vxlan.spec
+;
+; Initial set of table entries.
+;
+; The table entries can later be updated at run-time through the CLI commands.
+;
pipeline PIPELINE0 table vxlan_table add ./examples/pipeline/examples/vxlan_table.txt
pipeline PIPELINE0 commit
+;
+; Pipelines-to-threads mapping.
+;
thread 1 pipeline PIPELINE0 enable
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 01/17] pipeline: add pipeline name
2022-07-27 22:54 ` [PATCH V4 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (15 preceding siblings ...)
2022-07-27 22:54 ` [PATCH V4 17/17] examples/pipeline: call the code generation and build CLI commands Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
` (16 more replies)
16 siblings, 17 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add an unique name to every pipeline. This enables the library to
maintain a list of the existing pipeline objects, which can be
queried by the application.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/obj.c | 2 +-
lib/pipeline/rte_swx_ctl.c | 99 +++++++++++++++++++++
lib/pipeline/rte_swx_ctl.h | 15 ++++
lib/pipeline/rte_swx_pipeline.c | 107 ++++++++++++++++++++++-
lib/pipeline/rte_swx_pipeline.h | 18 +++-
lib/pipeline/rte_swx_pipeline_internal.h | 2 +
lib/pipeline/version.map | 4 +
7 files changed, 244 insertions(+), 3 deletions(-)
diff --git a/examples/pipeline/obj.c b/examples/pipeline/obj.c
index b79f044ac7..967342c580 100644
--- a/examples/pipeline/obj.c
+++ b/examples/pipeline/obj.c
@@ -533,7 +533,7 @@ pipeline_create(struct obj *obj, const char *name, int numa_node)
return NULL;
/* Resource create */
- status = rte_swx_pipeline_config(&p, numa_node);
+ status = rte_swx_pipeline_config(&p, name, numa_node);
if (status)
goto error;
diff --git a/lib/pipeline/rte_swx_ctl.c b/lib/pipeline/rte_swx_ctl.c
index 710e89a46a..1b776fc543 100644
--- a/lib/pipeline/rte_swx_ctl.c
+++ b/lib/pipeline/rte_swx_ctl.c
@@ -9,6 +9,8 @@
#include <rte_common.h>
#include <rte_byteorder.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_swx_table_selector.h>
@@ -1157,12 +1159,103 @@ table_state_create(struct rte_swx_ctl_pipeline *ctl)
return status;
}
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_ctl_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_ctl_pipeline_tailq = {
+ .name = "RTE_SWX_CTL_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_ctl_pipeline_tailq)
+
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_CTL_NAME_SIZE) >= RTE_SWX_CTL_NAME_SIZE))
+ return NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(name, ctl->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_read_unlock();
+ return ctl;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+ctl_register(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ struct rte_swx_ctl_pipeline *ctl_crt = (struct rte_swx_ctl_pipeline *)te->data;
+
+ if (!strncmp(ctl->info.name, ctl_crt->info.name, sizeof(ctl->info.name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)ctl;
+ TAILQ_INSERT_TAIL(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+ctl_unregister(struct rte_swx_ctl_pipeline *ctl)
+{
+ struct rte_swx_ctl_pipeline_list *ctl_list;
+ struct rte_tailq_entry *te = NULL;
+
+ ctl_list = RTE_TAILQ_CAST(rte_swx_ctl_pipeline_tailq.head, rte_swx_ctl_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, ctl_list, next) {
+ if (te->data == (void *)ctl) {
+ TAILQ_REMOVE(ctl_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_ctl_pipeline_free(struct rte_swx_ctl_pipeline *ctl)
{
if (!ctl)
return;
+ if (ctl->info.name[0])
+ ctl_unregister(ctl);
+
action_free(ctl);
table_state_free(ctl);
@@ -1441,6 +1534,12 @@ rte_swx_ctl_pipeline_create(struct rte_swx_pipeline *p)
if (status)
goto error;
+ if (ctl->info.name[0]) {
+ status = ctl_register(ctl);
+ if (status)
+ goto error;
+ }
+
return ctl;
error:
diff --git a/lib/pipeline/rte_swx_ctl.h b/lib/pipeline/rte_swx_ctl.h
index d771389d26..63ee479e47 100644
--- a/lib/pipeline/rte_swx_ctl.h
+++ b/lib/pipeline/rte_swx_ctl.h
@@ -35,6 +35,9 @@ struct rte_swx_pipeline;
/** Pipeline info. */
struct rte_swx_ctl_pipeline_info {
+ /** Pipeline name. */
+ char name[RTE_SWX_CTL_NAME_SIZE];
+
/** Number of input ports. */
uint32_t n_ports_in;
@@ -812,6 +815,18 @@ rte_swx_pipeline_table_state_set(struct rte_swx_pipeline *p,
/** Pipeline control opaque data structure. */
struct rte_swx_ctl_pipeline;
+/**
+ * Pipeline control find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline control handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_ctl_pipeline *
+rte_swx_ctl_pipeline_find(const char *name);
+
/**
* Pipeline control create
*
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 3e1c6e9edb..c8ccded4f8 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -6,6 +6,8 @@
#include <errno.h>
#include <dlfcn.h>
+#include <rte_tailq.h>
+#include <rte_eal_memconfig.h>
#include <rte_jhash.h>
#include <rte_hash_crc.h>
@@ -9578,6 +9580,95 @@ metarray_free(struct rte_swx_pipeline *p)
/*
* Pipeline.
*/
+
+/* Global list of pipeline instances. */
+TAILQ_HEAD(rte_swx_pipeline_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_swx_pipeline_tailq = {
+ .name = "RTE_SWX_PIPELINE",
+};
+
+EAL_REGISTER_TAILQ(rte_swx_pipeline_tailq)
+
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ if (!name || !name[0] || (strnlen(name, RTE_SWX_NAME_SIZE) >= RTE_SWX_NAME_SIZE))
+ return NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_read_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *p = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(name, p->name, sizeof(p->name))) {
+ rte_mcfg_tailq_read_unlock();
+ return p;
+ }
+ }
+
+ rte_mcfg_tailq_read_unlock();
+ return NULL;
+}
+
+static int
+pipeline_register(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ struct rte_swx_pipeline *pipeline = (struct rte_swx_pipeline *)te->data;
+
+ if (!strncmp(p->name, pipeline->name, sizeof(p->name))) {
+ rte_mcfg_tailq_write_unlock();
+ return -EEXIST;
+ }
+ }
+
+ te = calloc(1, sizeof(struct rte_tailq_entry));
+ if (!te) {
+ rte_mcfg_tailq_write_unlock();
+ return -ENOMEM;
+ }
+
+ te->data = (void *)p;
+ TAILQ_INSERT_TAIL(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ return 0;
+}
+
+static void
+pipeline_unregister(struct rte_swx_pipeline *p)
+{
+ struct rte_swx_pipeline_list *pipeline_list;
+ struct rte_tailq_entry *te = NULL;
+
+ pipeline_list = RTE_TAILQ_CAST(rte_swx_pipeline_tailq.head, rte_swx_pipeline_list);
+
+ rte_mcfg_tailq_write_lock();
+
+ TAILQ_FOREACH(te, pipeline_list, next) {
+ if (te->data == (void *)p) {
+ TAILQ_REMOVE(pipeline_list, te, next);
+ rte_mcfg_tailq_write_unlock();
+ free(te);
+ return;
+ }
+ }
+
+ rte_mcfg_tailq_write_unlock();
+}
+
void
rte_swx_pipeline_free(struct rte_swx_pipeline *p)
{
@@ -9586,6 +9677,9 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
if (!p)
return;
+ if (p->name[0])
+ pipeline_unregister(p);
+
lib = p->lib;
free(p->instruction_data);
@@ -9720,13 +9814,14 @@ hash_funcs_register(struct rte_swx_pipeline *p)
}
int
-rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
+rte_swx_pipeline_config(struct rte_swx_pipeline **p, const char *name, int numa_node)
{
struct rte_swx_pipeline *pipeline = NULL;
int status = 0;
/* Check input parameters. */
CHECK(p, EINVAL);
+ CHECK(!name || (strnlen(name, RTE_SWX_NAME_SIZE) < RTE_SWX_NAME_SIZE), EINVAL);
/* Memory allocation. */
pipeline = calloc(1, sizeof(struct rte_swx_pipeline));
@@ -9736,6 +9831,9 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
}
/* Initialization. */
+ if (name)
+ strcpy(pipeline->name, name);
+
TAILQ_INIT(&pipeline->struct_types);
TAILQ_INIT(&pipeline->port_in_types);
TAILQ_INIT(&pipeline->ports_in);
@@ -9776,6 +9874,12 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
if (status)
goto error;
+ if (pipeline->name[0]) {
+ status = pipeline_register(pipeline);
+ if (status)
+ goto error;
+ }
+
*p = pipeline;
return 0;
@@ -9966,6 +10070,7 @@ rte_swx_ctl_pipeline_info_get(struct rte_swx_pipeline *p,
TAILQ_FOREACH(table, &p->tables, node)
n_tables++;
+ strcpy(pipeline->name, p->name);
pipeline->n_ports_in = p->n_ports_in;
pipeline->n_ports_out = p->n_ports_out;
pipeline->n_mirroring_slots = p->n_mirroring_slots;
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index c41ca5cb15..ef50a0fa70 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -44,22 +44,38 @@ extern "C" {
/** Pipeline opaque data structure. */
struct rte_swx_pipeline;
+/**
+ * Pipeline find
+ *
+ * @param[in] name
+ * Pipeline name.
+ * @return
+ * Valid pipeline handle if found or NULL otherwise.
+ */
+__rte_experimental
+struct rte_swx_pipeline *
+rte_swx_pipeline_find(const char *name);
+
/**
* Pipeline configure
*
* @param[out] p
* Pipeline handle. Must point to valid memory. Contains valid pipeline handle
* when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
* @param[in] numa_node
* Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
- * -ENOMEM: Not enough space/cannot allocate memory.
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Pipeline with this name already exists.
*/
__rte_experimental
int
rte_swx_pipeline_config(struct rte_swx_pipeline **p,
+ const char *name,
int numa_node);
/*
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index a35635efb7..588cad62b5 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -1459,6 +1459,8 @@ instr_operand_nbo(struct thread *t, const struct instr_operand *x)
#endif
struct rte_swx_pipeline {
+ char name[RTE_SWX_NAME_SIZE];
+
struct struct_type_tailq struct_types;
struct port_in_type_tailq port_in_types;
struct port_in_tailq ports_in;
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8312307a7a..50029aadcf 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -145,4 +145,8 @@ EXPERIMENTAL {
rte_swx_ctl_pipeline_learner_timeout_get;
rte_swx_ctl_pipeline_learner_timeout_set;
rte_swx_pipeline_hash_func_register;
+
+ #added in 22.11
+ rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 02/17] pipeline: move specification data structures to internal header
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
` (15 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Move all the pipeline object specification data structures to an
internal header file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 126 +------------------
lib/pipeline/rte_swx_pipeline_spec.h | 176 +++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 125 deletions(-)
create mode 100644 lib/pipeline/rte_swx_pipeline_spec.h
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 904b9eb471..5e07b4f794 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,7 +9,7 @@
#include <rte_common.h>
-#include "rte_swx_pipeline.h"
+#include "rte_swx_pipeline_spec.h"
#ifndef MAX_LINE_LENGTH
#define MAX_LINE_LENGTH 2048
@@ -34,15 +34,7 @@
/*
* extobj.
- *
- * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
*/
-struct extobj_spec {
- char *name;
- char *extern_type_name;
- char *pragma;
-};
-
static void
extobj_spec_free(struct extobj_spec *s)
{
@@ -104,18 +96,7 @@ extobj_statement_parse(struct extobj_spec *s,
/*
* struct.
*
- * struct STRUCT_TYPE_NAME {
- * bit<SIZE> | varbit<SIZE> FIELD_NAME
- * ...
- * }
*/
-struct struct_spec {
- char *name;
- struct rte_swx_field_params *fields;
- uint32_t n_fields;
- int varbit;
-};
-
static void
struct_spec_free(struct struct_spec *s)
{
@@ -293,13 +274,7 @@ struct_block_parse(struct struct_spec *s,
/*
* header.
*
- * header HEADER_NAME instanceof STRUCT_TYPE_NAME
*/
-struct header_spec {
- char *name;
- char *struct_type_name;
-};
-
static void
header_spec_free(struct header_spec *s)
{
@@ -351,12 +326,7 @@ header_statement_parse(struct header_spec *s,
/*
* metadata.
*
- * metadata instanceof STRUCT_TYPE_NAME
*/
-struct metadata_spec {
- char *struct_type_name;
-};
-
static void
metadata_spec_free(struct metadata_spec *s)
{
@@ -400,18 +370,7 @@ metadata_statement_parse(struct metadata_spec *s,
/*
* action.
*
- * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
- * INSTRUCTION
- * ...
- * }
*/
-struct action_spec {
- char *name;
- char *args_struct_type_name;
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
action_spec_free(struct action_spec *s)
{
@@ -540,29 +499,7 @@ action_block_parse(struct action_spec *s,
/*
* table.
*
- * table TABLE_NAME {
- * key {
- * MATCH_FIELD_NAME exact | wildcard | lpm
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly ]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * instanceof TABLE_TYPE_NAME
- * pragma ARGS
- * size SIZE
- * }
*/
-struct table_spec {
- char *name;
- struct rte_swx_pipeline_table_params params;
- char *recommended_table_type_name;
- char *args;
- uint32_t size;
-};
-
static void
table_spec_free(struct table_spec *s)
{
@@ -1084,22 +1021,7 @@ table_block_parse(struct table_spec *s,
/*
* selector.
*
- * selector SELECTOR_NAME {
- * group_id FIELD_NAME
- * selector {
- * FIELD_NAME
- * ...
- * }
- * member_id FIELD_NAME
- * n_groups N_GROUPS
- * n_members_per_group N_MEMBERS_PER_GROUP
- * }
*/
-struct selector_spec {
- char *name;
- struct rte_swx_pipeline_selector_params params;
-};
-
static void
selector_spec_free(struct selector_spec *s)
{
@@ -1385,31 +1307,7 @@ selector_block_parse(struct selector_spec *s,
/*
* learner.
*
- * learner LEARNER_NAME {
- * key {
- * MATCH_FIELD_NAME
- * ...
- * }
- * actions {
- * ACTION_NAME [ @tableonly | @defaultonly]
- * ...
- * }
- * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
- * size SIZE
- * timeout {
- * TIMEOUT_IN_SECONDS
- * ...
- * }
- * }
*/
-struct learner_spec {
- char *name;
- struct rte_swx_pipeline_learner_params params;
- uint32_t size;
- uint32_t *timeout;
- uint32_t n_timeouts;
-};
-
static void
learner_spec_free(struct learner_spec *s)
{
@@ -1958,14 +1856,7 @@ learner_block_parse(struct learner_spec *s,
/*
* regarray.
*
- * regarray NAME size SIZE initval INITVAL
*/
-struct regarray_spec {
- char *name;
- uint64_t init_val;
- uint32_t size;
-};
-
static void
regarray_spec_free(struct regarray_spec *s)
{
@@ -2033,13 +1924,7 @@ regarray_statement_parse(struct regarray_spec *s,
/*
* metarray.
*
- * metarray NAME size SIZE
*/
-struct metarray_spec {
- char *name;
- uint32_t size;
-};
-
static void
metarray_spec_free(struct metarray_spec *s)
{
@@ -2095,16 +1980,7 @@ metarray_statement_parse(struct metarray_spec *s,
/*
* apply.
*
- * apply {
- * INSTRUCTION
- * ...
- * }
*/
-struct apply_spec {
- const char **instructions;
- uint32_t n_instructions;
-};
-
static void
apply_spec_free(struct apply_spec *s)
{
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
new file mode 100644
index 0000000000..8458de878a
--- /dev/null
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+
+#include <rte_swx_pipeline.h>
+
+/*
+ * extobj.
+ *
+ * extobj OBJ_NAME instanceof OBJ_TYPE [ pragma OBJ_CREATE_ARGS ]
+ */
+struct extobj_spec {
+ char *name;
+ char *extern_type_name;
+ char *pragma;
+};
+
+/*
+ * struct.
+ *
+ * struct STRUCT_TYPE_NAME {
+ * bit<SIZE> | varbit<SIZE> FIELD_NAME
+ * ...
+ * }
+ */
+struct struct_spec {
+ char *name;
+ struct rte_swx_field_params *fields;
+ uint32_t n_fields;
+ int varbit;
+};
+
+/*
+ * header.
+ *
+ * header HEADER_NAME instanceof STRUCT_TYPE_NAME
+ */
+struct header_spec {
+ char *name;
+ char *struct_type_name;
+};
+
+/*
+ * metadata.
+ *
+ * metadata instanceof STRUCT_TYPE_NAME
+ */
+struct metadata_spec {
+ char *struct_type_name;
+};
+
+/*
+ * action.
+ *
+ * action ACTION_NAME args none | instanceof STRUCT_TYPE_NAME {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct action_spec {
+ char *name;
+ char *args_struct_type_name;
+ const char **instructions;
+ uint32_t n_instructions;
+};
+
+/*
+ * table.
+ *
+ * table TABLE_NAME {
+ * key {
+ * MATCH_FIELD_NAME exact | wildcard | lpm
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly ]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * instanceof TABLE_TYPE_NAME
+ * pragma ARGS
+ * size SIZE
+ * }
+ */
+struct table_spec {
+ char *name;
+ struct rte_swx_pipeline_table_params params;
+ char *recommended_table_type_name;
+ char *args;
+ uint32_t size;
+};
+
+/*
+ * selector.
+ *
+ * selector SELECTOR_NAME {
+ * group_id FIELD_NAME
+ * selector {
+ * FIELD_NAME
+ * ...
+ * }
+ * member_id FIELD_NAME
+ * n_groups N_GROUPS
+ * n_members_per_group N_MEMBERS_PER_GROUP
+ * }
+ */
+struct selector_spec {
+ char *name;
+ struct rte_swx_pipeline_selector_params params;
+};
+
+/*
+ * learner.
+ *
+ * learner LEARNER_NAME {
+ * key {
+ * MATCH_FIELD_NAME
+ * ...
+ * }
+ * actions {
+ * ACTION_NAME [ @tableonly | @defaultonly]
+ * ...
+ * }
+ * default_action ACTION_NAME args none | ARG0_NAME ARG0_VALUE ... [ const ]
+ * size SIZE
+ * timeout {
+ * TIMEOUT_IN_SECONDS
+ * ...
+ * }
+ * }
+ */
+struct learner_spec {
+ char *name;
+ struct rte_swx_pipeline_learner_params params;
+ uint32_t size;
+ uint32_t *timeout;
+ uint32_t n_timeouts;
+};
+
+/*
+ * regarray.
+ *
+ * regarray NAME size SIZE initval INITVAL
+ */
+struct regarray_spec {
+ char *name;
+ uint64_t init_val;
+ uint32_t size;
+};
+
+/*
+ * metarray.
+ *
+ * metarray NAME size SIZE
+ */
+struct metarray_spec {
+ char *name;
+ uint32_t size;
+};
+
+/*
+ * apply.
+ *
+ * apply {
+ * INSTRUCTION
+ * ...
+ * }
+ */
+struct apply_spec {
+ const char **instructions;
+ uint32_t n_instructions;
+};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 03/17] pipeline: add pipeline specification data structure
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
` (14 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure for the entire pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 21 ++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 32 ++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 5e07b4f794..642091b678 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2082,6 +2082,27 @@ apply_block_parse(struct apply_spec *s,
/*
* Pipeline.
*/
+void
+pipeline_spec_free(struct pipeline_spec *s)
+{
+ if (!s)
+ return;
+
+ free(s->extobjs);
+ free(s->structs);
+ free(s->headers);
+ free(s->metadata);
+ free(s->actions);
+ free(s->tables);
+ free(s->selectors);
+ free(s->learners);
+ free(s->regarrays);
+ free(s->metarrays);
+ free(s->apply);
+
+ memset(s, 0, sizeof(struct pipeline_spec));
+}
+
int
rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
FILE *spec,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 8458de878a..e1170a33b1 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -174,3 +174,35 @@ struct apply_spec {
const char **instructions;
uint32_t n_instructions;
};
+
+/*
+ * Pipeline.
+ */
+struct pipeline_spec {
+ struct extobj_spec *extobjs;
+ struct struct_spec *structs;
+ struct header_spec *headers;
+ struct metadata_spec *metadata;
+ struct action_spec *actions;
+ struct table_spec *tables;
+ struct selector_spec *selectors;
+ struct learner_spec *learners;
+ struct regarray_spec *regarrays;
+ struct metarray_spec *metarrays;
+ struct apply_spec *apply;
+
+ uint32_t n_extobjs;
+ uint32_t n_structs;
+ uint32_t n_headers;
+ uint32_t n_metadata;
+ uint32_t n_actions;
+ uint32_t n_tables;
+ uint32_t n_selectors;
+ uint32_t n_learners;
+ uint32_t n_regarrays;
+ uint32_t n_metarrays;
+ uint32_t n_apply;
+};
+
+void
+pipeline_spec_free(struct pipeline_spec *s);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 04/17] pipeline: rework the specification file-based pipeline build
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 02/17] pipeline: move specification data structures to internal header Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 03/17] pipeline: add pipeline specification data structure Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
` (13 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Rework the specification file-based pipeline build operation to first
parse the specification file into the previously introduced pipeline
specification data structure, then use this structure to configure
and build the pipeline.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 478 +++++++++++++++++++++------
lib/pipeline/rte_swx_pipeline_spec.h | 9 +
2 files changed, 385 insertions(+), 102 deletions(-)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 642091b678..62929a9da6 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2103,11 +2103,10 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg)
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
{
struct extobj_spec extobj_spec = {0};
struct struct_spec struct_spec = {0};
@@ -2120,26 +2119,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
struct regarray_spec regarray_spec = {0};
struct metarray_spec metarray_spec = {0};
struct apply_spec apply_spec = {0};
- uint32_t n_lines;
+ struct pipeline_spec *s = NULL;
+ uint32_t n_lines = 0;
uint32_t block_mask = 0;
- int status;
+ int status = 0;
/* Check the input arguments. */
- if (!p) {
+ if (!spec) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null pipeline argument.";
+ *err_msg = "Invalid input argument.";
status = -EINVAL;
goto error;
}
- if (!spec) {
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_spec), 1);
+ if (!s) {
if (err_line)
- *err_line = 0;
+ *err_line = n_lines;
if (err_msg)
- *err_msg = "Null specification file argument.";
- status = -EINVAL;
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
@@ -2200,6 +2202,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* struct block. */
if (block_mask & (1 << STRUCT_BLOCK)) {
+ struct struct_spec *new_structs;
+
status = struct_block_parse(&struct_spec,
&block_mask,
tokens,
@@ -2214,26 +2218,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_struct_type_register(p,
- struct_spec.name,
- struct_spec.fields,
- struct_spec.n_fields,
- struct_spec.varbit);
- if (status) {
+ new_structs = realloc(s->structs,
+ (s->n_structs + 1) * sizeof(struct struct_spec));
+ if (!new_structs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Struct registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- struct_spec_free(&struct_spec);
+ s->structs = new_structs;
+ memcpy(&s->structs[s->n_structs], &struct_spec, sizeof(struct struct_spec));
+ s->n_structs++;
+ memset(&struct_spec, 0, sizeof(struct struct_spec));
continue;
}
/* action block. */
if (block_mask & (1 << ACTION_BLOCK)) {
+ struct action_spec *new_actions;
+
status = action_block_parse(&action_spec,
&block_mask,
tokens,
@@ -2248,26 +2255,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_action_config(p,
- action_spec.name,
- action_spec.args_struct_type_name,
- action_spec.instructions,
- action_spec.n_instructions);
- if (status) {
+ new_actions = realloc(s->actions,
+ (s->n_actions + 1) * sizeof(struct action_spec));
+ if (!new_actions) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Action config error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- action_spec_free(&action_spec);
+ s->actions = new_actions;
+ memcpy(&s->actions[s->n_actions], &action_spec, sizeof(struct action_spec));
+ s->n_actions++;
+ memset(&action_spec, 0, sizeof(struct action_spec));
continue;
}
/* table block. */
if (block_mask & (1 << TABLE_BLOCK)) {
+ struct table_spec *new_tables;
+
status = table_block_parse(&table_spec,
&block_mask,
tokens,
@@ -2282,27 +2292,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_table_config(p,
- table_spec.name,
- &table_spec.params,
- table_spec.recommended_table_type_name,
- table_spec.args,
- table_spec.size);
- if (status) {
+ new_tables = realloc(s->tables,
+ (s->n_tables + 1) * sizeof(struct table_spec));
+ if (!new_tables) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- table_spec_free(&table_spec);
+ s->tables = new_tables;
+ memcpy(&s->tables[s->n_tables], &table_spec, sizeof(struct table_spec));
+ s->n_tables++;
+ memset(&table_spec, 0, sizeof(struct table_spec));
continue;
}
/* selector block. */
if (block_mask & (1 << SELECTOR_BLOCK)) {
+ struct selector_spec *new_selectors;
+
status = selector_block_parse(&selector_spec,
&block_mask,
tokens,
@@ -2317,24 +2329,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_selector_config(p,
- selector_spec.name,
- &selector_spec.params);
- if (status) {
+ new_selectors = realloc(s->selectors,
+ (s->n_selectors + 1) * sizeof(struct selector_spec));
+ if (!new_selectors) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Selector configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- selector_spec_free(&selector_spec);
+ s->selectors = new_selectors;
+ memcpy(&s->selectors[s->n_selectors],
+ &selector_spec,
+ sizeof(struct selector_spec));
+ s->n_selectors++;
+ memset(&selector_spec, 0, sizeof(struct selector_spec));
continue;
}
/* learner block. */
if (block_mask & (1 << LEARNER_BLOCK)) {
+ struct learner_spec *new_learners;
+
status = learner_block_parse(&learner_spec,
&block_mask,
tokens,
@@ -2349,27 +2368,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_learner_config(p,
- learner_spec.name,
- &learner_spec.params,
- learner_spec.size,
- learner_spec.timeout,
- learner_spec.n_timeouts);
- if (status) {
+ new_learners = realloc(s->learners,
+ (s->n_learners + 1) * sizeof(struct learner_spec));
+ if (!new_learners) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Learner table configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- learner_spec_free(&learner_spec);
+ s->learners = new_learners;
+ memcpy(&s->learners[s->n_learners],
+ &learner_spec,
+ sizeof(struct learner_spec));
+ s->n_learners++;
+ memset(&learner_spec, 0, sizeof(struct learner_spec));
continue;
}
/* apply block. */
if (block_mask & (1 << APPLY_BLOCK)) {
+ struct apply_spec *new_apply;
+
status = apply_block_parse(&apply_spec,
&block_mask,
tokens,
@@ -2384,24 +2407,28 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
continue;
/* End of block. */
- status = rte_swx_pipeline_instructions_config(p,
- apply_spec.instructions,
- apply_spec.n_instructions);
- if (status) {
+ new_apply = realloc(s->apply, (s->n_apply + 1) * sizeof(struct apply_spec));
+ if (!new_apply) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Pipeline instructions err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- apply_spec_free(&apply_spec);
+ s->apply = new_apply;
+ memcpy(&s->apply[s->n_apply], &apply_spec, sizeof(struct apply_spec));
+ s->n_apply++;
+ memset(&apply_spec, 0, sizeof(struct apply_spec));
continue;
}
/* extobj. */
if (!strcmp(tokens[0], "extobj")) {
+ struct extobj_spec *new_extobjs;
+
status = extobj_statement_parse(&extobj_spec,
tokens,
n_tokens,
@@ -2411,19 +2438,21 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_extern_object_config(p,
- extobj_spec.name,
- extobj_spec.extern_type_name,
- extobj_spec.pragma);
- if (status) {
+ new_extobjs = realloc(s->extobjs,
+ (s->n_extobjs + 1) * sizeof(struct extobj_spec));
+ if (!new_extobjs) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Extern object config err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- extobj_spec_free(&extobj_spec);
+ s->extobjs = new_extobjs;
+ memcpy(&s->extobjs[s->n_extobjs], &extobj_spec, sizeof(struct extobj_spec));
+ s->n_extobjs++;
+ memset(&extobj_spec, 0, sizeof(struct extobj_spec));
continue;
}
@@ -2445,6 +2474,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* header. */
if (!strcmp(tokens[0], "header")) {
+ struct header_spec *new_headers;
+
status = header_statement_parse(&header_spec,
tokens,
n_tokens,
@@ -2454,24 +2485,29 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_header_register(p,
- header_spec.name,
- header_spec.struct_type_name);
- if (status) {
+ new_headers = realloc(s->headers,
+ (s->n_headers + 1) * sizeof(struct header_spec));
+ if (!new_headers) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Header registration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- header_spec_free(&header_spec);
+ s->headers = new_headers;
+ memcpy(&s->headers[s->n_headers], &header_spec, sizeof(struct header_spec));
+ s->n_headers++;
+ memset(&header_spec, 0, sizeof(struct header_spec));
continue;
}
/* metadata. */
if (!strcmp(tokens[0], "metadata")) {
+ struct metadata_spec *new_metadata;
+
status = metadata_statement_parse(&metadata_spec,
tokens,
n_tokens,
@@ -2481,17 +2517,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_packet_metadata_register(p,
- metadata_spec.struct_type_name);
- if (status) {
+ new_metadata = realloc(s->metadata,
+ (s->n_metadata + 1) * sizeof(struct metadata_spec));
+ if (!new_metadata) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meta-data reg err.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metadata_spec_free(&metadata_spec);
+ s->metadata = new_metadata;
+ memcpy(&s->metadata[s->n_metadata],
+ &metadata_spec,
+ sizeof(struct metadata_spec));
+ s->n_metadata++;
+ memset(&metadata_spec, 0, sizeof(struct metadata_spec));
continue;
}
@@ -2558,6 +2600,8 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
/* regarray. */
if (!strcmp(tokens[0], "regarray")) {
+ struct regarray_spec *new_regarrays;
+
status = regarray_statement_parse(®array_spec,
tokens,
n_tokens,
@@ -2567,25 +2611,31 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_regarray_config(p,
- regarray_spec.name,
- regarray_spec.size,
- regarray_spec.init_val);
- if (status) {
+ new_regarrays = realloc(s->regarrays,
+ (s->n_regarrays + 1) * sizeof(struct regarray_spec));
+ if (!new_regarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Register array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- regarray_spec_free(®array_spec);
+ s->regarrays = new_regarrays;
+ memcpy(&s->regarrays[s->n_regarrays],
+ ®array_spec,
+ sizeof(struct regarray_spec));
+ s->n_regarrays++;
+ memset(®array_spec, 0, sizeof(struct regarray_spec));
continue;
}
/* metarray. */
if (!strcmp(tokens[0], "metarray")) {
+ struct metarray_spec *new_metarrays;
+
status = metarray_statement_parse(&metarray_spec,
tokens,
n_tokens,
@@ -2595,18 +2645,23 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
if (status)
goto error;
- status = rte_swx_pipeline_metarray_config(p,
- metarray_spec.name,
- metarray_spec.size);
- if (status) {
+ new_metarrays = realloc(s->metarrays,
+ (s->n_metarrays + 1) * sizeof(struct metarray_spec));
+ if (!new_metarrays) {
if (err_line)
*err_line = n_lines;
if (err_msg)
- *err_msg = "Meter array configuration error.";
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
goto error;
}
- metarray_spec_free(&metarray_spec);
+ s->metarrays = new_metarrays;
+ memcpy(&s->metarrays[s->n_metarrays],
+ &metarray_spec,
+ sizeof(struct metarray_spec));
+ s->n_metarrays++;
+ memset(&metarray_spec, 0, sizeof(struct metarray_spec));
continue;
}
@@ -2644,17 +2699,7 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
goto error;
}
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = n_lines;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
+ return s;
error:
extobj_spec_free(&extobj_spec);
@@ -2668,5 +2713,234 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
regarray_spec_free(®array_spec);
metarray_spec_free(&metarray_spec);
apply_spec_free(&apply_spec);
+ pipeline_spec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* extobj. */
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ status = rte_swx_pipeline_extern_object_config(p,
+ extobj_spec->name,
+ extobj_spec->extern_type_name,
+ extobj_spec->pragma);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Extern object configuration error.";
+ return status;
+ }
+ }
+
+ /* regarray. */
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ status = rte_swx_pipeline_regarray_config(p,
+ regarray_spec->name,
+ regarray_spec->size,
+ regarray_spec->init_val);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Register array configuration error.";
+ return status;
+ }
+ }
+
+ /* metarray. */
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ status = rte_swx_pipeline_metarray_config(p,
+ metarray_spec->name,
+ metarray_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meter array configuration error.";
+ return status;
+ }
+ }
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ status = rte_swx_pipeline_struct_type_register(p,
+ struct_spec->name,
+ struct_spec->fields,
+ struct_spec->n_fields,
+ struct_spec->varbit);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Struct type registration error.";
+ return status;
+ }
+ }
+
+ /* header. */
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ status = rte_swx_pipeline_packet_header_register(p,
+ header_spec->name,
+ header_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Header configuration error.";
+ return status;
+ }
+ }
+
+ /* metadata. */
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ status = rte_swx_pipeline_packet_metadata_register(p,
+ metadata_spec->struct_type_name);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Meta-data registration error.";
+ return status;
+ }
+ }
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ status = rte_swx_pipeline_action_config(p,
+ action_spec->name,
+ action_spec->args_struct_type_name,
+ action_spec->instructions,
+ action_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Action configuration error.";
+ return status;
+ }
+ }
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ status = rte_swx_pipeline_table_config(p,
+ table_spec->name,
+ &table_spec->params,
+ table_spec->recommended_table_type_name,
+ table_spec->args,
+ table_spec->size);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Table configuration error.";
+ return status;
+ }
+ }
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ status = rte_swx_pipeline_selector_config(p,
+ selector_spec->name,
+ &selector_spec->params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Selector table configuration error.";
+ return status;
+ }
+ }
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ status = rte_swx_pipeline_learner_config(p,
+ learner_spec->name,
+ &learner_spec->params,
+ learner_spec->size,
+ learner_spec->timeout,
+ learner_spec->n_timeouts);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Learner table configuration error.";
+ return status;
+ }
+ }
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+
+ status = rte_swx_pipeline_instructions_config(p,
+ apply_spec->instructions,
+ apply_spec->n_instructions);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline instructions configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
+
+int
+rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
+ FILE *spec_file,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_spec *s = NULL;
+ int status = 0;
+
+ /* Check the input arguments. */
+ if (!p || !spec_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Spec file parse. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* Pipeline configure. */
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto error;
+ }
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline build error.";
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pipeline_spec_free(s);
return status;
}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index e1170a33b1..4f3a0b5958 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,3 +206,12 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+struct pipeline_spec *
+pipeline_spec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_spec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_spec *s,
+ const char **err_msg);
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 05/17] pipeline: generate the code for pipeline specification structure
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (2 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 04/17] pipeline: rework the specification file-based pipeline build Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
` (12 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add support to export the pipeline specification data structure to a C
source code file.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 622 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 5 +
2 files changed, 627 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index 62929a9da6..bf21fe17ba 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -2,6 +2,7 @@
* Copyright(c) 2020 Intel Corporation
*/
#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -2103,6 +2104,627 @@ pipeline_spec_free(struct pipeline_spec *s)
memset(s, 0, sizeof(struct pipeline_spec));
}
+static const char *
+match_type_string_get(enum rte_swx_table_match_type match_type)
+{
+ switch (match_type) {
+ case RTE_SWX_TABLE_MATCH_WILDCARD: return "RTE_SWX_TABLE_MATCH_WILDCARD";
+ case RTE_SWX_TABLE_MATCH_LPM: return "RTE_SWX_TABLE_MATCH_LPM";
+ case RTE_SWX_TABLE_MATCH_EXACT: return "RTE_SWX_TABLE_MATCH_EXACT";
+ default: return "RTE_SWX_TABLE_MATCH_UNKNOWN";
+ }
+}
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s)
+{
+ uint32_t i;
+
+ /* Check the input arguments. */
+ if (!f || !s)
+ return;
+
+ /* extobj. */
+ fprintf(f, "static struct extobj_spec extobjs[] = {\n");
+
+ for (i = 0; i < s->n_extobjs; i++) {
+ struct extobj_spec *extobj_spec = &s->extobjs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", extobj_spec->name);
+ fprintf(f, "\t\t.extern_type_name = \"%s\",\n", extobj_spec->extern_type_name);
+ if (extobj_spec->pragma)
+ fprintf(f, "\t\t.pragma = \"%s\",\n", extobj_spec->pragma);
+ else
+ fprintf(f, "\t\t.pragma = NULL,\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* regarray. */
+ fprintf(f, "static struct regarray_spec regarrays[] = {\n");
+
+ for (i = 0; i < s->n_regarrays; i++) {
+ struct regarray_spec *regarray_spec = &s->regarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", regarray_spec->name);
+ fprintf(f, "\t\t.init_val = %" PRIu64 ",\n", regarray_spec->init_val);
+ fprintf(f, "\t\t.size = %u,\n", regarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metarray. */
+ fprintf(f, "static struct metarray_spec metarrays[] = {\n");
+
+ for (i = 0; i < s->n_metarrays; i++) {
+ struct metarray_spec *metarray_spec = &s->metarrays[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", metarray_spec->name);
+ fprintf(f, "\t\t.size = %u,\n", metarray_spec->size);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* struct. */
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+ uint32_t j;
+
+ fprintf(f, "static struct rte_swx_field_params struct_%s_fields[] = {\n",
+ struct_spec->name);
+
+ for (j = 0; j < struct_spec->n_fields; j++) {
+ struct rte_swx_field_params *field = &struct_spec->fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.n_bits = %u,\n", field->n_bits);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct struct_spec structs[] = {\n");
+
+ for (i = 0; i < s->n_structs; i++) {
+ struct struct_spec *struct_spec = &s->structs[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", struct_spec->name);
+ fprintf(f, "\t\t.fields = struct_%s_fields,\n", struct_spec->name);
+ fprintf(f, "\t\t.n_fields = "
+ "sizeof(struct_%s_fields) / sizeof(struct_%s_fields[0]),\n",
+ struct_spec->name,
+ struct_spec->name);
+ fprintf(f, "\t\t.varbit = %d,\n", struct_spec->varbit);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* header. */
+ fprintf(f, "static struct header_spec headers[] = {\n");
+
+ for (i = 0; i < s->n_headers; i++) {
+ struct header_spec *header_spec = &s->headers[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", header_spec->name);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", header_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* metadata. */
+ fprintf(f, "static struct metadata_spec metadata[] = {\n");
+
+ for (i = 0; i < s->n_metadata; i++) {
+ struct metadata_spec *metadata_spec = &s->metadata[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.struct_type_name = \"%s\",\n", metadata_spec->struct_type_name);
+ fprintf(f, "\t},\n");
+
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* action. */
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *action_%s_initial_instructions[] = {\n",
+ action_spec->name);
+
+ for (j = 0; j < action_spec->n_instructions; j++) {
+ const char *instr = action_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct action_spec actions[] = {\n");
+
+ for (i = 0; i < s->n_actions; i++) {
+ struct action_spec *action_spec = &s->actions[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", action_spec->name);
+
+ if (action_spec->args_struct_type_name)
+ fprintf(f, "\t\t.args_struct_type_name = \"%s\",\n",
+ action_spec->args_struct_type_name);
+ else
+ fprintf(f, "\t\t.args_struct_type_name = NULL,\n");
+
+ fprintf(f, "\t\t.instructions = action_%s_initial_instructions,\n",
+ action_spec->name);
+ fprintf(f, "\t\t.n_instructions = "
+ "sizeof(action_%s_initial_instructions) / "
+ "sizeof(action_%s_initial_instructions[0]),\n",
+ action_spec->name,
+ action_spec->name);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* table. */
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+ uint32_t j;
+
+ /* fields. */
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "static struct rte_swx_match_field_params "
+ "table_%s_fields[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_fields; j++) {
+ struct rte_swx_match_field_params *field =
+ &table_spec->params.fields[j];
+
+ fprintf(f, "\t[%d] = {\n", j);
+ fprintf(f, "\t\t.name = \"%s\",\n", field->name);
+ fprintf(f, "\t\t.match_type = %s,\n",
+ match_type_string_get(field->match_type));
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (table_spec->params.action_names && table_spec->params.n_actions) {
+ fprintf(f, "static const char *table_%s_action_names[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ const char *action_name = table_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (table_spec->params.action_is_for_table_entries &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_table_entries[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (table_spec->params.action_is_for_default_entry &&
+ table_spec->params.n_actions) {
+ fprintf(f, "static int table_%s_action_is_for_default_entry[] = {\n",
+ table_spec->name);
+
+ for (j = 0; j < table_spec->params.n_actions; j++) {
+ int value = table_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct table_spec tables[] = {\n");
+
+ for (i = 0; i < s->n_tables; i++) {
+ struct table_spec *table_spec = &s->tables[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", table_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (table_spec->params.fields && table_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.fields = table_%s_fields,\n", table_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(table_%s_fields) / sizeof(table_%s_fields[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.fields = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (table_spec->params.action_names && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = table_%s_action_names,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (table_spec->params.action_is_for_table_entries && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "table_%s_action_is_for_table_entries,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (table_spec->params.action_is_for_default_entry && table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "table_%s_action_is_for_default_entry,\n",
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (table_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = sizeof(table_%s_action_names) / "
+ "sizeof(table_%s_action_names[0]),\n",
+ table_spec->name,
+ table_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = 0,\n");
+
+ if (table_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ table_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (table_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ table_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ table_spec->params.default_action_is_const);
+ fprintf(f, "\t\t},\n");
+
+ if (table_spec->recommended_table_type_name)
+ fprintf(f, "\t\t.recommended_table_type_name = \"%s\",\n",
+ table_spec->recommended_table_type_name);
+ else
+ fprintf(f, "\t\t.recommended_table_type_name = NULL,\n");
+
+ if (table_spec->args)
+ fprintf(f, "\t\t.args = \"%s\",\n", table_spec->args);
+ else
+ fprintf(f, "\t\t.args = NULL,\n");
+
+ fprintf(f, "\t\t.size = %u,\n", table_spec->size);
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* selector. */
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+ uint32_t j;
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "static const char *selector_%s_field_names[] = {\n",
+ selector_spec->name);
+
+ for (j = 0; j < selector_spec->params.n_selector_fields; j++) {
+ const char *field_name =
+ selector_spec->params.selector_field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct selector_spec selectors[] = {\n");
+
+ for (i = 0; i < s->n_selectors; i++) {
+ struct selector_spec *selector_spec = &s->selectors[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+
+ fprintf(f, "\t\t.name = \"%s\",\n", selector_spec->name);
+ fprintf(f, "\t\t.params = {\n");
+
+ if (selector_spec->params.group_id_field_name)
+ fprintf(f, "\t\t\t.group_id_field_name = \"%s\",\n",
+ selector_spec->params.group_id_field_name);
+ else
+ fprintf(f, "\t\t\t.group_id_field_name = NULL,\n");
+
+ if (selector_spec->params.selector_field_names &&
+ selector_spec->params.n_selector_fields) {
+ fprintf(f, "\t\t\t.selector_field_names = selector_%s_field_names,\n",
+ selector_spec->name);
+ fprintf(f, "\t\t\t.n_selector_fields = "
+ "sizeof(selector_%s_field_names) / sizeof(selector_%s_field_names[0]),\n",
+ selector_spec->name,
+ selector_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.selector_field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_selector_fields = 0,\n");
+ }
+
+ if (selector_spec->params.member_id_field_name)
+ fprintf(f, "\t\t\t.member_id_field_name = \"%s\",\n",
+ selector_spec->params.member_id_field_name);
+ else
+ fprintf(f, "\t\t\t.member_id_field_name = NULL,\n");
+
+ fprintf(f, "\t\t\t.n_groups_max = %u,\n", selector_spec->params.n_groups_max);
+
+ fprintf(f, "\t\t\t.n_members_per_group_max = %u,\n",
+ selector_spec->params.n_members_per_group_max);
+
+ fprintf(f, "\t\t},\n");
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* learner. */
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+ uint32_t j;
+
+ /* field_names. */
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "static const char *learner_%s_field_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_fields; j++) {
+ const char *field_name = learner_spec->params.field_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, field_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_names. */
+ if (learner_spec->params.action_names && learner_spec->params.n_actions) {
+ fprintf(f, "static const char *learner_%s_action_names[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ const char *action_name = learner_spec->params.action_names[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, action_name);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_table_entries. */
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_table_entries[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_table_entries[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* action_is_for_default_entry. */
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions) {
+ fprintf(f, "static int learner_%s_action_is_for_default_entry[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->params.n_actions; j++) {
+ int value = learner_spec->params.action_is_for_default_entry[j];
+
+ fprintf(f, "\t[%d] = %d,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ /* timeout. */
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "static uint32_t learner_%s_timeout[] = {\n",
+ learner_spec->name);
+
+ for (j = 0; j < learner_spec->n_timeouts; j++) {
+ uint32_t value = learner_spec->timeout[j];
+
+ fprintf(f, "\t[%d] = %u,\n", j, value);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+ }
+
+ fprintf(f, "static struct learner_spec learners[] = {\n");
+
+ for (i = 0; i < s->n_learners; i++) {
+ struct learner_spec *learner_spec = &s->learners[i];
+
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t\t.name = \"%s\",\n", learner_spec->name);
+
+ fprintf(f, "\t\t.params = {\n");
+
+ if (learner_spec->params.field_names && learner_spec->params.n_fields) {
+ fprintf(f, "\t\t\t.field_names = learner_%s_field_names,\n",
+ learner_spec->name);
+ fprintf(f, "\t\t\t.n_fields = "
+ "sizeof(learner_%s_field_names) / "
+ "sizeof(learner_%s_field_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t\t.field_names = NULL,\n");
+ fprintf(f, "\t\t\t.n_fields = 0,\n");
+ }
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_names = learner_%s_action_names,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_names = NULL,\n");
+
+ if (learner_spec->params.action_is_for_table_entries &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_table_entries = "
+ "learner_%s_action_is_for_table_entries,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_table_entries = NULL,\n");
+
+ if (learner_spec->params.action_is_for_default_entry &&
+ learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.action_is_for_default_entry = "
+ "learner_%s_action_is_for_default_entry,\n",
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.action_is_for_default_entry = NULL,\n");
+
+ if (learner_spec->params.action_names && learner_spec->params.n_actions)
+ fprintf(f, "\t\t\t.n_actions = "
+ "sizeof(learner_%s_action_names) / sizeof(learner_%s_action_names[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ else
+ fprintf(f, "\t\t\t.n_actions = NULL,\n");
+
+ if (learner_spec->params.default_action_name)
+ fprintf(f, "\t\t\t.default_action_name = \"%s\",\n",
+ learner_spec->params.default_action_name);
+ else
+ fprintf(f, "\t\t\t.default_action_name = NULL,\n");
+
+ if (learner_spec->params.default_action_args)
+ fprintf(f, "\t\t\t.default_action_args = \"%s\",\n",
+ learner_spec->params.default_action_args);
+ else
+ fprintf(f, "\t\t\t.default_action_args = NULL,\n");
+
+ fprintf(f, "\t\t\t.default_action_is_const = %d,\n",
+ learner_spec->params.default_action_is_const);
+
+ fprintf(f, "\t\t},\n");
+
+ fprintf(f, "\t\t.size = %u,\n", learner_spec->size);
+
+ if (learner_spec->timeout && learner_spec->n_timeouts) {
+ fprintf(f, "\t\t.timeout = learner_%s_timeout,\n", learner_spec->name);
+ fprintf(f, "\t\t\t.n_timeouts = "
+ "sizeof(learner_%s_timeout) / sizeof(learner_%s_timeout[0]),\n",
+ learner_spec->name,
+ learner_spec->name);
+ } else {
+ fprintf(f, "\t\t.timeout = NULL,\n");
+ fprintf(f, "\t\t\t.n_timeouts = 0,\n");
+ }
+
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* apply. */
+ for (i = 0; i < s->n_apply; i++) {
+ struct apply_spec *apply_spec = &s->apply[i];
+ uint32_t j;
+
+ fprintf(f, "static const char *apply%u_initial_instructions[] = {\n", i);
+
+ for (j = 0; j < apply_spec->n_instructions; j++) {
+ const char *instr = apply_spec->instructions[j];
+
+ fprintf(f, "\t[%d] = \"%s\",\n", j, instr);
+ }
+
+ fprintf(f, "};\n\n");
+ }
+
+ fprintf(f, "static struct apply_spec apply[] = {\n");
+
+ for (i = 0; i < s->n_apply; i++) {
+ fprintf(f, "\t[%d] = {\n", i);
+ fprintf(f, "\t.instructions = apply%u_initial_instructions,\n", i);
+ fprintf(f, "\t.n_instructions = "
+ "sizeof(apply%u_initial_instructions) / "
+ "sizeof(apply%u_initial_instructions[0]),\n",
+ i,
+ i);
+ fprintf(f, "\t},\n");
+ }
+
+ fprintf(f, "};\n\n");
+
+ /* pipeline. */
+ fprintf(f, "struct pipeline_spec pipeline_spec = {\n");
+ fprintf(f, "\t.extobjs = extobjs,\n");
+ fprintf(f, "\t.structs = structs,\n");
+ fprintf(f, "\t.headers = headers,\n");
+ fprintf(f, "\t.metadata = metadata,\n");
+ fprintf(f, "\t.actions = actions,\n");
+ fprintf(f, "\t.tables = tables,\n");
+ fprintf(f, "\t.selectors = selectors,\n");
+ fprintf(f, "\t.learners = learners,\n");
+ fprintf(f, "\t.regarrays = regarrays,\n");
+ fprintf(f, "\t.metarrays = metarrays,\n");
+ fprintf(f, "\t.apply = apply,\n");
+ fprintf(f, "\t.n_extobjs = sizeof(extobjs) / sizeof(extobjs[0]),\n");
+ fprintf(f, "\t.n_structs = sizeof(structs) / sizeof(structs[0]),\n");
+ fprintf(f, "\t.n_headers = sizeof(headers) / sizeof(headers[0]),\n");
+ fprintf(f, "\t.n_metadata = sizeof(metadata) / sizeof(metadata[0]),\n");
+ fprintf(f, "\t.n_actions = sizeof(actions) / sizeof(actions[0]),\n");
+ fprintf(f, "\t.n_tables = sizeof(tables) / sizeof(tables[0]),\n");
+ fprintf(f, "\t.n_selectors = sizeof(selectors) / sizeof(selectors[0]),\n");
+ fprintf(f, "\t.n_learners = sizeof(learners) / sizeof(learners[0]),\n");
+ fprintf(f, "\t.n_regarrays = sizeof(regarrays) / sizeof(regarrays[0]),\n");
+ fprintf(f, "\t.n_metarrays = sizeof(metarrays) / sizeof(metarrays[0]),\n");
+ fprintf(f, "\t.n_apply = sizeof(apply) / sizeof(apply[0]),\n");
+ fprintf(f, "};\n");
+}
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 4f3a0b5958..707b99ba09 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -206,6 +206,11 @@ struct pipeline_spec {
void
pipeline_spec_free(struct pipeline_spec *s);
+
+void
+pipeline_spec_codegen(FILE *f,
+ struct pipeline_spec *s);
+
struct pipeline_spec *
pipeline_spec_parse(FILE *spec,
uint32_t *err_line,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 06/17] pipeline: add support for pipeline I/O specification
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (3 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 05/17] pipeline: generate the code for pipeline specification structure Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
` (11 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add specification data structure and API for the pipeline I/O ports
and related pipeline configuration such as packet mirroring.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline_spec.c | 852 +++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline_spec.h | 58 ++
2 files changed, 910 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index bf21fe17ba..f34803793d 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -9,6 +9,12 @@
#include <errno.h>
#include <rte_common.h>
+#include <rte_mempool.h>
+
+#include <rte_swx_port_ethdev.h>
+#include <rte_swx_port_ring.h>
+#include <rte_swx_port_source_sink.h>
+#include <rte_swx_port_fd.h>
#include "rte_swx_pipeline_spec.h"
@@ -3566,3 +3572,849 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
pipeline_spec_free(s);
return status;
}
+
+static void
+port_in_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_reader_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "source")) {
+ struct rte_swx_port_source_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+static void
+port_out_params_free(void *params, const char *port_type)
+{
+ uintptr_t dev_name;
+
+ if (!params || !port_type)
+ return;
+
+ if (!strcmp(port_type, "ethdev")) {
+ struct rte_swx_port_ethdev_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->dev_name;
+ } else if (!strcmp(port_type, "ring")) {
+ struct rte_swx_port_ring_writer_params *p = params;
+
+ dev_name = (uintptr_t)p->name;
+ } else if (!strcmp(port_type, "sink")) {
+ struct rte_swx_port_sink_params *p = params;
+
+ dev_name = (uintptr_t)p->file_name;
+ } else
+ dev_name = (uintptr_t)NULL;
+
+ free((void *)dev_name);
+ free(params);
+}
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s)
+{
+ uint32_t i;
+
+ if (!s)
+ return;
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ uintptr_t name = (uintptr_t)s->port_in_type[i];
+
+ port_in_params_free(s->port_in_params[i], s->port_in_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_in_type);
+ free(s->port_in_params);
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ uintptr_t name = (uintptr_t)s->port_out_type[i];
+
+ port_out_params_free(s->port_out_params[i], s->port_out_type[i]);
+ free((void *)name);
+ }
+
+ free(s->port_out_type);
+ free(s->port_out_params);
+
+ free(s);
+}
+
+static int
+mirroring_parse(struct rte_swx_pipeline_mirroring_params *p,
+ char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ char *token;
+
+ if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return -EINVAL;
+ }
+
+ /* <n_slots>. */
+ token = tokens[1];
+ p->n_slots = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_slots> parameter.";
+ return -EINVAL;
+ }
+
+ /* <n_sessions>. */
+ token = tokens[3];
+ p->n_sessions = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_sessions> parameter.";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void *
+port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_reader_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_reader_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_reader_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_source_params *p = NULL;
+ struct rte_mempool *pool = NULL;
+ char *token, *file_name = NULL;
+ uint32_t n_loops, n_pkts_max;
+
+ if ((n_tokens != 8) ||
+ strcmp(tokens[0], "mempool") ||
+ strcmp(tokens[2], "file") ||
+ strcmp(tokens[4], "loop") ||
+ strcmp(tokens[6], "packets")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ pool = rte_mempool_lookup(tokens[1]);
+ if (!pool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <n_loops>. */
+ token = tokens[5];
+ n_loops = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_loops> parameter.";
+ return NULL;
+ }
+
+ /* <n_pkts_max>. */
+ token = tokens[7];
+ n_pkts_max = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <n_pkts_max> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ file_name = strdup(tokens[3]);
+ p = malloc(sizeof(struct rte_swx_port_source_params));
+ if (!file_name || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->pool = pool;
+ p->file_name = file_name;
+ p->n_loops = n_loops;
+ p->n_pkts_max = n_pkts_max;
+
+ return p;
+}
+
+static void *
+port_in_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_reader_params *p = NULL;
+ struct rte_mempool *mempool = NULL;
+ char *token;
+ uint32_t mtu, burst_size;
+ int fd;
+
+ if ((n_tokens != 7) ||
+ strcmp(tokens[1], "mtu") ||
+ strcmp(tokens[3], "mempool") ||
+ strcmp(tokens[5], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <mtu>. */
+ token = tokens[2];
+ mtu = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <mtu> parameter.";
+ return NULL;
+ }
+
+ /* <mempool_name>. */
+ mempool = rte_mempool_lookup(tokens[4]);
+ if (!mempool) {
+ if (err_msg)
+ *err_msg = "Invalid <mempool_name> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[6];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_reader_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->mtu = mtu;
+ p->mempool = mempool;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ethdev_writer_params *p = NULL;
+ char *token, *dev_name = NULL;
+ uint32_t queue_id, burst_size;
+
+ if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <queue_id>. */
+ token = tokens[2];
+ queue_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <queue_id> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[4];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ dev_name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params));
+ if (!dev_name || !p) {
+ free(dev_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->dev_name = dev_name;
+ p->queue_id = queue_id;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_ring_writer_params *p = NULL;
+ char *token, *name = NULL;
+ uint32_t burst_size;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ name = strdup(tokens[0]);
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if (!name || !p) {
+ free(name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->name = name;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+static void *
+port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg)
+{
+ struct rte_swx_port_sink_params *p = NULL;
+ char *file_name = NULL;
+ int file_name_valid = 0;
+
+ if ((n_tokens != 2) || strcmp(tokens[0], "file")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ if (strcmp(tokens[1], "none")) {
+ file_name_valid = 1;
+ file_name = strdup(tokens[1]);
+ }
+
+ p = malloc(sizeof(struct rte_swx_port_ring_writer_params));
+ if ((file_name_valid && !file_name) || !p) {
+ free(file_name);
+ free(p);
+
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->file_name = file_name;
+
+ return p;
+}
+
+static void *
+port_out_fd_parse(char **tokens,
+ uint32_t n_tokens,
+ const char **err_msg)
+{
+ struct rte_swx_port_fd_writer_params *p = NULL;
+ char *token;
+ uint32_t burst_size;
+ int fd;
+
+ if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) {
+ if (err_msg)
+ *err_msg = "Invalid statement.";
+ return NULL;
+ }
+
+ /* <file_descriptor>. */
+ token = tokens[0];
+ fd = strtol(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <file_descriptor> parameter.";
+ return NULL;
+ }
+
+ /* <burst_size>. */
+ token = tokens[2];
+ burst_size = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_msg)
+ *err_msg = "Invalid <burst_size> parameter.";
+ return NULL;
+ }
+
+ /* Memory allocation. */
+ p = malloc(sizeof(struct rte_swx_port_fd_writer_params));
+ if (!p) {
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ return NULL;
+ }
+
+ /* Initialization. */
+ p->fd = fd;
+ p->burst_size = burst_size;
+
+ return p;
+}
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg)
+{
+ struct pipeline_iospec *s = NULL;
+ uint32_t n_lines = 0;
+
+ /* Check the input arguments. */
+ if (!spec) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ goto error;
+ }
+
+ /* Memory allocation. */
+ s = calloc(sizeof(struct pipeline_iospec), 1);
+ if (!s) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ /* Initialize with the default values. */
+ s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT;
+ s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT;
+
+ for (n_lines = 1; ; n_lines++) {
+ char line[MAX_LINE_LENGTH];
+ char *tokens[MAX_TOKENS], *ptr = line;
+ uint32_t n_tokens = 0;
+
+ /* Read next line. */
+ if (!fgets(line, sizeof(line), spec))
+ break;
+
+ /* Parse the line into tokens. */
+ for ( ; ; ) {
+ char *token;
+
+ /* Get token. */
+ token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
+ if (!token)
+ break;
+
+ /* Handle comments. */
+ if ((token[0] == '#') ||
+ (token[0] == ';') ||
+ ((token[0] == '/') && (token[1] == '/'))) {
+ break;
+ }
+
+ /* Handle excessively long lines. */
+ if (n_tokens >= RTE_DIM(tokens)) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Too many tokens.";
+ goto error;
+ }
+
+ /* Handle excessively long tokens. */
+ if (strnlen(token, RTE_SWX_NAME_SIZE) >=
+ RTE_SWX_NAME_SIZE) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Token too big.";
+ goto error;
+ }
+
+ /* Save token. */
+ tokens[n_tokens] = token;
+ n_tokens++;
+ }
+
+ /* Handle empty lines. */
+ if (!n_tokens)
+ continue;
+
+ /* mirroring. */
+ if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) {
+ int status = 0;
+
+ status = mirroring_parse(&s->mirroring_params,
+ &tokens[1],
+ n_tokens - 1,
+ err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ continue;
+ }
+
+ /* port in. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "source"))
+ p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_in_id,
+ (s->n_ports_in + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_in_type,
+ (s->n_ports_in + 1) * sizeof(char *));
+ new_params = realloc(s->port_in_params,
+ (s->n_ports_in + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_in_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_in_id = new_id;
+ s->port_in_type = new_type;
+ s->port_in_params = new_params;
+
+ s->port_in_id[s->n_ports_in] = port_id;
+ s->port_in_type[s->n_ports_in] = port_type;
+ s->port_in_params[s->n_ports_in] = p;
+ s->n_ports_in++;
+
+ continue;
+ }
+
+ /* port out. */
+ if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) {
+ char *token = tokens[2];
+ uint32_t *new_id = NULL;
+ const char **new_type = NULL, *port_type = NULL;
+ void **new_params = NULL, *p = NULL;
+ uint32_t port_id;
+
+ /* <port_id>. */
+ port_id = strtoul(token, &token, 0);
+ if (token[0]) {
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Invalid port ID.";
+ goto error;
+ }
+
+ /* <port_type>. */
+ if (!strcmp(tokens[3], "ethdev"))
+ p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "ring"))
+ p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "sink"))
+ p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg);
+ else if (!strcmp(tokens[3], "fd"))
+ p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg);
+ else {
+ p = NULL;
+ if (err_msg)
+ *err_msg = "Invalid port type.";
+ }
+
+ if (!p) {
+ if (err_line)
+ *err_line = n_lines;
+ goto error;
+ }
+
+ /* New port. */
+ port_type = strdup(tokens[3]);
+ new_id = realloc(s->port_out_id,
+ (s->n_ports_out + 1) * sizeof(uint32_t));
+ new_type = realloc(s->port_out_type,
+ (s->n_ports_out + 1) * sizeof(char *));
+ new_params = realloc(s->port_out_params,
+ (s->n_ports_out + 1) * sizeof(void *));
+ if (!port_type || !new_id || !new_type || !new_params) {
+ uintptr_t pt = (uintptr_t)port_type;
+
+ port_out_params_free(p, tokens[3]);
+ free((void *)pt);
+ free(new_id);
+ free(new_type);
+ free(new_params);
+
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ goto error;
+ }
+
+ s->port_out_id = new_id;
+ s->port_out_type = new_type;
+ s->port_out_params = new_params;
+
+ s->port_out_id[s->n_ports_out] = port_id;
+ s->port_out_type[s->n_ports_out] = port_type;
+ s->port_out_params[s->n_ports_out] = p;
+ s->n_ports_out++;
+
+ continue;
+ }
+
+ /* Anything else. */
+ if (err_line)
+ *err_line = n_lines;
+ if (err_msg)
+ *err_msg = "Unknown I/O statement.";
+ goto error;
+ }
+
+ return s;
+
+error:
+ pipeline_iospec_free(s);
+
+ return NULL;
+}
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg)
+{
+ uint32_t i;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!p || !s) {
+ if (err_msg)
+ *err_msg = "Invalid input argument";
+ return -EINVAL;
+ }
+
+ /* Mirroring. */
+ status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline mirroring configuration error.";
+ return status;
+ }
+
+ /* Input ports. */
+ for (i = 0; i < s->n_ports_in; i++) {
+ status = rte_swx_pipeline_port_in_config(p,
+ i,
+ s->port_in_type[i],
+ s->port_in_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline input port configuration error.";
+ return status;
+ }
+ }
+
+ /* Output ports. */
+ for (i = 0; i < s->n_ports_out; i++) {
+ status = rte_swx_pipeline_port_out_config(p,
+ i,
+ s->port_out_type[i],
+ s->port_out_params[i]);
+ if (status) {
+ if (err_msg)
+ *err_msg = "Pipeline output port configuration error.";
+ return status;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h
index 707b99ba09..62ac4ecfc4 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.h
+++ b/lib/pipeline/rte_swx_pipeline_spec.h
@@ -1,6 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2022 Intel Corporation
*/
+#ifndef __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+#define __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include <stdio.h>
@@ -204,6 +211,38 @@ struct pipeline_spec {
uint32_t n_apply;
};
+/*
+ * Mirroring:
+ * mirroring slots <n_slots> sessions <n_sessions>
+ *
+ * Input ports:
+ * port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+ * port in <port_id> ring <ring_name> bsz <burst_size>
+ * port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops>
+ * packets <n_pkts_max>
+ * port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+ *
+ * Output ports:
+ * port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+ * port out <port_id> ring <ring_name> bsz <burst_size>
+ * port out <port_id> sink file <file_name> | none
+ * port out <port_id> fd <file_descriptor> bsz <burst_size>
+ */
+struct pipeline_iospec {
+ struct rte_swx_pipeline_mirroring_params mirroring_params;
+
+ uint32_t *port_in_id;
+ const char **port_in_type;
+ void **port_in_params;
+
+ uint32_t *port_out_id;
+ const char **port_out_type;
+ void **port_out_params;
+
+ uint32_t n_ports_in;
+ uint32_t n_ports_out;
+};
+
void
pipeline_spec_free(struct pipeline_spec *s);
@@ -220,3 +259,22 @@ int
pipeline_spec_configure(struct rte_swx_pipeline *p,
struct pipeline_spec *s,
const char **err_msg);
+
+void
+pipeline_iospec_free(struct pipeline_iospec *s);
+
+struct pipeline_iospec *
+pipeline_iospec_parse(FILE *spec,
+ uint32_t *err_line,
+ const char **err_msg);
+
+int
+pipeline_iospec_configure(struct rte_swx_pipeline *p,
+ struct pipeline_iospec *s,
+ const char **err_msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 07/17] pipeline: add API for pipeline code generation
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (4 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 06/17] pipeline: add support for pipeline I/O specification Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
` (10 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the C code generation for the pipeline was hidden under
the hood; now, we make this an explicit API operation. Besides the
functions for the pipeline actions and the pipeline instructions,
the generated C source code now includes the pipeline specification
structure required for the pipeline configuration operations.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
lib/pipeline/rte_swx_pipeline.c | 94 +++++++++++++++++++++++++++++++++
lib/pipeline/rte_swx_pipeline.h | 25 +++++++++
lib/pipeline/version.map | 1 +
3 files changed, 120 insertions(+)
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index c8ccded4f8..dd5f7107fa 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -20,6 +20,7 @@
#include <rte_swx_table_wm.h>
#include "rte_swx_pipeline_internal.h"
+#include "rte_swx_pipeline_spec.h"
#define CHECK(condition, err_code) \
do { \
@@ -13581,3 +13582,96 @@ pipeline_compile(struct rte_swx_pipeline *p)
return status;
}
+
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg)
+
+{
+ struct rte_swx_pipeline *p = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!spec_file || !code_file) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Invalid input argument.";
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration. */
+ s = pipeline_spec_parse(spec_file, err_line, err_msg);
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ status = rte_swx_pipeline_config(&p, NULL, 0);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Pipeline configuration error.";
+ goto free;
+ }
+
+ status = pipeline_spec_configure(p, s, err_msg);
+ if (status) {
+ if (err_line)
+ *err_line = 0;
+ goto free;
+ }
+
+ /*
+ * Pipeline code generation.
+ */
+
+ /* Instruction Group List (IGL) computation: the pipeline configuration must be done first,
+ * but there is no need for the pipeline build to be done as well.
+ */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ if (err_line)
+ *err_line = 0;
+ if (err_msg)
+ *err_msg = "Memory allocation failed.";
+ status = -ENOMEM;
+ goto free;
+ }
+
+ /* Header file inclusion. */
+ fprintf(code_file, "#include \"rte_swx_pipeline_internal.h\"\n");
+ fprintf(code_file, "#include \"rte_swx_pipeline_spec.h\"\n\n");
+
+ /* Code generation for the pipeline specification. */
+ pipeline_spec_codegen(code_file, s);
+ fprintf(code_file, "\n");
+
+ /* Code generation for the action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ fprintf(code_file, "/**\n * Action %s\n */\n\n", a->name);
+
+ action_data_codegen(a, code_file);
+ fprintf(code_file, "\n");
+
+ action_instr_codegen(a, code_file);
+ fprintf(code_file, "\n");
+ }
+
+ /* Code generation for the pipeline instructions. */
+ instruction_group_list_codegen(igl, p, code_file);
+
+free:
+ instruction_group_list_free(igl);
+ rte_swx_pipeline_free(p);
+ pipeline_spec_free(s);
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index ef50a0fa70..724607b87c 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -957,6 +957,31 @@ __rte_experimental
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p);
+/**
+ * Pipeline C code generate based on input specification file
+ *
+ * @param[in] spec_file
+ * Pipeline specification file (.spec) provided as input.
+ * @param[in] code_file
+ * Pipeline C language file (.c) to be generated.
+ * @param[out] err_line
+ * In case of error and non-NULL, the line number within the *spec* file where
+ * the error occurred. The first line number in the file is 1.
+ * @param[out] err_msg
+ * In case of error and non-NULL, the error message.
+ * @return
+ * 0 on success or the following error codes otherwise:
+ * -EINVAL: Invalid argument;
+ * -ENOMEM: Not enough space/cannot allocate memory;
+ * -EEXIST: Resource with the same name already exists.
+ */
+__rte_experimental
+int
+rte_swx_pipeline_codegen(FILE *spec_file,
+ FILE *code_file,
+ uint32_t *err_line,
+ const char **err_msg);
+
/**
* Pipeline build from specification file
*
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 50029aadcf..8d95005a5b 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -148,5 +148,6 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 08/17] pipeline: add API for shared library-based pipeline build
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (5 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 07/17] pipeline: add API for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
` (9 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Previously, the pipeline build operation was done based on the
specification file (typically produced by the P4 compiler), then the C
code with optimized functions for the pipeline actions and
instructions was generated, built into a shared object library, loaded
and installed into the pipeline in a completely hardcoded and
non-customizable way.
Now, this process is split into three explicit stages:
i) code generation (specification file -> C file);
ii) code build (C file -> shared object library);
iii) code installation (library load into the pipeline).
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 85 ++++---
lib/pipeline/rte_swx_pipeline.c | 319 +++++++++++----------------
lib/pipeline/rte_swx_pipeline.h | 38 ++--
lib/pipeline/rte_swx_pipeline_spec.c | 51 -----
lib/pipeline/version.map | 2 +-
5 files changed, 208 insertions(+), 287 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index ad553f19ab..f0285675b3 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -984,55 +984,88 @@ cmd_pipeline_port_out(char **tokens,
}
static const char cmd_pipeline_build_help[] =
-"pipeline <pipeline_name> build <spec_file>\n";
+"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
static void
cmd_pipeline_build(char **tokens,
uint32_t n_tokens,
char *out,
size_t out_size,
- void *obj)
+ void *obj __rte_unused)
{
- struct pipeline *p = NULL;
- FILE *spec = NULL;
- uint32_t err_line;
- const char *err_msg;
- int status;
+ struct rte_swx_pipeline *p = NULL;
+ struct rte_swx_ctl_pipeline *ctl = NULL;
+ char *pipeline_name, *lib_file_name, *iospec_file_name;
+ FILE *iospec_file = NULL;
+ uint32_t numa_node = 0;
+ int status = 0;
- if (n_tokens != 4) {
+ /* Parsing. */
+ if (n_tokens != 9) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
- p = pipeline_find(obj, tokens[1]);
- if (!p || p->ctl) {
- snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
+ pipeline_name = tokens[1];
+
+ if (strcmp(tokens[2], "build")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
return;
}
- spec = fopen(tokens[3], "r");
- if (!spec) {
- snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ if (strcmp(tokens[3], "lib")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
return;
}
- status = rte_swx_pipeline_build_from_spec(p->p,
- spec,
- &err_line,
- &err_msg);
- fclose(spec);
- if (status) {
- snprintf(out, out_size, "Error %d at line %u: %s\n.",
- status, err_line, err_msg);
+ lib_file_name = tokens[4];
+
+ if (strcmp(tokens[5], "io")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
return;
}
- p->ctl = rte_swx_ctl_pipeline_create(p->p);
- if (!p->ctl) {
- snprintf(out, out_size, "Pipeline control create failed.");
- rte_swx_pipeline_free(p->p);
+ iospec_file_name = tokens[6];
+
+ if (strcmp(tokens[7], "numa")) {
+ snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
return;
}
+
+ if (parser_read_uint32(&numa_node, tokens[8])) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+ return;
+ }
+
+ /* I/O spec file open. */
+ iospec_file = fopen(iospec_file_name, "r");
+ if (!iospec_file) {
+ snprintf(out, out_size, "Cannot open file \"%s\".\n", iospec_file_name);
+ return;
+ }
+
+ status = rte_swx_pipeline_build_from_lib(&p,
+ pipeline_name,
+ lib_file_name,
+ iospec_file,
+ (int)numa_node);
+ if (status) {
+ snprintf(out, out_size, "Pipeline build failed (%d).", status);
+ goto free;
+ }
+
+ ctl = rte_swx_ctl_pipeline_create(p);
+ if (!ctl) {
+ snprintf(out, out_size, "Pipeline control create failed.");
+ goto free;
+ }
+
+free:
+ if (status)
+ rte_swx_pipeline_free(p);
+
+ if (iospec_file)
+ fclose(iospec_file);
}
static void
diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index dd5f7107fa..12e156b00b 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -9911,9 +9911,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,
return 0;
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p);
-
int
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
{
@@ -10003,8 +10000,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
p->build_done = 1;
- pipeline_compile(p);
-
return 0;
error:
@@ -13327,160 +13322,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *
return n_custom_instr;
}
-static int
-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- FILE *f = NULL;
-
- /* Create the .c file. */
- f = fopen("/tmp/pipeline.c", "w");
- if (!f)
- return -EIO;
-
- /* Include the .h file. */
- fprintf(f, "#include \"rte_swx_pipeline_internal.h\"\n");
-
- /* Add the code for each action. */
- TAILQ_FOREACH(a, &p->actions, node) {
- fprintf(f, "/**\n * Action %s\n */\n\n", a->name);
-
- action_data_codegen(a, f);
-
- fprintf(f, "\n");
-
- action_instr_codegen(a, f);
-
- fprintf(f, "\n");
- }
-
- /* Add the pipeline code. */
- instruction_group_list_codegen(igl, p, f);
-
- /* Close the .c file. */
- fclose(f);
-
- return 0;
-}
-
-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE
-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096
-#endif
-
-static int
-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
-{
- struct action *a;
- struct instruction_group *g;
- char *dir_in, *buffer = NULL;
- const char *dir_out;
- int status = 0;
-
- /* Get the environment variables. */
- dir_in = getenv("RTE_INSTALL_DIR");
- if (!dir_in) {
- status = -EINVAL;
- goto free;
- }
-
- dir_out = "/tmp";
-
- /* Memory allocation for the command buffer. */
- buffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);
- if (!buffer) {
- status = -ENOMEM;
- goto free;
- }
-
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c "
- "-I %s/lib/pipeline "
- "-I %s/lib/eal/include "
- "-I %s/lib/eal/x86/include "
- "-I %s/lib/eal/include/generic "
- "-I %s/lib/meter "
- "-I %s/lib/port "
- "-I %s/lib/table "
- "-I %s/lib/pipeline "
- "-I %s/config "
- "-I %s/build "
- "-I %s/lib/eal/linux/include "
- ">%s/pipeline.log 2>&1 "
- "&& "
- "gcc -shared %s/pipeline.o -o %s/libpipeline.so "
- ">>%s/pipeline.log 2>&1",
- dir_out,
- dir_out,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_in,
- dir_out,
- dir_out,
- dir_out,
- dir_out);
-
- /* Build the shared object library. */
- status = system(buffer);
- if (status)
- goto free;
-
- /* Open library. */
- snprintf(buffer,
- RTE_SWX_PIPELINE_CMD_MAX_SIZE,
- "%s/libpipeline.so",
- dir_out);
-
- p->lib = dlopen(buffer, RTLD_LAZY);
- if (!p->lib) {
- status = -EIO;
- goto free;
- }
-
- /* Get the action function symbols. */
- TAILQ_FOREACH(a, &p->actions, node) {
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "action_%s_run", a->name);
-
- p->action_funcs[a->id] = dlsym(p->lib, buffer);
- if (!p->action_funcs[a->id]) {
- status = -EINVAL;
- goto free;
- }
- }
-
- /* Get the pipeline function symbols. */
- TAILQ_FOREACH(g, igl, node) {
- if (g->first_instr_id == g->last_instr_id)
- continue;
-
- snprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, "pipeline_func_%u", g->group_id);
-
- g->func = dlsym(p->lib, buffer);
- if (!g->func) {
- status = -EINVAL;
- goto free;
- }
- }
-
-free:
- if (status && p->lib) {
- dlclose(p->lib);
- p->lib = NULL;
- }
-
- free(buffer);
-
- return status;
-}
-
static int
pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,
struct instruction_group_list *igl)
@@ -13548,41 +13389,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)
instr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);
}
-static int
-pipeline_compile(struct rte_swx_pipeline *p)
-{
- struct instruction_group_list *igl = NULL;
- int status = 0;
-
- igl = instruction_group_list_create(p);
- if (!igl) {
- status = -ENOMEM;
- goto free;
- }
-
- /* Code generation. */
- status = pipeline_codegen(p, igl);
- if (status)
- goto free;
-
- /* Build and load the shared object library. */
- status = pipeline_libload(p, igl);
- if (status)
- goto free;
-
- /* Adjust instructions. */
- status = pipeline_adjust_check(p, igl);
- if (status)
- goto free;
-
- pipeline_adjust(p, igl);
-
-free:
- instruction_group_list_free(igl);
-
- return status;
-}
-
int
rte_swx_pipeline_codegen(FILE *spec_file,
FILE *code_file,
@@ -13675,3 +13481,128 @@ rte_swx_pipeline_codegen(FILE *spec_file,
return status;
}
+
+int
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node)
+{
+ struct rte_swx_pipeline *p = NULL;
+ void *lib = NULL;
+ struct pipeline_iospec *sio = NULL;
+ struct pipeline_spec *s = NULL;
+ struct instruction_group_list *igl = NULL;
+ struct action *a;
+ struct instruction_group *g;
+ int status = 0;
+
+ /* Check input arguments. */
+ if (!pipeline ||
+ !name ||
+ !name[0] ||
+ !lib_file_name ||
+ !lib_file_name[0] ||
+ !iospec_file) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Open the library. */
+ lib = dlopen(lib_file_name, RTLD_LAZY);
+ if (!lib) {
+ status = -EIO;
+ goto free;
+ }
+
+ /* Get the pipeline specification structures. */
+ s = dlsym(lib, "pipeline_spec");
+ if (!s) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ sio = pipeline_iospec_parse(iospec_file, NULL, NULL);
+ if (!sio) {
+ status = -EINVAL;
+ goto free;
+ }
+
+ /* Pipeline configuration based on the specification structures. */
+ status = rte_swx_pipeline_config(&p, name, numa_node);
+ if (status)
+ goto free;
+
+ status = pipeline_iospec_configure(p, sio, NULL);
+ if (status)
+ goto free;
+
+ status = pipeline_spec_configure(p, s, NULL);
+ if (status)
+ goto free;
+
+ /* Pipeline build. */
+ status = rte_swx_pipeline_build(p);
+ if (status)
+ goto free;
+
+ /* Action instructions. */
+ TAILQ_FOREACH(a, &p->actions, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ snprintf(name, sizeof(name), "action_%s_run", a->name);
+
+ p->action_funcs[a->id] = dlsym(lib, name);
+ if (!p->action_funcs[a->id]) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ /* Pipeline instructions. */
+ igl = instruction_group_list_create(p);
+ if (!igl) {
+ status = -ENOMEM;
+ goto free;
+ }
+
+ TAILQ_FOREACH(g, igl, node) {
+ char name[RTE_SWX_NAME_SIZE * 2];
+
+ if (g->first_instr_id == g->last_instr_id)
+ continue;
+
+ snprintf(name, sizeof(name), "pipeline_func_%u", g->group_id);
+
+ g->func = dlsym(lib, name);
+ if (!g->func) {
+ status = -EINVAL;
+ goto free;
+ }
+ }
+
+ status = pipeline_adjust_check(p, igl);
+ if (status)
+ goto free;
+
+ pipeline_adjust(p, igl);
+
+ p->lib = lib;
+
+ *pipeline = p;
+
+free:
+ instruction_group_list_free(igl);
+
+ pipeline_iospec_free(sio);
+
+ if (status) {
+ rte_swx_pipeline_free(p);
+
+ if (lib)
+ dlclose(lib);
+ }
+
+ return status;
+}
diff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h
index 724607b87c..9c629d4118 100644
--- a/lib/pipeline/rte_swx_pipeline.h
+++ b/lib/pipeline/rte_swx_pipeline.h
@@ -983,30 +983,38 @@ rte_swx_pipeline_codegen(FILE *spec_file,
const char **err_msg);
/**
- * Pipeline build from specification file
+ * Pipeline build from shared object library
*
- * @param[in] p
- * Pipeline handle.
- * @param[in] spec
- * Pipeline specification file.
- * @param[out] err_line
- * In case of error and non-NULL, the line number within the *spec* file where
- * the error occurred. The first line number in the file is 1.
- * @param[out] err_msg
- * In case of error and non-NULL, the error message.
+ * The shared object library must be built from the C language source code file
+ * previously generated by the rte_swx_pipeline_codegen() API function.
+ *
+ * The pipeline I/O specification file defines the I/O ports of the pipeline.
+ *
+ * @param[out] p
+ * Pipeline handle. Must point to valid memory. Contains valid pipeline handle
+ * when the function returns successfully.
+ * @param[in] name
+ * Pipeline unique name.
+ * @param[in] lib_file_name
+ * Shared object library file name.
+ * @param[in] iospec_file
+ * Pipeline I/O specification file.
+ * @param[in] numa_node
+ * Non-Uniform Memory Access (NUMA) node.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
- * -EEXIST: Resource with the same name already exists;
+ * -EEXIST: Pipeline with this name already exists;
* -ENODEV: Extern object or table creation error.
*/
__rte_experimental
int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec,
- uint32_t *err_line,
- const char **err_msg);
+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **p,
+ const char *name,
+ const char *lib_file_name,
+ FILE *iospec_file,
+ int numa_node);
/**
* Pipeline run
diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c
index f34803793d..3c16daf7de 100644
--- a/lib/pipeline/rte_swx_pipeline_spec.c
+++ b/lib/pipeline/rte_swx_pipeline_spec.c
@@ -3522,57 +3522,6 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,
return 0;
}
-int
-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,
- FILE *spec_file,
- uint32_t *err_line,
- const char **err_msg)
-{
- struct pipeline_spec *s = NULL;
- int status = 0;
-
- /* Check the input arguments. */
- if (!p || !spec_file) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Invalid input argument.";
- status = -EINVAL;
- goto error;
- }
-
- /* Spec file parse. */
- s = pipeline_spec_parse(spec_file, err_line, err_msg);
- if (!s) {
- status = -EINVAL;
- goto error;
- }
-
- /* Pipeline configure. */
- status = pipeline_spec_configure(p, s, err_msg);
- if (status) {
- if (err_line)
- *err_line = 0;
- goto error;
- }
-
- /* Pipeline build. */
- status = rte_swx_pipeline_build(p);
- if (status) {
- if (err_line)
- *err_line = 0;
- if (err_msg)
- *err_msg = "Pipeline build error.";
- goto error;
- }
-
- return 0;
-
-error:
- pipeline_spec_free(s);
- return status;
-}
-
static void
port_in_params_free(void *params, const char *port_type)
{
diff --git a/lib/pipeline/version.map b/lib/pipeline/version.map
index 8d95005a5b..16806e6802 100644
--- a/lib/pipeline/version.map
+++ b/lib/pipeline/version.map
@@ -82,7 +82,6 @@ EXPERIMENTAL {
rte_swx_ctl_table_ops_get;
rte_swx_pipeline_action_config;
rte_swx_pipeline_build;
- rte_swx_pipeline_build_from_spec;
rte_swx_pipeline_config;
rte_swx_pipeline_extern_func_register;
rte_swx_pipeline_extern_object_config;
@@ -148,6 +147,7 @@ EXPERIMENTAL {
#added in 22.11
rte_swx_ctl_pipeline_find;
+ rte_swx_pipeline_build_from_lib;
rte_swx_pipeline_codegen;
rte_swx_pipeline_find;
};
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 09/17] examples/pipeline: add CLI command for pipeline code generation
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (6 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 08/17] pipeline: add API for shared library-based pipeline build Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 10/17] examples/pipeline: add CLI command for shared library build Cristian Dumitrescu
` (8 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the pipeline code generation operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index f0285675b3..2b38977be1 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -983,6 +983,53 @@ cmd_pipeline_port_out(char **tokens,
}
}
+static const char cmd_pipeline_codegen_help[] =
+"pipeline codegen <spec_file> <code_file>\n";
+
+static void
+cmd_pipeline_codegen(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ FILE *spec_file = NULL;
+ FILE *code_file = NULL;
+ uint32_t err_line;
+ const char *err_msg;
+ int status;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ return;
+ }
+
+ spec_file = fopen(tokens[2], "r");
+ if (!spec_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+ return;
+ }
+
+ code_file = fopen(tokens[3], "w");
+ if (!code_file) {
+ snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+ return;
+ }
+
+ status = rte_swx_pipeline_codegen(spec_file,
+ code_file,
+ &err_line,
+ &err_msg);
+
+ fclose(spec_file);
+ fclose(code_file);
+
+ if (status) {
+ snprintf(out, out_size, "Error %d at line %u: %s\n.",
+ status, err_line, err_msg);
+ return;
+ }
+}
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -3009,6 +3056,7 @@ cmd_help(char **tokens,
"\tpipeline create\n"
"\tpipeline port in\n"
"\tpipeline port out\n"
+ "\tpipeline codegen\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3078,6 +3126,12 @@ cmd_help(char **tokens,
}
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "codegen") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_codegen_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3356,6 +3410,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "codegen") == 0)) {
+ cmd_pipeline_codegen(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [flat|nested] 90+ messages in thread
* [PATCH V5 10/17] examples/pipeline: add CLI command for shared library build
2022-07-27 23:01 ` [PATCH V5 01/17] pipeline: add pipeline name Cristian Dumitrescu
` (7 preceding siblings ...)
2022-07-27 23:01 ` [PATCH V5 09/17] examples/pipeline: add CLI command for pipeline code generation Cristian Dumitrescu
@ 2022-07-27 23:01 ` Cristian Dumitrescu
2022-07-27 23:01 ` [PATCH V5 11/17] examples/pipeline: remove the obsolete pipeline create CLI command Cristian Dumitrescu
` (7 subsequent siblings)
16 siblings, 0 replies; 90+ messages in thread
From: Cristian Dumitrescu @ 2022-07-27 23:01 UTC (permalink / raw)
To: dev; +Cc: Kamalakannan R .
Add CLI command for the shared object library build operation.
Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Kamalakannan R. <kamalakannan.r@intel.com>
---
examples/pipeline/cli.c | 157 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 153 insertions(+), 4 deletions(-)
diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c
index 2b38977be1..28cf8d4178 100644
--- a/examples/pipeline/cli.c
+++ b/examples/pipeline/cli.c
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <rte_common.h>
#include <rte_ethdev.h>
@@ -25,6 +26,10 @@
#define CMD_MAX_TOKENS 256
#endif
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
#define MSG_OUT_OF_MEMORY "Not enough memory.\n"
#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
@@ -1030,6 +1035,140 @@ cmd_pipeline_codegen(char **tokens,
return;
}
}
+
+static const char cmd_pipeline_libbuild_help[] =
+"pipeline libbuild <code_file> <lib_file>\n";
+
+static void
+cmd_pipeline_libbuild(char **tokens,
+ uint32_t n_tokens,
+ char *out,
+ size_t out_size,
+ void *obj __rte_unused)
+{
+ char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+ char *install_dir, *cwd = NULL, *buffer = NULL;
+ size_t length;
+ int status = 0;
+
+ if (n_tokens != 4) {
+ snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+ goto free;
+ }
+
+ install_dir = getenv("RTE_INSTALL_DIR");
+ if (!install_dir) {
+ cwd = malloc(MAX_LINE_SIZE);
+ if (!cwd) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ install_dir = getcwd(cwd, MAX_LINE_SIZE);
+ if (!install_dir) {
+ snprintf(out, out_size, "Error: Path too long.\n");
+ goto free;
+ }
+ }
+
+ snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+ out_size -= strlen(out);
+ out += strlen(out);
+
+ code_file = tokens[2];
+ length = strnlen(code_file, MAX_LINE_SIZE);
+ if ((length < 3) ||
+ (code_file[length - 2] != '.') ||
+ (code_file[length - 1] != 'c')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+ goto free;
+ }
+
+ lib_file = tokens[3];
+ length = strnlen(lib_file, MAX_LINE_SIZE);
+ if ((length < 4) ||
+ (lib_file[length - 3] != '.') ||
+ (lib_file[length - 2] != 's') ||
+ (lib_file[length - 1] != 'o')) {
+ snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+ goto free;
+ }
+
+ obj_file = malloc(length);
+ log_file = malloc(length + 2);
+ if (!obj_file || !log_file) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ goto free;
+ }
+
+ memcpy(obj_file, lib_file, length - 2);
+ obj_file[length - 2] = 'o';
+ obj_file[length - 1] = 0;
+
+ memcpy(log_file, lib_file, length - 2);
+ log_file[length - 2] = 'l';
+ log_file[length - 1] = 'o';
+ log_file[length] = 'g';
+ log_file[length + 1] = 0;
+
+ buffer = malloc(MAX_LINE_SIZE);
+ if (!buffer) {
+ snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+ return;
+ }
+
+ snprintf(buffer,
+ MAX_LINE_SIZE,
+ "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+ "-I %s/lib/pipeline "
+ "-I %s/lib/eal/include "
+ "-I %s/lib/eal/x86/include "
+ "-I %s/lib/eal/include/generic "
+ "-I %s/lib/meter "
+ "-I %s/lib/port "
+ "-I %s/lib/table "
+ "-I %s/lib/pipeline "
+ "-I %s/config "
+ "-I %s/build "
+ "-I %s/lib/eal/linux/include "
+ ">%s 2>&1 "
+ "&& "
+ "gcc -shared %s -o %s "
+ ">>%s 2>&1",
+ obj_file,
+ code_file,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ install_dir,
+ log_file,
+ obj_file,
+ lib_file,
+ log_file);
+
+ status = system(buffer);
+ if (status) {
+ snprintf(out,
+ out_size,
+ "Library build failed, see file \"%s\" for details.\n",
+ log_file);
+ goto free;
+ }
+
+free:
+ free(cwd);
+ free(obj_file);
+ free(log_file);
+ free(buffer);
+}
+
static const char cmd_pipeline_build_help[] =
"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\n";
@@ -1127,10 +1266,6 @@ table_entry_free(struct rte_swx_table_entry *entry)
free(entry);
}
-#ifndef MAX_LINE_SIZE
-#define MAX_LINE_SIZE 2048
-#endif
-
static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
const char *table_name,
@@ -3057,6 +3192,7 @@ cmd_help(char **tokens,
"\tpipeline port in\n"
"\tpipeline port out\n"
"\tpipeline codegen\n"
+ "\tpipeline libbuild\n"
"\tpipeline build\n"
"\tpipeline table add\n"
"\tpipeline table delete\n"
@@ -3132,6 +3268,12 @@ cmd_help(char **tokens,
return;
}
+ if ((strcmp(tokens[0], "pipeline") == 0) &&
+ (n_tokens == 2) && (strcmp(tokens[1], "libbuild") == 0)) {
+ snprintf(out, out_size, "\n%s\n", cmd_pipeline_libbuild_help);
+ return;
+ }
+
if ((strcmp(tokens[0], "pipeline") == 0) &&
(n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
@@ -3417,6 +3559,13 @@ cli_process(char *in, char *out, size_t out_size, void *obj)
return;
}
+ if ((n_tokens >= 3) &&
+ (strcmp(tokens[1], "libbuild") == 0)) {
+ cmd_pipeline_libbuild(tokens, n_tokens, out, out_size,
+ obj);
+ return;
+ }
+
if ((n_tokens >= 3) &&
(strcmp(tokens[2], "build") == 0)) {
cmd_pipeline_build(tokens, n_tokens, out, out_size,
--
2.34.1
^ permalink raw reply [