* [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