get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 7744,
    "url": "https://patches.dpdk.org/api/patches/7744/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445263220-3245-1-git-send-email-piotrx.t.azarewicz@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1445263220-3245-1-git-send-email-piotrx.t.azarewicz@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445263220-3245-1-git-send-email-piotrx.t.azarewicz@intel.com",
    "date": "2015-10-19T14:00:20",
    "name": "[dpdk-dev,v3,1/1] ip_pipeline: added dynamic pipeline reconfiguration",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "bbf741702cd6ba1021d1620d85a5f2afe64205f7",
    "submitter": {
        "id": 273,
        "url": "https://patches.dpdk.org/api/people/273/?format=api",
        "name": "Piotr Azarewicz",
        "email": "piotrx.t.azarewicz@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445263220-3245-1-git-send-email-piotrx.t.azarewicz@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7744/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7744/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id C52238E80;\n\tMon, 19 Oct 2015 16:02:53 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 6BDB28E70\n\tfor <dev@dpdk.org>; Mon, 19 Oct 2015 16:02:51 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP; 19 Oct 2015 07:02:20 -0700",
            "from unknown (HELO stargo) ([10.217.248.233])\n\tby orsmga002.jf.intel.com with SMTP; 19 Oct 2015 07:02:17 -0700",
            "by stargo (sSMTP sendmail emulation);\n\tMon, 19 Oct 2015 16:01:06 +0200"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,702,1437462000\"; d=\"scan'208\";a=\"830017574\"",
        "From": "Piotr Azarewicz <piotrx.t.azarewicz@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 19 Oct 2015 16:00:20 +0200",
        "Message-Id": "<1445263220-3245-1-git-send-email-piotrx.t.azarewicz@intel.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1443630350-31373-1-git-send-email-maciejx.t.gajdzica@intel.com>",
        "References": "<1443630350-31373-1-git-send-email-maciejx.t.gajdzica@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 1/1] ip_pipeline: added dynamic pipeline\n\treconfiguration",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Up till now pipeline was bound to thread selected in the initial config.\nThis patch allows binding pipeline to other threads at runtime using CLI\ncommands.\n\nv2 changes:\n- deleted debug printfs\n\nv3 changes:\n- add timer for thread message request\n- fix bug that the new functionality can't work\n- fix leaking memory\n- cleaning up\n\nSigned-off-by: Maciej Gajdzica <maciejx.t.gajdzica@intel.com>\nSigned-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>\n\nAcked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\n---\n examples/ip_pipeline/Makefile                      |    1 +\n examples/ip_pipeline/app.h                         |   12 +\n examples/ip_pipeline/config_parse.c                |    2 +-\n examples/ip_pipeline/init.c                        |   24 ++\n examples/ip_pipeline/pipeline.h                    |    6 +\n examples/ip_pipeline/pipeline/pipeline_common_fe.h |    3 +\n examples/ip_pipeline/thread.c                      |  157 ++++++++-\n examples/ip_pipeline/thread.h                      |   84 +++++\n examples/ip_pipeline/thread_fe.c                   |  344 ++++++++++++++++++++\n examples/ip_pipeline/thread_fe.h                   |   95 ++++++\n 10 files changed, 720 insertions(+), 8 deletions(-)\n create mode 100644 examples/ip_pipeline/thread.h\n create mode 100644 examples/ip_pipeline/thread_fe.c\n create mode 100644 examples/ip_pipeline/thread_fe.h",
    "diff": "diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile\nindex f3ff1ec..c8e80b5 100644\n--- a/examples/ip_pipeline/Makefile\n+++ b/examples/ip_pipeline/Makefile\n@@ -54,6 +54,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread_fe.c\n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c\n \n SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c\ndiff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h\nindex 521e3a0..3a57956 100644\n--- a/examples/ip_pipeline/app.h\n+++ b/examples/ip_pipeline/app.h\n@@ -220,9 +220,11 @@ struct app_pipeline_data {\n \tvoid *be;\n \tvoid *fe;\n \tuint64_t timer_period;\n+\tuint32_t enabled;\n };\n \n struct app_thread_pipeline_data {\n+\tuint32_t pipeline_id;\n \tvoid *be;\n \tpipeline_be_op_run f_run;\n \tpipeline_be_op_timer f_timer;\n@@ -234,6 +236,10 @@ struct app_thread_pipeline_data {\n #define APP_MAX_THREAD_PIPELINES                 16\n #endif\n \n+#ifndef APP_THREAD_TIMER_PERIOD\n+#define APP_THREAD_TIMER_PERIOD                  1\n+#endif\n+\n struct app_thread_data {\n \tstruct app_thread_pipeline_data regular[APP_MAX_THREAD_PIPELINES];\n \tstruct app_thread_pipeline_data custom[APP_MAX_THREAD_PIPELINES];\n@@ -241,7 +247,13 @@ struct app_thread_data {\n \tuint32_t n_regular;\n \tuint32_t n_custom;\n \n+\tuint64_t timer_period;\n+\tuint64_t thread_req_deadline;\n+\n \tuint64_t deadline;\n+\n+\tstruct rte_ring *msgq_in;\n+\tstruct rte_ring *msgq_out;\n };\n \n struct app_eal_params {\ndiff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c\nindex c9b78f9..d2aaadf 100644\n--- a/examples/ip_pipeline/config_parse.c\n+++ b/examples/ip_pipeline/config_parse.c\n@@ -362,7 +362,7 @@ parser_read_uint32(uint32_t *value, const char *p)\n \treturn 0;\n }\n \n-static int\n+int\n parse_pipeline_core(uint32_t *socket,\n \tuint32_t *core,\n \tuint32_t *ht,\ndiff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c\nindex 3f9c68d..8c63879 100644\n--- a/examples/ip_pipeline/init.c\n+++ b/examples/ip_pipeline/init.c\n@@ -50,6 +50,7 @@\n #include \"pipeline_firewall.h\"\n #include \"pipeline_flow_classification.h\"\n #include \"pipeline_routing.h\"\n+#include \"thread_fe.h\"\n \n #define APP_NAME_SIZE\t32\n \n@@ -1253,6 +1254,25 @@ app_init_threads(struct app_params *app)\n \n \t\tt = &app->thread_data[lcore_id];\n \n+\t\tt->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000;\n+\t\tt->thread_req_deadline = time + t->timer_period;\n+\n+\t\tt->msgq_in = app_thread_msgq_in_get(app,\n+\t\t\t\tparams->socket_id,\n+\t\t\t\tparams->core_id,\n+\t\t\t\tparams->hyper_th_id);\n+\t\tif (t->msgq_in == NULL)\n+\t\t\trte_panic(\"Init error: Cannot find MSGQ_IN for thread %\" PRId32,\n+\t\t\t\tlcore_id);\n+\n+\t\tt->msgq_out = app_thread_msgq_out_get(app,\n+\t\t\t\tparams->socket_id,\n+\t\t\t\tparams->core_id,\n+\t\t\t\tparams->hyper_th_id);\n+\t\tif (t->msgq_out == NULL)\n+\t\t\trte_panic(\"Init error: Cannot find MSGQ_OUT for thread %\" PRId32,\n+\t\t\t\tlcore_id);\n+\n \t\tptype = app_pipeline_type_find(app, params->type);\n \t\tif (ptype == NULL)\n \t\t\trte_panic(\"Init error: Unknown pipeline \"\n@@ -1262,12 +1282,15 @@ app_init_threads(struct app_params *app)\n \t\t\t&t->regular[t->n_regular] :\n \t\t\t&t->custom[t->n_custom];\n \n+\t\tp->pipeline_id = p_id;\n \t\tp->be = data->be;\n \t\tp->f_run = ptype->be_ops->f_run;\n \t\tp->f_timer = ptype->be_ops->f_timer;\n \t\tp->timer_period = data->timer_period;\n \t\tp->deadline = time + data->timer_period;\n \n+\t\tdata->enabled = 1;\n+\n \t\tif (ptype->be_ops->f_run == NULL)\n \t\t\tt->n_regular++;\n \t\telse\n@@ -1288,6 +1311,7 @@ int app_init(struct app_params *app)\n \tapp_init_msgq(app);\n \n \tapp_pipeline_common_cmd_push(app);\n+\tapp_pipeline_thread_cmd_push(app);\n \tapp_pipeline_type_register(app, &pipeline_master);\n \tapp_pipeline_type_register(app, &pipeline_passthrough);\n \tapp_pipeline_type_register(app, &pipeline_flow_classification);\ndiff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h\nindex b9a56ea..dab9c36 100644\n--- a/examples/ip_pipeline/pipeline.h\n+++ b/examples/ip_pipeline/pipeline.h\n@@ -84,4 +84,10 @@ pipeline_type_cmds_count(struct pipeline_type *ptype)\n \treturn n_cmds;\n }\n \n+int\n+parse_pipeline_core(uint32_t *socket,\n+\tuint32_t *core,\n+\tuint32_t *ht,\n+\tconst char *entry);\n+\n #endif\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h\nindex 693848d..e84aa3a 100644\n--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h\n+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h\n@@ -68,6 +68,9 @@ app_pipeline_data_fe(struct app_params *app, uint32_t id)\n \tif (pipeline_data == NULL)\n \t\treturn NULL;\n \n+\tif (pipeline_data->enabled == 0)\n+\t\treturn NULL;\n+\n \treturn pipeline_data->fe;\n }\n \ndiff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c\nindex b2a8656..53be20c 100644\n--- a/examples/ip_pipeline/thread.c\n+++ b/examples/ip_pipeline/thread.c\n@@ -37,18 +37,147 @@\n \n #include \"pipeline_common_be.h\"\n #include \"app.h\"\n+#include \"thread.h\"\n \n-int app_thread(void *arg)\n+static inline void *\n+thread_msg_recv(struct rte_ring *r)\n+{\n+\tvoid *msg;\n+\tint status = rte_ring_sc_dequeue(r, &msg);\n+\n+\tif (status != 0)\n+\t\treturn NULL;\n+\n+\treturn msg;\n+}\n+\n+static inline void\n+thread_msg_send(struct rte_ring *r,\n+\tvoid *msg)\n+{\n+\tint status;\n+\n+\tdo {\n+\t\tstatus = rte_ring_sp_enqueue(r, msg);\n+\t} while (status == -ENOBUFS);\n+}\n+\n+static int\n+thread_pipeline_enable(struct app_thread_data *t,\n+\t\tstruct thread_pipeline_enable_msg_req *req)\n+{\n+\tstruct app_thread_pipeline_data *p;\n+\n+\tif (req->f_run == NULL) {\n+\t\tif (t->n_regular >= APP_MAX_THREAD_PIPELINES)\n+\t\t\treturn -1;\n+\t} else {\n+\t\tif (t->n_custom >= APP_MAX_THREAD_PIPELINES)\n+\t\t\treturn -1;\n+\t}\n+\n+\tp = (req->f_run == NULL) ?\n+\t\t&t->regular[t->n_regular] :\n+\t\t&t->custom[t->n_custom];\n+\n+\tp->pipeline_id = req->pipeline_id;\n+\tp->be = req->be;\n+\tp->f_run = req->f_run;\n+\tp->f_timer = req->f_timer;\n+\tp->timer_period = req->timer_period;\n+\tp->deadline = 0;\n+\n+\tif (req->f_run == NULL)\n+\t\tt->n_regular++;\n+\telse\n+\t\tt->n_custom++;\n+\n+\treturn 0;\n+}\n+\n+static int\n+thread_pipeline_disable(struct app_thread_data *t,\n+\t\tstruct thread_pipeline_disable_msg_req *req)\n+{\n+\tuint32_t i;\n+\n+\t/* search regular pipelines of current thread */\n+\tfor (i = 0; i < t->n_regular; i++) {\n+\t\tif (t->regular[i].pipeline_id != req->pipeline_id)\n+\t\t\tcontinue;\n+\n+\t\tif (i < t->n_regular - 1)\n+\t\t\tmemcpy(&t->regular[i],\n+\t\t\t  &t->regular[i+1],\n+\t\t\t  (t->n_regular - 1 - i) * sizeof(struct app_thread_pipeline_data));\n+\n+\t\tt->n_regular--;\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* search custom pipelines of current thread */\n+\tfor (i = 0; i < t->n_custom; i++) {\n+\t\tif (t->custom[i].pipeline_id != req->pipeline_id)\n+\t\t\tcontinue;\n+\n+\t\tif (i < t->n_custom - 1)\n+\t\t\tmemcpy(&t->custom[i],\n+\t\t\t  &t->custom[i+1],\n+\t\t\t  (t->n_custom - 1 - i) * sizeof(struct app_thread_pipeline_data));\n+\n+\t\tt->n_custom--;\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* return if pipeline not found */\n+\treturn -1;\n+}\n+\n+static int\n+thread_msg_req_handle(struct app_thread_data *t)\n+{\n+\tvoid *msg_ptr;\n+\tstruct thread_msg_req *req;\n+\tstruct thread_msg_rsp *rsp;\n+\n+\tmsg_ptr = thread_msg_recv(t->msgq_in);\n+\treq = msg_ptr;\n+\trsp = msg_ptr;\n+\n+\tif (req != NULL)\n+\t\tswitch (req->type) {\n+\t\tcase THREAD_MSG_REQ_PIPELINE_ENABLE: {\n+\t\t\trsp->status = thread_pipeline_enable(t,\n+\t\t\t\t\t(struct thread_pipeline_enable_msg_req *) req);\n+\t\t\tthread_msg_send(t->msgq_out, rsp);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tcase THREAD_MSG_REQ_PIPELINE_DISABLE: {\n+\t\t\trsp->status = thread_pipeline_disable(t,\n+\t\t\t\t\t(struct thread_pipeline_disable_msg_req *) req);\n+\t\t\tthread_msg_send(t->msgq_out, rsp);\n+\t\t\tbreak;\n+\t\t}\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+app_thread(void *arg)\n {\n \tstruct app_params *app = (struct app_params *) arg;\n \tuint32_t core_id = rte_lcore_id(), i, j;\n \tstruct app_thread_data *t = &app->thread_data[core_id];\n-\tuint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular));\n-\tuint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom));\n \n \tfor (i = 0; ; i++) {\n \t\t/* Run regular pipelines */\n-\t\tfor (j = 0; j < n_regular; j++) {\n+\t\tfor (j = 0; j < t->n_regular; j++) {\n \t\t\tstruct app_thread_pipeline_data *data = &t->regular[j];\n \t\t\tstruct pipeline *p = data->be;\n \n@@ -56,7 +185,7 @@ int app_thread(void *arg)\n \t\t}\n \n \t\t/* Run custom pipelines */\n-\t\tfor (j = 0; j < n_custom; j++) {\n+\t\tfor (j = 0; j < t->n_custom; j++) {\n \t\t\tstruct app_thread_pipeline_data *data = &t->custom[j];\n \n \t\t\tdata->f_run(data->be);\n@@ -71,7 +200,7 @@ int app_thread(void *arg)\n \t\t\t\tcontinue;\n \n \t\t\t/* Timer for regular pipelines */\n-\t\t\tfor (j = 0; j < n_regular; j++) {\n+\t\t\tfor (j = 0; j < t->n_regular; j++) {\n \t\t\t\tstruct app_thread_pipeline_data *data =\n \t\t\t\t\t&t->regular[j];\n \t\t\t\tuint64_t p_deadline = data->deadline;\n@@ -87,7 +216,7 @@ int app_thread(void *arg)\n \t\t\t}\n \n \t\t\t/* Timer for custom pipelines */\n-\t\t\tfor (j = 0; j < n_custom; j++) {\n+\t\t\tfor (j = 0; j < t->n_custom; j++) {\n \t\t\t\tstruct app_thread_pipeline_data *data =\n \t\t\t\t\t&t->custom[j];\n \t\t\t\tuint64_t p_deadline = data->deadline;\n@@ -102,6 +231,20 @@ int app_thread(void *arg)\n \t\t\t\t\tt_deadline = p_deadline;\n \t\t\t}\n \n+\t\t\t/* Timer for thread message request */\n+\t\t\t{\n+\t\t\t\tuint64_t deadline = t->thread_req_deadline;\n+\n+\t\t\t\tif (deadline <= time) {\n+\t\t\t\t\tthread_msg_req_handle(t);\n+\t\t\t\t\tdeadline = time + t->timer_period;\n+\t\t\t\t\tt->thread_req_deadline = deadline;\n+\t\t\t\t}\n+\n+\t\t\t\tif (deadline < t_deadline)\n+\t\t\t\t\tt_deadline = deadline;\n+\t\t\t}\n+\n \t\t\tt->deadline = t_deadline;\n \t\t}\n \t}\ndiff --git a/examples/ip_pipeline/thread.h b/examples/ip_pipeline/thread.h\nnew file mode 100644\nindex 0000000..dc877c0\n--- /dev/null\n+++ b/examples/ip_pipeline/thread.h\n@@ -0,0 +1,84 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef THREAD_H_\n+#define THREAD_H_\n+\n+#include \"app.h\"\n+#include \"pipeline_be.h\"\n+\n+enum thread_msg_req_type {\n+\tTHREAD_MSG_REQ_PIPELINE_ENABLE = 0,\n+\tTHREAD_MSG_REQ_PIPELINE_DISABLE,\n+\tTHREAD_MSG_REQS\n+};\n+\n+struct thread_msg_req {\n+\tenum thread_msg_req_type type;\n+};\n+\n+struct thread_msg_rsp {\n+\tint status;\n+};\n+\n+/*\n+ * PIPELINE ENABLE\n+ */\n+struct thread_pipeline_enable_msg_req {\n+\tenum thread_msg_req_type type;\n+\n+\tuint32_t pipeline_id;\n+\tvoid *be;\n+\tpipeline_be_op_run f_run;\n+\tpipeline_be_op_timer f_timer;\n+\tuint64_t timer_period;\n+};\n+\n+struct thread_pipeline_enable_msg_rsp {\n+\tint status;\n+};\n+\n+/*\n+ * PIPELINE DISABLE\n+ */\n+struct thread_pipeline_disable_msg_req {\n+\tenum thread_msg_req_type type;\n+\n+\tuint32_t pipeline_id;\n+};\n+\n+struct thread_pipeline_disable_msg_rsp {\n+\tint status;\n+};\n+\n+#endif /* THREAD_H_ */\ndiff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c\nnew file mode 100644\nindex 0000000..b71153a\n--- /dev/null\n+++ b/examples/ip_pipeline/thread_fe.c\n@@ -0,0 +1,344 @@\n+#include <rte_common.h>\n+#include <rte_ring.h>\n+#include <rte_malloc.h>\n+#include <cmdline_rdline.h>\n+#include <cmdline_parse.h>\n+#include <cmdline_parse_num.h>\n+#include <cmdline_parse_string.h>\n+#include <cmdline_parse_ipaddr.h>\n+#include <cmdline_parse_etheraddr.h>\n+#include <cmdline_socket.h>\n+#include <cmdline.h>\n+\n+#include \"thread.h\"\n+#include \"thread_fe.h\"\n+#include \"pipeline.h\"\n+#include \"pipeline_common_fe.h\"\n+#include \"app.h\"\n+\n+static inline void *\n+thread_msg_send_recv(struct app_params *app,\n+\tuint32_t socket_id, uint32_t core_id, uint32_t ht_id,\n+\tvoid *msg,\n+\tuint32_t timeout_ms)\n+{\n+\tstruct rte_ring *r_req = app_thread_msgq_in_get(app,\n+\t\tsocket_id, core_id, ht_id);\n+\tstruct rte_ring *r_rsp = app_thread_msgq_out_get(app,\n+\t\tsocket_id, core_id, ht_id);\n+\tuint64_t hz = rte_get_tsc_hz();\n+\tvoid *msg_recv;\n+\tuint64_t deadline;\n+\tint status;\n+\n+\t/* send */\n+\tdo {\n+\t\tstatus = rte_ring_sp_enqueue(r_req, (void *) msg);\n+\t} while (status == -ENOBUFS);\n+\n+\t/* recv */\n+\tdeadline = (timeout_ms) ?\n+\t\t(rte_rdtsc() + ((hz * timeout_ms) / 1000)) :\n+\t\tUINT64_MAX;\n+\n+\tdo {\n+\t\tif (rte_rdtsc() > deadline)\n+\t\t\treturn NULL;\n+\n+\t\tstatus = rte_ring_sc_dequeue(r_rsp, &msg_recv);\n+\t} while (status != 0);\n+\n+\treturn msg_recv;\n+}\n+\n+int\n+app_pipeline_enable(struct app_params *app,\n+\t\tuint32_t socket_id,\n+\t\tuint32_t core_id,\n+\t\tuint32_t hyper_th_id,\n+\t\tuint32_t pipeline_id)\n+{\n+\tstruct thread_pipeline_enable_msg_req *req;\n+\tstruct thread_pipeline_enable_msg_rsp *rsp;\n+\tint thread_id;\n+\tstruct app_pipeline_data *p;\n+\tstruct app_pipeline_params *p_params;\n+\tstruct pipeline_type *p_type;\n+\tint status;\n+\n+\tif (app_pipeline_data(app, pipeline_id) == NULL)\n+\t\treturn -1;\n+\n+\tthread_id = cpu_core_map_get_lcore_id(app->core_map,\n+\t\t\tsocket_id,\n+\t\t\tcore_id,\n+\t\t\thyper_th_id);\n+\n+\tif (thread_id < 0)\n+\t\treturn -1;\n+\n+\tp = &app->pipeline_data[pipeline_id];\n+\tp_params = &app->pipeline_params[pipeline_id];\n+\tp_type = app_pipeline_type_find(app, p_params->type);\n+\n+\tif (p->enabled == 1)\n+\t\treturn -1;\n+\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL)\n+\t\treturn -1;\n+\n+\treq->type = THREAD_MSG_REQ_PIPELINE_ENABLE;\n+\treq->pipeline_id = pipeline_id;\n+\treq->be = p->be;\n+\treq->f_run = p_type->be_ops->f_run;\n+\treq->f_timer = p_type->be_ops->f_timer;\n+\treq->timer_period = p->timer_period;\n+\n+\trsp = thread_msg_send_recv(app,\n+\t\tsocket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);\n+\tif (rsp == NULL)\n+\t\treturn -1;\n+\n+\tstatus = rsp->status;\n+\tapp_msg_free(app, rsp);\n+\n+\tif (status != 0)\n+\t\treturn -1;\n+\n+\tp->enabled = 1;\n+\treturn 0;\n+}\n+\n+int\n+app_pipeline_disable(struct app_params *app,\n+\t\tuint32_t socket_id,\n+\t\tuint32_t core_id,\n+\t\tuint32_t hyper_th_id,\n+\t\tuint32_t pipeline_id)\n+{\n+\tstruct thread_pipeline_disable_msg_req *req;\n+\tstruct thread_pipeline_disable_msg_rsp *rsp;\n+\tint thread_id;\n+\tstruct app_pipeline_data *p;\n+\tint status;\n+\n+\tif (app_pipeline_data(app, pipeline_id) == NULL)\n+\t\treturn -1;\n+\n+\tif (strcmp(app->pipeline_params[pipeline_id].type, \"MASTER\") == 0)\n+\t\treturn -1;\n+\n+\tthread_id = cpu_core_map_get_lcore_id(app->core_map,\n+\t\t\tsocket_id,\n+\t\t\tcore_id,\n+\t\t\thyper_th_id);\n+\n+\tif (thread_id < 0)\n+\t\treturn -1;\n+\n+\tp = &app->pipeline_data[pipeline_id];\n+\n+\tif (p->enabled == 0)\n+\t\treturn -1;\n+\n+\treq = app_msg_alloc(app);\n+\tif (req == NULL)\n+\t\treturn -1;\n+\n+\treq->type = THREAD_MSG_REQ_PIPELINE_DISABLE;\n+\treq->pipeline_id = pipeline_id;\n+\n+\trsp = thread_msg_send_recv(app,\n+\t\tsocket_id, core_id, hyper_th_id, req, MSG_TIMEOUT_DEFAULT);\n+\n+\tif (rsp == NULL)\n+\t\treturn -1;\n+\n+\tstatus = rsp->status;\n+\tapp_msg_free(app, rsp);\n+\n+\tif (status != 0)\n+\t\treturn -1;\n+\n+\tp->enabled = 0;\n+\treturn 0;\n+}\n+\n+/*\n+ * pipeline enable\n+ */\n+\n+struct cmd_pipeline_enable_result {\n+\tcmdline_fixed_string_t t_string;\n+\tcmdline_fixed_string_t t_id_string;\n+\tcmdline_fixed_string_t pipeline_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t enable_string;\n+};\n+\n+static void\n+cmd_pipeline_enable_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\t void *data)\n+{\n+\tstruct cmd_pipeline_enable_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tint status;\n+\tuint32_t core_id, socket_id, hyper_th_id;\n+\n+\tif (parse_pipeline_core(&socket_id,\n+\t\t\t&core_id,\n+\t\t\t&hyper_th_id,\n+\t\t\tparams->t_id_string) != 0) {\n+\t\tprintf(\"Command failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tstatus = app_pipeline_enable(app,\n+\t\t\tsocket_id,\n+\t\t\tcore_id,\n+\t\t\thyper_th_id,\n+\t\t\tparams->pipeline_id);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_pipeline_enable_t_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, \"t\");\n+\n+cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string,\n+\t\tNULL);\n+\n+cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string,\n+\t\t\"pipeline\");\n+\n+cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id,\n+\t\tUINT32);\n+\n+cmdline_parse_token_string_t cmd_pipeline_enable_enable_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string,\n+\t\t\"enable\");\n+\n+cmdline_parse_inst_t cmd_pipeline_enable = {\n+\t.f = cmd_pipeline_enable_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Enable pipeline on specified core\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pipeline_enable_t_string,\n+\t\t(void *)&cmd_pipeline_enable_t_id_string,\n+\t\t(void *)&cmd_pipeline_enable_pipeline_string,\n+\t\t(void *)&cmd_pipeline_enable_pipeline_id,\n+\t\t(void *)&cmd_pipeline_enable_enable_string,\n+\t\tNULL,\n+\t},\n+};\n+\n+/*\n+ * pipeline disable\n+ */\n+\n+struct cmd_pipeline_disable_result {\n+\tcmdline_fixed_string_t t_string;\n+\tcmdline_fixed_string_t t_id_string;\n+\tcmdline_fixed_string_t pipeline_string;\n+\tuint32_t pipeline_id;\n+\tcmdline_fixed_string_t disable_string;\n+};\n+\n+static void\n+cmd_pipeline_disable_parsed(\n+\tvoid *parsed_result,\n+\t__rte_unused struct cmdline *cl,\n+\t void *data)\n+{\n+\tstruct cmd_pipeline_disable_result *params = parsed_result;\n+\tstruct app_params *app = data;\n+\tint status;\n+\tuint32_t core_id, socket_id, hyper_th_id;\n+\n+\tif (parse_pipeline_core(&socket_id,\n+\t\t\t&core_id,\n+\t\t\t&hyper_th_id,\n+\t\t\tparams->t_id_string) != 0) {\n+\t\tprintf(\"Command failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tstatus = app_pipeline_disable(app,\n+\t\t\tsocket_id,\n+\t\t\tcore_id,\n+\t\t\thyper_th_id,\n+\t\t\tparams->pipeline_id);\n+\n+\tif (status != 0)\n+\t\tprintf(\"Command failed\\n\");\n+}\n+\n+cmdline_parse_token_string_t cmd_pipeline_disable_t_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, \"t\");\n+\n+cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string,\n+\t\tNULL);\n+\n+cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result,\n+\t\tpipeline_string, \"pipeline\");\n+\n+cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id =\n+\tTOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id,\n+\t\tUINT32);\n+\n+cmdline_parse_token_string_t cmd_pipeline_disable_disable_string =\n+\tTOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string,\n+\t\t\"disable\");\n+\n+cmdline_parse_inst_t cmd_pipeline_disable = {\n+\t.f = cmd_pipeline_disable_parsed,\n+\t.data = NULL,\n+\t.help_str = \"Disable pipeline on specified core\",\n+\t.tokens = {\n+\t\t(void *)&cmd_pipeline_disable_t_string,\n+\t\t(void *)&cmd_pipeline_disable_t_id_string,\n+\t\t(void *)&cmd_pipeline_disable_pipeline_string,\n+\t\t(void *)&cmd_pipeline_disable_pipeline_id,\n+\t\t(void *)&cmd_pipeline_disable_disable_string,\n+\t\tNULL,\n+\t},\n+};\n+\n+static cmdline_parse_ctx_t thread_cmds[] = {\n+\t(cmdline_parse_inst_t *) &cmd_pipeline_enable,\n+\t(cmdline_parse_inst_t *) &cmd_pipeline_disable,\n+\tNULL,\n+};\n+\n+int\n+app_pipeline_thread_cmd_push(struct app_params *app)\n+{\n+\tuint32_t n_cmds, i;\n+\n+\t/* Check for available slots in the application commands array */\n+\tn_cmds = RTE_DIM(thread_cmds) - 1;\n+\tif (n_cmds > APP_MAX_CMDS - app->n_cmds)\n+\t\treturn -ENOMEM;\n+\n+\t/* Push thread commands into the application */\n+\tmemcpy(&app->cmds[app->n_cmds],\n+\t\t\tthread_cmds,\n+\t\tn_cmds * sizeof(cmdline_parse_ctx_t *));\n+\n+\tfor (i = 0; i < n_cmds; i++)\n+\t\tapp->cmds[app->n_cmds + i]->data = app;\n+\n+\tapp->n_cmds += n_cmds;\n+\tapp->cmds[app->n_cmds] = NULL;\n+\n+\treturn 0;\n+}\ndiff --git a/examples/ip_pipeline/thread_fe.h b/examples/ip_pipeline/thread_fe.h\nnew file mode 100644\nindex 0000000..52352c1\n--- /dev/null\n+++ b/examples/ip_pipeline/thread_fe.h\n@@ -0,0 +1,95 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef THREAD_FE_H_\n+#define THREAD_FE_H_\n+\n+static inline struct rte_ring *\n+app_thread_msgq_in_get(struct app_params *app,\n+\t\tuint32_t socket_id, uint32_t core_id, uint32_t ht_id)\n+{\n+\tchar msgq_name[32];\n+\tssize_t param_idx;\n+\n+\tsnprintf(msgq_name, sizeof(msgq_name),\n+\t\t\"MSGQ-REQ-CORE-s%\" PRIu32 \"c%\" PRIu32 \"%s\",\n+\t\tsocket_id,\n+\t\tcore_id,\n+\t\t(ht_id) ? \"h\" : \"\");\n+\tparam_idx = APP_PARAM_FIND(app->msgq_params, msgq_name);\n+\n+\tif (param_idx < 0)\n+\t\treturn NULL;\n+\n+\treturn app->msgq[param_idx];\n+}\n+\n+static inline struct rte_ring *\n+app_thread_msgq_out_get(struct app_params *app,\n+\t\tuint32_t socket_id, uint32_t core_id, uint32_t ht_id)\n+{\n+\tchar msgq_name[32];\n+\tssize_t param_idx;\n+\n+\tsnprintf(msgq_name, sizeof(msgq_name),\n+\t\t\"MSGQ-RSP-CORE-s%\" PRIu32 \"c%\" PRIu32 \"%s\",\n+\t\tsocket_id,\n+\t\tcore_id,\n+\t\t(ht_id) ? \"h\" : \"\");\n+\tparam_idx = APP_PARAM_FIND(app->msgq_params, msgq_name);\n+\n+\tif (param_idx < 0)\n+\t\treturn NULL;\n+\n+\treturn app->msgq[param_idx];\n+\n+}\n+\n+int\n+app_pipeline_thread_cmd_push(struct app_params *app);\n+\n+int\n+app_pipeline_enable(struct app_params *app,\n+\t\tuint32_t core_id,\n+\t\tuint32_t socket_id,\n+\t\tuint32_t hyper_th_id,\n+\t\tuint32_t pipeline_id);\n+\n+int\n+app_pipeline_disable(struct app_params *app,\n+\t\tuint32_t core_id,\n+\t\tuint32_t socket_id,\n+\t\tuint32_t hyper_th_id,\n+\t\tuint32_t pipeline_id);\n+\n+#endif /* THREAD_FE_H_ */\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "1/1"
    ]
}