@@ -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
@@ -507,6 +507,7 @@ CONFIG_RTE_KNI_VHOST_DEBUG_TX=n
#
CONFIG_RTE_KCP_KMOD=y
CONFIG_RTE_KCP_KO_DEBUG=n
+CONFIG_RTE_LIBRTE_CTRL_IF=y
#
# Compile vhost library
@@ -149,4 +149,5 @@ There are many libraries, so their headers may be grouped by topics:
[common] (@ref rte_common.h),
[ABI compat] (@ref rte_compat.h),
[keepalive] (@ref rte_keepalive.h),
- [version] (@ref rte_version.h)
+ [version] (@ref rte_version.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_hash \
@@ -4,6 +4,14 @@ DPDK Release 2.3
New Features
------------
+* **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
---------------
@@ -51,6 +59,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_hash.so.2
@@ -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
@@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
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_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_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,162 @@
+/*-
+ * 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 <sys/ioctl.h>
+
+#include <rte_ethdev.h>
+#include "rte_ctrl_if.h"
+#include "rte_nl.h"
+
+static int kcp_fd = -1;
+static int kcp_fd_ref;
+
+static int
+control_interface_init(void)
+{
+ int ret;
+ kcp_fd = open("/dev/" KCP_DEVICE, O_RDWR);
+
+ if (kcp_fd < 0) {
+ RTE_LOG(ERR, CTRL_IF,
+ "Failed to initialize control interface.\n");
+ return -1;
+ }
+
+ ret = control_interface_nl_init();
+ if (ret < 0)
+ close(kcp_fd);
+
+ 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++;
+
+ return kcp_fd_ref;
+}
+
+static void
+control_interface_release(void)
+{
+ close(kcp_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
+rte_eth_control_interface_create_one(uint8_t port_id)
+{
+ if (control_interface_ref_get() != 0) {
+ ioctl(kcp_fd, RTE_KCP_IOCTL_CREATE, port_id);
+ RTE_LOG(DEBUG, CTRL_IF,
+ "Control interface created for port:%u\n",
+ 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)) {
+ ret = rte_eth_control_interface_create_one(i);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int
+rte_eth_control_interface_destroy_one(uint8_t port_id)
+{
+ ioctl(kcp_fd, RTE_KCP_IOCTL_RELEASE, 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)) {
+ ret = rte_eth_control_interface_destroy_one(i);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+int
+rte_eth_control_interface_process_msg(int flag, unsigned int timeout_sec)
+{
+ return control_interface_process_msg(flag, timeout_sec);
+}
new file mode 100644
@@ -0,0 +1,115 @@
+/*-
+ * 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);
+
+/**
+ * Process if any received message is available.
+ *
+ * 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.
+ *
+ * @param flag
+ * Defines what to do with message, can be process or discard.
+ *
+ * @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
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_process_msg(int flag, unsigned int timeout_sec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_IF_H_ */
new file mode 100644
@@ -0,0 +1,9 @@
+DPDK_2.3 {
+ global:
+
+ rte_eth_control_interface_create;
+ rte_eth_control_interface_destroy;
+ rte_eth_control_interface_process_msg;
+
+ local: *;
+};
new file mode 100644
@@ -0,0 +1,354 @@
+/*-
+ * 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 <linux/if_link.h>
+
+#include <rte_version.h>
+#include <rte_ethdev.h>
+#include "rte_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;
+ struct rte_eth_dev_info dev_info;
+ int n;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+ snprintf(info->driver, sizeof(info->driver), "%s",
+ dev_info.driver_name);
+ snprintf(info->version, sizeof(info->version), "%s",
+ rte_version());
+ snprintf(info->bus_info, sizeof(info->bus_info),
+ "%04x:%02x:%02x.%x",
+ dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus,
+ dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);
+
+ n = rte_eth_dev_get_reg_length(port_id);
+ info->regdump_len = n < 0 ? 0 : n;
+
+ n = rte_eth_dev_get_eeprom_length(port_id);
+ info->eedump_len = n < 0 ? 0 : n;
+
+ info->n_stats = sizeof(struct rte_eth_stats) / sizeof(uint64_t);
+ info->testinfo_len = 0;
+
+ *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_eth_dev_get_reg_length(port_id);
+ if (reg_length < 0)
+ return reg_length;
+
+ *(int *)data = reg_length * sizeof(uint32_t);
+ *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;
+ struct rte_dev_reg_info regs = {
+ .data = out_data,
+ .length = 0,
+ };
+ int ret;
+
+ ret = get_reg_len(port_id, ®_length, ®_length_out_len);
+ if (ret < 0 || reg_length > ethtool_regs->len)
+ return -1;
+
+ ret = rte_eth_dev_get_reg_info(port_id, ®s);
+ if (ret < 0)
+ return ret;
+
+ ethtool_regs->version = regs.version;
+ *out_data_len = reg_length;
+
+ return 0;
+}
+
+static int
+get_link(int port_id, void *data, int *data_len)
+{
+ struct rte_eth_link link;
+
+ rte_eth_link_get(port_id, &link);
+
+ *(int *)data = link.link_status;
+ *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_eth_dev_get_eeprom_length(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)
+{
+ struct ethtool_eeprom *eeprom = in_data;
+ struct rte_dev_eeprom_info eeprom_info = {
+ .data = out_data,
+ .offset = eeprom->offset,
+ .length = eeprom->len,
+ };
+ int ret;
+
+ ret = rte_eth_dev_get_eeprom(port_id, &eeprom_info);
+ if (ret < 0)
+ return ret;
+
+ eeprom->magic = eeprom_info.magic;
+
+ return 0;
+}
+
+static int
+set_eeprom(int port_id, void *in_data, void *out_data)
+{
+ struct ethtool_eeprom *eeprom = in_data;
+ struct rte_dev_eeprom_info eeprom_info = {
+ .data = out_data,
+ .offset = eeprom->offset,
+ .length = eeprom->len,
+ };
+ int ret;
+
+ ret = rte_eth_dev_set_eeprom(port_id, &eeprom_info);
+ if (ret < 0)
+ return ret;
+
+ eeprom->magic = eeprom_info.magic;
+
+ return 0;
+}
+
+static int
+get_pauseparam(int port_id, void *data, void *data_len)
+{
+ struct ethtool_pauseparam *pauseparam = data;
+ struct rte_eth_fc_conf fc_conf;
+ int ret;
+
+ ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
+ if (ret)
+ return ret;
+
+ pauseparam->tx_pause = 0;
+ pauseparam->rx_pause = 0;
+
+ switch (fc_conf.mode) {
+ case RTE_FC_RX_PAUSE:
+ pauseparam->rx_pause = 1;
+ break;
+ case RTE_FC_TX_PAUSE:
+ pauseparam->tx_pause = 1;
+ break;
+ case RTE_FC_FULL:
+ pauseparam->rx_pause = 1;
+ pauseparam->tx_pause = 1;
+ default:
+ break;
+ }
+ pauseparam->autoneg = (uint32_t)fc_conf.autoneg;
+
+ *(int *)data_len = sizeof(struct ethtool_pauseparam);
+
+ return 0;
+}
+
+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);
+ case ETHTOOL_SEEPROM:
+ return set_eeprom(port_id, in_data, out_data);
+ case ETHTOOL_GPAUSEPARAM:
+ return get_pauseparam(port_id, out_data, out_data_len);
+ default:
+ ret = -95 /* 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;
+}
+
+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);
+ default:
+ ret = -95 /* 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_ETHTOOL_H_
+#define _RTE_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_ETHTOOL_H_ */
new file mode 100644
@@ -0,0 +1,259 @@
+/*-
+ * 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_ethtool.h"
+#include "rte_nl.h"
+#include "rte_ctrl_if.h"
+
+#define KCP_NL_GRP 31
+#define MAX_PAYLOAD 1024
+
+struct ctrl_if_nl {
+ struct nlmsghdr *nlh;
+ struct msghdr msg;
+ struct iovec iov;
+};
+
+static int sock_fd = -1;
+pthread_t thread_id;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t msg_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint8_t nlmsg[NLMSG_SPACE(MAX_PAYLOAD) * 2];
+static struct sockaddr_nl dest_addr;
+static struct sockaddr_nl src_addr;
+
+static struct ctrl_if_nl nl_s = {
+ .nlh = (struct nlmsghdr *)nlmsg,
+};
+
+static struct ctrl_if_nl nl_r = {
+ .nlh = (struct nlmsghdr *)(nlmsg + NLMSG_SPACE(MAX_PAYLOAD)),
+};
+
+static int kcp_ethtool_msg_count;
+static struct kcp_ethtool_msg msg_storage;
+
+static void
+control_interface_nl_send(void *buf, size_t len)
+{
+ int ret;
+
+ /* Fill in the netlink message payload */
+ memcpy(NLMSG_DATA(nl_s.nlh), 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);
+}
+
+static void
+control_interface_nl_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);
+ }
+
+ control_interface_nl_send((void *)msg,
+ sizeof(struct kcp_ethtool_msg));
+}
+
+int
+control_interface_process_msg(int flag, unsigned int timeout_sec)
+{
+ int ret = 0;
+ struct timespec ts;
+
+ pthread_mutex_lock(&msg_lock);
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += timeout_sec;
+ while (timeout_sec && !kcp_ethtool_msg_count && !ret)
+ ret = pthread_cond_timedwait(&cond, &msg_lock, &ts);
+
+ switch (flag) {
+ case RTE_ETHTOOL_CTRL_IF_PROCESS_MSG:
+ if (kcp_ethtool_msg_count) {
+ control_interface_nl_process_msg(&msg_storage);
+ kcp_ethtool_msg_count = 0;
+ }
+ ret = 0;
+ break;
+
+ case RTE_ETHTOOL_CTRL_IF_DISCARD_MSG:
+ if (kcp_ethtool_msg_count) {
+ msg_storage.err = -1;
+ control_interface_nl_send((void *)&msg_storage,
+ sizeof(struct kcp_ethtool_msg));
+ kcp_ethtool_msg_count = 0;
+ }
+ ret = 0;
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+ pthread_mutex_unlock(&msg_lock);
+
+ return ret;
+}
+
+static int
+msg_add_and_signal(struct nlmsghdr *nlh)
+{
+ pthread_mutex_lock(&msg_lock);
+
+ memcpy(&msg_storage, NLMSG_DATA(nlh), sizeof(struct kcp_ethtool_msg));
+ kcp_ethtool_msg_count = 1;
+
+ pthread_cond_signal(&cond);
+
+ pthread_mutex_unlock(&msg_lock);
+
+ return 0;
+}
+
+static void *
+control_interface_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, struct sockaddr_nl *daddr)
+{
+ memset(nl->nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
+
+ /* Fill the netlink message header */
+ nl->nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
+ nl->nlh->nlmsg_pid = getpid(); /* self pid */
+ nl->nlh->nlmsg_flags = 0;
+
+ nl->iov.iov_base = (void *)nl->nlh;
+ nl->iov.iov_len = nl->nlh->nlmsg_len;
+ memset(&nl->msg, 0, sizeof(struct msghdr));
+ nl->msg.msg_name = (void *)daddr;
+ nl->msg.msg_namelen = sizeof(struct sockaddr_nl);
+ nl->msg.msg_iov = &nl->iov;
+ nl->msg.msg_iovlen = 1;
+}
+
+static int
+control_interface_nl_socket_init(void)
+{
+ 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;
+ }
+
+ dest_addr.nl_family = AF_NETLINK;
+ dest_addr.nl_pid = 0; /* For Linux Kernel */
+ dest_addr.nl_groups = 0;
+
+ nl_setup_header(&nl_s, &dest_addr);
+ nl_setup_header(&nl_r, &dest_addr);
+
+ return fd;
+}
+
+int
+control_interface_nl_init(void)
+{
+ int ret;
+ char buf[] = "pid";
+ sock_fd = control_interface_nl_socket_init();
+
+ if (sock_fd < 0) {
+ RTE_LOG(ERR, CTRL_IF,
+ "Failed to initialize control interface.\n");
+ return -1;
+ }
+
+ ret = pthread_create(&thread_id, NULL, control_interface_nl_recv,
+ NULL);
+ if (ret != 0)
+ return -1;
+ control_interface_nl_send((void *)buf, sizeof(buf));
+
+ 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,60 @@
+/*-
+ * 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
+
+#define KCP_ETHTOOL_MSG_LEN 500
+struct kcp_ethtool_msg {
+ int cmd_id;
+ int port_id;
+ char input_buffer[KCP_ETHTOOL_MSG_LEN];
+ char output_buffer[KCP_ETHTOOL_MSG_LEN];
+ int input_buffer_len;
+ int output_buffer_len;
+ int err;
+};
+
+int control_interface_nl_init(void);
+void control_interface_nl_release(void);
+int control_interface_process_msg(int flag, unsigned int timeout_sec);
+
+#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.
#
@@ -122,6 +122,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF) += -lrte_mbuf
_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_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