get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 13520,
    "url": "http://patches.dpdk.org/api/patches/13520/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/3EB4FA525960D640B5BDFFD6A3D8912647A02427@IRSMSX108.ger.corp.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": "<3EB4FA525960D640B5BDFFD6A3D8912647A02427@IRSMSX108.ger.corp.intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/3EB4FA525960D640B5BDFFD6A3D8912647A02427@IRSMSX108.ger.corp.intel.com",
    "date": "2016-06-13T10:25:15",
    "name": "[dpdk-dev] port: add kni interface support",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "a65bf0ac39cdb552a33749654db69d1d35962758",
    "submitter": {
        "id": 19,
        "url": "http://patches.dpdk.org/api/people/19/?format=api",
        "name": "Cristian Dumitrescu",
        "email": "cristian.dumitrescu@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/3EB4FA525960D640B5BDFFD6A3D8912647A02427@IRSMSX108.ger.corp.intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/13520/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/13520/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 105F6558E;\n\tMon, 13 Jun 2016 12:25:22 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 500F92BC3\n\tfor <dev@dpdk.org>; Mon, 13 Jun 2016 12:25:19 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby orsmga102.jf.intel.com with ESMTP; 13 Jun 2016 03:25:18 -0700",
            "from irsmsx102.ger.corp.intel.com ([163.33.3.155])\n\tby FMSMGA003.fm.intel.com with ESMTP; 13 Jun 2016 03:25:17 -0700",
            "from irsmsx108.ger.corp.intel.com ([169.254.11.183]) by\n\tIRSMSX102.ger.corp.intel.com ([169.254.2.10]) with mapi id\n\t14.03.0248.002; Mon, 13 Jun 2016 11:25:16 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.26,466,1459839600\"; d=\"scan'208\";a=\"718196089\"",
        "From": "\"Dumitrescu, Cristian\" <cristian.dumitrescu@intel.com>",
        "To": "WeiJie Zhuang <zhuangwj@gmail.com>",
        "CC": "\"dev@dpdk.org\" <dev@dpdk.org>, \"Singh, Jasvinder\"\n\t<jasvinder.singh@intel.com>, \"Yigit, Ferruh\" <ferruh.yigit@intel.com>",
        "Thread-Topic": "[PATCH] port: add kni interface support",
        "Thread-Index": "AQHRuNPzqUvoK3y1DESiX5+hyUDcX5/hyG9ggAV8CeA=",
        "Date": "Mon, 13 Jun 2016 10:25:15 +0000",
        "Message-ID": "<3EB4FA525960D640B5BDFFD6A3D8912647A02427@IRSMSX108.ger.corp.intel.com>",
        "References": "<1464325653-6912-1-git-send-email-zhuangwj@gmail.com>\n\t<1464434757-10860-1-git-send-email-zhuangwj@gmail.com>\n\t<3EB4FA525960D640B5BDFFD6A3D8912647A00F57@IRSMSX108.ger.corp.intel.com>",
        "In-Reply-To": "<3EB4FA525960D640B5BDFFD6A3D8912647A00F57@IRSMSX108.ger.corp.intel.com>",
        "Accept-Language": "en-US",
        "Content-Language": "en-US",
        "X-MS-Has-Attach": "",
        "X-MS-TNEF-Correlator": "",
        "x-titus-metadata-40": "eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYmU1MWVmNjMtZjFmZC00MjdjLTk4ZDEtYzM0NDZiOTg5ZGU5IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX0lDIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE1LjkuNi42IiwiVHJ1c3RlZExhYmVsSGFzaCI6ImNNbW9SUld3TXNHaEVDNWV2eW5JUnNzXC9aczJlZGNqZ2hsZVZxZ3dzMWJBPSJ9",
        "x-ctpclassification": "CTP_IC",
        "x-originating-ip": "[163.33.239.182]",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "quoted-printable",
        "MIME-Version": "1.0",
        "Subject": "Re: [dpdk-dev] [PATCH] port: add kni interface support",
        "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": "Hi Ethan,\n\nIn the process of testing your patch, I actually had to do the rebase on the latest code and fix all the comments that I previously sent as part of my reply. I also did a few other cosmetic changes and fixes required by the latest code (see below), therefore I think it makes sense to send you this code for quick review rather than have you spend time doing the same work. It would also save some iterations on the email list and speed up the integration of this patch.\n\nPlease review this code and let us know as soon as possible if you are OK with us sending it as the next version of this patch keeping your initial signoff as well. Thank you!\n\nChanges included in the code below:\n1. Rebase on top of latest DPDK head\n2. Fixing all the previous code comments\n3. Fix the binding of KNI device kernel space thread to CPU core (struct app_pktq_kni_params::force_bind)\n4. The KNI requests handled by master pipeline rather than on data path (pipeline_master_be.c: call to rte_kni_handle_request())\n5. Fixing the tracking feature for KNI (pipeline_common_fe.c: function app_pipeline_track_pktq_out_to_link())\n6. Enhanced config file with two KNI interfaces connected using a Linux kernel bridge (./config/kni.cfg)\n7. Cosmetic improvements\n\nRegards,\nCristian",
    "diff": "diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h\nold mode 100644\nnew mode 100755\nindex 848244a..555c6bd\n--- a/examples/ip_pipeline/app.h\n+++ b/examples/ip_pipeline/app.h\n@@ -44,6 +44,7 @@\n #include <cmdline_parse.h>\n \n #include <rte_ethdev.h>\n+#include <rte_kni.h>\n \n #include \"cpu_core_map.h\"\n #include \"pipeline.h\"\n@@ -158,6 +159,20 @@ struct app_pktq_tm_params {\n \tuint32_t burst_write;\n };\n \n+struct app_pktq_kni_params {\n+\tchar *name;\n+\tuint32_t parsed;\n+\n+\tuint32_t socket_id;\n+\tuint32_t core_id;\n+\tuint32_t hyper_th_id;\n+\tuint32_t force_bind;\n+\n+\tuint32_t mempool_id; /* Position in the app->mempool_params */\n+\tuint32_t burst_read;\n+\tuint32_t burst_write;\n+};\n+\n struct app_pktq_source_params {\n \tchar *name;\n \tuint32_t parsed;\n@@ -185,6 +200,7 @@ enum app_pktq_in_type {\n \tAPP_PKTQ_IN_HWQ,\n \tAPP_PKTQ_IN_SWQ,\n \tAPP_PKTQ_IN_TM,\n+\tAPP_PKTQ_IN_KNI,\n \tAPP_PKTQ_IN_SOURCE,\n };\n \n@@ -197,6 +213,7 @@ enum app_pktq_out_type {\n \tAPP_PKTQ_OUT_HWQ,\n \tAPP_PKTQ_OUT_SWQ,\n \tAPP_PKTQ_OUT_TM,\n+\tAPP_PKTQ_OUT_KNI,\n \tAPP_PKTQ_OUT_SINK,\n };\n \n@@ -420,6 +437,8 @@ struct app_eal_params {\n \n #define APP_MAX_PKTQ_TM                          APP_MAX_LINKS\n \n+#define APP_MAX_PKTQ_KNI                         APP_MAX_LINKS\n+\n #ifndef APP_MAX_PKTQ_SOURCE\n #define APP_MAX_PKTQ_SOURCE                      64\n #endif\n@@ -471,6 +490,7 @@ struct app_params {\n \tstruct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT];\n \tstruct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ];\n \tstruct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM];\n+\tstruct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI];\n \tstruct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE];\n \tstruct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK];\n \tstruct app_msgq_params msgq_params[APP_MAX_MSGQ];\n@@ -482,6 +502,7 @@ struct app_params {\n \tuint32_t n_pktq_hwq_out;\n \tuint32_t n_pktq_swq;\n \tuint32_t n_pktq_tm;\n+\tuint32_t n_pktq_kni;\n \tuint32_t n_pktq_source;\n \tuint32_t n_pktq_sink;\n \tuint32_t n_msgq;\n@@ -495,6 +516,7 @@ struct app_params {\n \tstruct app_link_data link_data[APP_MAX_LINKS];\n \tstruct rte_ring *swq[APP_MAX_PKTQ_SWQ];\n \tstruct rte_sched_port *tm[APP_MAX_PKTQ_TM];\n+\tstruct rte_kni *kni[APP_MAX_PKTQ_KNI];\n \tstruct rte_ring *msgq[APP_MAX_MSGQ];\n \tstruct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES];\n \tstruct app_pipeline_data pipeline_data[APP_MAX_PIPELINES];\n@@ -758,6 +780,66 @@ app_tm_get_reader(struct app_params *app,\n }\n \n static inline uint32_t\n+app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni)\n+{\n+\tuint32_t pos = kni - app->kni_params;\n+\tuint32_t n_pipelines = RTE_MIN(app->n_pipelines,\n+\t\tRTE_DIM(app->pipeline_params));\n+\tuint32_t n_readers = 0, i;\n+\n+\tfor (i = 0; i < n_pipelines; i++) {\n+\t\tstruct app_pipeline_params *p = &app->pipeline_params[i];\n+\t\tuint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));\n+\t\tuint32_t j;\n+\n+\t\tfor (j = 0; j < n_pktq_in; j++) {\n+\t\t\tstruct app_pktq_in_params *pktq = &p->pktq_in[j];\n+\n+\t\t\tif ((pktq->type == APP_PKTQ_IN_KNI) &&\n+\t\t\t\t(pktq->id == pos))\n+\t\t\t\tn_readers++;\n+\t\t}\n+\t}\n+\n+\treturn n_readers;\n+}\n+\n+static inline struct app_pipeline_params *\n+app_kni_get_reader(struct app_params *app,\n+\tstruct app_pktq_kni_params *kni,\n+\tuint32_t *pktq_in_id)\n+{\n+\tstruct app_pipeline_params *reader = NULL;\n+\tuint32_t pos = kni - app->kni_params;\n+\tuint32_t n_pipelines = RTE_MIN(app->n_pipelines,\n+\t\tRTE_DIM(app->pipeline_params));\n+\tuint32_t n_readers = 0, id = 0, i;\n+\n+\tfor (i = 0; i < n_pipelines; i++) {\n+\t\tstruct app_pipeline_params *p = &app->pipeline_params[i];\n+\t\tuint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));\n+\t\tuint32_t j;\n+\n+\t\tfor (j = 0; j < n_pktq_in; j++) {\n+\t\t\tstruct app_pktq_in_params *pktq = &p->pktq_in[j];\n+\n+\t\t\tif ((pktq->type == APP_PKTQ_IN_KNI) &&\n+\t\t\t\t(pktq->id == pos)) {\n+\t\t\t\tn_readers++;\n+\t\t\t\treader = p;\n+\t\t\t\tid = j;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (n_readers != 1)\n+\t\treturn NULL;\n+\n+\t*pktq_in_id = id;\n+\treturn reader;\n+}\n+\n+static inline uint32_t\n app_source_get_readers(struct app_params *app,\n struct app_pktq_source_params *source)\n {\n@@ -954,6 +1036,67 @@ app_tm_get_writer(struct app_params *app,\n }\n \n static inline uint32_t\n+app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni)\n+{\n+\tuint32_t pos = kni - app->kni_params;\n+\tuint32_t n_pipelines = RTE_MIN(app->n_pipelines,\n+\t\tRTE_DIM(app->pipeline_params));\n+\tuint32_t n_writers = 0, i;\n+\n+\tfor (i = 0; i < n_pipelines; i++) {\n+\t\tstruct app_pipeline_params *p = &app->pipeline_params[i];\n+\t\tuint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,\n+\t\t\tRTE_DIM(p->pktq_out));\n+\t\tuint32_t j;\n+\n+\t\tfor (j = 0; j < n_pktq_out; j++) {\n+\t\t\tstruct app_pktq_out_params *pktq = &p->pktq_out[j];\n+\n+\t\t\tif ((pktq->type == APP_PKTQ_OUT_KNI) &&\n+\t\t\t\t(pktq->id == pos))\n+\t\t\t\tn_writers++;\n+\t\t}\n+\t}\n+\n+\treturn n_writers;\n+}\n+\n+static inline struct app_pipeline_params *\n+app_kni_get_writer(struct app_params *app,\n+\tstruct app_pktq_kni_params *kni,\n+\tuint32_t *pktq_out_id)\n+{\n+\tstruct app_pipeline_params *writer = NULL;\n+\tuint32_t pos = kni - app->kni_params;\n+\tuint32_t n_pipelines = RTE_MIN(app->n_pipelines,\n+\t\tRTE_DIM(app->pipeline_params));\n+\tuint32_t n_writers = 0, id = 0, i;\n+\n+\tfor (i = 0; i < n_pipelines; i++) {\n+\t\tstruct app_pipeline_params *p = &app->pipeline_params[i];\n+\t\tuint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,\n+\t\t\tRTE_DIM(p->pktq_out));\n+\t\tuint32_t j;\n+\n+\t\tfor (j = 0; j < n_pktq_out; j++) {\n+\t\t\tstruct app_pktq_out_params *pktq = &p->pktq_out[j];\n+\n+\t\t\tif ((pktq->type == APP_PKTQ_OUT_KNI) &&\n+\t\t\t\t(pktq->id == pos))\n+\t\t\t\tn_writers++;\n+\t\t\t\twriter = p;\n+\t\t\t\tid = j;\n+\t\t}\n+\t}\n+\n+\tif (n_writers != 1)\n+\t\treturn NULL;\n+\n+\t*pktq_out_id = id;\n+\treturn writer;\n+}\n+\n+static inline uint32_t\n app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink)\n {\n \tuint32_t pos = sink - app->sink_params;\n@@ -1051,6 +1194,22 @@ app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm)\n \treturn &app->link_params[link_param_idx];\n }\n \n+static inline struct app_link_params *\n+app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni)\n+{\n+\tchar link_name[APP_PARAM_NAME_SIZE];\n+\tuint32_t link_id;\n+\tssize_t link_param_idx;\n+\n+\tsscanf(p_kni->name, \"KNI%\" PRIu32, &link_id);\n+\tsprintf(link_name, \"LINK%\" PRIu32, link_id);\n+\tlink_param_idx = APP_PARAM_FIND(app->link_params, link_name);\n+\tAPP_CHECK((link_param_idx >= 0),\n+\t\t\"Cannot find %s for %s\", link_name, p_kni->name);\n+\n+\treturn &app->link_params[link_param_idx];\n+}\n+\n void app_pipeline_params_get(struct app_params *app,\n \tstruct app_pipeline_params *p_in,\n \tstruct pipeline_params *p_out);\ndiff --git a/examples/ip_pipeline/config/kni.cfg b/examples/ip_pipeline/config/kni.cfg\nnew file mode 100755\nindex 0000000..55ad966\n--- /dev/null\n+++ b/examples/ip_pipeline/config/kni.cfg\n@@ -0,0 +1,67 @@\n+;   BSD LICENSE\n+;\n+;   Copyright(c) 2015-2016 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+;            |              |  KNI0  |                      |\n+; RXQ0.0 --->|              |------->|--+                   |\n+;            |              |  KNI1  |  | br0               |\n+; TXQ0.0 <---|              |<-------|<-+                   |\n+;            | Pass-through |        |     Linux Kernel     |\n+;            |     (P1)     |        |     Network Stack    |\n+;            |              |  KNI0  |                      |\n+; RXQ0.0 --->|              |------->|--+                   |\n+;            |              |  KNI1  |  | br0               |\n+; TXQ0.0 <---|              |<-------|<-+                   |\n+;            |______________|        |______________________|\n+;\n+; Insert Linux kernel KNI module:\n+;    [Linux]$ insmod rte_kni.ko\n+;\n+; Configure Linux kernel bridge between KNI0 and KNI1 interfaces:\n+;    [Linux]$ ifconfig KNI0 up\n+;    [Linux]$ ifconfig KNI1 up\n+;    [Linux]$ brctl addbr \"br0\"\n+;    [Linux]$ brctl addif br0 KNI0\n+;    [Linux]$ brctl addif br0 KNI1\n+;    [Linux]$ ifconfig br0 up\n+\n+[EAL]\n+log_level = 0\n+\n+[PIPELINE0]\n+type = MASTER\n+core = 0\n+\n+[PIPELINE1]\n+type = PASS-THROUGH\n+core = 1\n+pktq_in = RXQ0.0 KNI1 RXQ1.0 KNI0\n+pktq_out = KNI0 TXQ1.0 KNI1 TXQ0.0\ndiff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c\nold mode 100644\nnew mode 100755\nindex 18f57be..01fa030\n--- a/examples/ip_pipeline/config_check.c\n+++ b/examples/ip_pipeline/config_check.c\n@@ -316,6 +316,29 @@ check_tms(struct app_params *app)\n }\n \n static void\n+check_knis(struct app_params *app) {\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < app->n_pktq_kni; i++) {\n+\t\tstruct app_pktq_kni_params *p = &app->kni_params[i];\n+\t\tuint32_t n_readers = app_kni_get_readers(app, p);\n+\t\tuint32_t n_writers = app_kni_get_writers(app, p);\n+\n+\t\tAPP_CHECK((n_readers != 0),\n+\t\t\t\"%s has no reader\\n\", p->name);\n+\n+\t\tAPP_CHECK((n_readers == 1),\n+\t\t\t\"%s has more than one reader\\n\", p->name);\n+\n+\t\tAPP_CHECK((n_writers != 0),\n+\t\t\t\"%s has no writer\\n\", p->name);\n+\n+\t\tAPP_CHECK((n_writers == 1),\n+\t\t\t\"%s has more than one writer\\n\", p->name);\n+\t}\n+}\n+\n+static void\n check_sources(struct app_params *app)\n {\n \tuint32_t i;\n@@ -453,6 +476,7 @@ app_config_check(struct app_params *app)\n \tcheck_txqs(app);\n \tcheck_swqs(app);\n \tcheck_tms(app);\n+\tcheck_knis(app);\n \tcheck_sources(app);\n \tcheck_sinks(app);\n \tcheck_msgqs(app);\ndiff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c\nold mode 100644\nnew mode 100755\nindex 504018e..a286291\n--- a/examples/ip_pipeline/config_parse.c\n+++ b/examples/ip_pipeline/config_parse.c\n@@ -189,6 +189,18 @@ struct app_pktq_tm_params default_tm_params = {\n \t.burst_write = 32,\n };\n \n+struct app_pktq_kni_params default_kni_params = {\n+\t.parsed = 0,\n+\t.socket_id = 0,\n+\t.core_id = 0,\n+\t.hyper_th_id = 0,\n+\t.force_bind = 0,\n+\n+\t.mempool_id = 0,\n+\t.burst_read = 32,\n+\t.burst_write = 32,\n+};\n+\n struct app_pktq_source_params default_source_params = {\n \t.parsed = 0,\n \t.mempool_id = 0,\n@@ -300,6 +312,18 @@ app_print_usage(char *prgname)\n \tlink_param_pos;\t\t\t\t\t\t\t\\\n })\n \n+#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name)\t\t\t\t\\\n+({\t\t\t\t\t\t\t\t\t\\\n+\tchar link_name[APP_PARAM_NAME_SIZE];\t\t\t\t\\\n+\tssize_t link_param_pos;\t\t\t\t\t\t\\\n+\tuint32_t link_id;\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tsscanf((kni_name), \"KNI%\" SCNu32, &link_id);\t\t\t\\\n+\tsprintf(link_name, \"LINK%\" PRIu32, link_id);\t\t\t\\\n+\tlink_param_pos = APP_PARAM_ADD((app)->link_params, link_name);\t\\\n+\tlink_param_pos;\t\t\t\t\t\t\t\\\n+})\n+\n #define PARSE_CHECK_DUPLICATE_SECTION(obj)\t\t\t\t\\\n do {\t\t\t\t\t\t\t\t\t\\\n \tAPP_CHECK(((obj)->parsed == 0),\t\t\t\t\t\\\n@@ -826,6 +850,10 @@ parse_pipeline_pktq_in(struct app_params *app,\n \t\t\ttype = APP_PKTQ_IN_TM;\n \t\t\tid = APP_PARAM_ADD(app->tm_params, name);\n \t\t\tAPP_PARAM_ADD_LINK_FOR_TM(app, name);\n+\t\t} else if (validate_name(name, \"KNI\", 1) == 0) {\n+\t\t\ttype = APP_PKTQ_IN_KNI;\n+\t\t\tid = APP_PARAM_ADD(app->kni_params, name);\n+\t\t\tAPP_PARAM_ADD_LINK_FOR_KNI(app, name);\n \t\t} else if (validate_name(name, \"SOURCE\", 1) == 0) {\n \t\t\ttype = APP_PKTQ_IN_SOURCE;\n \t\t\tid = APP_PARAM_ADD(app->source_params, name);\n@@ -871,6 +899,10 @@ parse_pipeline_pktq_out(struct app_params *app,\n \t\t\ttype = APP_PKTQ_OUT_TM;\n \t\t\tid = APP_PARAM_ADD(app->tm_params, name);\n \t\t\tAPP_PARAM_ADD_LINK_FOR_TM(app, name);\n+\t\t} else if (validate_name(name, \"KNI\", 1) == 0) {\n+\t\t\ttype = APP_PKTQ_OUT_KNI;\n+\t\t\tid = APP_PARAM_ADD(app->kni_params, name);\n+\t\t\tAPP_PARAM_ADD_LINK_FOR_KNI(app, name);\n \t\t} else if (validate_name(name, \"SINK\", 1) == 0) {\n \t\t\ttype = APP_PKTQ_OUT_SINK;\n \t\t\tid = APP_PARAM_ADD(app->sink_params, name);\n@@ -1816,7 +1848,7 @@ parse_tm(struct app_params *app,\n \tparam = &app->tm_params[param_idx];\n \tPARSE_CHECK_DUPLICATE_SECTION(param);\n \n-\tAPP_PARAM_ADD_LINK_FOR_TXQ(app, section_name);\n+\tAPP_PARAM_ADD_LINK_FOR_TM(app, section_name);\n \n \tfor (i = 0; i < n_entries; i++) {\n \t\tstruct rte_cfgfile_entry *ent = &entries[i];\n@@ -1853,6 +1885,87 @@ parse_tm(struct app_params *app,\n }\n \n static void\n+parse_kni(struct app_params *app,\n+\tconst char *section_name,\n+\tstruct rte_cfgfile *cfg)\n+{\n+\tstruct app_pktq_kni_params *param;\n+\tstruct rte_cfgfile_entry *entries;\n+\tint n_entries, i;\n+\tssize_t param_idx;\n+\n+\tn_entries = rte_cfgfile_section_num_entries(cfg, section_name);\n+\tPARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);\n+\n+\tentries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));\n+\tPARSE_ERROR_MALLOC(entries != NULL);\n+\n+\trte_cfgfile_section_entries(cfg, section_name, entries, n_entries);\n+\n+\tparam_idx = APP_PARAM_ADD(app->kni_params, section_name);\n+\tparam = &app->kni_params[param_idx];\n+\tPARSE_CHECK_DUPLICATE_SECTION(param);\n+\n+\tAPP_PARAM_ADD_LINK_FOR_KNI(app, section_name);\n+\n+\tfor (i = 0; i < n_entries; i++) {\n+\t\tstruct rte_cfgfile_entry *ent = &entries[i];\n+\n+\t\tif (strcmp(ent->name, \"core\") == 0) {\n+\t\t\tint status = parse_pipeline_core(\n+\t\t\t\t&param->socket_id,\n+\t\t\t\t&param->core_id,\n+\t\t\t\t&param->hyper_th_id,\n+\t\t\t\tent->value);\n+\n+\t\t\tparam->force_bind = 1;\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"mempool\") == 0) {\n+\t\t\tint status = validate_name(ent->value,\n+\t\t\t\t\"MEMPOOL\", 1);\n+\t\t\tssize_t idx;\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\n+\t\t\tidx = APP_PARAM_ADD(app->mempool_params, ent->value);\n+\t\t\tparam->mempool_id = idx;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_read\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->burst_read,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (strcmp(ent->name, \"burst_write\") == 0) {\n+\t\t\tint status = parser_read_uint32(&param->burst_write,\n+\t\t\t\tent->value);\n+\n+\t\t\tPARSE_ERROR((status == 0), section_name,\n+\t\t\t\tent->name);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* unrecognized */\n+\t\tPARSE_ERROR_INVALID(0, section_name, ent->name);\n+\t}\n+\n+\tparam->parsed = 1;\n+\n+\tfree(entries);\n+}\n+\n+static void\n parse_source(struct app_params *app,\n \tconst char *section_name,\n \tstruct rte_cfgfile *cfg)\n@@ -2147,6 +2260,7 @@ static const struct config_section cfg_file_scheme[] = {\n \t{\"TXQ\", 2, parse_txq},\n \t{\"SWQ\", 1, parse_swq},\n \t{\"TM\", 1, parse_tm},\n+\t{\"KNI\", 1, parse_kni},\n \t{\"SOURCE\", 1, parse_source},\n \t{\"SINK\", 1, parse_sink},\n \t{\"MSGQ-REQ-PIPELINE\", 1, parse_msgq_req_pipeline},\n@@ -2285,6 +2399,7 @@ app_config_parse(struct app_params *app, const char *file_name)\n \tAPP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out);\n \tAPP_PARAM_COUNT(app->swq_params, app->n_pktq_swq);\n \tAPP_PARAM_COUNT(app->tm_params, app->n_pktq_tm);\n+\tAPP_PARAM_COUNT(app->kni_params, app->n_pktq_kni);\n \tAPP_PARAM_COUNT(app->source_params, app->n_pktq_source);\n \tAPP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);\n \tAPP_PARAM_COUNT(app->msgq_params, app->n_msgq);\n@@ -2647,6 +2762,46 @@ save_tm_params(struct app_params *app, FILE *f)\n }\n \n static void\n+save_kni_params(struct app_params *app, FILE *f)\n+{\n+\tstruct app_pktq_kni_params *p;\n+\tsize_t i, count;\n+\n+\tcount = RTE_DIM(app->kni_params);\n+\tfor (i = 0; i < count; i++) {\n+\t\tp = &app->kni_params[i];\n+\t\tif (!APP_PARAM_VALID(p))\n+\t\t\tcontinue;\n+\n+\t\t/* section name */\n+\t\tfprintf(f, \"[%s]\\n\", p->name);\n+\n+\t\t/* core */\n+\t\tif (p->force_bind) {\n+\t\t\tfprintf(f, \"; force_bind = 1\\n\");\n+\t\t\tfprintf(f, \"core = s%\" PRIu32 \"c%\" PRIu32 \"%s\\n\",\n+\t\t\t\tp->socket_id,\n+\t\t\t\tp->core_id,\n+\t\t\t\t(p->hyper_th_id) ? \"h\" : \"\");\n+\t\t} else\n+\t\t\tfprintf(f, \"; force_bind = 0\\n\");\n+\n+\t\t/* mempool */\n+\t\tfprintf(f, \"%s = %s\\n\",\n+\t\t\t\"mempool\",\n+\t\t\tapp->mempool_params[p->mempool_id].name);\n+\n+\t\t/* burst_read */\n+\t\tfprintf(f, \"%s = %\" PRIu32 \"\\n\", \"burst_read\", p->burst_read);\n+\n+\t\t/* burst_write */\n+\t\tfprintf(f, \"%s = %\" PRIu32 \"\\n\", \"burst_write\", p->burst_read);\n+\n+\t\tfputc('\\n', f);\n+\t}\n+}\n+\n+static void\n save_source_params(struct app_params *app, FILE *f)\n {\n \tstruct app_pktq_source_params *p;\n@@ -2753,6 +2908,9 @@ save_pipeline_params(struct app_params *app, FILE *f)\n \t\t\t\tcase APP_PKTQ_IN_TM:\n \t\t\t\t\tname = app->tm_params[pp->id].name;\n \t\t\t\t\tbreak;\n+\t\t\t\tcase APP_PKTQ_IN_KNI:\n+\t\t\t\t\tname = app->kni_params[pp->id].name;\n+\t\t\t\t\tbreak;\n \t\t\t\tcase APP_PKTQ_IN_SOURCE:\n \t\t\t\t\tname = app->source_params[pp->id].name;\n \t\t\t\t\tbreak;\n@@ -2787,6 +2945,9 @@ save_pipeline_params(struct app_params *app, FILE *f)\n \t\t\t\tcase APP_PKTQ_OUT_TM:\n \t\t\t\t\tname = app->tm_params[pp->id].name;\n \t\t\t\t\tbreak;\n+\t\t\t\tcase APP_PKTQ_OUT_KNI:\n+\t\t\t\t\tname = app->kni_params[pp->id].name;\n+\t\t\t\t\tbreak;\n \t\t\t\tcase APP_PKTQ_OUT_SINK:\n \t\t\t\t\tname = app->sink_params[pp->id].name;\n \t\t\t\t\tbreak;\n@@ -2872,6 +3033,7 @@ app_config_save(struct app_params *app, const char *file_name)\n \tsave_txq_params(app, file);\n \tsave_swq_params(app, file);\n \tsave_tm_params(app, file);\n+\tsave_kni_params(app, file);\n \tsave_source_params(app, file);\n \tsave_sink_params(app, file);\n \tsave_msgq_params(app, file);\n@@ -2921,6 +3083,11 @@ app_config_init(struct app_params *app)\n \t\t\t&default_tm_params,\n \t\t\tsizeof(default_tm_params));\n \n+\tfor (i = 0; i < RTE_DIM(app->kni_params); i++)\n+\t\tmemcpy(&app->kni_params[i],\n+\t\t\t&default_kni_params,\n+\t\t\tsizeof(default_kni_params));\n+\n \tfor (i = 0; i < RTE_DIM(app->source_params); i++)\n \t\tmemcpy(&app->source_params[i],\n \t\t\t&default_source_params,\ndiff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c\nold mode 100644\nnew mode 100755\nindex 7120bab..0c76d91\n--- a/examples/ip_pipeline/init.c\n+++ b/examples/ip_pipeline/init.c\n@@ -1176,6 +1176,109 @@ app_init_tm(struct app_params *app)\n \t}\n }\n \n+static int\n+kni_change_mtu(uint8_t port_id, unsigned new_mtu) {\n+\tint ret;\n+\n+\tif (port_id >= rte_eth_dev_count())\n+\t\treturn -EINVAL;\n+\n+\tif (new_mtu > ETHER_MAX_LEN)\n+\t\treturn -EINVAL;\n+\n+\t/* Stop specific port */\n+\trte_eth_dev_stop(port_id);\n+\n+\t/* Set new MTU */\n+\tret = rte_eth_dev_set_mtu(port_id, new_mtu);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\t/* Restart specific port */\n+\tret = rte_eth_dev_start(port_id);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+static int\n+kni_config_network_interface(uint8_t port_id, uint8_t if_up) {\n+\tint ret = 0;\n+\n+\tif (port_id >= rte_eth_dev_count())\n+\t\treturn -EINVAL;\n+\n+\tif (if_up) {\n+\t\trte_eth_dev_stop(port_id);\n+\t\tret = rte_eth_dev_start(port_id);\n+\t} else\n+\t\trte_eth_dev_stop(port_id);\n+\n+\treturn ret;\n+}\n+\n+static void\n+app_init_kni(struct app_params *app) {\n+\tuint32_t i;\n+\n+\tif (app->n_pktq_kni == 0)\n+\t\treturn;\n+\n+\trte_kni_init(app->n_pktq_kni);\n+\n+\tfor (i = 0; i < app->n_pktq_kni; i++) {\n+\t\tstruct app_pktq_kni_params *p_kni = &app->kni_params[i];\n+\t\tstruct app_link_params *p_link;\n+\t\tstruct rte_eth_dev_info dev_info;\n+\t\tstruct app_mempool_params *mempool_params;\n+\t\tstruct rte_mempool *mempool;\n+\t\tstruct rte_kni_conf conf;\n+\t\tstruct rte_kni_ops ops;\n+\n+\t\t/* LINK */\n+\t\tp_link = app_get_link_for_kni(app, p_kni);\n+\t\tmemset(&dev_info, 0, sizeof(dev_info));\n+\t\trte_eth_dev_info_get(p_link->pmd_id, &dev_info);\n+\n+\t\t/* MEMPOOL */\n+\t\tmempool_params = &app->mempool_params[p_kni->mempool_id];\n+\t\tmempool = app->mempool[p_kni->mempool_id];\n+\n+\t\t/* KNI */\n+\t\tmemset(&conf, 0, sizeof(conf));\n+\t\tsnprintf(conf.name, RTE_KNI_NAMESIZE, \"%s\", p_kni->name);\n+\t\tconf.force_bind = p_kni->force_bind;\n+\t\tif (conf.force_bind) {\n+\t\t\tint lcore_id;\n+\n+\t\t\tlcore_id = cpu_core_map_get_lcore_id(app->core_map,\n+\t\t\t\tp_kni->socket_id,\n+\t\t\t\tp_kni->core_id,\n+\t\t\t\tp_kni->hyper_th_id);\n+\n+\t\t\tif (lcore_id < 0)\n+\t\t\t\trte_panic(\"%s invalid CPU core\\n\", p_kni->name);\n+\n+\t\t\tconf.core_id = (uint32_t) lcore_id;\n+\t\t}\n+\t\tconf.group_id = p_link->pmd_id;\n+\t\tconf.mbuf_size = mempool_params->buffer_size;\n+\t\tconf.addr = dev_info.pci_dev->addr;\n+\t\tconf.id = dev_info.pci_dev->id;\n+\n+\t\tmemset(&ops, 0, sizeof(ops));\n+\t\tops.port_id = (uint8_t) p_link->pmd_id;\n+\t\tops.change_mtu = kni_change_mtu;\n+\t\tops.config_network_if = kni_config_network_interface;\n+\n+\t\tAPP_LOG(app, HIGH, \"Initializing %s ...\", p_kni->name);\n+\t\tapp->kni[i] = rte_kni_alloc(mempool, &conf, &ops);\n+\t\tif (!app->kni[i])\n+\t\t\trte_panic(\"%s init error\\n\", p_kni->name);\n+\t}\n+}\n+\n static void\n app_init_msgq(struct app_params *app)\n {\n@@ -1285,6 +1388,11 @@ void app_pipeline_params_get(struct app_params *app,\n \t\t\tout->params.sched.sched = app->tm[in->id];\n \t\t\tout->burst_size = app->tm_params[in->id].burst_read;\n \t\t\tbreak;\n+\t\tcase APP_PKTQ_IN_KNI:\n+\t\t\tout->type = PIPELINE_PORT_IN_KNI_READER;\n+\t\t\tout->params.kni.kni = app->kni[in->id];\n+\t\t\tout->burst_size = app->kni_params[in->id].burst_read;\n+\t\t\tbreak;\n \t\tcase APP_PKTQ_IN_SOURCE:\n \t\t{\n \t\t\tuint32_t mempool_id =\n@@ -1409,7 +1517,8 @@ void app_pipeline_params_get(struct app_params *app,\n \t\t\t}\n \t\t\tbreak;\n \t\t}\n-\t\tcase APP_PKTQ_OUT_TM: {\n+\t\tcase APP_PKTQ_OUT_TM:\n+\t\t{\n \t\t\tstruct rte_port_sched_writer_params *params =\n \t\t\t\t&out->params.sched;\n \n@@ -1419,6 +1528,11 @@ void app_pipeline_params_get(struct app_params *app,\n \t\t\t\tapp->tm_params[in->id].burst_write;\n \t\t\tbreak;\n \t\t}\n+\t\tcase APP_PKTQ_OUT_KNI:\n+\t\t\tout->type = PIPELINE_PORT_OUT_KNI_WRITER;\n+\t\t\tout->params.kni.kni = app->kni[in->id];\n+\t\t\tout->params.kni.tx_burst_sz = app->kni_params[in->id].burst_write;\n+\t\t\tbreak;\n \t\tcase APP_PKTQ_OUT_SINK:\n \t\t{\n \t\t\tout->type = PIPELINE_PORT_OUT_SINK;\n@@ -1607,6 +1721,7 @@ int app_init(struct app_params *app)\n \tapp_init_link(app);\n \tapp_init_swq(app);\n \tapp_init_tm(app);\n+\tapp_init_kni(app);\n \tapp_init_msgq(app);\n \n \tapp_pipeline_common_cmd_push(app);\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c\nold mode 100644\nnew mode 100755\nindex 70c57e4..cd1d082\n--- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.c\n@@ -130,6 +130,33 @@ app_pipeline_track_pktq_out_to_link(struct app_params *app,\n \t\t\tbreak;\n \t\t}\n \n+\t\tcase APP_PKTQ_OUT_KNI:\n+\t\t{\n+\t\t\tstruct pipeline_params pp;\n+\t\t\tstruct pipeline_type *ptype;\n+\t\t\tstruct app_pktq_kni_params *kni;\n+\t\t\tuint32_t pktq_in_id;\n+\t\t\tint status;\n+\n+\t\t\tkni = &app->kni_params[pktq_out->id];\n+\t\t\tp = app_kni_get_reader(app, kni, &pktq_in_id);\n+\t\t\tif (p == NULL)\n+\t\t\t\treturn NULL;\n+\n+\t\t\tptype = app_pipeline_type_find(app, p->type);\n+\t\t\tif ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))\n+\t\t\t\treturn NULL;\n+\n+\t\t\tapp_pipeline_params_get(app, p, &pp);\n+\t\t\tstatus = ptype->fe_ops->f_track(&pp,\n+\t\t\t\tpktq_in_id,\n+\t\t\t\t&pktq_out_id);\n+\t\t\tif (status)\n+\t\t\t\treturn NULL;\n+\n+\t\t\tbreak;\n+\t\t}\n+\n \t\tcase APP_PKTQ_OUT_SINK:\n \t\tdefault:\n \t\t\treturn NULL;\ndiff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.c b/examples/ip_pipeline/pipeline/pipeline_master_be.c\nold mode 100644\nnew mode 100755\nindex 79869a4..ba2a863\n--- a/examples/ip_pipeline/pipeline/pipeline_master_be.c\n+++ b/examples/ip_pipeline/pipeline/pipeline_master_be.c\n@@ -105,6 +105,7 @@ pipeline_run(void *pipeline)\n {\n \tstruct pipeline_master *p = (struct pipeline_master *) pipeline;\n \tstruct app_params *app = p->app;\n+\tuint32_t i;\n \tint status;\n \n \t/* Application post-init phase */\n@@ -144,6 +145,10 @@ pipeline_run(void *pipeline)\n \t\trte_exit(0, \"Bye!\\n\");\n \t}\n \n+\t/* Handle KNI requests from Linux kernel */\n+\tfor (i = 0; i < app->n_pktq_kni; i++)\n+\t\trte_kni_handle_request(app->kni[i]);\n+\n \treturn 0;\n }\n \ndiff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h\nold mode 100644\nnew mode 100755\nindex 5501ab7..972708e\n--- a/examples/ip_pipeline/pipeline_be.h\n+++ b/examples/ip_pipeline/pipeline_be.h\n@@ -40,6 +40,7 @@\n #include <rte_port_ras.h>\n #include <rte_port_sched.h>\n #include <rte_port_source_sink.h>\n+#include <rte_port_kni.h>\n #include <rte_pipeline.h>\n \n enum pipeline_port_in_type {\n@@ -49,6 +50,7 @@ enum pipeline_port_in_type {\n \tPIPELINE_PORT_IN_RING_READER_IPV4_FRAG,\n \tPIPELINE_PORT_IN_RING_READER_IPV6_FRAG,\n \tPIPELINE_PORT_IN_SCHED_READER,\n+\tPIPELINE_PORT_IN_KNI_READER,\n \tPIPELINE_PORT_IN_SOURCE,\n };\n \n@@ -61,6 +63,7 @@ struct pipeline_port_in_params {\n \t\tstruct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag;\n \t\tstruct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag;\n \t\tstruct rte_port_sched_reader_params sched;\n+\t\tstruct rte_port_kni_reader_params kni;\n \t\tstruct rte_port_source_params source;\n \t} params;\n \tuint32_t burst_size;\n@@ -82,6 +85,8 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params  *p)\n \t\treturn (void *) &p->params.ring_ipv6_frag;\n \tcase PIPELINE_PORT_IN_SCHED_READER:\n \t\treturn (void *) &p->params.sched;\n+\tcase PIPELINE_PORT_IN_KNI_READER:\n+\t\treturn (void *) &p->params.kni;\n \tcase PIPELINE_PORT_IN_SOURCE:\n \t\treturn (void *) &p->params.source;\n \tdefault:\n@@ -105,6 +110,8 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params  *p)\n \t\treturn &rte_port_ring_reader_ipv6_frag_ops;\n \tcase PIPELINE_PORT_IN_SCHED_READER:\n \t\treturn &rte_port_sched_reader_ops;\n+\tcase PIPELINE_PORT_IN_KNI_READER:\n+\t\treturn &rte_port_kni_reader_ops;\n \tcase PIPELINE_PORT_IN_SOURCE:\n \t\treturn &rte_port_source_ops;\n \tdefault:\n@@ -122,6 +129,7 @@ enum pipeline_port_out_type {\n \tPIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,\n \tPIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,\n \tPIPELINE_PORT_OUT_SCHED_WRITER,\n+\tPIPELINE_PORT_OUT_KNI_WRITER,\n \tPIPELINE_PORT_OUT_SINK,\n };\n \n@@ -137,6 +145,7 @@ struct pipeline_port_out_params {\n \t\tstruct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras;\n \t\tstruct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras;\n \t\tstruct rte_port_sched_writer_params sched;\n+\t\tstruct rte_port_kni_writer_params kni;\n \t\tstruct rte_port_sink_params sink;\n \t} params;\n };\n@@ -163,6 +172,8 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params  *p)\n \t\treturn (void *) &p->params.ring_ipv6_ras;\n \tcase PIPELINE_PORT_OUT_SCHED_WRITER:\n \t\treturn (void *) &p->params.sched;\n+\tcase PIPELINE_PORT_OUT_KNI_WRITER:\n+\t\treturn (void *) &p->params.kni;\n \tcase PIPELINE_PORT_OUT_SINK:\n \t\treturn (void *) &p->params.sink;\n \tdefault:\n@@ -192,6 +203,8 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params  *p)\n \t\treturn &rte_port_ring_writer_ipv6_ras_ops;\n \tcase PIPELINE_PORT_OUT_SCHED_WRITER:\n \t\treturn &rte_port_sched_writer_ops;\n+\tcase PIPELINE_PORT_OUT_KNI_WRITER:\n+\t\treturn &rte_port_kni_writer_ops;\n \tcase PIPELINE_PORT_OUT_SINK:\n \t\treturn &rte_port_sink_ops;\n \tdefault:\ndiff --git a/lib/librte_port/Makefile b/lib/librte_port/Makefile\nold mode 100644\nnew mode 100755\nindex d4de5af..52d2485\n--- a/lib/librte_port/Makefile\n+++ b/lib/librte_port/Makefile\n@@ -57,6 +57,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_ras.c\n endif\n SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_sched.c\n SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_source_sink.c\n+ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)\n+SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_kni.c\n+endif\n \n # install includes\n SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port.h\n@@ -68,6 +71,9 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_ras.h\n endif\n SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_sched.h\n SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_source_sink.h\n+ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)\n+SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_kni.h\n+endif\n \n # this lib depends upon:\n DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) := lib/librte_eal\n@@ -75,5 +81,8 @@ DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_mbuf\n DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_mempool\n DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_ether\n DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_ip_frag\n+ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)\n+DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_kni\n+endif\n \n include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_port/rte_port_kni.c b/lib/librte_port/rte_port_kni.c\nnew file mode 100755\nindex 0000000..ddc26c9\n--- /dev/null\n+++ b/lib/librte_port/rte_port_kni.c\n@@ -0,0 +1,318 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 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+#include <string.h>\n+\n+#include <rte_common.h>\n+#include <rte_malloc.h>\n+#include <rte_kni.h>\n+\n+#include \"rte_port_kni.h\"\n+\n+/*\n+ * Port KNI Reader\n+ */\n+#ifdef RTE_PORT_STATS_COLLECT\n+\n+#define RTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(port, val) \\\n+\tport->stats.n_pkts_in += val\n+#define RTE_PORT_KNI_READER_STATS_PKTS_DROP_ADD(port, val) \\\n+\tport->stats.n_pkts_drop += val\n+\n+#else\n+\n+#define RTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(port, val)\n+#define RTE_PORT_KNI_READER_STATS_PKTS_DROP_ADD(port, val)\n+\n+#endif\n+\n+struct rte_port_kni_reader {\n+\tstruct rte_port_in_stats stats;\n+\n+\tstruct rte_kni *kni;\n+};\n+\n+static void *\n+rte_port_kni_reader_create(void *params, int socket_id) {\n+\tstruct rte_port_kni_reader_params *conf =\n+\t\t\t(struct rte_port_kni_reader_params *) params;\n+\tstruct rte_port_kni_reader *port;\n+\n+\t/* Check input parameters */\n+\tif (conf == NULL) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: params is NULL\\n\", __func__);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Memory allocation */\n+\tport = rte_zmalloc_socket(\"PORT\", sizeof(*port),\n+\t\tRTE_CACHE_LINE_SIZE, socket_id);\n+\tif (port == NULL) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: Failed to allocate port\\n\", __func__);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Initialization */\n+\tport->kni = conf->kni;\n+\n+\treturn port;\n+}\n+\n+static int\n+rte_port_kni_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) {\n+\tstruct rte_port_kni_reader *p =\n+\t\t\t(struct rte_port_kni_reader *) port;\n+\tuint16_t rx_pkt_cnt;\n+\n+\trx_pkt_cnt = rte_kni_rx_burst(p->kni, pkts, n_pkts);\n+\tRTE_PORT_KNI_READER_STATS_PKTS_IN_ADD(p, rx_pkt_cnt);\n+\treturn rx_pkt_cnt;\n+}\n+\n+static int\n+rte_port_kni_reader_free(void *port) {\n+\tif (port == NULL) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: port is NULL\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trte_free(port);\n+\n+\treturn 0;\n+}\n+\n+static int rte_port_kni_reader_stats_read(void *port,\n+\tstruct rte_port_in_stats *stats, int clear)\n+{\n+\tstruct rte_port_kni_reader *p =\n+\t\t\t(struct rte_port_kni_reader *) port;\n+\n+\tif (stats != NULL)\n+\t\tmemcpy(stats, &p->stats, sizeof(p->stats));\n+\n+\tif (clear)\n+\t\tmemset(&p->stats, 0, sizeof(p->stats));\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Port KNI Writer\n+ */\n+#ifdef RTE_PORT_STATS_COLLECT\n+\n+#define RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(port, val) \\\n+\tport->stats.n_pkts_in += val\n+#define RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(port, val) \\\n+\tport->stats.n_pkts_drop += val\n+\n+#else\n+\n+#define RTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(port, val)\n+#define RTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(port, val)\n+\n+#endif\n+\n+struct rte_port_kni_writer {\n+\tstruct rte_port_out_stats stats;\n+\n+\tstruct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];\n+\tuint32_t tx_burst_sz;\n+\tuint16_t tx_buf_count;\n+\tuint64_t bsz_mask;\n+\tstruct rte_kni *kni;\n+};\n+\n+static void *\n+rte_port_kni_writer_create(void *params, int socket_id) {\n+\tstruct rte_port_kni_writer_params *conf =\n+\t\t\t(struct rte_port_kni_writer_params *) params;\n+\tstruct rte_port_kni_writer *port;\n+\n+\t/* Check input parameters */\n+\tif ((conf == NULL) ||\n+\t\t(conf->tx_burst_sz == 0) ||\n+\t\t(conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) ||\n+\t\t(!rte_is_power_of_2(conf->tx_burst_sz))) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: Invalid input parameters\\n\", __func__);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Memory allocation */\n+\tport = rte_zmalloc_socket(\"PORT\", sizeof(*port),\n+\t\tRTE_CACHE_LINE_SIZE, socket_id);\n+\tif (port == NULL) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: Failed to allocate port\\n\", __func__);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Initialization */\n+\tport->kni = conf->kni;\n+\tport->tx_burst_sz = conf->tx_burst_sz;\n+\tport->tx_buf_count = 0;\n+\tport->bsz_mask = 1LLU << (conf->tx_burst_sz - 1);\n+\n+\treturn port;\n+}\n+\n+static inline void\n+send_burst(struct rte_port_kni_writer *p) {\n+\tuint32_t nb_tx;\n+\n+\tnb_tx = rte_kni_tx_burst(p->kni, p->tx_buf, p->tx_buf_count);\n+\n+\tRTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx);\n+\tfor ( ; nb_tx < p->tx_buf_count; nb_tx++)\n+\t\trte_pktmbuf_free(p->tx_buf[nb_tx]);\n+\n+\tp->tx_buf_count = 0;\n+}\n+\n+static int\n+rte_port_kni_writer_tx(void *port, struct rte_mbuf *pkt) {\n+\tstruct rte_port_kni_writer *p =\n+\t\t(struct rte_port_kni_writer *) port;\n+\n+\tp->tx_buf[p->tx_buf_count++] = pkt;\n+\tRTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, 1);\n+\tif (p->tx_buf_count >= p->tx_burst_sz)\n+\t\tsend_burst(p);\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_port_kni_writer_tx_bulk(void *port,\n+\tstruct rte_mbuf **pkts,\n+\tuint64_t pkts_mask)\n+{\n+\tstruct rte_port_kni_writer *p =\n+\t\t(struct rte_port_kni_writer *) port;\n+\tuint64_t bsz_mask = p->bsz_mask;\n+\tuint32_t tx_buf_count = p->tx_buf_count;\n+\tuint64_t expr = (pkts_mask & (pkts_mask + 1)) |\n+\t\t((pkts_mask & bsz_mask) ^ bsz_mask);\n+\n+\tif (expr == 0) {\n+\t\tuint64_t n_pkts = __builtin_popcountll(pkts_mask);\n+\t\tuint32_t n_pkts_ok;\n+\n+\t\tif (tx_buf_count)\n+\t\t\tsend_burst(p);\n+\n+\t\tRTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, n_pkts);\n+\t\tn_pkts_ok = rte_kni_tx_burst(p->kni, pkts, n_pkts);\n+\n+\t\tRTE_PORT_KNI_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok);\n+\t\tfor ( ; n_pkts_ok < n_pkts; n_pkts_ok++) {\n+\t\t\tstruct rte_mbuf *pkt = pkts[n_pkts_ok];\n+\n+\t\t\trte_pktmbuf_free(pkt);\n+\t\t}\n+\t} else {\n+\t\tfor ( ; pkts_mask; ) {\n+\t\t\tuint32_t pkt_index = __builtin_ctzll(pkts_mask);\n+\t\t\tuint64_t pkt_mask = 1LLU << pkt_index;\n+\t\t\tstruct rte_mbuf *pkt = pkts[pkt_index];\n+\n+\t\t\tp->tx_buf[tx_buf_count++] = pkt;\n+\t\t\tRTE_PORT_KNI_WRITER_STATS_PKTS_IN_ADD(p, 1);\n+\t\t\tpkts_mask &= ~pkt_mask;\n+\t\t}\n+\n+\t\tp->tx_buf_count = tx_buf_count;\n+\t\tif (tx_buf_count >= p->tx_burst_sz)\n+\t\t\tsend_burst(p);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_port_kni_writer_flush(void *port)\n+{\n+\tstruct rte_port_kni_writer *p =\n+\t\t(struct rte_port_kni_writer *) port;\n+\n+\tif (p->tx_buf_count > 0)\n+\t\tsend_burst(p);\n+\n+\treturn 0;\n+}\n+\n+static int\n+rte_port_kni_writer_free(void *port)\n+{\n+\tif (port == NULL) {\n+\t\tRTE_LOG(ERR, PORT, \"%s: Port is NULL\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trte_port_kni_writer_flush(port);\n+\trte_free(port);\n+\n+\treturn 0;\n+}\n+\n+static int rte_port_kni_writer_stats_read(void *port,\n+\tstruct rte_port_out_stats *stats, int clear)\n+{\n+\tstruct rte_port_kni_writer *p =\n+\t\t(struct rte_port_kni_writer *) port;\n+\n+\tif (stats != NULL)\n+\t\tmemcpy(stats, &p->stats, sizeof(p->stats));\n+\n+\tif (clear)\n+\t\tmemset(&p->stats, 0, sizeof(p->stats));\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Summary of port operations\n+ */\n+struct rte_port_in_ops rte_port_kni_reader_ops = {\n+\t.f_create = rte_port_kni_reader_create,\n+\t.f_free = rte_port_kni_reader_free,\n+\t.f_rx = rte_port_kni_reader_rx,\n+\t.f_stats = rte_port_kni_reader_stats_read,\n+};\n+\n+struct rte_port_out_ops rte_port_kni_writer_ops = {\n+\t.f_create = rte_port_kni_writer_create,\n+\t.f_free = rte_port_kni_writer_free,\n+\t.f_tx = rte_port_kni_writer_tx,\n+\t.f_tx_bulk = rte_port_kni_writer_tx_bulk,\n+\t.f_flush = rte_port_kni_writer_flush,\n+\t.f_stats = rte_port_kni_writer_stats_read,\n+};\ndiff --git a/lib/librte_port/rte_port_kni.h b/lib/librte_port/rte_port_kni.h\nnew file mode 100755\nindex 0000000..5b729c6\n--- /dev/null\n+++ b/lib/librte_port/rte_port_kni.h\n@@ -0,0 +1,82 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2016 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 __INCLUDE_RTE_PORT_KNI_H__\n+#define __INCLUDE_RTE_PORT_KNI_H__\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * @file\n+ * RTE Port KNI Interface\n+ *\n+ * kni_reader: input port built on top of pre-initialized KNI interface\n+ * kni_writer: output port built on top of pre-initialized KNI interface\n+ *\n+ ***/\n+\n+#include <stdint.h>\n+\n+#include <rte_kni.h>\n+\n+#include \"rte_port.h\"\n+\n+/** kni_reader port parameters */\n+struct rte_port_kni_reader_params {\n+\t/** KNI interface reference */\n+\tstruct rte_kni *kni;\n+};\n+\n+/** kni_reader port operations */\n+extern struct rte_port_in_ops rte_port_kni_reader_ops;\n+\n+\n+/** kni_writer port parameters */\n+struct rte_port_kni_writer_params {\n+\t/** KNI interface reference */\n+\tstruct rte_kni *kni;\n+\n+\t/** Burst size to KNI interface. */\n+\tuint32_t tx_burst_sz;\n+};\n+\n+/** kni_writer port operations */\n+extern struct rte_port_out_ops rte_port_kni_writer_ops;\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif\n",
    "prefixes": [
        "dpdk-dev"
    ]
}