get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/114361/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 114361,
    "url": "http://patches.dpdk.org/api/patches/114361/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20220728151147.603265-9-cristian.dumitrescu@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20220728151147.603265-9-cristian.dumitrescu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220728151147.603265-9-cristian.dumitrescu@intel.com",
    "date": "2022-07-28T15:11:38",
    "name": "[V6,08/17] pipeline: add API for shared library-based pipeline build",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "4b5a268ac665924b7d9f8c8cc38f2733eb3d7260",
    "submitter": {
        "id": 19,
        "url": "http://patches.dpdk.org/api/people/19/?format=api",
        "name": "Cristian Dumitrescu",
        "email": "cristian.dumitrescu@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20220728151147.603265-9-cristian.dumitrescu@intel.com/mbox/",
    "series": [
        {
            "id": 24117,
            "url": "http://patches.dpdk.org/api/series/24117/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=24117",
            "date": "2022-07-28T15:11:30",
            "name": "pipeline: pipeline configuration and build improvements",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/24117/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/114361/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/114361/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 8853DA00C5;\n\tThu, 28 Jul 2022 17:12:55 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E6BEF42BFD;\n\tThu, 28 Jul 2022 17:12:04 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by mails.dpdk.org (Postfix) with ESMTP id D983842BD9\n for <dev@dpdk.org>; Thu, 28 Jul 2022 17:12:00 +0200 (CEST)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 28 Jul 2022 08:11:59 -0700",
            "from silpixa00400573.ir.intel.com (HELO\n silpixa00400573.ger.corp.intel.com.) ([10.237.223.157])\n by orsmga001.jf.intel.com with ESMTP; 28 Jul 2022 08:11:58 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1659021121; x=1690557121;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=rMHq8sXj8IPmdHWPEBo/ABaiCJEn99cOCPu+oxWnHws=;\n b=HveLlq1yNdBfum4b2eVKfsKn0MduTLg7NsNvuT9ABZvRljhVkMt4eCKL\n J/2m5ToG5EBt5sgYP55SUeguzQopgqSo57fUq7N209EnqVZ5hvBNsDDrI\n bik0DC/wHZUnevSLpZN431XUg4QzSgGMTa0bvVSkKPNDuz32iDNkZJbid\n xlnCRUPHwcWdCq/jG6U4yPDFdx7djBVMfjja7UPM7anwkfNHUXPF0EEfB\n VYDC0KcfhfEKcU5+Yz9wBNk7kDD8/iTfkT9KFdpHHqLNc0ir7SUvAic90\n lSj43lSiVh/coMxrt7oTZk4DiBxs8GwrZIqNJxVZTztiHTp8erV8syOdP A==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6400,9594,10422\"; a=\"288547389\"",
            "E=Sophos;i=\"5.93,198,1654585200\"; d=\"scan'208\";a=\"288547389\"",
            "E=Sophos;i=\"5.93,198,1654585200\"; d=\"scan'208\";a=\"633727230\""
        ],
        "X-ExtLoop1": "1",
        "From": "Cristian Dumitrescu <cristian.dumitrescu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "\"Kamalakannan R .\" <kamalakannan.r@intel.com>",
        "Subject": "[PATCH V6 08/17] pipeline: add API for shared library-based pipeline\n build",
        "Date": "Thu, 28 Jul 2022 15:11:38 +0000",
        "Message-Id": "<20220728151147.603265-9-cristian.dumitrescu@intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20220728151147.603265-1-cristian.dumitrescu@intel.com>",
        "References": "<20220718130713.339003-1-cristian.dumitrescu@intel.com>\n <20220728151147.603265-1-cristian.dumitrescu@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Previously, the pipeline build operation was done based on the\nspecification file (typically produced by the P4 compiler), then the C\ncode with optimized functions for the pipeline actions and\ninstructions was generated, built into a shared object library, loaded\nand installed into the pipeline in a completely hardcoded and\nnon-customizable way.\n\nNow, this process is split into three explicit stages:\ni) code generation (specification file -> C file);\nii) code build (C file -> shared object library);\niii) code installation (library load into the pipeline).\n\nSigned-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\nSigned-off-by: Kamalakannan R. <kamalakannan.r@intel.com>\n---\n examples/pipeline/cli.c              |  85 ++++---\n lib/pipeline/rte_swx_pipeline.c      | 319 +++++++++++----------------\n lib/pipeline/rte_swx_pipeline.h      |  38 ++--\n lib/pipeline/rte_swx_pipeline_spec.c |  51 -----\n lib/pipeline/version.map             |   2 +-\n 5 files changed, 208 insertions(+), 287 deletions(-)",
    "diff": "diff --git a/examples/pipeline/cli.c b/examples/pipeline/cli.c\nindex ad553f19ab..f0285675b3 100644\n--- a/examples/pipeline/cli.c\n+++ b/examples/pipeline/cli.c\n@@ -984,55 +984,88 @@ cmd_pipeline_port_out(char **tokens,\n }\n \n static const char cmd_pipeline_build_help[] =\n-\"pipeline <pipeline_name> build <spec_file>\\n\";\n+\"pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>\\n\";\n \n static void\n cmd_pipeline_build(char **tokens,\n \tuint32_t n_tokens,\n \tchar *out,\n \tsize_t out_size,\n-\tvoid *obj)\n+\tvoid *obj __rte_unused)\n {\n-\tstruct pipeline *p = NULL;\n-\tFILE *spec = NULL;\n-\tuint32_t err_line;\n-\tconst char *err_msg;\n-\tint status;\n+\tstruct rte_swx_pipeline *p = NULL;\n+\tstruct rte_swx_ctl_pipeline *ctl = NULL;\n+\tchar *pipeline_name, *lib_file_name, *iospec_file_name;\n+\tFILE *iospec_file = NULL;\n+\tuint32_t numa_node = 0;\n+\tint status = 0;\n \n-\tif (n_tokens != 4) {\n+\t/* Parsing. */\n+\tif (n_tokens != 9) {\n \t\tsnprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);\n \t\treturn;\n \t}\n \n-\tp = pipeline_find(obj, tokens[1]);\n-\tif (!p || p->ctl) {\n-\t\tsnprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);\n+\tpipeline_name = tokens[1];\n+\n+\tif (strcmp(tokens[2], \"build\")) {\n+\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"build\");\n \t\treturn;\n \t}\n \n-\tspec = fopen(tokens[3], \"r\");\n-\tif (!spec) {\n-\t\tsnprintf(out, out_size, \"Cannot open file %s.\\n\", tokens[3]);\n+\tif (strcmp(tokens[3], \"lib\")) {\n+\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"lib\");\n \t\treturn;\n \t}\n \n-\tstatus = rte_swx_pipeline_build_from_spec(p->p,\n-\t\tspec,\n-\t\t&err_line,\n-\t\t&err_msg);\n-\tfclose(spec);\n-\tif (status) {\n-\t\tsnprintf(out, out_size, \"Error %d at line %u: %s\\n.\",\n-\t\t\tstatus, err_line, err_msg);\n+\tlib_file_name = tokens[4];\n+\n+\tif (strcmp(tokens[5], \"io\")) {\n+\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"io\");\n \t\treturn;\n \t}\n \n-\tp->ctl = rte_swx_ctl_pipeline_create(p->p);\n-\tif (!p->ctl) {\n-\t\tsnprintf(out, out_size, \"Pipeline control create failed.\");\n-\t\trte_swx_pipeline_free(p->p);\n+\tiospec_file_name = tokens[6];\n+\n+\tif (strcmp(tokens[7], \"numa\")) {\n+\t\tsnprintf(out, out_size, MSG_ARG_NOT_FOUND, \"numa\");\n \t\treturn;\n \t}\n+\n+\tif (parser_read_uint32(&numa_node, tokens[8])) {\n+\t\tsnprintf(out, out_size, MSG_ARG_INVALID, \"numa_node\");\n+\t\treturn;\n+\t}\n+\n+\t/* I/O spec file open. */\n+\tiospec_file = fopen(iospec_file_name, \"r\");\n+\tif (!iospec_file) {\n+\t\tsnprintf(out, out_size, \"Cannot open file \\\"%s\\\".\\n\", iospec_file_name);\n+\t\treturn;\n+\t}\n+\n+\tstatus = rte_swx_pipeline_build_from_lib(&p,\n+\t\t\t\t\t\t pipeline_name,\n+\t\t\t\t\t\t lib_file_name,\n+\t\t\t\t\t\t iospec_file,\n+\t\t\t\t\t\t (int)numa_node);\n+\tif (status) {\n+\t\tsnprintf(out, out_size, \"Pipeline build failed (%d).\", status);\n+\t\tgoto free;\n+\t}\n+\n+\tctl = rte_swx_ctl_pipeline_create(p);\n+\tif (!ctl) {\n+\t\tsnprintf(out, out_size, \"Pipeline control create failed.\");\n+\t\tgoto free;\n+\t}\n+\n+free:\n+\tif (status)\n+\t\trte_swx_pipeline_free(p);\n+\n+\tif (iospec_file)\n+\t\tfclose(iospec_file);\n }\n \n static void\ndiff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c\nindex dd5f7107fa..12e156b00b 100644\n--- a/lib/pipeline/rte_swx_pipeline.c\n+++ b/lib/pipeline/rte_swx_pipeline.c\n@@ -9911,9 +9911,6 @@ rte_swx_pipeline_instructions_config(struct rte_swx_pipeline *p,\n \treturn 0;\n }\n \n-static int\n-pipeline_compile(struct rte_swx_pipeline *p);\n-\n int\n rte_swx_pipeline_build(struct rte_swx_pipeline *p)\n {\n@@ -10003,8 +10000,6 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)\n \n \tp->build_done = 1;\n \n-\tpipeline_compile(p);\n-\n \treturn 0;\n \n error:\n@@ -13327,160 +13322,6 @@ instruction_group_list_custom_instructions_count(struct instruction_group_list *\n \treturn n_custom_instr;\n }\n \n-static int\n-pipeline_codegen(struct rte_swx_pipeline *p, struct instruction_group_list *igl)\n-{\n-\tstruct action *a;\n-\tFILE *f = NULL;\n-\n-\t/* Create the .c file. */\n-\tf = fopen(\"/tmp/pipeline.c\", \"w\");\n-\tif (!f)\n-\t\treturn -EIO;\n-\n-\t/* Include the .h file. */\n-\tfprintf(f, \"#include \\\"rte_swx_pipeline_internal.h\\\"\\n\");\n-\n-\t/* Add the code for each action. */\n-\tTAILQ_FOREACH(a, &p->actions, node) {\n-\t\tfprintf(f, \"/**\\n * Action %s\\n */\\n\\n\", a->name);\n-\n-\t\taction_data_codegen(a, f);\n-\n-\t\tfprintf(f, \"\\n\");\n-\n-\t\taction_instr_codegen(a, f);\n-\n-\t\tfprintf(f, \"\\n\");\n-\t}\n-\n-\t/* Add the pipeline code. */\n-\tinstruction_group_list_codegen(igl, p, f);\n-\n-\t/* Close the .c file. */\n-\tfclose(f);\n-\n-\treturn 0;\n-}\n-\n-#ifndef RTE_SWX_PIPELINE_CMD_MAX_SIZE\n-#define RTE_SWX_PIPELINE_CMD_MAX_SIZE 4096\n-#endif\n-\n-static int\n-pipeline_libload(struct rte_swx_pipeline *p, struct instruction_group_list *igl)\n-{\n-\tstruct action *a;\n-\tstruct instruction_group *g;\n-\tchar *dir_in, *buffer = NULL;\n-\tconst char *dir_out;\n-\tint status = 0;\n-\n-\t/* Get the environment variables. */\n-\tdir_in = getenv(\"RTE_INSTALL_DIR\");\n-\tif (!dir_in) {\n-\t\tstatus = -EINVAL;\n-\t\tgoto free;\n-\t}\n-\n-\tdir_out = \"/tmp\";\n-\n-\t/* Memory allocation for the command buffer. */\n-\tbuffer = malloc(RTE_SWX_PIPELINE_CMD_MAX_SIZE);\n-\tif (!buffer) {\n-\t\tstatus = -ENOMEM;\n-\t\tgoto free;\n-\t}\n-\n-\tsnprintf(buffer,\n-\t\t RTE_SWX_PIPELINE_CMD_MAX_SIZE,\n-\t\t \"gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s/pipeline.o %s/pipeline.c \"\n-\t\t \"-I %s/lib/pipeline \"\n-\t\t \"-I %s/lib/eal/include \"\n-\t\t \"-I %s/lib/eal/x86/include \"\n-\t\t \"-I %s/lib/eal/include/generic \"\n-\t\t \"-I %s/lib/meter \"\n-\t\t \"-I %s/lib/port \"\n-\t\t \"-I %s/lib/table \"\n-\t\t \"-I %s/lib/pipeline \"\n-\t\t \"-I %s/config \"\n-\t\t \"-I %s/build \"\n-\t\t \"-I %s/lib/eal/linux/include \"\n-\t\t \">%s/pipeline.log 2>&1 \"\n-\t\t \"&& \"\n-\t\t \"gcc -shared %s/pipeline.o -o %s/libpipeline.so \"\n-\t\t \">>%s/pipeline.log 2>&1\",\n-\t\t dir_out,\n-\t\t dir_out,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_in,\n-\t\t dir_out,\n-\t\t dir_out,\n-\t\t dir_out,\n-\t\t dir_out);\n-\n-\t/* Build the shared object library. */\n-\tstatus = system(buffer);\n-\tif (status)\n-\t\tgoto free;\n-\n-\t/* Open library. */\n-\tsnprintf(buffer,\n-\t\t RTE_SWX_PIPELINE_CMD_MAX_SIZE,\n-\t\t \"%s/libpipeline.so\",\n-\t\t dir_out);\n-\n-\tp->lib = dlopen(buffer, RTLD_LAZY);\n-\tif (!p->lib) {\n-\t\tstatus = -EIO;\n-\t\tgoto free;\n-\t}\n-\n-\t/* Get the action function symbols. */\n-\tTAILQ_FOREACH(a, &p->actions, node) {\n-\t\tsnprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, \"action_%s_run\", a->name);\n-\n-\t\tp->action_funcs[a->id] = dlsym(p->lib, buffer);\n-\t\tif (!p->action_funcs[a->id]) {\n-\t\t\tstatus = -EINVAL;\n-\t\t\tgoto free;\n-\t\t}\n-\t}\n-\n-\t/* Get the pipeline function symbols. */\n-\tTAILQ_FOREACH(g, igl, node) {\n-\t\tif (g->first_instr_id == g->last_instr_id)\n-\t\t\tcontinue;\n-\n-\t\tsnprintf(buffer, RTE_SWX_PIPELINE_CMD_MAX_SIZE, \"pipeline_func_%u\", g->group_id);\n-\n-\t\tg->func = dlsym(p->lib, buffer);\n-\t\tif (!g->func) {\n-\t\t\tstatus = -EINVAL;\n-\t\t\tgoto free;\n-\t\t}\n-\t}\n-\n-free:\n-\tif (status && p->lib) {\n-\t\tdlclose(p->lib);\n-\t\tp->lib = NULL;\n-\t}\n-\n-\tfree(buffer);\n-\n-\treturn status;\n-}\n-\n static int\n pipeline_adjust_check(struct rte_swx_pipeline *p __rte_unused,\n \t\t      struct instruction_group_list *igl)\n@@ -13548,41 +13389,6 @@ pipeline_adjust(struct rte_swx_pipeline *p, struct instruction_group_list *igl)\n \tinstr_jmp_resolve(p->instructions, p->instruction_data, p->n_instructions);\n }\n \n-static int\n-pipeline_compile(struct rte_swx_pipeline *p)\n-{\n-\tstruct instruction_group_list *igl = NULL;\n-\tint status = 0;\n-\n-\tigl = instruction_group_list_create(p);\n-\tif (!igl) {\n-\t\tstatus = -ENOMEM;\n-\t\tgoto free;\n-\t}\n-\n-\t/* Code generation. */\n-\tstatus = pipeline_codegen(p, igl);\n-\tif (status)\n-\t\tgoto free;\n-\n-\t/* Build and load the shared object library. */\n-\tstatus = pipeline_libload(p, igl);\n-\tif (status)\n-\t\tgoto free;\n-\n-\t/* Adjust instructions. */\n-\tstatus = pipeline_adjust_check(p, igl);\n-\tif (status)\n-\t\tgoto free;\n-\n-\tpipeline_adjust(p, igl);\n-\n-free:\n-\tinstruction_group_list_free(igl);\n-\n-\treturn status;\n-}\n-\n int\n rte_swx_pipeline_codegen(FILE *spec_file,\n \t\t\t FILE *code_file,\n@@ -13675,3 +13481,128 @@ rte_swx_pipeline_codegen(FILE *spec_file,\n \n \treturn status;\n }\n+\n+int\n+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **pipeline,\n+\t\t\t\tconst char *name,\n+\t\t\t\tconst char *lib_file_name,\n+\t\t\t\tFILE *iospec_file,\n+\t\t\t\tint numa_node)\n+{\n+\tstruct rte_swx_pipeline *p = NULL;\n+\tvoid *lib = NULL;\n+\tstruct pipeline_iospec *sio = NULL;\n+\tstruct pipeline_spec *s = NULL;\n+\tstruct instruction_group_list *igl = NULL;\n+\tstruct action *a;\n+\tstruct instruction_group *g;\n+\tint status = 0;\n+\n+\t/* Check input arguments. */\n+\tif (!pipeline ||\n+\t    !name ||\n+\t    !name[0] ||\n+\t    !lib_file_name ||\n+\t    !lib_file_name[0] ||\n+\t    !iospec_file) {\n+\t\tstatus = -EINVAL;\n+\t\tgoto free;\n+\t}\n+\n+\t/* Open the library. */\n+\tlib = dlopen(lib_file_name, RTLD_LAZY);\n+\tif (!lib) {\n+\t\tstatus = -EIO;\n+\t\tgoto free;\n+\t}\n+\n+\t/* Get the pipeline specification structures. */\n+\ts = dlsym(lib, \"pipeline_spec\");\n+\tif (!s) {\n+\t\tstatus = -EINVAL;\n+\t\tgoto free;\n+\t}\n+\n+\tsio = pipeline_iospec_parse(iospec_file, NULL, NULL);\n+\tif (!sio) {\n+\t\tstatus = -EINVAL;\n+\t\tgoto free;\n+\t}\n+\n+\t/* Pipeline configuration based on the specification structures. */\n+\tstatus = rte_swx_pipeline_config(&p, name, numa_node);\n+\tif (status)\n+\t\tgoto free;\n+\n+\tstatus = pipeline_iospec_configure(p, sio, NULL);\n+\tif (status)\n+\t\tgoto free;\n+\n+\tstatus = pipeline_spec_configure(p, s, NULL);\n+\tif (status)\n+\t\tgoto free;\n+\n+\t/* Pipeline build. */\n+\tstatus = rte_swx_pipeline_build(p);\n+\tif (status)\n+\t\tgoto free;\n+\n+\t/* Action instructions. */\n+\tTAILQ_FOREACH(a, &p->actions, node) {\n+\t\tchar name[RTE_SWX_NAME_SIZE * 2];\n+\n+\t\tsnprintf(name, sizeof(name), \"action_%s_run\", a->name);\n+\n+\t\tp->action_funcs[a->id] = dlsym(lib, name);\n+\t\tif (!p->action_funcs[a->id]) {\n+\t\t\tstatus = -EINVAL;\n+\t\t\tgoto free;\n+\t\t}\n+\t}\n+\n+\t/* Pipeline instructions. */\n+\tigl = instruction_group_list_create(p);\n+\tif (!igl) {\n+\t\tstatus = -ENOMEM;\n+\t\tgoto free;\n+\t}\n+\n+\tTAILQ_FOREACH(g, igl, node) {\n+\t\tchar name[RTE_SWX_NAME_SIZE * 2];\n+\n+\t\tif (g->first_instr_id == g->last_instr_id)\n+\t\t\tcontinue;\n+\n+\t\tsnprintf(name, sizeof(name), \"pipeline_func_%u\", g->group_id);\n+\n+\t\tg->func = dlsym(lib, name);\n+\t\tif (!g->func) {\n+\t\t\tstatus = -EINVAL;\n+\t\t\tgoto free;\n+\t\t}\n+\t}\n+\n+\tstatus = pipeline_adjust_check(p, igl);\n+\tif (status)\n+\t\tgoto free;\n+\n+\tpipeline_adjust(p, igl);\n+\n+\tp->lib = lib;\n+\n+\t*pipeline = p;\n+\n+free:\n+\tinstruction_group_list_free(igl);\n+\n+\tpipeline_iospec_free(sio);\n+\n+\tif (status) {\n+\t\trte_swx_pipeline_free(p);\n+\n+\t\tif (lib)\n+\t\t\tdlclose(lib);\n+\t}\n+\n+\treturn status;\n+}\ndiff --git a/lib/pipeline/rte_swx_pipeline.h b/lib/pipeline/rte_swx_pipeline.h\nindex 724607b87c..9c629d4118 100644\n--- a/lib/pipeline/rte_swx_pipeline.h\n+++ b/lib/pipeline/rte_swx_pipeline.h\n@@ -983,30 +983,38 @@ rte_swx_pipeline_codegen(FILE *spec_file,\n \t\t\t const char **err_msg);\n \n /**\n- * Pipeline build from specification file\n+ * Pipeline build from shared object library\n  *\n- * @param[in] p\n- *   Pipeline handle.\n- * @param[in] spec\n- *   Pipeline specification file.\n- * @param[out] err_line\n- *   In case of error and non-NULL, the line number within the *spec* file where\n- *   the error occurred. The first line number in the file is 1.\n- * @param[out] err_msg\n- *   In case of error and non-NULL, the error message.\n+ * The shared object library must be built from the C language source code file\n+ * previously generated by the rte_swx_pipeline_codegen() API function.\n+ *\n+ * The pipeline I/O specification file defines the I/O ports of the pipeline.\n+ *\n+ * @param[out] p\n+ *   Pipeline handle. Must point to valid memory. Contains valid pipeline handle\n+ *   when the function returns successfully.\n+ * @param[in] name\n+ *   Pipeline unique name.\n+ * @param[in] lib_file_name\n+ *   Shared object library file name.\n+ * @param[in] iospec_file\n+ *   Pipeline I/O specification file.\n+ * @param[in] numa_node\n+ *   Non-Uniform Memory Access (NUMA) node.\n  * @return\n  *   0 on success or the following error codes otherwise:\n  *   -EINVAL: Invalid argument;\n  *   -ENOMEM: Not enough space/cannot allocate memory;\n- *   -EEXIST: Resource with the same name already exists;\n+ *   -EEXIST: Pipeline with this name already exists;\n  *   -ENODEV: Extern object or table creation error.\n  */\n __rte_experimental\n int\n-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,\n-\t\t\t\t FILE *spec,\n-\t\t\t\t uint32_t *err_line,\n-\t\t\t\t const char **err_msg);\n+rte_swx_pipeline_build_from_lib(struct rte_swx_pipeline **p,\n+\t\t\t\tconst char *name,\n+\t\t\t\tconst char *lib_file_name,\n+\t\t\t\tFILE *iospec_file,\n+\t\t\t\tint numa_node);\n \n /**\n  * Pipeline run\ndiff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c\nindex f34803793d..3c16daf7de 100644\n--- a/lib/pipeline/rte_swx_pipeline_spec.c\n+++ b/lib/pipeline/rte_swx_pipeline_spec.c\n@@ -3522,57 +3522,6 @@ pipeline_spec_configure(struct rte_swx_pipeline *p,\n \treturn 0;\n }\n \n-int\n-rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p,\n-\t\t\t\t FILE *spec_file,\n-\t\t\t\t uint32_t *err_line,\n-\t\t\t\t const char **err_msg)\n-{\n-\tstruct pipeline_spec *s = NULL;\n-\tint status = 0;\n-\n-\t/* Check the input arguments. */\n-\tif (!p || !spec_file) {\n-\t\tif (err_line)\n-\t\t\t*err_line = 0;\n-\t\tif (err_msg)\n-\t\t\t*err_msg = \"Invalid input argument.\";\n-\t\tstatus = -EINVAL;\n-\t\tgoto error;\n-\t}\n-\n-\t/* Spec file parse. */\n-\ts = pipeline_spec_parse(spec_file, err_line, err_msg);\n-\tif (!s) {\n-\t\tstatus = -EINVAL;\n-\t\tgoto error;\n-\t}\n-\n-\t/* Pipeline configure. */\n-\tstatus = pipeline_spec_configure(p, s, err_msg);\n-\tif (status) {\n-\t\tif (err_line)\n-\t\t\t*err_line = 0;\n-\t\tgoto error;\n-\t}\n-\n-\t/* Pipeline build. */\n-\tstatus = rte_swx_pipeline_build(p);\n-\tif (status) {\n-\t\tif (err_line)\n-\t\t\t*err_line = 0;\n-\t\tif (err_msg)\n-\t\t\t*err_msg = \"Pipeline build error.\";\n-\t\tgoto error;\n-\t}\n-\n-\treturn 0;\n-\n-error:\n-\tpipeline_spec_free(s);\n-\treturn status;\n-}\n-\n static void\n port_in_params_free(void *params, const char *port_type)\n {\ndiff --git a/lib/pipeline/version.map b/lib/pipeline/version.map\nindex 8d95005a5b..16806e6802 100644\n--- a/lib/pipeline/version.map\n+++ b/lib/pipeline/version.map\n@@ -82,7 +82,6 @@ EXPERIMENTAL {\n \trte_swx_ctl_table_ops_get;\n \trte_swx_pipeline_action_config;\n \trte_swx_pipeline_build;\n-\trte_swx_pipeline_build_from_spec;\n \trte_swx_pipeline_config;\n \trte_swx_pipeline_extern_func_register;\n \trte_swx_pipeline_extern_object_config;\n@@ -148,6 +147,7 @@ EXPERIMENTAL {\n \n \t#added in 22.11\n \trte_swx_ctl_pipeline_find;\n+\trte_swx_pipeline_build_from_lib;\n \trte_swx_pipeline_codegen;\n \trte_swx_pipeline_find;\n };\n",
    "prefixes": [
        "V6",
        "08/17"
    ]
}