This library gets control messages form kernelspace and forwards them to librte_ether and returns response back to the kernelspace.
Library does: 1) Trigger Linux virtual interface creation 2) Initialize the netlink socket communication 3) Provides process() API to the application that does processing the received messages This library requires corresponding kernel module to be inserted. Signed-off-by: Ferruh Yigit <ferruh.yi...@intel.com> --- v8: * rename kernel module to unci v7: * rebase v17.08 v6: * rebase v17.05 v5: * Use unsigned primitive types as possible v4: * Add ethtool_get_settings as dummy v3: * Use librte_ethtool * Don't create interfaces for virtual PMDs * Add a new API ...msg_exist() to support port based locking * Add enable/disable promisc, allmulti support v2: * User rtnetlink to create interfaces. * Add more ethtool support: get/set ringparam, set pauseparam. * return defined error instead of hardcoded value --- MAINTAINERS | 1 + config/common_base | 5 + config/common_linuxapp | 1 + doc/api/doxy-api-index.md | 3 +- doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/ctrl_if_lib.rst | 52 ++++ doc/guides/prog_guide/index.rst | 1 + doc/guides/rel_notes/release_17_08.rst | 9 + lib/Makefile | 2 + lib/librte_ctrl_if/Makefile | 56 +++++ lib/librte_ctrl_if/rte_ctrl_ethtool.c | 390 +++++++++++++++++++++++++++++ lib/librte_ctrl_if/rte_ctrl_ethtool.h | 54 ++++ lib/librte_ctrl_if/rte_ctrl_if.c | 347 +++++++++++++++++++++++++ lib/librte_ctrl_if/rte_ctrl_if.h | 88 +++++++ lib/librte_ctrl_if/rte_ctrl_if_version.map | 10 + lib/librte_ctrl_if/rte_nl.c | 291 +++++++++++++++++++++ lib/librte_ctrl_if/rte_nl.h | 48 ++++ lib/librte_eal/common/include/rte_log.h | 1 + mk/rte.app.mk | 1 + 19 files changed, 1360 insertions(+), 1 deletion(-) create mode 100644 doc/guides/prog_guide/ctrl_if_lib.rst create mode 100644 lib/librte_ctrl_if/Makefile create mode 100644 lib/librte_ctrl_if/rte_ctrl_ethtool.c create mode 100644 lib/librte_ctrl_if/rte_ctrl_ethtool.h create mode 100644 lib/librte_ctrl_if/rte_ctrl_if.c create mode 100644 lib/librte_ctrl_if/rte_ctrl_if.h create mode 100644 lib/librte_ctrl_if/rte_ctrl_if_version.map create mode 100644 lib/librte_ctrl_if/rte_nl.c create mode 100644 lib/librte_ctrl_if/rte_nl.h diff --git a/MAINTAINERS b/MAINTAINERS index 8d1fb0431..2fb18ab79 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -280,6 +280,7 @@ F: doc/guides/sample_app_ug/kernel_nic_interface.rst Linux Userspace Network Control Interface (UNCI) M: Ferruh Yigit <ferruh.yi...@intel.com> F: lib/librte_eal/linuxapp/unci/ +F: lib/librte_ctrl_if/ Linux AF_PACKET M: John W. Linville <linvi...@tuxdriver.com> diff --git a/config/common_base b/config/common_base index f50ccc193..98652b556 100644 --- a/config/common_base +++ b/config/common_base @@ -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 diff --git a/config/common_linuxapp b/config/common_linuxapp index 4deab42c3..209a6d3d1 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -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 diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 71350849f..ba45ff69a 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -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) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b66e86541..896c2b247 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -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 \ diff --git a/doc/guides/prog_guide/ctrl_if_lib.rst b/doc/guides/prog_guide/ctrl_if_lib.rst new file mode 100644 index 000000000..407cf0dca --- /dev/null +++ b/doc/guides/prog_guide/ctrl_if_lib.rst @@ -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()`` diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 54f9538ea..c7cb4b0f8 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -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 diff --git a/doc/guides/rel_notes/release_17_08.rst b/doc/guides/rel_notes/release_17_08.rst index dbe1ee906..af7ddace0 100644 --- a/doc/guides/rel_notes/release_17_08.rst +++ b/doc/guides/rel_notes/release_17_08.rst @@ -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 diff --git a/lib/Makefile b/lib/Makefile index 434237d6e..45c3168e3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -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 diff --git a/lib/librte_ctrl_if/Makefile b/lib/librte_ctrl_if/Makefile new file mode 100644 index 000000000..686eb25d2 --- /dev/null +++ b/lib/librte_ctrl_if/Makefile @@ -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 diff --git a/lib/librte_ctrl_if/rte_ctrl_ethtool.c b/lib/librte_ctrl_if/rte_ctrl_ethtool.c new file mode 100644 index 000000000..70c60197b --- /dev/null +++ b/lib/librte_ctrl_if/rte_ctrl_ethtool.c @@ -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; +} diff --git a/lib/librte_ctrl_if/rte_ctrl_ethtool.h b/lib/librte_ctrl_if/rte_ctrl_ethtool.h new file mode 100644 index 000000000..caa4f15f3 --- /dev/null +++ b/lib/librte_ctrl_if/rte_ctrl_ethtool.h @@ -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_ */ diff --git a/lib/librte_ctrl_if/rte_ctrl_if.c b/lib/librte_ctrl_if/rte_ctrl_if.c new file mode 100644 index 000000000..6255a2a1a --- /dev/null +++ b/lib/librte_ctrl_if/rte_ctrl_if.c @@ -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; +} diff --git a/lib/librte_ctrl_if/rte_ctrl_if.h b/lib/librte_ctrl_if/rte_ctrl_if.h new file mode 100644 index 000000000..54696bd93 --- /dev/null +++ b/lib/librte_ctrl_if/rte_ctrl_if.h @@ -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_ */ diff --git a/lib/librte_ctrl_if/rte_ctrl_if_version.map b/lib/librte_ctrl_if/rte_ctrl_if_version.map new file mode 100644 index 000000000..3a86ab1a8 --- /dev/null +++ b/lib/librte_ctrl_if/rte_ctrl_if_version.map @@ -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: *; +}; diff --git a/lib/librte_ctrl_if/rte_nl.c b/lib/librte_ctrl_if/rte_nl.c new file mode 100644 index 000000000..011f5207b --- /dev/null +++ b/lib/librte_ctrl_if/rte_nl.c @@ -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); +} diff --git a/lib/librte_ctrl_if/rte_nl.h b/lib/librte_ctrl_if/rte_nl.h new file mode 100644 index 000000000..889be87e8 --- /dev/null +++ b/lib/librte_ctrl_if/rte_nl.h @@ -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_ */ diff --git a/lib/librte_eal/common/include/rte_log.h b/lib/librte_eal/common/include/rte_log.h index 341913851..1dbf6b1a3 100644 --- a/lib/librte_eal/common/include/rte_log.h +++ b/lib/librte_eal/common/include/rte_log.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. */ diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 449bd2f61..866bd41c5 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -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 -- 2.13.0