get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 9922,
    "url": "https://patches.dpdk.org/api/patches/9922/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1452874684-12750-3-git-send-email-ferruh.yigit@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": "<1452874684-12750-3-git-send-email-ferruh.yigit@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1452874684-12750-3-git-send-email-ferruh.yigit@intel.com",
    "date": "2016-01-15T16:18:03",
    "name": "[dpdk-dev,RFC,2/3] kcp: add kernel control path kernel module",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "00707b08673851552e6abb665064fe6b12adfdff",
    "submitter": {
        "id": 324,
        "url": "https://patches.dpdk.org/api/people/324/?format=api",
        "name": "Ferruh Yigit",
        "email": "ferruh.yigit@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1452874684-12750-3-git-send-email-ferruh.yigit@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/9922/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/9922/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 A9DFE8E95;\n\tFri, 15 Jan 2016 17:18:15 +0100 (CET)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby dpdk.org (Postfix) with ESMTP id 8D6468E8D\n\tfor <dev@dpdk.org>; Fri, 15 Jan 2016 17:18:13 +0100 (CET)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga101.fm.intel.com with ESMTP; 15 Jan 2016 08:18:13 -0800",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby orsmga003.jf.intel.com with ESMTP; 15 Jan 2016 08:18:11 -0800",
            "from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com\n\t[10.237.217.46])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tu0FGIAd1024915; Fri, 15 Jan 2016 16:18:10 GMT",
            "from sivswdev02.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev02.ir.intel.com with ESMTP id u0FGIAJ6012944;\n\tFri, 15 Jan 2016 16:18:10 GMT",
            "(from fyigit@localhost)\n\tby sivswdev02.ir.intel.com with  id u0FGIAxB012940;\n\tFri, 15 Jan 2016 16:18:10 GMT"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.22,300,1449561600\"; d=\"scan'208\";a=\"727759716\"",
        "From": "Ferruh Yigit <ferruh.yigit@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri, 15 Jan 2016 16:18:03 +0000",
        "Message-Id": "<1452874684-12750-3-git-send-email-ferruh.yigit@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1452874684-12750-1-git-send-email-ferruh.yigit@intel.com>",
        "References": "<1452874684-12750-1-git-send-email-ferruh.yigit@intel.com>",
        "Subject": "[dpdk-dev] [RFC 2/3] kcp: add kernel control path kernel module",
        "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": "This kernel module is based on KNI module, but this one is stripped\nversion of it and only for control messages, no data transfer\nfunctionality provided.\n\nThis Linux kernel module helps userspace application create virtual\ninterfaces and when a control command issued into that virtual\ninterface, module pushes the command to the userspace and gets the\nresponse back for the caller application.\n\nThe Linux tools like ethtool/ifconfig/ip can be used on virtual\ninterfaces but not ones for related data, like tcpdump.\n\nSigned-off-by: Ferruh Yigit <ferruh.yigit@intel.com>\n---\n config/common_linuxapp                    |   2 +\n lib/librte_eal/linuxapp/Makefile          |   5 +-\n lib/librte_eal/linuxapp/kcp/Makefile      |  58 ++++++\n lib/librte_eal/linuxapp/kcp/kcp_dev.h     |  81 +++++++++\n lib/librte_eal/linuxapp/kcp/kcp_ethtool.c | 261 +++++++++++++++++++++++++++\n lib/librte_eal/linuxapp/kcp/kcp_misc.c    | 282 ++++++++++++++++++++++++++++++\n lib/librte_eal/linuxapp/kcp/kcp_net.c     | 209 ++++++++++++++++++++++\n lib/librte_eal/linuxapp/kcp/kcp_nl.c      | 194 ++++++++++++++++++++\n 8 files changed, 1091 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_eal/linuxapp/kcp/Makefile\n create mode 100644 lib/librte_eal/linuxapp/kcp/kcp_dev.h\n create mode 100644 lib/librte_eal/linuxapp/kcp/kcp_ethtool.c\n create mode 100644 lib/librte_eal/linuxapp/kcp/kcp_misc.c\n create mode 100644 lib/librte_eal/linuxapp/kcp/kcp_net.c\n create mode 100644 lib/librte_eal/linuxapp/kcp/kcp_nl.c",
    "diff": "diff --git a/config/common_linuxapp b/config/common_linuxapp\nindex de705d0..ed32ca8 100644\n--- a/config/common_linuxapp\n+++ b/config/common_linuxapp\n@@ -506,6 +506,8 @@ CONFIG_RTE_KNI_VHOST_DEBUG_TX=n\n # Compile librte_ctrl_if\n #\n CONFIG_RTE_LIBRTE_CTRL_IF=y\n+CONFIG_RTE_KCP_KMOD=y\n+CONFIG_RTE_KCP_KO_DEBUG=n\n \n #\n # Compile vhost library\ndiff --git a/lib/librte_eal/linuxapp/Makefile b/lib/librte_eal/linuxapp/Makefile\nindex d9c5233..d1fa3a3 100644\n--- a/lib/librte_eal/linuxapp/Makefile\n+++ b/lib/librte_eal/linuxapp/Makefile\n@@ -1,6 +1,6 @@\n #   BSD LICENSE\n #\n-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\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@@ -38,6 +38,9 @@ DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal\n ifeq ($(CONFIG_RTE_KNI_KMOD),y)\n DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += kni\n endif\n+ifeq ($(CONFIG_RTE_KCP_KMOD),y)\n+DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += kcp\n+endif\n ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)\n DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += xen_dom0\n endif\ndiff --git a/lib/librte_eal/linuxapp/kcp/Makefile b/lib/librte_eal/linuxapp/kcp/Makefile\nnew file mode 100644\nindex 0000000..e7472f3\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/Makefile\n@@ -0,0 +1,58 @@\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 $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# module name and path\n+#\n+MODULE = rte_kcp\n+\n+#\n+# CFLAGS\n+#\n+MODULE_CFLAGS += -I$(SRCDIR)\n+MODULE_CFLAGS += -I$(RTE_OUTPUT)/include\n+MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h\n+MODULE_CFLAGS += -Wall -Werror\n+\n+# this lib needs main eal\n+DEPDIRS-y += lib/librte_eal/linuxapp/eal\n+\n+#\n+# all source are stored in SRCS-y\n+#\n+SRCS-y += kcp_misc.c\n+SRCS-y += kcp_net.c\n+SRCS-y += kcp_ethtool.c\n+SRCS-y += kcp_nl.c\n+\n+include $(RTE_SDK)/mk/rte.module.mk\ndiff --git a/lib/librte_eal/linuxapp/kcp/kcp_dev.h b/lib/librte_eal/linuxapp/kcp/kcp_dev.h\nnew file mode 100644\nindex 0000000..1097cb4\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/kcp_dev.h\n@@ -0,0 +1,81 @@\n+/*-\n+ * GPL LICENSE SUMMARY\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *\n+ *   This program is free software; you can redistribute it and/or modify\n+ *   it under the terms of version 2 of the GNU General Public License as\n+ *   published by the Free Software Foundation.\n+ *\n+ *   This program is distributed in the hope that it will be useful, but\n+ *   WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *   General Public License for more details.\n+ *\n+ *   You should have received a copy of the GNU General Public License\n+ *   along with this program; if not, write to the Free Software\n+ *   Foundation.\n+ *   The full GNU General Public License is included in this distribution\n+ *   in the file called LICENSE.GPL.\n+ *\n+ *   Contact Information:\n+ *   Intel Corporation\n+ */\n+\n+#ifndef _KCP_DEV_H_\n+#define _KCP_DEV_H_\n+\n+#include <linux/netdevice.h>\n+\n+#define RTE_KCP_NAMESIZE 32\n+#define KCP_DEVICE \"kcp\"\n+\n+#define RTE_KCP_IOCTL_TEST    _IOWR(0, 1, int)\n+#define RTE_KCP_IOCTL_CREATE  _IOWR(0, 2, int)\n+#define RTE_KCP_IOCTL_RELEASE _IOWR(0, 3, int)\n+\n+enum rte_kcp_req_id {\n+\tRTE_KCP_REQ_UNKNOWN = (1 << 16),\n+\tRTE_KCP_REQ_CHANGE_MTU,\n+\tRTE_KCP_REQ_CFG_NETWORK_IF,\n+\tRTE_KCP_REQ_GET_STATS,\n+\tRTE_KCP_REQ_GET_MAC,\n+\tRTE_KCP_REQ_SET_MAC,\n+\tRTE_KCP_REQ_START_PORT,\n+\tRTE_KCP_REQ_STOP_PORT,\n+\tRTE_KCP_REQ_MAX,\n+};\n+\n+struct kcp_dev {\n+\t/* kcp list */\n+\tstruct list_head list;\n+\n+\tchar name[RTE_KCP_NAMESIZE]; /* Network device name */\n+\n+\t/* kcp device */\n+\tstruct net_device *net_dev;\n+\n+\tint port_id;\n+\tstruct completion msg_received;\n+};\n+\n+void kcp_net_init(struct net_device *dev);\n+\n+void kcp_nl_init(void);\n+void kcp_nl_release(void);\n+int kcp_nl_exec(int cmd, struct net_device *dev, void *in_data, int in_len,\n+\t\tvoid *out_data, int out_len);\n+\n+void kcp_set_ethtool_ops(struct net_device *netdev);\n+\n+#define KCP_ERR(args...) printk(KERN_ERR \"KCP: \" args)\n+#define KCP_INFO(args...) printk(KERN_INFO \"KCP: \" args)\n+#define KCP_PRINT(args...) printk(KERN_DEBUG \"KCP: \" args)\n+\n+#ifdef RTE_KCP_KO_DEBUG\n+#define KCP_DBG(args...) printk(KERN_DEBUG \"KCP: \" args)\n+#else\n+#define KCP_DBG(args...)\n+#endif\n+\n+#endif /* _KCP_DEV_H_ */\ndiff --git a/lib/librte_eal/linuxapp/kcp/kcp_ethtool.c b/lib/librte_eal/linuxapp/kcp/kcp_ethtool.c\nnew file mode 100644\nindex 0000000..0f5b583\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/kcp_ethtool.c\n@@ -0,0 +1,261 @@\n+/*-\n+ * GPL LICENSE SUMMARY\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *\n+ *   This program is free software; you can redistribute it and/or modify\n+ *   it under the terms of version 2 of the GNU General Public License as\n+ *   published by the Free Software Foundation.\n+ *\n+ *   This program is distributed in the hope that it will be useful, but\n+ *   WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *   General Public License for more details.\n+ *\n+ *   You should have received a copy of the GNU General Public License\n+ *   along with this program; if not, write to the Free Software\n+ *   Foundation.\n+ *   The full GNU General Public License is included in this distribution\n+ *   in the file called LICENSE.GPL.\n+ *\n+ *   Contact Information:\n+ *   Intel Corporation\n+ */\n+\n+#include \"kcp_dev.h\"\n+\n+#define ETHTOOL_GEEPROM_LEN 99\n+#define ETHTOOL_GREGS_LEN 98\n+#define ETHTOOL_GSSET_COUNT 97\n+\n+static int\n+kcp_check_if_running(struct net_device *dev)\n+{\n+\treturn 0;\n+}\n+\n+static void\n+kcp_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)\n+{\n+\tint ret;\n+\n+\tret = kcp_nl_exec(info->cmd, dev, NULL, 0,\n+\t\t\tinfo, sizeof(struct ethtool_drvinfo));\n+\tif (ret < 0)\n+\t\tmemset(info, 0, sizeof(struct ethtool_drvinfo));\n+}\n+\n+static int\n+kcp_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)\n+{\n+\treturn kcp_nl_exec(ecmd->cmd, dev, NULL, 0,\n+\t\t\tecmd, sizeof(struct ethtool_cmd));\n+}\n+\n+static int\n+kcp_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)\n+{\n+\treturn kcp_nl_exec(ecmd->cmd, dev, ecmd, sizeof(struct ethtool_cmd),\n+\t\t\tNULL, 0);\n+}\n+\n+static void\n+kcp_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)\n+{\n+\tint ret;\n+\n+\tret = kcp_nl_exec(wol->cmd, dev, NULL, 0,\n+\t\t\twol, sizeof(struct ethtool_wolinfo));\n+\tif (ret < 0)\n+\t\tmemset(wol, 0, sizeof(struct ethtool_wolinfo));\n+}\n+\n+static int\n+kcp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)\n+{\n+\treturn kcp_nl_exec(wol->cmd, dev, wol, sizeof(struct ethtool_wolinfo),\n+\t\t\tNULL, 0);\n+}\n+\n+static int\n+kcp_nway_reset(struct net_device *dev)\n+{\n+\treturn kcp_nl_exec(ETHTOOL_NWAY_RST, dev, NULL, 0, NULL, 0);\n+}\n+\n+static int\n+kcp_get_eeprom_len(struct net_device *dev)\n+{\n+\tint data;\n+\tint ret;\n+\n+\tret = kcp_nl_exec(ETHTOOL_GEEPROM_LEN, dev, NULL, 0,\n+\t\t\t&data, sizeof(int));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn data;\n+}\n+\n+static int\n+kcp_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,\n+\t\tu8 *bytes)\n+{\n+\tint ret;\n+\n+\tret = kcp_nl_exec(eeprom->cmd, dev,\n+\t\t\teeprom, sizeof(struct ethtool_eeprom),\n+\t\t\tbytes, eeprom->len);\n+\t*bytes = 0;\n+\treturn ret;\n+}\n+\n+static int\n+kcp_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,\n+\t\tu8 *bytes)\n+{\n+\tint ret;\n+\n+\tret = kcp_nl_exec(eeprom->cmd, dev,\n+\t\t\teeprom, sizeof(struct ethtool_eeprom),\n+\t\t\tbytes, eeprom->len);\n+\t*bytes = 0;\n+\treturn ret;\n+}\n+\n+static void\n+kcp_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)\n+{\n+\n+\tkcp_nl_exec(ring->cmd, dev, NULL, 0,\n+\t\t\tring, sizeof(struct ethtool_ringparam));\n+}\n+\n+static int\n+kcp_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)\n+{\n+\tint ret;\n+\n+\tret = kcp_nl_exec(ring->cmd, dev,\n+\t\t\tring, sizeof(struct ethtool_ringparam),\n+\t\t\tNULL, 0);\n+\treturn ret;\n+}\n+\n+static void\n+kcp_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)\n+{\n+\n+\tkcp_nl_exec(pause->cmd, dev, NULL, 0,\n+\t\t\tpause, sizeof(struct ethtool_pauseparam));\n+}\n+\n+static int\n+kcp_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause)\n+{\n+\treturn kcp_nl_exec(pause->cmd, dev,\n+\t\t\tpause, sizeof(struct ethtool_pauseparam),\n+\t\t\tNULL, 0);\n+}\n+\n+static u32\n+kcp_get_msglevel(struct net_device *dev)\n+{\n+\tint data;\n+\tint ret;\n+\n+\tret = kcp_nl_exec(ETHTOOL_GMSGLVL, dev, NULL, 0, &data, sizeof(int));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn data;\n+}\n+\n+static void\n+kcp_set_msglevel(struct net_device *dev, u32 data)\n+{\n+\n+\tkcp_nl_exec(ETHTOOL_SMSGLVL, dev, &data, sizeof(int), NULL, 0);\n+}\n+\n+static int\n+kcp_get_regs_len(struct net_device *dev)\n+{\n+\tint data;\n+\tint ret;\n+\n+\tret = kcp_nl_exec(ETHTOOL_GREGS_LEN, dev, NULL, 0, &data, sizeof(int));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn data;\n+}\n+\n+static void\n+kcp_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)\n+{\n+\n+\tkcp_nl_exec(regs->cmd, dev, regs, sizeof(struct ethtool_regs),\n+\t\t\tp, regs->len);\n+}\n+\n+static void\n+kcp_get_strings(struct net_device *dev, u32 stringset, u8 *data)\n+{\n+\n+\tkcp_nl_exec(ETHTOOL_GSTRINGS, dev, &stringset, sizeof(u32), data, 0);\n+}\n+\n+static int\n+kcp_get_sset_count(struct net_device *dev, int sset)\n+{\n+\tint data;\n+\tint ret;\n+\n+\tret = kcp_nl_exec(ETHTOOL_GSSET_COUNT, dev, &sset, sizeof(int),\n+\t\t\t&data, sizeof(int));\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\treturn data;\n+}\n+\n+static void\n+kcp_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats,\n+\t\tu64 *data)\n+{\n+\n+\tkcp_nl_exec(stats->cmd, dev, stats, sizeof(struct ethtool_stats),\n+\t\t\tdata, stats->n_stats);\n+}\n+\n+static const struct ethtool_ops kcp_ethtool_ops = {\n+\t.begin\t\t\t= kcp_check_if_running,\n+\t.get_drvinfo\t\t= kcp_get_drvinfo,\n+\t.get_settings\t\t= kcp_get_settings,\n+\t.set_settings\t\t= kcp_set_settings,\n+\t.get_regs_len\t\t= kcp_get_regs_len,\n+\t.get_regs\t\t= kcp_get_regs,\n+\t.get_wol\t\t= kcp_get_wol,\n+\t.set_wol\t\t= kcp_set_wol,\n+\t.nway_reset\t\t= kcp_nway_reset,\n+\t.get_link\t\t= ethtool_op_get_link,\n+\t.get_eeprom_len\t\t= kcp_get_eeprom_len,\n+\t.get_eeprom\t\t= kcp_get_eeprom,\n+\t.set_eeprom\t\t= kcp_set_eeprom,\n+\t.get_ringparam\t\t= kcp_get_ringparam,\n+\t.set_ringparam\t\t= kcp_set_ringparam,\n+\t.get_pauseparam\t\t= kcp_get_pauseparam,\n+\t.set_pauseparam\t\t= kcp_set_pauseparam,\n+\t.get_msglevel\t\t= kcp_get_msglevel,\n+\t.set_msglevel\t\t= kcp_set_msglevel,\n+\t.get_strings\t\t= kcp_get_strings,\n+\t.get_sset_count\t\t= kcp_get_sset_count,\n+\t.get_ethtool_stats\t= kcp_get_ethtool_stats,\n+};\n+\n+void\n+kcp_set_ethtool_ops(struct net_device *netdev)\n+{\n+\tnetdev->ethtool_ops = &kcp_ethtool_ops;\n+}\ndiff --git a/lib/librte_eal/linuxapp/kcp/kcp_misc.c b/lib/librte_eal/linuxapp/kcp/kcp_misc.c\nnew file mode 100644\nindex 0000000..eadd1d7\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/kcp_misc.c\n@@ -0,0 +1,282 @@\n+/*-\n+ * GPL LICENSE SUMMARY\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *\n+ *   This program is free software; you can redistribute it and/or modify\n+ *   it under the terms of version 2 of the GNU General Public License as\n+ *   published by the Free Software Foundation.\n+ *\n+ *   This program is distributed in the hope that it will be useful, but\n+ *   WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *   General Public License for more details.\n+ *\n+ *   You should have received a copy of the GNU General Public License\n+ *   along with this program; if not, write to the Free Software\n+ *   Foundation.\n+ *   The full GNU General Public License is included in this distribution\n+ *   in the file called LICENSE.GPL.\n+ *\n+ *   Contact Information:\n+ *   Intel Corporation\n+ */\n+\n+#include <linux/module.h>\n+#include <linux/miscdevice.h>\n+\n+#include \"kcp_dev.h\"\n+\n+#define KCP_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */\n+\n+static volatile unsigned long device_in_use; /* device in use flag */\n+\n+/* kcp list lock */\n+static DECLARE_RWSEM(kcp_list_lock);\n+\n+/* kcp list */\n+static struct list_head kcp_list_head = LIST_HEAD_INIT(kcp_list_head);\n+\n+static int\n+kcp_open(struct inode *inode, struct file *file)\n+{\n+\t/* kcp device can be opened by one user only, test and set bit */\n+\tif (test_and_set_bit(KCP_DEV_IN_USE_BIT_NUM, &device_in_use))\n+\t\treturn -EBUSY;\n+\n+\tKCP_PRINT(\"/dev/kcp opened\\n\");\n+\n+\tkcp_nl_init();\n+\n+\treturn 0;\n+}\n+\n+static int\n+kcp_dev_remove(struct kcp_dev *dev)\n+{\n+\tif (!dev)\n+\t\treturn -ENODEV;\n+\n+\tif (dev->net_dev) {\n+\t\tunregister_netdev(dev->net_dev);\n+\t\tfree_netdev(dev->net_dev);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+kcp_release(struct inode *inode, struct file *file)\n+{\n+\tstruct kcp_dev *dev, *n;\n+\n+\tdown_write(&kcp_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &kcp_list_head, list) {\n+\t\tkcp_dev_remove(dev);\n+\t\tlist_del(&dev->list);\n+\t}\n+\tup_write(&kcp_list_lock);\n+\n+\tkcp_nl_release();\n+\n+\t/* Clear the bit of device in use */\n+\tclear_bit(KCP_DEV_IN_USE_BIT_NUM, &device_in_use);\n+\n+\tKCP_PRINT(\"/dev/kcp closed\\n\");\n+\n+\treturn 0;\n+}\n+\n+static int\n+kcp_check_param(struct kcp_dev *kcp, char *name)\n+{\n+\tif (!kcp)\n+\t\treturn -1;\n+\n+\t/* Check if network name has been used */\n+\tif (!strncmp(kcp->name, name, RTE_KCP_NAMESIZE)) {\n+\t\tKCP_ERR(\"KCP interface name %s duplicated\\n\", name);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+kcp_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param)\n+{\n+\tint ret;\n+\tstruct net_device *net_dev = NULL;\n+\tstruct kcp_dev *kcp, *dev, *n;\n+\tstruct net *net;\n+\tchar name[RTE_KCP_NAMESIZE];\n+\tunsigned int instance = ioctl_param;\n+\tchar mac[ETH_ALEN];\n+\n+\tKCP_PRINT(\"Creating kcp...\\n\");\n+\n+\tsnprintf(name, RTE_KCP_NAMESIZE, \"dpdk%u\", instance);\n+\n+\t/* Check if it has been created */\n+\tdown_read(&kcp_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &kcp_list_head, list) {\n+\t\tif (kcp_check_param(dev, name) < 0) {\n+\t\t\tup_read(&kcp_list_lock);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\tup_read(&kcp_list_lock);\n+\n+\tnet_dev = alloc_netdev(sizeof(struct kcp_dev), name,\n+#ifdef NET_NAME_UNKNOWN\n+\t\t\t\t\t\t\tNET_NAME_UNKNOWN,\n+#endif\n+\t\t\t\t\t\t\tkcp_net_init);\n+\tif (net_dev == NULL) {\n+\t\tKCP_ERR(\"error allocating device \\\"%s\\\"\\n\", name);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tnet = get_net_ns_by_pid(task_pid_vnr(current));\n+\tif (IS_ERR(net)) {\n+\t\tfree_netdev(net_dev);\n+\t\treturn PTR_ERR(net);\n+\t}\n+\tdev_net_set(net_dev, net);\n+\tput_net(net);\n+\n+\tkcp = netdev_priv(net_dev);\n+\n+\tkcp->net_dev = net_dev;\n+\tkcp->port_id = instance;\n+\tinit_completion(&kcp->msg_received);\n+\tstrncpy(kcp->name, name, RTE_KCP_NAMESIZE);\n+\n+\tkcp_nl_exec(RTE_KCP_REQ_GET_MAC, net_dev, NULL, 0, mac, ETH_ALEN);\n+\tmemcpy(net_dev->dev_addr, mac, net_dev->addr_len);\n+\n+\tkcp_set_ethtool_ops(net_dev);\n+\tret = register_netdev(net_dev);\n+\tif (ret) {\n+\t\tKCP_ERR(\"error %i registering device \\\"%s\\\"\\n\", ret, name);\n+\t\tkcp_dev_remove(kcp);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tdown_write(&kcp_list_lock);\n+\tlist_add(&kcp->list, &kcp_list_head);\n+\tup_write(&kcp_list_lock);\n+\n+\treturn 0;\n+}\n+\n+static int\n+kcp_ioctl_release(unsigned int ioctl_num, unsigned long ioctl_param)\n+{\n+\tint ret = -EINVAL;\n+\tstruct kcp_dev *dev;\n+\tstruct kcp_dev *n;\n+\tchar name[RTE_KCP_NAMESIZE];\n+\tunsigned int instance = ioctl_param;\n+\n+\tsnprintf(name, RTE_KCP_NAMESIZE, \"dpdk%u\", instance);\n+\n+\tdown_write(&kcp_list_lock);\n+\tlist_for_each_entry_safe(dev, n, &kcp_list_head, list) {\n+\t\tif (strncmp(dev->name, name, RTE_KCP_NAMESIZE) != 0)\n+\t\t\tcontinue;\n+\t\tkcp_dev_remove(dev);\n+\t\tlist_del(&dev->list);\n+\t\tret = 0;\n+\t\tbreak;\n+\t}\n+\tup_write(&kcp_list_lock);\n+\tKCP_INFO(\"%s release kcp named %s\\n\",\n+\t\t(ret == 0 ? \"Successfully\" : \"Unsuccessfully\"), name);\n+\n+\treturn ret;\n+}\n+\n+static int\n+kcp_ioctl(struct inode *inode, unsigned int ioctl_num,\n+\tunsigned long ioctl_param)\n+{\n+\tint ret = -EINVAL;\n+\n+\tKCP_DBG(\"IOCTL num=0x%0x param=0x%0lx\\n\", ioctl_num, ioctl_param);\n+\n+\t/*\n+\t * Switch according to the ioctl called\n+\t */\n+\tswitch (_IOC_NR(ioctl_num)) {\n+\tcase _IOC_NR(RTE_KCP_IOCTL_TEST):\n+\t\t/* For test only, not used */\n+\t\tbreak;\n+\tcase _IOC_NR(RTE_KCP_IOCTL_CREATE):\n+\t\tret = kcp_ioctl_create(ioctl_num, ioctl_param);\n+\t\tbreak;\n+\tcase _IOC_NR(RTE_KCP_IOCTL_RELEASE):\n+\t\tret = kcp_ioctl_release(ioctl_num, ioctl_param);\n+\t\tbreak;\n+\tdefault:\n+\t\tKCP_DBG(\"IOCTL default\\n\");\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+kcp_compat_ioctl(struct inode *inode, unsigned int ioctl_num,\n+\t\tunsigned long ioctl_param)\n+{\n+\t/* 32 bits app on 64 bits OS to be supported later */\n+\tKCP_PRINT(\"Not implemented.\\n\");\n+\n+\treturn -EINVAL;\n+}\n+\n+static const struct file_operations kcp_fops = {\n+\t.owner = THIS_MODULE,\n+\t.open = kcp_open,\n+\t.release = kcp_release,\n+\t.unlocked_ioctl = (void *)kcp_ioctl,\n+\t.compat_ioctl = (void *)kcp_compat_ioctl,\n+};\n+\n+static struct miscdevice kcp_misc = {\n+\t.minor = MISC_DYNAMIC_MINOR,\n+\t.name = KCP_DEVICE,\n+\t.fops = &kcp_fops,\n+};\n+\n+static int __init\n+kcp_init(void)\n+{\n+\tKCP_PRINT(\"DPDK kcp module loading\\n\");\n+\n+\tif (misc_register(&kcp_misc) != 0) {\n+\t\tKCP_ERR(\"Misc registration failed\\n\");\n+\t\treturn -EPERM;\n+\t}\n+\n+\t/* Clear the bit of device in use */\n+\tclear_bit(KCP_DEV_IN_USE_BIT_NUM, &device_in_use);\n+\n+\tKCP_PRINT(\"DPDK kcp module loaded\\n\");\n+\n+\treturn 0;\n+}\n+module_init(kcp_init);\n+\n+static void __exit\n+kcp_exit(void)\n+{\n+\tmisc_deregister(&kcp_misc);\n+\tKCP_PRINT(\"DPDK kcp module unloaded\\n\");\n+}\n+module_exit(kcp_exit);\n+\n+MODULE_LICENSE(\"Dual BSD/GPL\");\n+MODULE_AUTHOR(\"Intel Corporation\");\n+MODULE_DESCRIPTION(\"Kernel Module for managing kcp devices\");\ndiff --git a/lib/librte_eal/linuxapp/kcp/kcp_net.c b/lib/librte_eal/linuxapp/kcp/kcp_net.c\nnew file mode 100644\nindex 0000000..8aba386\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/kcp_net.c\n@@ -0,0 +1,209 @@\n+/*-\n+ * GPL LICENSE SUMMARY\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *\n+ *   This program is free software; you can redistribute it and/or modify\n+ *   it under the terms of version 2 of the GNU General Public License as\n+ *   published by the Free Software Foundation.\n+ *\n+ *   This program is distributed in the hope that it will be useful, but\n+ *   WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *   General Public License for more details.\n+ *\n+ *   You should have received a copy of the GNU General Public License\n+ *   along with this program; if not, write to the Free Software\n+ *   Foundation.\n+ *   The full GNU General Public License is included in this distribution\n+ *   in the file called LICENSE.GPL.\n+ *\n+ *   Contact Information:\n+ *   Intel Corporation\n+ */\n+\n+/*\n+ * This code is inspired from the book \"Linux Device Drivers\" by\n+ * Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates\n+ */\n+\n+#include <linux/version.h>\n+#include <linux/etherdevice.h> /* eth_type_trans */\n+\n+#include \"kcp_dev.h\"\n+\n+/*\n+ * Open and close\n+ */\n+static int\n+kcp_net_open(struct net_device *dev)\n+{\n+\tkcp_nl_exec(RTE_KCP_REQ_START_PORT, dev, NULL, 0, NULL, 0);\n+\tnetif_start_queue(dev);\n+\treturn 0;\n+}\n+\n+static int\n+kcp_net_release(struct net_device *dev)\n+{\n+\tkcp_nl_exec(RTE_KCP_REQ_STOP_PORT, dev, NULL, 0, NULL, 0);\n+\tnetif_stop_queue(dev); /* can't transmit any more */\n+\treturn 0;\n+}\n+\n+/*\n+ * Configuration changes (passed on by ifconfig)\n+ */\n+static int\n+kcp_net_config(struct net_device *dev, struct ifmap *map)\n+{\n+\tif (dev->flags & IFF_UP) /* can't act on a running interface */\n+\t\treturn -EBUSY;\n+\n+\t/* ignore other fields */\n+\treturn 0;\n+}\n+\n+static int\n+kcp_net_change_mtu(struct net_device *dev, int new_mtu)\n+{\n+\tint err;\n+\n+\tKCP_DBG(\"kcp_net_change_mtu new mtu %d to be set\\n\", new_mtu);\n+\terr = kcp_nl_exec(RTE_KCP_REQ_CHANGE_MTU, dev, &new_mtu, sizeof(int),\n+\t\t\tNULL, 0);\n+\n+\tif (err == 0)\n+\t\tdev->mtu = new_mtu;\n+\n+\treturn err;\n+}\n+\n+/*\n+ * Ioctl commands\n+ */\n+static int\n+kcp_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)\n+{\n+\tKCP_DBG(\"kcp_net_ioctl\\n\");\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Return statistics to the caller\n+ */\n+static struct  rtnl_link_stats64 *\n+kcp_net_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)\n+{\n+\tint err;\n+\n+\terr = kcp_nl_exec(RTE_KCP_REQ_GET_STATS, dev, NULL, 0,\n+\t\t\tstats, sizeof(struct rtnl_link_stats64));\n+\n+\treturn stats;\n+}\n+\n+/**\n+ * kcp_net_set_mac - Change the Ethernet Address of the KCP NIC\n+ * @netdev: network interface device structure\n+ * @p: pointer to an address structure\n+ *\n+ * Returns 0 on success, negative on failure\n+ **/\n+static int\n+kcp_net_set_mac(struct net_device *dev, void *p)\n+{\n+\tstruct sockaddr *addr = p;\n+\tint err;\n+\n+\tif (!is_valid_ether_addr((unsigned char *)(addr->sa_data)))\n+\t\treturn -EADDRNOTAVAIL;\n+\n+\terr = kcp_nl_exec(RTE_KCP_REQ_SET_MAC, dev, addr->sa_data,\n+\t\t\tdev->addr_len, NULL, 0);\n+\tif (err < 0)\n+\t\treturn -EADDRNOTAVAIL;\n+\n+\tmemcpy(dev->dev_addr, addr->sa_data, dev->addr_len);\n+\treturn 0;\n+}\n+\n+#if (KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE)\n+static int\n+kcp_net_change_carrier(struct net_device *dev, bool new_carrier)\n+{\n+\tif (new_carrier)\n+\t\tnetif_carrier_on(dev);\n+\telse\n+\t\tnetif_carrier_off(dev);\n+\treturn 0;\n+}\n+#endif\n+\n+static const struct net_device_ops kcp_net_netdev_ops = {\n+\t.ndo_open = kcp_net_open,\n+\t.ndo_stop = kcp_net_release,\n+\t.ndo_set_config = kcp_net_config,\n+\t.ndo_change_mtu = kcp_net_change_mtu,\n+\t.ndo_do_ioctl = kcp_net_ioctl,\n+\t.ndo_get_stats64 = kcp_net_stats64,\n+\t.ndo_set_mac_address = kcp_net_set_mac,\n+#if (KERNEL_VERSION(3, 9, 0) <= LINUX_VERSION_CODE)\n+\t.ndo_change_carrier = kcp_net_change_carrier,\n+#endif\n+};\n+\n+/*\n+ *  Fill the eth header\n+ */\n+static int\n+kcp_net_header(struct sk_buff *skb, struct net_device *dev,\n+\t\tunsigned short type, const void *daddr,\n+\t\tconst void *saddr, unsigned int len)\n+{\n+\tstruct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);\n+\n+\tmemcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);\n+\tmemcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);\n+\teth->h_proto = htons(type);\n+\n+\treturn dev->hard_header_len;\n+}\n+\n+/*\n+ * Re-fill the eth header\n+ */\n+#if (KERNEL_VERSION(4, 1, 0) > LINUX_VERSION_CODE)\n+static int\n+kcp_net_rebuild_header(struct sk_buff *skb)\n+{\n+\tstruct net_device *dev = skb->dev;\n+\tstruct ethhdr *eth = (struct ethhdr *) skb->data;\n+\n+\tmemcpy(eth->h_source, dev->dev_addr, dev->addr_len);\n+\tmemcpy(eth->h_dest, dev->dev_addr, dev->addr_len);\n+\n+\treturn 0;\n+}\n+#endif\n+\n+static const struct header_ops kcp_net_header_ops = {\n+\t.create  = kcp_net_header,\n+#if (KERNEL_VERSION(4, 1, 0) > LINUX_VERSION_CODE)\n+\t.rebuild = kcp_net_rebuild_header,\n+#endif\n+\t.cache   = NULL,  /* disable caching */\n+};\n+\n+void\n+kcp_net_init(struct net_device *dev)\n+{\n+\tKCP_DBG(\"kcp_net_init\\n\");\n+\n+\tether_setup(dev); /* assign some of the fields */\n+\tdev->netdev_ops      = &kcp_net_netdev_ops;\n+\tdev->header_ops      = &kcp_net_header_ops;\n+\n+\tdev->flags |= IFF_UP;\n+}\ndiff --git a/lib/librte_eal/linuxapp/kcp/kcp_nl.c b/lib/librte_eal/linuxapp/kcp/kcp_nl.c\nnew file mode 100644\nindex 0000000..3c2ed5b\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/kcp/kcp_nl.c\n@@ -0,0 +1,194 @@\n+/*-\n+ * GPL LICENSE SUMMARY\n+ *\n+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+ *\n+ *   This program is free software; you can redistribute it and/or modify\n+ *   it under the terms of version 2 of the GNU General Public License as\n+ *   published by the Free Software Foundation.\n+ *\n+ *   This program is distributed in the hope that it will be useful, but\n+ *   WITHOUT ANY WARRANTY; without even the implied warranty of\n+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+ *   General Public License for more details.\n+ *\n+ *   You should have received a copy of the GNU General Public License\n+ *   along with this program;\n+ *   The full GNU General Public License is included in this distribution\n+ *   in the file called LICENSE.GPL.\n+ *\n+ *   Contact Information:\n+ *   Intel Corporation\n+ */\n+\n+#include <net/sock.h>\n+\n+#include \"kcp_dev.h\"\n+\n+#define KCP_NL_GRP 31\n+\n+#define KCP_ETHTOOL_MSG_LEN 500\n+struct kcp_ethtool_msg {\n+\tint cmd_id;\n+\tint port_id;\n+\tchar input_buffer[KCP_ETHTOOL_MSG_LEN];\n+\tchar output_buffer[KCP_ETHTOOL_MSG_LEN];\n+\tint input_buf_len;\n+\tint output_buf_len;\n+\tint err;\n+};\n+\n+static struct ethtool_input_buffer {\n+\tint magic;\n+\tvoid *buffer;\n+\tint length;\n+\tstruct completion *msg_received;\n+\tint *err;\n+} ethtool_input_buffer;\n+\n+static struct sock *nl_sock;\n+static int pid __read_mostly = -1;\n+static struct mutex sync_lock;\n+\n+static int\n+kcp_input_buffer_register(int magic, void *buffer, int length,\n+\t\tstruct completion *msg_received, int *err)\n+{\n+\tif (ethtool_input_buffer.buffer == NULL) {\n+\t\tethtool_input_buffer.magic = magic;\n+\t\tethtool_input_buffer.buffer = buffer;\n+\t\tethtool_input_buffer.length = length;\n+\t\tethtool_input_buffer.msg_received = msg_received;\n+\t\tethtool_input_buffer.err = err;\n+\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+static void\n+kcp_input_buffer_unregister(int magic)\n+{\n+\tif (ethtool_input_buffer.buffer != NULL) {\n+\t\tif (magic == ethtool_input_buffer.magic) {\n+\t\t\tethtool_input_buffer.magic = -1;\n+\t\t\tethtool_input_buffer.buffer = NULL;\n+\t\t\tethtool_input_buffer.length = 0;\n+\t\t\tethtool_input_buffer.msg_received = NULL;\n+\t\t\tethtool_input_buffer.err = NULL;\n+\t\t}\n+\t}\n+}\n+\n+static void\n+nl_recv(struct sk_buff *skb)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct kcp_ethtool_msg ethtool_msg;\n+\n+\tnlh = (struct nlmsghdr *)skb->data;\n+\tif (pid < 0) {\n+\t\tpid = nlh->nlmsg_pid;\n+\t\tKCP_INFO(\"PID: %d\\n\", pid);\n+\t\treturn;\n+\t} else if (pid != nlh->nlmsg_pid) {\n+\t\tKCP_INFO(\"Message from unexpected peer: %d\", nlh->nlmsg_pid);\n+\t\treturn;\n+\t}\n+\n+\tmemcpy(&ethtool_msg, NLMSG_DATA(nlh), sizeof(struct kcp_ethtool_msg));\n+\tKCP_DBG(\"CMD: %d\\n\", ethtool_msg.cmd_id);\n+\n+\tif (ethtool_input_buffer.magic > 0) {\n+\t\tif (ethtool_input_buffer.buffer != NULL) {\n+\t\t\tmemcpy(ethtool_input_buffer.buffer,\n+\t\t\t\t\t&ethtool_msg.output_buffer,\n+\t\t\t\t\tethtool_input_buffer.length);\n+\t\t}\n+\t\t*ethtool_input_buffer.err = ethtool_msg.err;\n+\t\tcomplete(ethtool_input_buffer.msg_received);\n+\t\tkcp_input_buffer_unregister(ethtool_input_buffer.magic);\n+\t}\n+}\n+\n+static int\n+kcp_nl_send(int cmd_id, int port_id, void *input_buffer, int input_buf_len)\n+{\n+\tstruct sk_buff *skb;\n+\tstruct nlmsghdr *nlh;\n+\tstruct kcp_ethtool_msg ethtool_msg;\n+\n+\tmemset(&ethtool_msg, 0, sizeof(struct kcp_ethtool_msg));\n+\tethtool_msg.cmd_id = cmd_id;\n+\tethtool_msg.port_id = port_id;\n+\n+\tif (input_buffer) {\n+\t\tif (input_buf_len == 0 || input_buf_len > KCP_ETHTOOL_MSG_LEN)\n+\t\t\treturn -EINVAL;\n+\t\tethtool_msg.input_buf_len = input_buf_len;\n+\t\tmemcpy(ethtool_msg.input_buffer, input_buffer, input_buf_len);\n+\t}\n+\n+\tskb = nlmsg_new(NLMSG_ALIGN(sizeof(struct kcp_ethtool_msg)),\n+\t\t\tGFP_ATOMIC);\n+\tnlh = nlmsg_put(skb, 0, 0, NLMSG_DONE, sizeof(struct kcp_ethtool_msg),\n+\t\t\t0);\n+\n+\tNETLINK_CB(skb).dst_group = 0;\n+\n+\tmemcpy(nlmsg_data(nlh), &ethtool_msg, sizeof(struct kcp_ethtool_msg));\n+\n+\tnlmsg_unicast(nl_sock, skb, pid);\n+\tKCP_DBG(\"Sent cmd:%d port:%d\\n\", cmd_id, port_id);\n+\n+\t/*nlmsg_free(skb);*/\n+\n+\treturn 0;\n+}\n+\n+int\n+kcp_nl_exec(int cmd, struct net_device *dev, void *in_data, int in_len,\n+\t\tvoid *out_data, int out_len)\n+{\n+\tstruct kcp_dev *priv = netdev_priv(dev);\n+\tint err = -EINVAL;\n+\tint ret;\n+\n+\tmutex_lock(&sync_lock);\n+\tret = kcp_input_buffer_register(cmd, out_data, out_len,\n+\t\t\t&priv->msg_received, &err);\n+\tif (ret) {\n+\t\tmutex_unlock(&sync_lock);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tkcp_nl_send(cmd, priv->port_id, in_data, in_len);\n+\tret = wait_for_completion_interruptible_timeout(&priv->msg_received,\n+\t\t\t msecs_to_jiffies(10));\n+\tif (ret == 0 || err < 0) {\n+\t\tkcp_input_buffer_unregister(ethtool_input_buffer.magic);\n+\t\tmutex_unlock(&sync_lock);\n+\t\treturn ret == 0 ? -EINVAL : err;\n+\t}\n+\tmutex_unlock(&sync_lock);\n+\n+\treturn 0;\n+}\n+\n+static struct netlink_kernel_cfg cfg = {\n+\t.input = nl_recv,\n+};\n+\n+void\n+kcp_nl_init(void)\n+{\n+\tnl_sock = netlink_kernel_create(&init_net, KCP_NL_GRP, &cfg);\n+\tmutex_init(&sync_lock);\n+}\n+\n+void\n+kcp_nl_release(void)\n+{\n+\tnetlink_kernel_release(nl_sock);\n+\tpid = -1;\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "RFC",
        "2/3"
    ]
}