@@ -260,6 +260,7 @@ F: doc/guides/sample_app_ug/kernel_nic_interface.rst
Linux KCP
M: Ferruh Yigit <ferruh.yigit@intel.com>
F: lib/librte_eal/linuxapp/kcp/
+F: lib/librte_ctrl_if/
Linux AF_PACKET
M: John W. Linville <linville@tuxdriver.com>
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -506,6 +506,7 @@ CONFIG_RTE_LIBRTE_ETHTOOL=y
#
CONFIG_RTE_KCP_KMOD=y
CONFIG_RTE_KCP_KO_DEBUG=n
+CONFIG_RTE_LIBRTE_CTRL_IF=y
#
# Compile vhost library
@@ -151,3 +151,4 @@ There are many libraries, so their headers may be grouped by topics:
[keepalive] (@ref rte_keepalive.h),
[version] (@ref rte_version.h),
[ethtool] (@ref rte_ethtool.h),
+ [control interface] (@ref rte_ctrl_if.h)
@@ -39,6 +39,7 @@ INPUT = doc/api/doxy-api-index.md \
lib/librte_cmdline \
lib/librte_compat \
lib/librte_cryptodev \
+ lib/librte_ctrl_if \
lib/librte_distributor \
lib/librte_ether \
lib/librte_ethtool \
new file mode 100644
@@ -0,0 +1,52 @@
+.. BSD LICENSE
+ Copyright(c) 2016 Intel Corporation. All rights reserved.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+.. _Ctrl_If_Library:
+
+Control Interface Library
+=========================
+
+This Library is to create/destroy control interfaces and process messages
+received by control interface.
+
+Control Interface is Linux network interface and it is possible to call
+various Linux commands to this interface and commands will be forwarded
+to the matching DPDK PMD, and response will be generated by PMD.
+
+Control interface required KCP kernel module to be inserted to function.
+
+Control Interface APIS
+----------------------
+
+
+- ``rte_eth_control_interface_create()``
+- ``rte_eth_control_interface_destroy()``
+- ``rte_eth_control_interface_msg_exist()``
+- ``rte_eth_control_interface_msg_process()``
@@ -52,6 +52,7 @@ Programmer's Guide
reorder_lib
ip_fragment_reassembly_lib
ethtool_lib
+ ctrl_if_lib
multi_proc_support
kernel_nic_interface
thread_safety_dpdk_functions
@@ -46,6 +46,14 @@ This section should contain new features added in this release. Sample format:
* **Added vhost-user live migration support.**
+* **Control interface support added.**
+
+ To enable controlling DPDK ports by common Linux tools.
+ Following modules added to DPDK:
+
+ * librte_ctrl_if library
+ * librte_eal/linuxapp/kcp kernel module
+
Resolved Issues
---------------
@@ -127,6 +135,7 @@ The libraries prepended with a plus sign were incremented in this version.
librte_acl.so.2
librte_cfgfile.so.2
librte_cmdline.so.1
+ + librte_ctrl_if.so.1
librte_distributor.so.1
librte_eal.so.2
+ librte_ethtool.so.1
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table
DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline
DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
DIRS-$(CONFIG_RTE_LIBRTE_ETHTOOL) += librte_ethtool
+DIRS-$(CONFIG_RTE_LIBRTE_CTRL_IF) += librte_ctrl_if
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
new file mode 100644
@@ -0,0 +1,58 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_ctrl_if.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_ctrl_if_version.map
+
+LIBABIVER := 1
+
+SRCS-y += rte_ctrl_if.c
+SRCS-y += rte_nl.c
+SRCS-y += rte_ctrl_ethtool.c
+
+#
+# Export include files
+#
+SYMLINK-y-include += rte_ctrl_if.h
+
+# this lib depends upon:
+DEPDIRS-y += lib/librte_ether
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,376 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <error.h>
+
+#include <linux/if_link.h>
+
+#include <rte_version.h>
+#include <rte_ethdev.h>
+#include <rte_ethtool.h>
+#include "rte_ctrl_ethtool.h"
+
+#define ETHTOOL_GEEPROM_LEN 99
+#define ETHTOOL_GREGS_LEN 98
+#define ETHTOOL_GSSET_COUNT 97
+
+static int
+get_drvinfo(int port_id, void *data, int *data_len)
+{
+ struct ethtool_drvinfo *info = data;
+ int ret;
+
+ ret = rte_ethtool_get_drvinfo(port_id, info);
+ if (ret < 0)
+ return ret;
+
+ *data_len = sizeof(struct ethtool_drvinfo);
+
+ return 0;
+}
+
+static int
+get_reg_len(int port_id, void *data, int *data_len)
+{
+ int reg_length = 0;
+
+ reg_length = rte_ethtool_get_regs_len(port_id);
+ if (reg_length < 0)
+ return reg_length;
+
+ *(int *)data = reg_length;
+ *data_len = sizeof(int);
+
+ return 0;
+}
+
+static int
+get_reg(int port_id, void *in_data, void *out_data, int *out_data_len)
+{
+ unsigned int reg_length;
+ int reg_length_out_len;
+ struct ethtool_regs *ethtool_regs = in_data;
+ int ret;
+
+ ret = get_reg_len(port_id, ®_length, ®_length_out_len);
+
+ /* not enough space in out data buffer */
+ if (ret < 0 || reg_length > ethtool_regs->len)
+ return -1;
+
+ ret = rte_ethtool_get_regs(port_id, ethtool_regs, out_data);
+ if (ret < 0)
+ return ret;
+
+ *out_data_len = reg_length;
+
+ return 0;
+}
+
+static int
+get_link(int port_id, void *data, int *data_len)
+{
+ int ret;
+
+ ret = rte_ethtool_get_link(port_id);
+
+ *(int *)data = ret;
+ *data_len = sizeof(int);
+
+ return 0;
+}
+
+static int
+get_eeprom_length(int port_id, void *data, int *data_len)
+{
+ int eeprom_length = 0;
+
+ eeprom_length = rte_ethtool_get_eeprom_len(port_id);
+ if (eeprom_length < 0)
+ return eeprom_length;
+
+ *(int *)data = eeprom_length;
+ *data_len = sizeof(int);
+
+ return 0;
+}
+
+static int
+get_eeprom(int port_id, void *in_data, void *out_data, int *out_data_len)
+{
+ struct ethtool_eeprom *eeprom = in_data;
+ int ret;
+
+ ret = rte_ethtool_get_eeprom(port_id, eeprom, out_data);
+ if (ret < 0)
+ return ret;
+
+ *out_data_len = eeprom->len;
+
+ return 0;
+}
+
+static int
+set_eeprom(int port_id, void *in_data)
+{
+ struct ethtool_eeprom *eeprom = in_data;
+ int ret;
+
+ ret = rte_ethtool_set_eeprom(port_id, eeprom, eeprom->data);
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+get_ringparam(int port_id, void *data, int *data_len)
+{
+ struct ethtool_ringparam *ringparam = data;
+ int ret;
+
+ ret = rte_ethtool_get_ringparam(port_id, ringparam);
+ if (ret < 0)
+ return ret;
+
+ *data_len = sizeof(struct ethtool_ringparam);
+
+ return 0;
+}
+
+static int
+set_ringparam(int port_id, void *data)
+{
+ struct ethtool_ringparam *ringparam = data;
+ int ret;
+
+ ret = rte_ethtool_set_ringparam(port_id, ringparam);
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+get_pauseparam(int port_id, void *data, int *data_len)
+{
+ struct ethtool_pauseparam *pauseparam = data;
+ int ret;
+
+ ret = rte_ethtool_get_pauseparam(port_id, pauseparam);
+ if (ret < 0)
+ return ret;
+
+ *data_len = sizeof(struct ethtool_pauseparam);
+
+ return 0;
+}
+
+static int
+set_pauseparam(int port_id, void *data)
+{
+ struct ethtool_pauseparam *pauseparam = data;
+
+ return rte_ethtool_set_pauseparam(port_id, pauseparam);
+}
+
+int
+rte_eth_dev_ethtool_process(int cmd_id, int port_id, void *in_data,
+ void *out_data, int *out_data_len)
+{
+ int ret = 0;
+
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ switch (cmd_id) {
+ case ETHTOOL_GDRVINFO:
+ return get_drvinfo(port_id, out_data, out_data_len);
+ case ETHTOOL_GREGS_LEN:
+ return get_reg_len(port_id, out_data, out_data_len);
+ case ETHTOOL_GREGS:
+ return get_reg(port_id, in_data, out_data, out_data_len);
+ case ETHTOOL_GLINK:
+ return get_link(port_id, out_data, out_data_len);
+ case ETHTOOL_GEEPROM_LEN:
+ return get_eeprom_length(port_id, out_data, out_data_len);
+ case ETHTOOL_GEEPROM:
+ return get_eeprom(port_id, in_data, out_data, out_data_len);
+ case ETHTOOL_SEEPROM:
+ return set_eeprom(port_id, in_data);
+ case ETHTOOL_GRINGPARAM:
+ return get_ringparam(port_id, out_data, out_data_len);
+ case ETHTOOL_SRINGPARAM:
+ return set_ringparam(port_id, in_data);
+ case ETHTOOL_GPAUSEPARAM:
+ return get_pauseparam(port_id, out_data, out_data_len);
+ case ETHTOOL_SPAUSEPARAM:
+ return set_pauseparam(port_id, in_data);
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int
+set_mtu(int port_id, void *in_data)
+{
+ int *mtu = in_data;
+
+ return rte_eth_dev_set_mtu(port_id, *mtu);
+}
+
+static int
+get_stats(int port_id, void *data, int *data_len)
+{
+ struct rte_eth_stats stats;
+ struct rtnl_link_stats64 *if_stats = data;
+ int ret;
+
+ ret = rte_eth_stats_get(port_id, &stats);
+ if (ret < 0)
+ return -EOPNOTSUPP;
+
+ if_stats->rx_packets = stats.ipackets;
+ if_stats->tx_packets = stats.opackets;
+ if_stats->rx_bytes = stats.ibytes;
+ if_stats->tx_bytes = stats.obytes;
+ if_stats->rx_errors = stats.ierrors;
+ if_stats->tx_errors = stats.oerrors;
+ if_stats->rx_dropped = stats.imissed;
+ if_stats->multicast = stats.imcasts;
+
+ *data_len = sizeof(struct rtnl_link_stats64);
+
+ return 0;
+}
+
+static int
+get_mac(int port_id, void *data, int *data_len)
+{
+ struct ether_addr addr;
+
+ rte_eth_macaddr_get(port_id, &addr);
+ memcpy(data, &addr, sizeof(struct ether_addr));
+
+ *data_len = sizeof(struct ether_addr);
+
+ return 0;
+}
+
+static int
+set_mac(int port_id, void *in_data)
+{
+ struct ether_addr addr;
+
+ memcpy(&addr, in_data, ETHER_ADDR_LEN);
+
+ return rte_eth_dev_default_mac_addr_set(port_id, &addr);
+}
+
+static int
+start_port(int port_id)
+{
+ rte_eth_dev_stop(port_id);
+ return rte_eth_dev_start(port_id);
+}
+
+static int
+stop_port(int port_id)
+{
+ rte_eth_dev_stop(port_id);
+ return 0;
+}
+
+static int
+set_promisc(int port_id, void *in_data)
+{
+ int promisc = *(int *)in_data;
+
+ if (promisc)
+ rte_eth_promiscuous_enable(port_id);
+ else
+ rte_eth_promiscuous_disable(port_id);
+
+ return 0;
+}
+
+static int
+set_allmulti(int port_id, void *in_data)
+{
+ int allmulti = *(int *)in_data;
+
+ if (allmulti)
+ rte_eth_allmulticast_enable(port_id);
+ else
+ rte_eth_allmulticast_disable(port_id);
+
+ return 0;
+}
+
+int
+rte_eth_dev_control_process(int cmd_id, int port_id, void *in_data,
+ void *out_data, int *out_data_len)
+{
+ int ret = 0;
+
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ switch (cmd_id) {
+ case RTE_KCP_REQ_CHANGE_MTU:
+ return set_mtu(port_id, in_data);
+ case RTE_KCP_REQ_GET_STATS:
+ return get_stats(port_id, out_data, out_data_len);
+ case RTE_KCP_REQ_GET_MAC:
+ return get_mac(port_id, out_data, out_data_len);
+ case RTE_KCP_REQ_SET_MAC:
+ return set_mac(port_id, in_data);
+ case RTE_KCP_REQ_START_PORT:
+ return start_port(port_id);
+ case RTE_KCP_REQ_STOP_PORT:
+ return stop_port(port_id);
+ case RTE_KCP_REQ_SET_PROMISC:
+ return set_promisc(port_id, in_data);
+ case RTE_KCP_REQ_SET_ALLMULTI:
+ return set_allmulti(port_id, in_data);
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,54 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CTRL_ETHTOOL_H_
+#define _RTE_CTRL_ETHTOOL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/ethtool.h>
+
+#include <exec-env/rte_kcp_common.h>
+
+int rte_eth_dev_ethtool_process(int cmd_id, int port_id, void *in_data,
+ void *out_data, int *out_data_len);
+int rte_eth_dev_control_process(int cmd_id, int port_id, void *in_data,
+ void *out_data, int *out_data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_ETHTOOL_H_ */
new file mode 100644
@@ -0,0 +1,395 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <rte_ethdev.h>
+#include "rte_ctrl_if.h"
+#include "rte_nl.h"
+
+#define NAMESZ 32
+#define IFNAME "dpdk"
+#define BUFSZ 1024
+
+static int kcp_rtnl_fd = -1;
+static int kcp_fd_ref;
+
+struct kcp_request {
+ struct nlmsghdr nlmsg;
+ char buf[BUFSZ];
+};
+
+static int
+conrol_interface_rtnl_init(void)
+{
+ struct sockaddr_nl src;
+ int ret;
+
+ kcp_rtnl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (kcp_rtnl_fd < 0) {
+ RTE_LOG(ERR, CTRL_IF, "socket for create failed\n");
+ return -1;
+ }
+
+ memset(&src, 0, sizeof(struct sockaddr_nl));
+
+ src.nl_family = AF_NETLINK;
+ src.nl_pid = getpid();
+
+ ret = bind(kcp_rtnl_fd, (struct sockaddr *)&src,
+ sizeof(struct sockaddr_nl));
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Bind for create failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+control_interface_init(void)
+{
+ int ret;
+
+ ret = conrol_interface_rtnl_init();
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Failed to initialize rtnetlink\n");
+ return -1;
+ }
+
+ ret = control_interface_nl_init();
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Failed to initialize netlink\n");
+ close(kcp_rtnl_fd);
+ kcp_rtnl_fd = -1;
+ }
+
+ return ret;
+}
+
+static int
+control_interface_ref_get(void)
+{
+ int ret = 0;
+
+ if (kcp_fd_ref == 0)
+ ret = control_interface_init();
+
+ if (ret == 0)
+ kcp_fd_ref++;
+ else
+ RTE_LOG(ERR, CTRL_IF,
+ "Failed to initialize control interface\n");
+
+ return kcp_fd_ref;
+}
+
+static void
+control_interface_release(void)
+{
+ close(kcp_rtnl_fd);
+ control_interface_nl_release();
+}
+
+static int
+control_interface_ref_put(void)
+{
+ if (kcp_fd_ref == 0)
+ return 0;
+
+ kcp_fd_ref--;
+
+ if (kcp_fd_ref == 0)
+ control_interface_release();
+
+ return kcp_fd_ref;
+}
+
+static int
+add_attr(struct kcp_request *req, unsigned short type, void *buf, size_t len)
+{
+ struct rtattr *rta;
+ int nlmsg_len;
+
+ nlmsg_len = NLMSG_ALIGN(req->nlmsg.nlmsg_len);
+ rta = (struct rtattr *)((char *)&req->nlmsg + nlmsg_len);
+ if (nlmsg_len + RTA_LENGTH(len) > sizeof(struct kcp_request))
+ return -1;
+ rta->rta_type = type;
+ rta->rta_len = RTA_LENGTH(len);
+ memcpy(RTA_DATA(rta), buf, len);
+ req->nlmsg.nlmsg_len = nlmsg_len + RTA_LENGTH(len);
+
+ return 0;
+}
+
+static struct
+rtattr *add_attr_nested(struct kcp_request *req, unsigned short type)
+{
+ struct rtattr *rta;
+ int nlmsg_len;
+
+ nlmsg_len = NLMSG_ALIGN(req->nlmsg.nlmsg_len);
+ rta = (struct rtattr *)((char *)&req->nlmsg + nlmsg_len);
+ if (nlmsg_len + RTA_LENGTH(0) > sizeof(struct kcp_request))
+ return NULL;
+ rta->rta_type = type;
+ rta->rta_len = nlmsg_len;
+ req->nlmsg.nlmsg_len = nlmsg_len + RTA_LENGTH(0);
+
+ return rta;
+}
+
+static void
+end_attr_nested(struct kcp_request *req, struct rtattr *rta)
+{
+ rta->rta_len = req->nlmsg.nlmsg_len - rta->rta_len;
+}
+
+static int
+rte_eth_rtnl_create(uint8_t port_id)
+{
+ struct kcp_request req;
+ struct ifinfomsg *info;
+ struct rtattr *rta1;
+ struct rtattr *rta2;
+ unsigned int pid = getpid();
+ char name[NAMESZ];
+ char type[NAMESZ];
+ struct iovec iov;
+ struct msghdr msg;
+ struct sockaddr_nl nladdr;
+ int ret;
+ char buf[BUFSZ];
+
+ memset(&req, 0, sizeof(struct kcp_request));
+
+ req.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nlmsg.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
+ req.nlmsg.nlmsg_flags |= NLM_F_ACK;
+ req.nlmsg.nlmsg_type = RTM_NEWLINK;
+
+ info = NLMSG_DATA(&req.nlmsg);
+
+ info->ifi_family = AF_UNSPEC;
+ info->ifi_index = 0;
+
+ snprintf(name, NAMESZ, IFNAME"%u", port_id);
+ ret = add_attr(&req, IFLA_IFNAME, name, strlen(name) + 1);
+ if (ret < 0)
+ return -1;
+
+ rta1 = add_attr_nested(&req, IFLA_LINKINFO);
+ if (rta1 == NULL)
+ return -1;
+
+ snprintf(type, NAMESZ, KCP_DEVICE);
+ ret = add_attr(&req, IFLA_INFO_KIND, type, strlen(type) + 1);
+ if (ret < 0)
+ return -1;
+
+ rta2 = add_attr_nested(&req, IFLA_INFO_DATA);
+ if (rta2 == NULL)
+ return -1;
+
+ ret = add_attr(&req, IFLA_KCP_PORTID, &port_id, sizeof(uint8_t));
+ if (ret < 0)
+ return -1;
+
+ ret = add_attr(&req, IFLA_KCP_PID, &pid, sizeof(unsigned int));
+ if (ret < 0)
+ return -1;
+
+ end_attr_nested(&req, rta2);
+ end_attr_nested(&req, rta1);
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ iov.iov_base = (void *)&req.nlmsg;
+ iov.iov_len = req.nlmsg.nlmsg_len;
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_name = &nladdr;
+ msg.msg_namelen = sizeof(nladdr);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(kcp_rtnl_fd, &msg, 0);
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Send for create failed %d.\n", errno);
+ return -1;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ iov.iov_base = buf;
+ iov.iov_len = sizeof(buf);
+
+ ret = recvmsg(kcp_rtnl_fd, &msg, 0);
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Recv for create failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+rte_eth_control_interface_create_one(uint8_t port_id)
+{
+ int ret;
+
+ if (control_interface_ref_get() != 0) {
+ ret = rte_eth_rtnl_create(port_id);
+ RTE_LOG(DEBUG, CTRL_IF,
+ "Control interface %s for port:%u\n",
+ ret < 0 ? "failed" : "created", port_id);
+ }
+
+ return 0;
+}
+
+int
+rte_eth_control_interface_create(void)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if (rte_eth_dev_is_valid_port(i)) {
+ if (rte_eth_devices[i].dev_type == RTE_ETH_DEV_VIRTUAL)
+ continue;
+ ret = rte_eth_control_interface_create_one(i);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int
+rte_eth_rtnl_destroy(uint8_t port_id)
+{
+ struct kcp_request req;
+ struct ifinfomsg *info;
+ char name[NAMESZ];
+ struct iovec iov;
+ struct msghdr msg;
+ struct sockaddr_nl nladdr;
+ int ret;
+
+ memset(&req, 0, sizeof(struct kcp_request));
+
+ req.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.nlmsg.nlmsg_flags = NLM_F_REQUEST;
+ req.nlmsg.nlmsg_type = RTM_DELLINK;
+
+ info = NLMSG_DATA(&req.nlmsg);
+
+ info->ifi_family = AF_UNSPEC;
+ info->ifi_index = 0;
+
+ snprintf(name, NAMESZ, IFNAME"%u", port_id);
+ ret = add_attr(&req, IFLA_IFNAME, name, strlen(name) + 1);
+ if (ret < 0)
+ return -1;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ iov.iov_base = (void *)&req.nlmsg;
+ iov.iov_len = req.nlmsg.nlmsg_len;
+
+ memset(&msg, 0, sizeof(struct msghdr));
+ msg.msg_name = &nladdr;
+ msg.msg_namelen = sizeof(nladdr);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ ret = sendmsg(kcp_rtnl_fd, &msg, 0);
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Send for destroy failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+rte_eth_control_interface_destroy_one(uint8_t port_id)
+{
+ rte_eth_rtnl_destroy(port_id);
+ control_interface_ref_put();
+ RTE_LOG(DEBUG, CTRL_IF, "Control interface destroyed for port:%u\n",
+ port_id);
+
+ return 0;
+}
+
+int
+rte_eth_control_interface_destroy(void)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if (rte_eth_dev_is_valid_port(i)) {
+ if (rte_eth_devices[i].dev_type == RTE_ETH_DEV_VIRTUAL)
+ continue;
+ ret = rte_eth_control_interface_destroy_one(i);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+int
+rte_eth_control_interface_msg_exist(unsigned int timeout_sec)
+{
+ return control_interface_msg_exist(timeout_sec);
+}
+
+int
+rte_eth_control_interface_msg_process(int flag)
+{
+ return control_interface_msg_process(flag);
+}
new file mode 100644
@@ -0,0 +1,129 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CTRL_IF_H_
+#define _RTE_CTRL_IF_H_
+
+/**
+ * @file
+ *
+ * Control Interface Library for RTE
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <exec-env/rte_kcp_common.h>
+
+/**
+ * Flags values for rte_eth_control_interface_process_msg() API
+ */
+enum control_interface_process_flag {
+ /**< Process if msg available. */
+ RTE_ETHTOOL_CTRL_IF_PROCESS_MSG,
+
+ /**< Discard msg if available, respond with a error value. */
+ RTE_ETHTOOL_CTRL_IF_DISCARD_MSG,
+};
+
+/**
+ * Creates control interfaces (Linux virtual network interface)for
+ * each existing eal port.
+ *
+ * This API opens device created by supportive kernel module and initializes
+ * kernel communication interface.
+ *
+ * If supportive kernel module is not inserted this API will return
+ * an error.
+ *
+ * @return
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_create(void);
+
+/**
+ * Destroys control interfaces.
+ *
+ * This API close device created by supportive kernel module and release
+ * underlying communication interface.
+ *
+ * @return
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_destroy(void);
+
+/**
+ * Check if any msg exist to process.
+ *
+ * This function can be blocking or unblocking according timeout_sec
+ * parameter value. If function will be continuous loop, like can be
+ * called by any forwarding lcore, nonblocking mode should be preferred.
+ * If a separate thread created to handle control messages, blocking
+ * mode can be preferred to save CPU cycles.
+ *
+ * When this function sends a valid port_id, application must call
+ * msg_process() afterwards, to accept new commands.
+ *
+ * @param timeout_sec
+ * if 0, function is in nonblocking mode.
+ * if > 0, blocks for given time, if there is no message available,
+ * sleeps again same amount of time. Value is in seconds.
+ *
+ * @return
+ * port_id the msg for on success. -1 if no msg waiting.
+ */
+int rte_eth_control_interface_msg_exist(unsigned int timeout_sec);
+
+/**
+ * Process if any received message is available.
+ *
+ * If message exists this function will create a local copy of it and
+ * process or discard the message according flag.
+ *
+ * @param flag
+ * Defines what to do with message, can be process or discard.
+ *
+ * @return
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_msg_process(int flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_IF_H_ */
new file mode 100644
@@ -0,0 +1,10 @@
+DPDK_2.3 {
+ global:
+
+ rte_eth_control_interface_create;
+ rte_eth_control_interface_destroy;
+ rte_eth_control_interface_msg_exist;
+ rte_eth_control_interface_msg_process;
+
+ local: *;
+};
new file mode 100644
@@ -0,0 +1,313 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+
+#include <rte_spinlock.h>
+#include <rte_ethdev.h>
+#include "rte_ctrl_ethtool.h"
+#include "rte_nl.h"
+#include "rte_ctrl_if.h"
+
+#define MAX_PAYLOAD sizeof(struct kcp_ethtool_msg)
+
+struct ctrl_if_nl {
+ union {
+ struct nlmsghdr nlh;
+ uint8_t nlmsg[NLMSG_SPACE(MAX_PAYLOAD)];
+ };
+ struct msghdr msg;
+ struct iovec iov;
+ struct sockaddr_nl dest_addr;
+};
+
+struct ctrl_if_msg_sync {
+ int kcp_ethtool_msg_count;
+ struct kcp_ethtool_msg msg_storage;
+ pthread_cond_t cond;
+ pthread_mutex_t msg_lock;
+ int pending_process;
+};
+
+static int sock_fd = -1;
+static pthread_t thread_id;
+
+static struct ctrl_if_nl nl_s;
+static struct ctrl_if_nl nl_r;
+
+static struct ctrl_if_msg_sync ctrl_if_sync = {
+ .cond = PTHREAD_COND_INITIALIZER,
+ .msg_lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
+static int
+nl_send(void *buf, size_t len)
+{
+ int ret;
+
+ if (nl_s.nlh.nlmsg_len < len) {
+ RTE_LOG(ERR, CTRL_IF, "Message is too big, len:%zu\n", len);
+ return -1;
+ }
+
+ if (!NLMSG_OK(&nl_s.nlh, NLMSG_SPACE(MAX_PAYLOAD))) {
+ RTE_LOG(ERR, CTRL_IF, "Message is not OK\n");
+ return -1;
+ }
+
+ /* Fill in the netlink message payload */
+ memcpy(NLMSG_DATA(nl_s.nlmsg), buf, len);
+
+ ret = sendmsg(sock_fd, &nl_s.msg, 0);
+
+ if (ret < 0)
+ RTE_LOG(ERR, CTRL_IF, "Failed nl msg send. ret:%d, err:%d\n",
+ ret, errno);
+ return ret;
+}
+
+static int
+nl_ethtool_msg_send(struct kcp_ethtool_msg *msg)
+{
+ return nl_send((void *)msg, sizeof(struct kcp_ethtool_msg));
+}
+
+static void
+process_msg(struct kcp_ethtool_msg *msg)
+{
+ if (msg->cmd_id > RTE_KCP_REQ_UNKNOWN) {
+ msg->err = rte_eth_dev_control_process(msg->cmd_id,
+ msg->port_id, msg->input_buffer,
+ msg->output_buffer, &msg->output_buffer_len);
+ } else {
+ msg->err = rte_eth_dev_ethtool_process(msg->cmd_id,
+ msg->port_id, msg->input_buffer,
+ msg->output_buffer, &msg->output_buffer_len);
+ }
+
+ if (msg->err)
+ memset(msg->output_buffer, 0, msg->output_buffer_len);
+
+ nl_ethtool_msg_send(msg);
+}
+
+
+int
+control_interface_msg_exist(unsigned int timeout_sec)
+{
+ struct timespec ts;
+ int port_id;
+ int ret = 0;
+
+ if (timeout_sec) {
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += timeout_sec;
+ }
+
+ pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+ while (timeout_sec && !ctrl_if_sync.kcp_ethtool_msg_count && !ret)
+ ret = pthread_cond_timedwait(&ctrl_if_sync.cond,
+ &ctrl_if_sync.msg_lock, &ts);
+
+ if (ctrl_if_sync.kcp_ethtool_msg_count == 0) {
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+ return -1;
+ }
+
+ ctrl_if_sync.pending_process = 1;
+
+ port_id = ctrl_if_sync.msg_storage.port_id;
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+ return port_id;
+}
+
+int
+control_interface_msg_process(int flag)
+{
+ struct kcp_ethtool_msg msg_storage;
+ int ret = 0;
+
+ pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+ if (ctrl_if_sync.kcp_ethtool_msg_count == 0) {
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+ return 0;
+ }
+
+ memcpy(&msg_storage, &ctrl_if_sync.msg_storage,
+ sizeof(struct kcp_ethtool_msg));
+ ctrl_if_sync.pending_process = 0;
+ ctrl_if_sync.kcp_ethtool_msg_count = 0;
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+ switch (flag) {
+ case RTE_ETHTOOL_CTRL_IF_PROCESS_MSG:
+ process_msg(&msg_storage);
+ break;
+
+ case RTE_ETHTOOL_CTRL_IF_DISCARD_MSG:
+ msg_storage.err = -1;
+ nl_ethtool_msg_send(&msg_storage);
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+static int
+msg_add_and_signal(struct nlmsghdr *nlh)
+{
+ pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+
+ if (ctrl_if_sync.pending_process) {
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+ return -1;
+ }
+
+ memcpy(&ctrl_if_sync.msg_storage, NLMSG_DATA(nlh),
+ sizeof(struct kcp_ethtool_msg));
+ ctrl_if_sync.kcp_ethtool_msg_count = 1;
+ ctrl_if_sync.msg_storage.flag = KCP_MSG_FLAG_RESPONSE;
+
+ pthread_cond_signal(&ctrl_if_sync.cond);
+
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+ return 0;
+}
+
+static void *
+nl_recv(void *arg)
+{
+ int ret;
+
+ for (;;) {
+ ret = recvmsg(sock_fd, &nl_r.msg, 0);
+ if (ret < 0)
+ continue;
+
+ if ((unsigned)ret < sizeof(struct kcp_ethtool_msg)) {
+ RTE_LOG(WARNING, CTRL_IF,
+ "Received %u bytes, payload %lu\n",
+ ret, sizeof(struct kcp_ethtool_msg));
+ continue;
+ }
+
+ msg_add_and_signal(&nl_r.nlh);
+ }
+
+ return arg;
+}
+
+static void
+nl_setup_header(struct ctrl_if_nl *nl)
+{
+ nl->dest_addr.nl_family = AF_NETLINK;
+ nl->dest_addr.nl_pid = 0; /* For Linux Kernel */
+ nl->dest_addr.nl_groups = 0;
+
+ memset(nl->nlmsg, 0, NLMSG_SPACE(MAX_PAYLOAD));
+
+ /* Fill the netlink message header */
+ nl->nlh.nlmsg_len = NLMSG_LENGTH(MAX_PAYLOAD);
+ nl->nlh.nlmsg_pid = getpid(); /* self pid */
+ nl->nlh.nlmsg_flags = 0;
+
+ nl->iov.iov_base = (void *)nl->nlmsg;
+ nl->iov.iov_len = nl->nlh.nlmsg_len;
+ memset(&nl->msg, 0, sizeof(struct msghdr));
+ nl->msg.msg_name = (void *)&nl->dest_addr;
+ nl->msg.msg_namelen = sizeof(struct sockaddr_nl);
+ nl->msg.msg_iov = &nl->iov;
+ nl->msg.msg_iovlen = 1;
+}
+
+static int
+nl_socket_init(void)
+{
+ struct sockaddr_nl src_addr;
+ int fd;
+ int ret;
+
+ fd = socket(PF_NETLINK, SOCK_RAW, KCP_NL_GRP);
+ if (fd < 0)
+ return -1;
+
+ src_addr.nl_family = AF_NETLINK;
+ src_addr.nl_pid = getpid();
+ ret = bind(fd, (struct sockaddr *)&src_addr, sizeof(src_addr));
+ if (ret) {
+ close(fd);
+ return -1;
+ }
+
+ nl_setup_header(&nl_s);
+ nl_setup_header(&nl_r);
+
+ return fd;
+}
+
+int
+control_interface_nl_init(void)
+{
+ int ret;
+
+ sock_fd = nl_socket_init();
+ if (sock_fd < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Failed to initialize netlink socket\n");
+ return -1;
+ }
+
+ ret = pthread_create(&thread_id, NULL, nl_recv, NULL);
+ if (ret != 0) {
+ RTE_LOG(ERR, CTRL_IF, "Failed to create receive thread\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+control_interface_nl_release(void)
+{
+ pthread_cancel(thread_id);
+ pthread_join(thread_id, NULL);
+ close(sock_fd);
+}
new file mode 100644
@@ -0,0 +1,50 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_NL_H_
+#define _RTE_NL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int control_interface_nl_init(void);
+void control_interface_nl_release(void);
+int control_interface_msg_exist(unsigned int timeout_sec);
+int control_interface_msg_process(int flag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_NL_H_ */
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,7 @@ extern struct rte_logs rte_logs;
#define RTE_LOGTYPE_PIPELINE 0x00008000 /**< Log related to pipeline. */
#define RTE_LOGTYPE_MBUF 0x00010000 /**< Log related to mbuf. */
#define RTE_LOGTYPE_CRYPTODEV 0x00020000 /**< Log related to cryptodev. */
+#define RTE_LOGTYPE_CTRL_IF 0x00040000 /**< Log related to control interface. */
/* these log types can be used in an application */
#define RTE_LOGTYPE_USER1 0x01000000 /**< User-defined log type 1. */
@@ -1,6 +1,6 @@
# BSD LICENSE
#
-# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
# Copyright(c) 2014-2015 6WIND S.A.
# All rights reserved.
#
@@ -123,6 +123,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF_OFFLOAD) += -lrte_mbuf_offload
_LDLIBS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += -lrte_ip_frag
_LDLIBS-$(CONFIG_RTE_LIBRTE_ETHER) += -lethdev
_LDLIBS-$(CONFIG_RTE_LIBRTE_ETHTOOL) += -lrte_ethtool
+_LDLIBS-$(CONFIG_RTE_LIBRTE_CTRL_IF) += -lrte_ctrl_if
_LDLIBS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += -lrte_cryptodev
_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool
_LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring