@@ -280,6 +280,7 @@ F: doc/guides/sample_app_ug/kernel_nic_interface.rst
Linux Userspace Network Control Interface (UNCI)
M: Ferruh Yigit <ferruh.yigit@intel.com>
F: lib/librte_eal/linuxapp/unci/
+F: lib/librte_ctrl_if/
Linux AF_PACKET
M: John W. Linville <linville@tuxdriver.com>
@@ -710,6 +710,11 @@ CONFIG_RTE_UNCI_KMOD=n
CONFIG_RTE_UNCI_KO_DEBUG=n
#
+# Compile librte_ctrl_if
+#
+CONFIG_RTE_LIBRTE_CTRL_IF=n
+
+#
# Compile vhost user library
#
CONFIG_RTE_LIBRTE_VHOST=n
@@ -42,6 +42,7 @@ CONFIG_RTE_LIBRTE_KNI=y
CONFIG_RTE_LIBRTE_PMD_KNI=y
CONFIG_RTE_LIBRTE_ETHTOOL=y
CONFIG_RTE_UNCI_KMOD=y
+CONFIG_RTE_LIBRTE_CTRL_IF=y
CONFIG_RTE_LIBRTE_VHOST=y
CONFIG_RTE_LIBRTE_PMD_VHOST=y
CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
@@ -162,4 +162,5 @@ There are many libraries, so their headers may be grouped by topics:
[bitrate statistics] (@ref rte_bitrate.h),
[latency statistics] (@ref rte_latencystats.h),
[version] (@ref rte_version.h),
- [ethtool] (@ref rte_ethtool.h)
+ [ethtool] (@ref rte_ethtool.h),
+ [control interface] (@ref rte_ctrl_if.h)
@@ -42,6 +42,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_efd \
lib/librte_ether \
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 UNCI 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()``
@@ -55,6 +55,7 @@ Programmer's Guide
ip_fragment_reassembly_lib
pdump_lib
ethtool_lib
+ ctrl_if_lib
multi_proc_support
kernel_nic_interface
thread_safety_dpdk_functions
@@ -75,6 +75,14 @@ New Features
Added support for firmwares with multiple Ethernet ports per physical port.
+* **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/unci kernel module
+
Resolved Issues
---------------
@@ -183,6 +191,7 @@ The libraries prepended with a plus sign were incremented in this version.
librte_cfgfile.so.2
librte_cmdline.so.2
librte_cryptodev.so.2
+ + librte_ctrl_if.so.1
librte_distributor.so.1
librte_eal.so.4
librte_ethdev.so.6
@@ -108,6 +108,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
DEPDIRS-librte_pdump := librte_eal librte_mempool librte_mbuf librte_ether
DIRS-$(CONFIG_RTE_LIBRTE_ETHTOOL) += librte_ethtool
DEPDIRS-librte_ethtool := librte_eal librte_ether
+DIRS-$(CONFIG_RTE_LIBRTE_CTRL_IF) += librte_ctrl_if
+DEPDIRS-librte_ctrl_if := librte_ether
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
new file mode 100644
@@ -0,0 +1,56 @@
+# 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)
+LDLIBS += -lpthread
+
+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
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,390 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 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_settings(uint8_t port_id __rte_unused, void *data, size_t *data_len)
+{
+ struct ethtool_cmd *ecmd = data;
+
+ /* No PMD equivalent, added to make get pauseparam work */
+ memset(ecmd, 0, sizeof(struct ethtool_cmd));
+
+ *data_len = sizeof(struct ethtool_cmd);
+ return 0;
+}
+
+static int
+get_drvinfo(uint8_t port_id, void *data, size_t *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(uint8_t port_id, void *data, size_t *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_len_internal(uint8_t port_id, size_t *reg_length)
+{
+ size_t reg_length_out_len;
+
+ return get_reg_len(port_id, reg_length, ®_length_out_len);
+}
+
+static int
+get_reg(uint8_t port_id, void *in_data, void *out_data, size_t *out_data_len)
+{
+ size_t reg_length;
+ struct ethtool_regs *ethtool_regs = in_data;
+ int ret;
+
+ ret = get_reg_len_internal(port_id, ®_length);
+ /* 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(uint8_t port_id, void *data, size_t *data_len)
+{
+ int ret;
+
+ ret = rte_ethtool_get_link(port_id);
+
+ *(int *)data = ret;
+ *data_len = sizeof(size_t);
+
+ return 0;
+}
+
+static int
+get_eeprom_length(uint8_t port_id, void *data, size_t *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(uint8_t port_id, void *in_data, void *out_data,
+ size_t *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(uint8_t 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(uint8_t port_id, void *data, size_t *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(uint8_t 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(uint8_t port_id, void *data, size_t *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(uint8_t port_id, void *data)
+{
+ struct ethtool_pauseparam *pauseparam = data;
+
+ return rte_ethtool_set_pauseparam(port_id, pauseparam);
+}
+
+int
+rte_eth_dev_ethtool_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+ void *out_data, size_t *out_data_len)
+{
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ switch (cmd_id) {
+ case ETHTOOL_GSET:
+ return get_settings(port_id, out_data, out_data_len);
+ 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:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int
+set_mtu(uint8_t port_id, void *in_data)
+{
+ int *mtu = in_data;
+
+ return rte_eth_dev_set_mtu(port_id, *mtu);
+}
+
+static int
+get_stats(uint8_t port_id, void *data, size_t *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;
+
+ *data_len = sizeof(struct rtnl_link_stats64);
+
+ return 0;
+}
+
+static int
+get_mac(uint8_t port_id, void *data, size_t *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(uint8_t 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(uint8_t port_id)
+{
+ rte_eth_dev_stop(port_id);
+ return rte_eth_dev_start(port_id);
+}
+
+static int
+stop_port(uint8_t port_id)
+{
+ rte_eth_dev_stop(port_id);
+ return 0;
+}
+
+static int
+set_promisc(uint8_t port_id, void *in_data)
+{
+ int *promisc = in_data;
+
+ if (*promisc)
+ rte_eth_promiscuous_enable(port_id);
+ else
+ rte_eth_promiscuous_disable(port_id);
+
+ return 0;
+}
+
+static int
+set_allmulti(uint8_t port_id, void *in_data)
+{
+ int *allmulti = 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(uint32_t cmd_id, uint8_t port_id, void *in_data,
+ void *out_data, size_t *out_data_len)
+{
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -ENODEV;
+
+ switch (cmd_id) {
+ case RTE_UNCI_REQ_CHANGE_MTU:
+ return set_mtu(port_id, in_data);
+ case RTE_UNCI_REQ_GET_STATS:
+ return get_stats(port_id, out_data, out_data_len);
+ case RTE_UNCI_REQ_GET_MAC:
+ return get_mac(port_id, out_data, out_data_len);
+ case RTE_UNCI_REQ_SET_MAC:
+ return set_mac(port_id, in_data);
+ case RTE_UNCI_REQ_START_PORT:
+ return start_port(port_id);
+ case RTE_UNCI_REQ_STOP_PORT:
+ return stop_port(port_id);
+ case RTE_UNCI_REQ_SET_PROMISC:
+ return set_promisc(port_id, in_data);
+ case RTE_UNCI_REQ_SET_ALLMULTI:
+ return set_allmulti(port_id, in_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
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_unci_common.h>
+
+int rte_eth_dev_ethtool_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+ void *out_data, size_t *out_data_len);
+int rte_eth_dev_control_process(uint32_t cmd_id, uint8_t port_id, void *in_data,
+ void *out_data, size_t *out_data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_ETHTOOL_H_ */
new file mode 100644
@@ -0,0 +1,347 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 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 <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <rte_log.h>
+#include "rte_ctrl_if.h"
+#include "rte_nl.h"
+
+#define NAMESZ 32
+#define IFNAME "dpdk"
+#define BUFSZ 1024
+
+static int unci_rtnl_fd = -1;
+static uint32_t unci_fd_ref;
+
+struct unci_request {
+ struct nlmsghdr nlmsg;
+ uint8_t buf[BUFSZ];
+};
+
+static int
+conrol_interface_rtnl_init(void)
+{
+ struct sockaddr_nl src;
+ int ret;
+
+ unci_rtnl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (unci_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(unci_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(unci_rtnl_fd);
+ unci_rtnl_fd = -1;
+ }
+
+ return ret;
+}
+
+static int
+control_interface_ref_get(void)
+{
+ int ret = 0;
+
+ if (unci_fd_ref == 0)
+ ret = control_interface_init();
+
+ if (ret == 0)
+ unci_fd_ref++;
+ else
+ RTE_LOG(ERR, CTRL_IF,
+ "Failed to initialize control interface\n");
+
+ return unci_fd_ref;
+}
+
+static void
+control_interface_release(void)
+{
+ close(unci_rtnl_fd);
+ control_interface_nl_release();
+}
+
+static int
+control_interface_ref_put(void)
+{
+ if (unci_fd_ref == 0)
+ return 0;
+
+ unci_fd_ref--;
+
+ if (unci_fd_ref == 0)
+ control_interface_release();
+
+ return unci_fd_ref;
+}
+
+static int
+add_attr(struct unci_request *req, uint16_t 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 unci_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 unci_request *req, unsigned short type)
+{
+ struct rtattr *rta;
+ uint32_t nlmsg_len;
+
+ nlmsg_len = NLMSG_ALIGN(req->nlmsg.nlmsg_len);
+ rta = (struct rtattr *)((uint8_t *)&req->nlmsg + nlmsg_len);
+ if (nlmsg_len + RTA_LENGTH(0) > sizeof(struct unci_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 unci_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 unci_request req;
+ struct ifinfomsg *info;
+ struct rtattr *rta1;
+ struct rtattr *rta2;
+ uint32_t pid = getpid();
+ char name[NAMESZ];
+ char type[NAMESZ];
+ struct iovec iov;
+ struct msghdr msg;
+ struct sockaddr_nl nladdr;
+ int ret;
+ uint8_t buf[BUFSZ];
+
+ memset(&req, 0, sizeof(struct unci_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, UNCI_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_UNCI_PORTID, &port_id, sizeof(uint8_t));
+ if (ret < 0)
+ return -1;
+
+ ret = add_attr(&req, IFLA_UNCI_PID, &pid, sizeof(uint32_t));
+ 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(unci_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(unci_rtnl_fd, &msg, 0);
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Recv for create failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+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;
+}
+
+static int
+rte_eth_rtnl_destroy(uint8_t port_id)
+{
+ struct unci_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 unci_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(unci_rtnl_fd, &msg, 0);
+ if (ret < 0) {
+ RTE_LOG(ERR, CTRL_IF, "Send for destroy failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+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;
+}
new file mode 100644
@@ -0,0 +1,88 @@
+/*-
+ * 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_unci_common.h>
+
+/**
+ * Creates control interfaces (Linux virtual network interface)for
+ * given ethdev port.
+ *
+ * This API opens device created by supportive kernel module and initializes
+ * kernel communication interface.
+ *
+ * With first interface created, a pthread created to receive the control
+ * messages.
+ *
+ * If supportive kernel module is not inserted this API will return
+ * an error.
+ *
+ * @param port_id
+ * port id to create virtual interface
+ * @return
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_create_one(uint8_t port_id);
+
+/**
+ * Destroys control interfaces.
+ *
+ * This API close device created by supportive kernel module and release
+ * underlying communication interface.
+ *
+ * @return
+ * @param port_id
+ * port id to destroy virtual interface
+ * 0 on success.
+ * Negative value on error.
+ */
+int rte_eth_control_interface_destroy_one(uint8_t port_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CTRL_IF_H_ */
new file mode 100644
@@ -0,0 +1,10 @@
+DPDK_17.02 {
+ 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,291 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 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 <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+
+#include <rte_spinlock.h>
+#include <rte_log.h>
+#include "rte_ctrl_ethtool.h"
+#include "rte_nl.h"
+#include "rte_ctrl_if.h"
+
+#define MAX_PAYLOAD sizeof(struct unci_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 {
+ struct unci_ethtool_msg msg_storage;
+ pthread_mutex_t msg_lock;
+ uint32_t pending_process;
+};
+
+
+/**
+ * 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,
+};
+
+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 = {
+ .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 unci_ethtool_msg *msg)
+{
+ return nl_send((void *)msg, sizeof(struct unci_ethtool_msg));
+}
+
+static void
+process_msg(struct unci_ethtool_msg *msg)
+{
+ if (msg->cmd_id > RTE_UNCI_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);
+}
+
+static int
+control_interface_msg_process(uint32_t flag)
+{
+ struct unci_ethtool_msg msg_storage;
+ int ret = 0;
+
+ pthread_mutex_lock(&ctrl_if_sync.msg_lock);
+ if (ctrl_if_sync.pending_process == 0) {
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+ return 0;
+ }
+
+ memcpy(&msg_storage, &ctrl_if_sync.msg_storage,
+ sizeof(struct unci_ethtool_msg));
+ ctrl_if_sync.pending_process = 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_process(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 unci_ethtool_msg));
+ ctrl_if_sync.msg_storage.flag = UNCI_MSG_FLAG_RESPONSE;
+ ctrl_if_sync.pending_process = 1;
+
+ pthread_mutex_unlock(&ctrl_if_sync.msg_lock);
+
+ control_interface_msg_process(RTE_ETHTOOL_CTRL_IF_PROCESS_MSG);
+
+ 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 int)ret < sizeof(struct unci_ethtool_msg)) {
+ RTE_LOG(WARNING, CTRL_IF,
+ "Received %d bytes, payload %zu\n",
+ ret, sizeof(struct unci_ethtool_msg));
+ continue;
+ }
+
+ msg_add_and_process(&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, UNCI_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,48 @@
+/*-
+ * 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_NL_H_ */
@@ -87,6 +87,7 @@ extern struct rte_logs rte_logs;
#define RTE_LOGTYPE_CRYPTODEV 17 /**< Log related to cryptodev. */
#define RTE_LOGTYPE_EFD 18 /**< Log related to EFD. */
#define RTE_LOGTYPE_EVENTDEV 19 /**< Log related to eventdev. */
+#define RTE_LOGTYPE_CTRL_IF 20 /**< Log related to control interface. */
/* these log types can be used in an application */
#define RTE_LOGTYPE_USER1 24 /**< User-defined log type 1. */
@@ -91,6 +91,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF) += -lrte_mbuf
_LDLIBS-$(CONFIG_RTE_LIBRTE_NET) += -lrte_net
_LDLIBS-$(CONFIG_RTE_LIBRTE_ETHER) += -lrte_ethdev
_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_EVENTDEV) += -lrte_eventdev
_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool