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.dumitre...@intel.com>
Signed-off-by: Kamalakannan R. <kamalakanna...@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

Reply via email to