introduce fail-safe PMD
Re: [PATCH v7 03/11] net/failsafe: add fail-safe PMD
In reply to Gaetan RivetQuoted 680 lines · Gaetan Rivet
Introduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/fail_safe.rst | 133 +++++ doc/guides/nics/features/failsafe.ini | 24 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 76 +++ drivers/net/failsafe/failsafe.c | 231 ++++++++ drivers/net/failsafe/failsafe_args.c | 331 +++++++++++ drivers/net/failsafe/failsafe_eal.c | 154 +++++ drivers/net/failsafe/failsafe_ops.c | 663 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 227 ++++++++ drivers/net/failsafe/failsafe_rxtx.c | 107 ++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + mk/rte.app.mk | 1 + 15 files changed, 1965 insertions(+) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.mapMAINTAINERS +5
-0@@ -336,6 +336,11 @@ F: drivers/net/enic/ F: doc/guides/nics/enic.rst F: doc/guides/nics/features/enic.ini +Fail-safe PMD +M: Gaetan Rivet <[email protected]> +F: drivers/net/failsafe/ +F: doc/guides/nics/fail_safe.rst + Intel e1000 M: Wenzhuo Lu <[email protected]> F: drivers/net/e1000/config/common_base +6
-0@@ -420,6 +420,12 @@ CONFIG_RTE_LIBRTE_PMD_XENVIRT=n CONFIG_RTE_LIBRTE_PMD_NULL=y # +# Compile fail-safe PMD +# +CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y +CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG=n + +# # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=ydoc/guides/nics/fail_safe.rst new file +133
-0@@ -0,0 +1,133 @@ +.. BSD LICENSE + Copyright 2017 6WIND S.A. + + 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 6WIND S.A. 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. + +Fail-safe poll mode driver library +================================== + +The Fail-safe poll mode driver library (**librte_pmd_failsafe**) is a virtual +device that allows using any device supporting hotplug (sudden device removal +and plugging on its bus), without modifying other components relying on such +device (application, other PMDs). + +Additionally to the Seamless Hotplug feature, the Fail-safe PMD offers the +ability to redirect operations to secondary devices when the primary has been +removed from the system. + +.. note:: + + The library is enabled by default. You can enable it or disable it manually + by setting the ``CONFIG_RTE_LIBRTE_PMD_FAILSAFE`` configuration option. + +Features +-------- + +The Fail-safe PMD only supports a limited set of features. If you plan to use a +device underneath the Fail-safe PMD with a specific feature, this feature must +be supported by the Fail-safe PMD to avoid throwing any error. + +Check the feature matrix for the complete set of supported features. + +Compilation options +------------------- + +These options can be modified in the ``$RTE_TARGET/build/.config`` file. + +- ``CONFIG_RTE_LIBRTE_PMD_FAILSAFE`` (default **y**) + + Toggle compiling librte_pmd_failsafe itself. + +- ``CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG`` (default **n**) + + Toggle debugging code. + +Using the Fail-safe PMD from the EAL command line +------------------------------------------------- + +The Fail-safe PMD can be used like most other DPDK virtual devices, by passing a +``--vdev`` parameter to the EAL when starting the application. The device name +must start with the *net_failsafe* prefix, followed by numbers or letters. This +name must be unique for each device. Each fail-safe instance must have at least one +sub-device, up to ``RTE_MAX_ETHPORTS-1``. + +A sub-device can be any legal DPDK device, including possibly another fail-safe +instance. + +Fail-safe command line parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- **dev(<iface>)** parameter + + This parameter allows the user to define a sub-device. The ``<iface>`` part of + this parameter must be a valid device definition. It could be the argument + provided to a ``-w`` PCI device specification or the argument that would be + given to a ``--vdev`` parameter (including a fail-safe). + Enclosing the device definition within parenthesis here allows using + additional sub-device parameters if need be. They will be passed on to the + sub-device. + +- **mac** parameter [MAC address] + + This parameter allows the user to set a default MAC address to the fail-safe + and all of its sub-devices. + If no default mac address is provided, the fail-safe PMD will read the MAC + address of the first of its sub-device to be successfully probed and use it as + its default MAC address, trying to set it to all of its other sub-devices. + If no sub-device was successfully probed at initialization, then a random MAC + address is generated, that will be subsequently applied to all sub-device once + they are probed. + +Usage example +~~~~~~~~~~~~~ + +This section shows some example of using **testpmd** with a fail-safe PMD. + +#. Request huge pages: + + .. code-block:: console + + echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + +#. Start testpmd + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0,nodeaction=r1:0:CREATE)' -- \ + -i + +Using the Fail-safe PMD from an application +------------------------------------------- + +This driver strives to be as seamless as possible to existing applications, in +order to propose the hotplug functionality in the easiest way possible. + +Care must be taken, however, to respect the **ether** API concerning device +access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate +over ethernet devices, instead of directly accessing them or by writing one's +own device iterator.doc/guides/nics/features/failsafe.ini new file +24
-0@@ -0,0 +1,24 @@ +; +; Supported features of the 'fail-safe' poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status = Y +Queue start/stop = Y +MTU update = Y +Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +VLAN filter = Y +Packet type parsing = Y +Basic stats = Y +Stats per queue = Y +ARMv7 = Y +ARMv8 = Y +Power8 = Y +x86-32 = Y +x86-64 = Y +Usage doc = Ydoc/guides/nics/index.rst +1
-0@@ -64,6 +64,7 @@ Network Interface Controller Drivers vhost vmxnet3 pcap_ring + fail_safe **Figures**drivers/net/Makefile +2
-0@@ -59,6 +59,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena DEPDIRS-ena = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DEPDIRS-enic = $(core-libs) librte_hash +DIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe +DEPDIRS-failsafe = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DEPDIRS-fm10k = $(core-libs) librte_hash DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40edrivers/net/failsafe/Makefile new file +76
-0@@ -0,0 +1,76 @@ +# BSD LICENSE +# +# Copyright 2017 6WIND S.A. +# Copyright 2017 Mellanox. +# +# 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 6WIND S.A. 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_pmd_failsafe.a + +EXPORT_MAP := rte_pmd_failsafe_version.map + +LIBABIVER := 1 + +# Sources are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c + +# No exported include files + +# This lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_kvargs +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_mbuf + +ifneq ($(DEBUG),) +CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG := y +endif + +# Basic CFLAGS: +CFLAGS += -std=gnu99 -Wall -Wextra +CFLAGS += -I. +CFLAGS += -D_DEFAULT_SOURCE +CFLAGS += -D_XOPEN_SOURCE=700 +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -Wno-strict-prototypes +CFLAGS += -pedantic -DPEDANTIC + +ifeq ($(CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG),y) +CFLAGS += -g -UNDEBUG +else +CFLAGS += -O3 +CFLAGS += -DNDEBUG +endif + +include $(RTE_SDK)/mk/rte.lib.mkdrivers/net/failsafe/failsafe.c new file +231
-0@@ -0,0 +1,231 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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_alarm.h> +#include <rte_malloc.h> +#include <rte_ethdev.h> +#include <rte_ethdev_vdev.h> +#include <rte_devargs.h> +#include <rte_kvargs.h> +#include <rte_vdev.h> + +#include "failsafe_private.h" + +const char pmd_failsafe_driver_name[] =FAILSAFE_DRIVER_NAME ; +static const struct rte_eth_link eth_link = { + .link_speed =ETH_SPEED_NUM_10G , + .link_duplex =ETH_LINK_FULL_DUPLEX , + .link_status =ETH_LINK_UP , + .link_autoneg =ETH_LINK_SPEED_AUTONEG , +}; + +static int +fs_sub_device_create (struct rte_eth_dev *dev, +const char *params) +{ +uint8_t nb_subs; +int ret; + + ret =failsafe_args_count_subdevice (dev, params); +if (ret) +return ret; +if (PRIV (dev)->subs_tail >FAILSAFE_MAX_ETHPORTS ) { +ERROR ("Cannot allocate more than %d ports" , +FAILSAFE_MAX_ETHPORTS ); +return -ENOSPC ; + } + nb_subs =PRIV (dev)->subs_tail; +PRIV (dev)->subs =rte_zmalloc (NULL , +sizeof (struct sub_device ) * nb_subs, +RTE_CACHE_LINE_SIZE ); +if (PRIV (dev)->subs ==NULL ) { +ERROR ("Could not allocate sub_devices" ); +return -ENOMEM ; + } +return 0 ; +} + +static void +fs_sub_device_free (struct rte_eth_dev *dev) +{ +rte_free (PRIV (dev)->subs); +} + +static int +fs_eth_dev_create (struct rte_vdev_device *vdev) +{ +struct rte_eth_dev *dev; +struct ether_addr *mac; +struct fs_priv *priv; +struct sub_device *sdev; +const char *params; +unsigned int socket_id; +uint8_t i; +int ret; + + dev =NULL ; + priv =NULL ; + params =rte_vdev_device_args (vdev); + socket_id =rte_socket_id (); +INFO ("Creating fail-safe device on NUMA socket %u" , + socket_id); + dev =rte_eth_vdev_allocate (vdev,sizeof (*priv)); +if (dev ==NULL ) { +ERROR ("Unable to allocate rte_eth_dev" ); +return -1 ; + } + priv = dev->data->dev_private; +PRIV (dev)->dev = dev; + dev->dev_ops = &failsafe_ops; +TAILQ_INIT (&dev->link_intr_cbs); + dev->data->dev_flags =0x0 ; + dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; + dev->data->dev_link = eth_link; +PRIV (dev)->nb_mac_addr =1 ; + dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; + dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; +if (params ==NULL ) { +ERROR ("This PMD requires sub-devices, none provided" ); + goto free_dev; + } + ret =fs_sub_device_create (dev, params); +if (ret) { +ERROR ("Could not allocate sub_devices" ); + goto free_dev; + } + ret =failsafe_args_parse (dev, params); +if (ret) + goto free_subs; + ret =failsafe_eal_init (dev); +if (ret) + goto free_args; + mac = &dev->data->mac_addrs[0 ]; +if (mac_from_arg) { +/* +* If MAC address was provided as a parameter, +* apply to all probed slaves. +*/ + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { + ret =rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), + mac); +if (ret) { +ERROR ("Failed to set default MAC address" ); + goto free_args; + } + } + }else { +/* +* Use the ether_addr from first probed +* device, either preferred or fallback. +*/ + FOREACH_SUBDEV(sdev, i, dev) +if (sdev->state >=DEV_PROBED ) { +ether_addr_copy (Ð (sdev)->data->mac_addrs[0 ], + mac); +break ; + } +/* +* If no device has been probed and no ether_addr +* has been provided on the command line, use a random +* valid one. +* It will be applied during future slave state syncs to +* probed slaves. +*/ +if (i == priv->subs_tail) +eth_random_addr (&mac->addr_bytes[0 ]); + } +INFO ("MAC address is %02x:%02x:%02x:%02x:%02x:%02x" , + mac->addr_bytes[0 ], mac->addr_bytes[1 ], + mac->addr_bytes[2 ], mac->addr_bytes[3 ], + mac->addr_bytes[4 ], mac->addr_bytes[5 ]); +return 0 ; +free_args: +failsafe_args_free (dev); +free_subs: +fs_sub_device_free (dev); +free_dev: +rte_eth_dev_release_port (dev); +return -1 ; +} + +static int +fs_rte_eth_free (const char *name) +{ +struct rte_eth_dev *dev; +int ret; + + dev =rte_eth_dev_allocated (name); +if (dev ==NULL ) +return -ENODEV ; + ret =failsafe_eal_uninit (dev); +if (ret) +ERROR ("Error while uninitializing sub-EAL" ); +failsafe_args_free (dev); +fs_sub_device_free (dev); +rte_free (PRIV (dev)); +rte_eth_dev_release_port (dev); +return ret; +} + +static int +rte_pmd_failsafe_probe (struct rte_vdev_device *vdev) +{ +const char *name; + + name =rte_vdev_device_name (vdev); +if (vdev ==NULL ) +return -EINVAL ; +INFO ("Initializing " FAILSAFE_DRIVER_NAME " for %s" , + name); +return fs_eth_dev_create (vdev); +} + +static int +rte_pmd_failsafe_remove (struct rte_vdev_device *vdev) +{ +const char *name; + + name =rte_vdev_device_name (vdev); +if (name ==NULL ) +return -EINVAL ; +INFO ("Uninitializing " FAILSAFE_DRIVER_NAME " for %s" , name); +return fs_rte_eth_free (name); +} + +static struct rte_vdev_driver failsafe_drv = { + .probe = rte_pmd_failsafe_probe, + .remove = rte_pmd_failsafe_remove, +}; + +RTE_PMD_REGISTER_VDEV (net_failsafe, failsafe_drv); +RTE_PMD_REGISTER_ALIAS (net_failsafe, eth_failsafe); +RTE_PMD_REGISTER_PARAM_STRING (net_failsafe,PMD_FAILSAFE_PARAM_STRING );drivers/net/failsafe/failsafe_args.c new file +83
-0@@ -0,0 +1,331 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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 <errno.h> + +#include <rte_devargs.h> +#include <rte_malloc.h> +#include <rte_kvargs.h> + +#include "failsafe_private.h" + +#define DEVARGS_MAXLEN 4096 + +/* Callback used when a new device is found in devargs */ +typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params, +uint8_t head); + +int mac_from_arg; + +const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_MAC_KVARG , +NULL , +}; + +/* +* input: text. +* output: 0: if text[0] != '(', +* 0: if there are no corresponding ')' +* n: distance to corresponding ')' otherwise +*/ +static size_t +closing_paren (const char *text) +{ +int nb_open =0 ; +size_t i =0 ; + +while (text[i] !='\0' ) { +if (text[i] =='(' ) + nb_open++; +if (text[i] ==')' ) + nb_open--; +if (nb_open ==0 ) +return i; + i++; + } +return 0 ; +} + +static int +fs_parse_device (struct sub_device *sdev,char *args) +{ +struct rte_devargs *d; +int ret;
drivers/net/failsafe/failsafe_args.c line 93
Quoted 10 lines
drivers/net/failsafe/failsafe_args.c new file +10
-0+ + d = &sdev->devargs; +DEBUG ("%s" , args); + ret =rte_eal_devargs_parse (args, d); +if (ret) { +DEBUG ("devargs parsing failed with code %d" , ret); +return ret; + } + sdev->bus = d->bus; + sdev->state =DEV_PARSED ;
You seem to be mostly interested in the bus name for the device. Why don't you track this via your sub_device structure instead of using rte_devargs?
Quoted 284 lines
drivers/net/failsafe/failsafe_args.c new file +238
-0+return 0 ; +} + +static int +fs_parse_device_param (struct rte_eth_dev *dev,const char *param, +uint8_t head) +{ +struct fs_priv *priv; +struct sub_device *sdev; +char *args =NULL ; +size_t a, b; +int ret; + + priv =PRIV (dev); + a =0 ; + b =0 ; + ret =0 ; +while (param[b] !='(' && + param[b] !='\0' ) + b++; + a = b; + b +=closing_paren (¶m[b]); +if (a == b) { +ERROR ("Dangling parenthesis" ); +return -EINVAL ; + } + a +=1 ; + args =strndup (¶m[a], b - a); +if (args ==NULL ) { +ERROR ("Not enough memory for parameter parsing" ); +return -ENOMEM ; + } + sdev = &priv->subs[head]; +if (strncmp (param,"dev" ,3 ) ==0 ) { + ret =fs_parse_device (sdev, args); +if (ret) + goto free_args; + }else { +ERROR ("Unrecognized device type: %.*s" , (int )b, param); +return -EINVAL ; + } +free_args: +free (args); +return ret; +} + +static int +fs_parse_sub_devices (parse_cb *cb, +struct rte_eth_dev *dev,const char *params) +{ +size_t a, b; +uint8_t head; +int ret; + + a =0 ; + head =0 ; + ret =0 ; +while (params[a] !='\0' ) { + b = a; +while (params[b] !='(' && + params[b] !=',' && + params[b] !='\0' ) + b++; +if (b == a) { +ERROR ("Invalid parameter" ); +return -EINVAL ; + } +if (params[b] ==',' ) { + a = b +1 ; +continue ; + } +if (params[b] =='(' ) { +size_t start = b; + + b +=closing_paren (¶ms[b]); +if (b == start) { +ERROR ("Dangling parenthesis" ); +return -EINVAL ; + } + ret = (*cb)(dev, ¶ms[a], head); +if (ret) +return ret; + head +=1 ; + b +=1 ; +if (params[b] =='\0' ) +return 0 ; + } + a = b +1 ; + } +return 0 ; +} + +static int +fs_remove_sub_devices_definition (char params[DEVARGS_MAXLEN ]) +{ +char buffer[DEVARGS_MAXLEN ] = {0 }; +size_t a, b; +int i; + + a =0 ; + i =0 ; +while (params[a] !='\0' ) { + b = a; +while (params[b] !='(' && + params[b] !=',' && + params[b] !='\0' ) + b++; +if (b == a) { +ERROR ("Invalid parameter" ); +return -EINVAL ; + } +if (params[b] ==',' || params[b] =='\0' ) + i +=snprintf (&buffer[i], b - a +1 ,"%s" , ¶ms[a]); +if (params[b] =='(' ) { +size_t start = b; + b +=closing_paren (¶ms[b]); +if (b == start) +return -EINVAL ; + b +=1 ; +if (params[b] =='\0' ) + goto out; + } + a = b +1 ; + } +out: +snprintf (params,DEVARGS_MAXLEN ,"%s" , buffer); +return 0 ; +} + +static int +fs_get_mac_addr_arg(const char *key __rte_unused, +const char *value,void *out) +{ +struct ether_addr *ea = out; +int ret; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + ret =sscanf (value,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" , + &ea->addr_bytes[0 ], &ea->addr_bytes[1 ], + &ea->addr_bytes[2 ], &ea->addr_bytes[3 ], + &ea->addr_bytes[4 ], &ea->addr_bytes[5 ]); +return ret !=ETHER_ADDR_LEN ; +} + +int +failsafe_args_parse (struct rte_eth_dev *dev,const char *params) +{ +struct fs_priv *priv; +char mut_params[DEVARGS_MAXLEN ] ="" ; +struct rte_kvargs *kvlist =NULL ; +unsigned int arg_count; +size_t n; +int ret; + +if (dev ==NULL || params ==NULL ) +return -EINVAL ; + priv =PRIV (dev); + ret =0 ; + priv->subs_tx =FAILSAFE_MAX_ETHPORTS ; +/* default parameters */ + mac_from_arg =0 ; + n =snprintf (mut_params,sizeof (mut_params),"%s" , params); +if (n >=sizeof (mut_params)) { +ERROR ("Parameter string too long (>=%zu)" , +sizeof (mut_params)); +return -ENOMEM ; + } + ret =fs_parse_sub_devices (fs_parse_device_param, + dev, params); +if (ret <0 ) +return ret; + ret =fs_remove_sub_devices_definition (mut_params); +if (ret <0 ) +return ret; +if (strnlen (mut_params,sizeof (mut_params)) >0 ) { + kvlist =rte_kvargs_parse (mut_params, + pmd_failsafe_init_parameters); +if (kvlist ==NULL ) { +ERROR ("Error parsing parameters, usage:\n" +PMD_FAILSAFE_PARAM_STRING ); +return -1 ; + } +/* MAC addr */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_MAC_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_MAC_KVARG , + &fs_get_mac_addr_arg, + &dev->data->mac_addrs[0 ]); +if (ret <0 ) + goto free_kvlist; + mac_from_arg =1 ; + } + } +free_kvlist: +rte_kvargs_free (kvlist); +return ret; +} + +void +failsafe_args_free (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV(sdev, i, dev) { +free (sdev->devargs.args); + sdev->devargs.args =NULL ; + } +} + +static int +fs_count_device (struct rte_eth_dev *dev,const char *param, + uint8_t head __rte_unused) +{ +size_t b =0 ; + +while (param[b] !='(' && + param[b] !='\0' ) + b++; +if (strncmp (param,"dev" , b) && +strncmp (param,"exec" , b)) { +ERROR ("Unrecognized device type: %.*s" , (int )b, param); +return -EINVAL ; + } +PRIV (dev)->subs_tail +=1 ; +return 0 ; +} + +int +failsafe_args_count_subdevice (struct rte_eth_dev *dev, +const char *params) +{ +return fs_parse_sub_devices (fs_count_device, + dev, params); +}drivers/net/failsafe/failsafe_eal.c new file +40
-0@@ -0,0 +1,154 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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_malloc.h> + +#include "failsafe_private.h" + +static struct rte_eth_dev * +fs_find_ethdev (const struct rte_device *dev) +{
drivers/net/failsafe/failsafe_eal.c line 50
Quoted 10 lines
drivers/net/failsafe/failsafe_eal.c new file +10
-0+struct rte_eth_dev *eth_dev; +uint8_t i; + +RTE_ETH_FOREACH_DEV (i) { + eth_dev = &rte_eth_devices[i]; +if (eth_dev->device == dev) +return eth_dev; + } +return NULL ; +}
Why don't you use rte_eth_dev_allocated() here?
Quoted 7 lines
drivers/net/failsafe/failsafe_eal.c new file +7
-0+ +static int +fs_bus_init (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +struct rte_device *rdev; +struct rte_devargs *da;
drivers/net/failsafe/failsafe_eal.c line 67
Quoted 10 lines
drivers/net/failsafe/failsafe_eal.c new file +10
-0+uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state !=DEV_PARSED ) +continue ; + da = &sdev->devargs; + rdev =rte_eal_hotplug_add (da->bus->name, + da->name, + da->args);
Why don't you track the bus name through your sub_device structure instead?
Quoted 1,127 lines
drivers/net/failsafe/failsafe_eal.c new file +87
-0+ ret = rdev ?0 : -rte_errno; +if (ret) { +ERROR ("sub_device %d probe failed %s%s%s" , i, + errno ?"(" :"" , + errno ?strerror (rte_errno) :"" , + errno ?")" :"" ); +continue ; + } +ETH (sdev) =fs_find_ethdev (rdev); +if (ETH (sdev) ==NULL ) { +ERROR ("sub_device %d init went wrong" , i); +return -ENODEV ; + } + sdev->dev =ETH (sdev)->device; +ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; + sdev->state =DEV_PROBED ; + } +return 0 ; +} + +int +failsafe_eal_init (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + ret =fs_bus_init (dev); +if (ret) +return ret; +/* +* We only update TX_SUBDEV if we are not started. +* If a sub_device is emitting, we will switch the TX_SUBDEV to the +* preferred port only upon starting it, so that the switch is smoother. +*/ +if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { +if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && + (TX_SUBDEV (dev) ==NULL || + (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { +DEBUG ("Switching tx_dev to preferred sub_device" ); +PRIV (dev)->subs_tx =0 ; + } + }else { +if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || +TX_SUBDEV (dev) ==NULL ) { +/* Using first probed device */ + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { +DEBUG ("Switching tx_dev to sub_device %d" , + i); +PRIV (dev)->subs_tx = i; +break ; + } + } + } +return 0 ; +} + +static int +fs_bus_uninit (struct rte_eth_dev *dev) +{ +struct sub_device *sdev =NULL ; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { + ret =rte_eal_hotplug_remove (sdev->bus->name, + sdev->dev->name); +if (ret) { +ERROR ("Failed to remove requested device %s" , + sdev->dev->name); +continue ; + } + sdev->state =DEV_PROBED -1 ; + } +return 0 ; +} + +int +failsafe_eal_uninit (struct rte_eth_dev *dev) +{ +int ret; + + ret =fs_bus_uninit (dev); +if (ret) +return ret; +return 0 ; +}drivers/net/failsafe/failsafe_ops.c new file +663
-0@@ -0,0 +1,663 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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 <assert.h> +#include <stdint.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> + +#include "failsafe_private.h" + +static struct rte_eth_dev_info default_infos = { + .driver_name = pmd_failsafe_driver_name, +/* Max possible number of elements */ + .max_rx_pktlen =UINT32_MAX , + .max_rx_queues =RTE_MAX_QUEUES_PER_PORT , + .max_tx_queues =RTE_MAX_QUEUES_PER_PORT , + .max_mac_addrs =FAILSAFE_MAX_ETHADDR , + .max_hash_mac_addrs =UINT32_MAX , + .max_vfs =UINT16_MAX , + .max_vmdq_pools =UINT16_MAX , + .rx_desc_lim = { + .nb_max =UINT16_MAX , + .nb_min =0 , + .nb_align =1 , + .nb_seg_max =UINT16_MAX , + .nb_mtu_seg_max =UINT16_MAX , + }, + .tx_desc_lim = { + .nb_max =UINT16_MAX , + .nb_min =0 , + .nb_align =1 , + .nb_seg_max =UINT16_MAX , + .nb_mtu_seg_max =UINT16_MAX , + }, +/* Set of understood capabilities */ + .rx_offload_capa =0x0 , + .tx_offload_capa =0x0 , + .flow_type_rss_offloads =0x0 , +}; + +static int +fs_dev_configure (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state !=DEV_PROBED ) +continue ; +DEBUG ("Configuring sub-device %d" , i); + ret =rte_eth_dev_configure (PORT_ID (sdev), + dev->data->nb_rx_queues, + dev->data->nb_tx_queues, + &dev->data->dev_conf); +if (ret) { +ERROR ("Could not configure sub_device %d" , i); +return ret; + } + sdev->state =DEV_ACTIVE ; + } +return 0 ; +} + +static int +fs_dev_start (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state !=DEV_ACTIVE ) +continue ; +DEBUG ("Starting sub_device %d" , i); + ret =rte_eth_dev_start (PORT_ID (sdev)); +if (ret) +return ret; + sdev->state =DEV_STARTED ; + } +if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { +if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { +DEBUG ("Switching tx_dev to preferred sub_device" ); +PRIV (dev)->subs_tx =0 ; + } + }else { +if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || +TX_SUBDEV (dev) ==NULL ) { + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { +DEBUG ("Switching tx_dev to sub_device %d" , i); +PRIV (dev)->subs_tx = i; +break ; + } + } + } +return 0 ; +} + +static void +fs_dev_stop (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { +rte_eth_dev_stop (PORT_ID (sdev)); + sdev->state =DEV_STARTED -1 ; + } +} + +static int +fs_dev_set_link_up (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_set_link_up on sub_device %d" , i); + ret =rte_eth_dev_set_link_up (PORT_ID (sdev)); +if (ret) { +ERROR ("Operation rte_eth_dev_set_link_up failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} + +static int +fs_dev_set_link_down (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_set_link_down on sub_device %d" , i); + ret =rte_eth_dev_set_link_down (PORT_ID (sdev)); +if (ret) { +ERROR ("Operation rte_eth_dev_set_link_down failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} + +static void fs_dev_free_queues (struct rte_eth_dev *dev); +static void +fs_dev_close (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Closing sub_device %d" , i); +rte_eth_dev_close (PORT_ID (sdev)); + sdev->state =DEV_ACTIVE -1 ; + } +fs_dev_free_queues (dev); +} + +static void +fs_rx_queue_release (void *queue) +{ +struct rte_eth_dev *dev; +struct sub_device *sdev; +uint8_t i; +struct rxq *rxq; + +if (queue ==NULL ) +return ; + rxq = queue; + dev = rxq->priv->dev; + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +SUBOPS (sdev, rx_queue_release) + (ETH (sdev)->data->rx_queues[rxq->qid]); + dev->data->rx_queues[rxq->qid] =NULL ; +rte_free (rxq); +} + +static int +fs_rx_queue_setup (struct rte_eth_dev *dev, +uint16_t rx_queue_id, +uint16_t nb_rx_desc, +unsigned int socket_id, +const struct rte_eth_rxconf *rx_conf, +struct rte_mempool *mb_pool) +{ +struct sub_device *sdev; +struct rxq *rxq; +uint8_t i; +int ret; + + rxq = dev->data->rx_queues[rx_queue_id]; +if (rxq !=NULL ) { +fs_rx_queue_release (rxq); + dev->data->rx_queues[rx_queue_id] =NULL ; + } + rxq =rte_zmalloc (NULL ,sizeof (*rxq), +RTE_CACHE_LINE_SIZE ); +if (rxq ==NULL ) +return -ENOMEM ; + rxq->qid = rx_queue_id; + rxq->socket_id = socket_id; + rxq->info.mp = mb_pool; + rxq->info.conf = *rx_conf; + rxq->info.nb_desc = nb_rx_desc; + rxq->priv =PRIV (dev); + dev->data->rx_queues[rx_queue_id] = rxq; + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + ret =rte_eth_rx_queue_setup (PORT_ID (sdev), + rx_queue_id, + nb_rx_desc, socket_id, + rx_conf, mb_pool); +if (ret) { +ERROR ("RX queue setup failed for sub_device %d" , i); + goto free_rxq; + } + } +return 0 ; +free_rxq: +fs_rx_queue_release (rxq); +return ret; +} + +static void +fs_tx_queue_release (void *queue) +{ +struct rte_eth_dev *dev; +struct sub_device *sdev; +uint8_t i; +struct txq *txq; + +if (queue ==NULL ) +return ; + txq = queue; + dev = txq->priv->dev; + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +SUBOPS (sdev, tx_queue_release) + (ETH (sdev)->data->tx_queues[txq->qid]); + dev->data->tx_queues[txq->qid] =NULL ; +rte_free (txq); +} + +static int +fs_tx_queue_setup (struct rte_eth_dev *dev, +uint16_t tx_queue_id, +uint16_t nb_tx_desc, +unsigned int socket_id, +const struct rte_eth_txconf *tx_conf) +{ +struct sub_device *sdev; +struct txq *txq; +uint8_t i; +int ret; + + txq = dev->data->tx_queues[tx_queue_id]; +if (txq !=NULL ) { +fs_tx_queue_release (txq); + dev->data->tx_queues[tx_queue_id] =NULL ; + } + txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), +RTE_CACHE_LINE_SIZE ); +if (txq ==NULL ) +return -ENOMEM ; + txq->qid = tx_queue_id; + txq->socket_id = socket_id; + txq->info.conf = *tx_conf; + txq->info.nb_desc = nb_tx_desc; + txq->priv =PRIV (dev); + dev->data->tx_queues[tx_queue_id] = txq; + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + ret =rte_eth_tx_queue_setup (PORT_ID (sdev), + tx_queue_id, + nb_tx_desc, socket_id, + tx_conf); +if (ret) { +ERROR ("TX queue setup failed for sub_device %d" , i); + goto free_txq; + } + } +return 0 ; +free_txq: +fs_tx_queue_release (txq); +return ret; +} + +static void +fs_dev_free_queues (struct rte_eth_dev *dev) +{ +uint16_t i; + +for (i =0 ; i < dev->data->nb_rx_queues; i++) { +fs_rx_queue_release (dev->data->rx_queues[i]); + dev->data->rx_queues[i] =NULL ; + } + dev->data->nb_rx_queues =0 ; +for (i =0 ; i < dev->data->nb_tx_queues; i++) { +fs_tx_queue_release (dev->data->tx_queues[i]); + dev->data->tx_queues[i] =NULL ; + } + dev->data->nb_tx_queues =0 ; +} + +static void +fs_promiscuous_enable (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_promiscuous_enable (PORT_ID (sdev)); +} + +static void +fs_promiscuous_disable (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_promiscuous_disable (PORT_ID (sdev)); +} + +static void +fs_allmulticast_enable (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_allmulticast_enable (PORT_ID (sdev)); +} + +static void +fs_allmulticast_disable (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_allmulticast_disable (PORT_ID (sdev)); +} + +static int +fs_link_update (struct rte_eth_dev *dev, +int wait_to_complete) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling link_update on sub_device %d" , i); + ret = (SUBOPS (sdev, link_update))(ETH (sdev), wait_to_complete); +if (ret && ret !=-1 ) { +ERROR ("Link update failed for sub_device %d with error %d" , + i, ret); +return ret; + } + } +if (TX_SUBDEV (dev)) { +struct rte_eth_link *l1; +struct rte_eth_link *l2; + + l1 = &dev->data->dev_link; + l2 = Ð (TX_SUBDEV (dev))->data->dev_link; +if (memcmp (l1, l2,sizeof (*l1))) { + *l1 = *l2; +return 0 ; + } + } +return -1 ; +} + +static void +fs_stats_get (struct rte_eth_dev *dev, +struct rte_eth_stats *stats) +{ +memset (stats,0 ,sizeof (*stats)); +if (TX_SUBDEV (dev) ==NULL ) +return ; +rte_eth_stats_get (PORT_ID (TX_SUBDEV (dev)), stats); +} + +static void +fs_stats_reset (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_stats_reset (PORT_ID (sdev)); +} + +/** +* Fail-safe dev_infos_get rules: +* +* No sub_device: +* Numerables: +* Use the maximum possible values for any field, so as not +* to impede any further configuration effort. +* Capabilities: +* Limits capabilities to those that are understood by the +* fail-safe PMD. This understanding stems from the fail-safe +* being capable of verifying that the related capability is +* expressed within the device configuration (struct rte_eth_conf). +* +* At least one probed sub_device: +* Numerables: +* Uses values from the active probed sub_device +* The rationale here is that if any sub_device is less capable +* (for example concerning the number of queues) than the active +* sub_device, then its subsequent configuration will fail. +* It is impossible to foresee this failure when the failing sub_device +* is supposed to be plugged-in later on, so the configuration process +* is the single point of failure and error reporting. +* Capabilities: +* Uses a logical AND of RX capabilities among +* all sub_devices and the default capabilities. +* Uses a logical AND of TX capabilities among +* the active probed sub_device and the default capabilities. +* +*/ +static void +fs_dev_infos_get (struct rte_eth_dev *dev, +struct rte_eth_dev_info *infos) +{ +struct sub_device *sdev; +uint8_t i; + + sdev =TX_SUBDEV (dev); +if (sdev ==NULL ) { +DEBUG ("No probed device, using default infos" ); +rte_memcpy (&PRIV (dev)->infos, &default_infos, +sizeof (default_infos)); + }else { +uint32_t rx_offload_capa; + + rx_offload_capa = default_infos.rx_offload_capa; + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { +rte_eth_dev_info_get (PORT_ID (sdev), + &PRIV (dev)->infos); + rx_offload_capa &=PRIV (dev)->infos.rx_offload_capa; + } + sdev =TX_SUBDEV (dev); +rte_eth_dev_info_get (PORT_ID (sdev), &PRIV (dev)->infos); +PRIV (dev)->infos.rx_offload_capa = rx_offload_capa; +PRIV (dev)->infos.tx_offload_capa &= + default_infos.tx_offload_capa; +PRIV (dev)->infos.flow_type_rss_offloads &= + default_infos.flow_type_rss_offloads; + } +rte_memcpy (infos, &PRIV (dev)->infos,sizeof (*infos)); +} + +static const uint32_t * +fs_dev_supported_ptypes_get (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +struct rte_eth_dev *edev; + + sdev =TX_SUBDEV (dev); +if (sdev ==NULL ) +return NULL ; + edev =ETH (sdev); +/* ENOTSUP: counts as no supported ptypes */ +if (SUBOPS (sdev, dev_supported_ptypes_get) ==NULL ) +return NULL ; +/* +* The API does not permit to do a clean AND of all ptypes, +* It is also incomplete by design and we do not really care +* to have a best possible value in this context. +* We just return the ptypes of the device of highest +* priority, usually the PREFERRED device. +*/ +return SUBOPS (sdev, dev_supported_ptypes_get)(edev); +} + +static int +fs_mtu_set (struct rte_eth_dev *dev,uint16_t mtu) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_set_mtu on sub_device %d" , i); + ret =rte_eth_dev_set_mtu (PORT_ID (sdev), mtu); +if (ret) { +ERROR ("Operation rte_eth_dev_set_mtu failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} + +static int +fs_vlan_filter_set (struct rte_eth_dev *dev,uint16_t vlan_id,int on) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_vlan_filter on sub_device %d" , i); + ret =rte_eth_dev_vlan_filter (PORT_ID (sdev), vlan_id, on); +if (ret) { +ERROR ("Operation rte_eth_dev_vlan_filter failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} + +static int +fs_flow_ctrl_get (struct rte_eth_dev *dev, +struct rte_eth_fc_conf *fc_conf) +{ +struct sub_device *sdev; + + sdev =TX_SUBDEV (dev); +if (sdev ==NULL ) +return 0 ; +if (SUBOPS (sdev, flow_ctrl_get) ==NULL ) +return -ENOTSUP ; +return SUBOPS (sdev, flow_ctrl_get)(ETH (sdev), fc_conf); +} + +static int +fs_flow_ctrl_set (struct rte_eth_dev *dev, +struct rte_eth_fc_conf *fc_conf) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_flow_ctrl_set on sub_device %d" , i); + ret =rte_eth_dev_flow_ctrl_set (PORT_ID (sdev), fc_conf); +if (ret) { +ERROR ("Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} + +static void +fs_mac_addr_remove (struct rte_eth_dev *dev,uint32_t index) +{ +struct sub_device *sdev; +uint8_t i; + +/* No check: already done within the rte_eth_dev_mac_addr_remove +* call for the fail-safe device. +*/ + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_dev_mac_addr_remove (PORT_ID (sdev), + &dev->data->mac_addrs[index]); +PRIV (dev)->mac_addr_pool[index] =0 ; +} + +static int +fs_mac_addr_add (struct rte_eth_dev *dev, +struct ether_addr *mac_addr, +uint32_t index, +uint32_t vmdq) +{ +struct sub_device *sdev; +int ret; +uint8_t i; + +assert (index <FAILSAFE_MAX_ETHADDR ); + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + ret =rte_eth_dev_mac_addr_add (PORT_ID (sdev), mac_addr, vmdq); +if (ret) { +ERROR ("Operation rte_eth_dev_mac_addr_add failed for sub_device %" + PRIu8" with error %d" , i, ret); +return ret; + } + } +if (index >=PRIV (dev)->nb_mac_addr) { +DEBUG ("Growing mac_addrs array" ); +PRIV (dev)->nb_mac_addr = index; + } +PRIV (dev)->mac_addr_pool[index] = vmdq; +return 0 ; +} + +static void +fs_mac_addr_set (struct rte_eth_dev *dev,struct ether_addr *mac_addr) +{ +struct sub_device *sdev; +uint8_t i; + + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) +rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); +} + +const struct eth_dev_ops failsafe_ops = { + .dev_configure = fs_dev_configure, + .dev_start = fs_dev_start, + .dev_stop = fs_dev_stop, + .dev_set_link_down = fs_dev_set_link_down, + .dev_set_link_up = fs_dev_set_link_up, + .dev_close = fs_dev_close, + .promiscuous_enable = fs_promiscuous_enable, + .promiscuous_disable = fs_promiscuous_disable, + .allmulticast_enable = fs_allmulticast_enable, + .allmulticast_disable = fs_allmulticast_disable, + .link_update = fs_link_update, + .stats_get = fs_stats_get, + .stats_reset = fs_stats_reset, + .dev_infos_get = fs_dev_infos_get, + .dev_supported_ptypes_get = fs_dev_supported_ptypes_get, + .mtu_set = fs_mtu_set, + .vlan_filter_set = fs_vlan_filter_set, + .rx_queue_setup = fs_rx_queue_setup, + .tx_queue_setup = fs_tx_queue_setup, + .rx_queue_release = fs_rx_queue_release, + .tx_queue_release = fs_tx_queue_release, + .flow_ctrl_get = fs_flow_ctrl_get, + .flow_ctrl_set = fs_flow_ctrl_set, + .mac_addr_remove = fs_mac_addr_remove, + .mac_addr_add = fs_mac_addr_add, + .mac_addr_set = fs_mac_addr_set, +};drivers/net/failsafe/failsafe_private.h new file +227
-0@@ -0,0 +1,227 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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_ETH_FAILSAFE_PRIVATE_H_ +#define _RTE_ETH_FAILSAFE_PRIVATE_H_ + +#include <rte_dev.h> +#include <rte_ethdev.h> +#include <rte_devargs.h> + +#define FAILSAFE_DRIVER_NAME "Fail-safe PMD" + +#define PMD_FAILSAFE_MAC_KVARG "mac" +#define PMD_FAILSAFE_PARAM_STRING \ + "dev(<ifc>)," \ + "mac=mac_addr" \ + "" + +#define FAILSAFE_PLUGIN_DEFAULT_TIMEOUT_MS 2000 + +#define FAILSAFE_MAX_ETHPORTS 2 +#define FAILSAFE_MAX_ETHADDR 128 + +/* TYPES */ + +struct rxq { +struct fs_priv *priv; +uint16_t qid; +/* id of last sub_device polled */ +uint8_t last_polled; +unsigned int socket_id; +struct rte_eth_rxq_info info; +}; + +struct txq { +struct fs_priv *priv; +uint16_t qid; +unsigned int socket_id; +struct rte_eth_txq_info info; +}; + +enum dev_state { +DEV_UNDEFINED =0 , +DEV_PARSED , +DEV_PROBED , +DEV_ACTIVE , +DEV_STARTED , +}; + +struct sub_device { +/* Exhaustive DPDK device description */ +struct rte_devargs devargs; +struct rte_bus *bus; +struct rte_device *dev; +struct rte_eth_dev *edev; +/* Device state machine */ +enum dev_state state; +}; + +struct fs_priv { +struct rte_eth_dev *dev; +/* +* Set of sub_devices. +* subs[0] is the preferred device +* any other is just another slave +*/ +struct sub_device *subs; +uint8_t subs_head;/* if head == tail, no subs */ +uint8_t subs_tail;/* first invalid */ +uint8_t subs_tx;/* current emitting device */ +uint8_t current_probed; +/* current number of mac_addr slots allocated. */ +uint32_t nb_mac_addr; +struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ]; +uint32_t mac_addr_pool[FAILSAFE_MAX_ETHADDR ]; +/* current capabilities */ +struct rte_eth_dev_info infos; +}; + +/* RX / TX */ + +uint16_t failsafe_rx_burst (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); + +/* ARGS */ + +int failsafe_args_parse (struct rte_eth_dev *dev,const char *params); +void failsafe_args_free (struct rte_eth_dev *dev); +int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); + +/* EAL */ + +int failsafe_eal_init (struct rte_eth_dev *dev); +int failsafe_eal_uninit (struct rte_eth_dev *dev); + +/* GLOBALS */ + +extern const char pmd_failsafe_driver_name[]; +extern const struct eth_dev_ops failsafe_ops; +extern int mac_from_arg; + +/* HELPERS */ + +/* dev: (struct rte_eth_dev *) fail-safe device */ +#define PRIV (dev) \ + ((struct fs_priv *)(dev)->data->dev_private) + +/* sdev: (struct sub_device *) */ +#define ETH (sdev) \ + ((sdev)->edev) + +/* sdev: (struct sub_device *) */ +#define PORT_ID (sdev) \ + (ETH(sdev)->data->port_id) + +/** +* Stateful iterator construct over fail-safe sub-devices: +* s: (struct sub_device *), iterator +* i: (uint8_t), increment +* dev: (struct rte_eth_dev *), fail-safe ethdev +* state: (enum dev_state), minimum acceptable device state +*/ +#define FOREACH_SUBDEV_ST (s, i, dev, state) \ + for (i = fs_find_next((dev), 0, state); \ + i < PRIV(dev)->subs_tail && (s = &PRIV(dev)->subs[i]); \ + i = fs_find_next((dev), i + 1, state)) + +/** +* Iterator construct over fail-safe sub-devices: +* s: (struct sub_device *), iterator +* i: (uint8_t), increment +* dev: (struct rte_eth_dev *), fail-safe ethdev +*/ +#define FOREACH_SUBDEV (s, i, dev) \ + FOREACH_SUBDEV_ST(s, i, dev, DEV_UNDEFINED) + +/* dev: (struct rte_eth_dev *) fail-safe device */ +#define PREFERRED_SUBDEV (dev) \ + (&PRIV(dev)->subs[0]) + +/* dev: (struct rte_eth_dev *) fail-safe device */ +#define TX_SUBDEV (dev) \ + (PRIV(dev)->subs_tx >= PRIV(dev)->subs_tail ? NULL \ + : (PRIV(dev)->subs[PRIV(dev)->subs_tx].state < DEV_PROBED ? NULL \ + : &PRIV(dev)->subs[PRIV(dev)->subs_tx])) + +/** +* s: (struct sub_device *) +* ops: (struct eth_dev_ops) member +*/ +#define SUBOPS (s, ops) \ + (ETH(s)->dev_ops->ops) + +#ifndef NDEBUG +#include <stdio.h> +#define DEBUG__ (m, ...) \ + (fprintf(stderr, "%s:%d: %s(): " m "%c", \ + __FILE__, __LINE__, __func__, __VA_ARGS__), \ + (void)0) +#define DEBUG_ (...) \ + (errno = ((int []){ \ + *(volatile int *)&errno, \ + (DEBUG__(__VA_ARGS__), 0) \ + })[0]) +#define DEBUG (...) DEBUG_(__VA_ARGS__, '\n') +#define INFO (...) DEBUG(__VA_ARGS__) +#define WARN (...) DEBUG(__VA_ARGS__) +#define ERROR (...) DEBUG(__VA_ARGS__) +#else +#define DEBUG (...) ((void)0) +#define LOG__ (level, m, ...) \ + RTE_LOG(level, PMD, "net_failsafe: " m "%c", __VA_ARGS__) +#define LOG_ (level, ...) LOG__(level, __VA_ARGS__, '\n') +#define INFO (...) LOG_(INFO, __VA_ARGS__) +#define WARN (...) LOG_(WARNING, "WARNING: " __VA_ARGS__) +#define ERROR (...) LOG_(ERR, "ERROR: " __VA_ARGS__) +#endif + +/* inlined functions */ + +static inline uint8_t +fs_find_next (struct rte_eth_dev *dev,uint8_t sid, +enum dev_state min_state) +{ +while (sid <PRIV (dev)->subs_tail) { +if (PRIV (dev)->subs[sid].state >= min_state) +break ; + sid++; + } +if (sid >=PRIV (dev)->subs_tail) +return PRIV (dev)->subs_tail; +return sid; +} + +#endif /* _RTE_ETH_FAILSAFE_PRIVATE_H_ */ drivers/net/failsafe/failsafe_rxtx.c new file +107
-0@@ -0,0 +1,107 @@ +/*- +* BSD LICENSE +* +* Copyright 2017 6WIND S.A. +* Copyright 2017 Mellanox. +* +* 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 6WIND S.A. 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_mbuf.h> +#include <rte_ethdev.h> + +#include "failsafe_private.h" + +/* +* TODO: write fast version, +* without additional checks, to be activated once +* everything has been verified to comply. +*/ +uint16_t +failsafe_rx_burst (void *queue, +struct rte_mbuf **rx_pkts, +uint16_t nb_pkts) +{ +struct fs_priv *priv; +struct sub_device *sdev; +struct rxq *rxq; +void *sub_rxq; +uint16_t nb_rx; +uint8_t nb_polled, nb_subs; +uint8_t i; + + rxq = queue; + priv = rxq->priv; + nb_subs = priv->subs_tail - priv->subs_head; + nb_polled =0 ; +for (i = rxq->last_polled; nb_polled < nb_subs; nb_polled++) { + i++; +if (i == priv->subs_tail) + i = priv->subs_head; + sdev = &priv->subs[i]; +if (unlikely (ETH (sdev) ==NULL )) +continue ; +if (unlikely (ETH (sdev)->rx_pkt_burst ==NULL )) +continue ; +if (unlikely (sdev->state !=DEV_STARTED )) +continue ; + sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; + nb_rx =ETH (sdev)-> +rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +if (nb_rx) { + rxq->last_polled = i; +return nb_rx; + } + } +return 0 ; +} + +/* +* TODO: write fast version, +* without additional checks, to be activated once +* everything has been verified to comply. +*/ +uint16_t +failsafe_tx_burst (void *queue, +struct rte_mbuf **tx_pkts, +uint16_t nb_pkts) +{ +struct sub_device *sdev; +struct txq *txq; +void *sub_txq; + + txq = queue; + sdev =TX_SUBDEV (txq->priv->dev); +if (unlikely (sdev ==NULL )) +return 0 ; +if (unlikely (ETH (sdev) ==NULL )) +return 0 ; +if (unlikely (ETH (sdev)->tx_pkt_burst ==NULL )) +return 0 ; + sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; +return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +}drivers/net/failsafe/rte_pmd_failsafe_version.map new file +4
-0@@ -0,0 +1,4 @@ +DPDK_17.08 { + + local: *; +};mk/rte.app.mk +1
-1@@ -120,6 +120,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += -lrte_pmd_ena _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += -lrte_pmd_failsafe _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe ifeq ($(CONFIG_RTE_LIBRTE_KNI),y) --2.1.4
Re: [PATCH v7 03/11] net/failsafe: add fail-safe PMD
Quoted 12 lines · Jan Blunck
Quoted 11 lines · Gaetan Rivet
drivers/net/failsafe/failsafe_args.c new file +11
-0+static int +fs_parse_device (struct sub_device *sdev,char *args) +{ +struct rte_devargs *d; +int ret; + + d = &sdev->devargs; +DEBUG ("%s" , args); + ret =rte_eal_devargs_parse (args, d); +if (ret) { +DEBUG ("devargs parsing failed with code %d" , ret);
Quoted 10 lines
drivers/net/failsafe/failsafe_args.c line 93
Quoted 4 lines
drivers/net/failsafe/failsafe_args.c new file +4
-0+return ret; + } + sdev->bus = d->bus; + sdev->state =DEV_PARSED ;You seem to be mostly interested in the bus name for the device. Why don't you track this via your
sub_devicestructure instead of usingrte_devargs?
I don't understand. I track it in my sub_device structure by copying the info from the devargs? How would you get it otherwise?
Devargs still has to be used as a common format that can be parsed by EAL helpers. I could certainly parse it myself, but then I would have to follow any evolution of the parameter format, and I prefer to delegate this to the EAL.
Quoted 3 lines
Quoted 3 lines
drivers/net/failsafe/failsafe.c new file +3
-0+return 0 ; +} +
[...]
Quoted 7 lines
Quoted 7 lines
drivers/net/failsafe/failsafe_eal.c new file +7
-0+static struct rte_eth_dev * +fs_find_ethdev (const struct rte_device *dev) +{ +struct rte_eth_dev *eth_dev; +uint8_t i; + +RTE_ETH_FOREACH_DEV (i) {
Quoted 10 lines
drivers/net/failsafe/failsafe_eal.c line 50
Quoted 6 lines
drivers/net/failsafe/failsafe_eal.c new file +6
-0+ eth_dev = &rte_eth_devices[i]; +if (eth_dev->device == dev) +return eth_dev; + } +return NULL ; +}Why don't you use
rte_eth_dev_allocated()here?
IIRC, at the time I choose to roll out my own version, there was ambiguities about device names availability, with some devices using their rte_devargs name, others writing their own.
It has been stabilized it seems, and now I think rte_eth_dev_allocated could be used.
[...]
Quoted 11 lines
Quoted 11 lines
drivers/net/failsafe/failsafe_eal.c new file +11
-0+ +static int +fs_bus_init (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +struct rte_device *rdev; +struct rte_devargs *da; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) {
Quoted 10 lines
drivers/net/failsafe/failsafe_eal.c line 67
Quoted 6 lines
drivers/net/failsafe/failsafe_eal.c new file +6
-0+if (sdev->state !=DEV_PARSED ) +continue ; + da = &sdev->devargs; + rdev =rte_eal_hotplug_add (da->bus->name, + da->name, + da->args);Why don't you track the bus name through your
sub_devicestructure instead?
Do you mean
+ rdev = rte_eal_hotplug_add(sdev->bus->name,
+ da->name,
+ da->args);
instead? I guess for this example it was mostly for the sake of consistency, but the bus handle within the sub_device could be used.
Actually I dislike having a copy of an info. I have this info both within the sub_device directly and within the rte_devargs within the sub_device. It should be streamlined.
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v7 03/11] net/failsafe: add fail-safe PMD
In reply to Gaetan Rivet09/07/2017 03:47, Gaetan Rivet:
doc/guides/nics/fail_safe.rst line 122
Quoted 7 lines
doc/guides/nics/fail_safe.rst new file +7
-0+#. Start testpmd + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0,nodeaction=r1:0:CREATE)' -- \ + -i
It cannot work because rte_pci_scan is disabled with --no-pci. The PCI device will be unknown when adding it as slave of failsafe.
PATCH v7 4/11 net/failsafe: add plug-in support
In reply to Gaetan RivetPeriodically check for the existence of a device.
If a device has not been initialized and exists on the system, then it is probed and configured.
The configuration process strives to synchronize the states between the plugged-in sub-device and the fail-safe device.
--- doc/guides/nics/fail_safe.rst | 19 +++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 71 ++++++++++ drivers/net/failsafe/failsafe_args.c | 32 +++++ drivers/net/failsafe/failsafe_eal.c | 30 +---- drivers/net/failsafe/failsafe_ether.c | 228 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 25 ++-- drivers/net/failsafe/failsafe_private.h | 60 ++++++++- 8 files changed, 423 insertions(+), 43 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c
doc/guides/nics/fail_safe.rst +19 -0
@@ -102,6 +102,11 @@ Fail-safe command line parameters address is generated, that will be subsequently applied to all sub-device once they are probed. +- **hotplug_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two slave upkeep round. + Usage example ~~~~~~~~~~~~~
@@ -131,3 +136,17 @@ Care must be taken, however, to respect the **ether** API concerning device access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate over ethernet devices, instead of directly accessing them or by writing one's own device iterator. + +Plug-in feature +--------------- + +A sub-device can be defined without existing on the system when the fail-safe +PMD is initialized. Upon probing this device, the fail-safe PMD will detect its +absence and postpone its use. It will then register for a periodic check on any +missing sub-device. + +During this time, the fail-safe PMD can be used normally, configured and told to +emit and receive packets. It will store any applied configuration, and try to +apply it upon the probing of its missing sub-device. After this configuration +pass, the new sub-device will be synchronized with other sub-devices, i.e. be +started if the fail-safe PMD has been started by the user before.
drivers/net/failsafe/Makefile +1 -0
@@ -44,6 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c # No exported include files
drivers/net/failsafe/failsafe.c +71 -0
83 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c +32 -0
@@ -45,9 +45,11 @@typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params,uint8_t head); +uint64_t hotplug_poll;int mac_from_arg;const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ,PMD_FAILSAFE_MAC_KVARG ,NULL , };
@@ -221,6 +223,24 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) }static int +fs_get_u64_arg(const char *key __rte_unused, +const char *value,void *out) +{ +uint64_t *u64 = out; +char *endptr =NULL ; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + errno =0 ; + *u64 =strtoull (value, &endptr,0 ); +if (errno !=0 ) +return -errno; +if (endptr == value) +return -1 ; +return 0 ; +} + +static int fs_get_mac_addr_arg(const char *key __rte_unused,const char *value,void *out) {
@@ -252,6 +272,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret =0 ; priv->subs_tx =FAILSAFE_MAX_ETHPORTS ;/* default parameters */ + hotplug_poll =FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS ; mac_from_arg =0 ; n =snprintf (mut_params,sizeof (mut_params),"%s" , params);if (n >=sizeof (mut_params)) {
@@ -274,6 +295,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING);return -1 ; } +/* PLUG_IN event poll timer */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG , + &fs_get_u64_arg, &hotplug_poll); +if (ret <0 ) + goto free_kvlist; + }/* MAC addr */ arg_count =rte_kvargs_count (kvlist,PMD_FAILSAFE_MAC_KVARG );
@@ -287,6 +318,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) mac_from_arg =1 ; } } +PRIV (dev)->state =DEV_PARSED ; free_kvlist:rte_kvargs_free (kvlist);return ret;
drivers/net/failsafe/failsafe_eal.c +4 -26
@@ -88,37 +88,14 @@ fs_bus_init(struct rte_eth_dev *dev)int failsafe_eal_init (struct rte_eth_dev *dev) { -struct sub_device *sdev; -uint8_t i;int ret; ret =fs_bus_init (dev);if (ret)return ret; -/* -* We only update TX_SUBDEV if we are not started. -* If a sub_device is emitting, we will switch the TX_SUBDEV to the -* preferred port only upon starting it, so that the switch is smoother. -*/ -if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && - (TX_SUBDEV (dev) ==NULL || - (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || -TX_SUBDEV (dev) ==NULL ) { -/* Using first probed device */ - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { -DEBUG ("Switching tx_dev to sub_device %d" , - i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_PROBED ) +PRIV (dev)->state =DEV_PROBED ; +fs_switch_dev (dev);return 0 ; }
@@ -150,5 +127,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret =fs_bus_uninit (dev);if (ret)return ret; +PRIV (dev)->state =DEV_PROBED -1 ;return 0 ; }
drivers/net/failsafe/failsafe_ether.c new file +228 -0
228 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +10 -15
@@ -89,6 +89,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } sdev->state =DEV_ACTIVE ; } +if (PRIV (dev)->state <DEV_ACTIVE ) +PRIV (dev)->state =DEV_ACTIVE ;return 0 ; }
@@ -108,21 +110,9 @@ fs_dev_start(struct rte_eth_dev *dev)return ret; sdev->state =DEV_STARTED ; } -if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || -TX_SUBDEV (dev) ==NULL ) { - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { -DEBUG ("Switching tx_dev to sub_device %d" , i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_STARTED ) +PRIV (dev)->state =DEV_STARTED ; +fs_switch_dev (dev);return 0 ; }
@@ -132,6 +122,7 @@ fs_dev_stop(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +PRIV (dev)->state =DEV_STARTED -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) {rte_eth_dev_stop (PORT_ID (sdev)); sdev->state =DEV_STARTED -1 ;
@@ -183,6 +174,10 @@ fs_dev_close(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +failsafe_hotplug_alarm_cancel (dev); +if (PRIV (dev)->state ==DEV_STARTED ) + dev->dev_ops->dev_stop (dev); +PRIV (dev)->state =DEV_ACTIVE -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {DEBUG ("Closing sub_device %d" , i);rte_eth_dev_close (PORT_ID (sdev));
drivers/net/failsafe/failsafe_private.h +58 -2
92 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v7 5/11 net/failsafe: add flexible device definition
In reply to Gaetan RivetAdd the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.
That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 99 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 130 insertions(+)
doc/guides/nics/fail_safe.rst +20 -0
@@ -91,6 +91,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
@@ -126,6 +139,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. --vdev='net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0,nodeaction=r1:0:CREATE)' -- \ -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i + Using the Fail-safe PMD from an application -------------------------------------------
drivers/net/failsafe/failsafe_args.c +99 -0
126 lines not on this page · raw message
drivers/net/failsafe/failsafe_ether.c +7 -0
@@ -188,6 +188,13 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)int ret;uint8_t i; +if (PRIV (dev)->state <DEV_PARSED ) +return 0 ; + + ret =failsafe_args_parse_subs (dev); +if (ret) +return ret; +if (PRIV (dev)->state <DEV_PROBED )return 0 ; ret =failsafe_eal_init (dev);
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -44,6 +44,7 @@#define PMD_FAILSAFE_PLUG_IN_POLL_KVARG "hotplug_poll"#define PMD_FAILSAFE_PARAM_STRING \ "dev(<ifc>)," \ + "exec(<shell command>)," \ "mac=mac_addr," \ "hotplug_poll=u64" \ ""
@@ -87,6 +88,8 @@ struct sub_device {struct rte_eth_dev *edev;/* Device state machine */ enum dev_state state; +/* Some device are defined as a command line */ +char *cmdline; };struct fs_priv {
@@ -135,6 +138,7 @@ uint16_t failsafe_tx_burst(void *txq,int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);void failsafe_args_free (struct rte_eth_dev *dev);int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); +int failsafe_args_parse_subs (struct rte_eth_dev *dev);/* EAL */
Signature · 1 line
2.1.4
PATCH v7 6/11 net/failsafe: support flow API
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 216 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 337 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c
doc/guides/nics/features/failsafe.ini +1 -0
@@ -13,6 +13,7 @@ Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/Makefile +1 -0
@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files
drivers/net/failsafe/failsafe.c +1 -0
@@ -177,6 +177,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; dev->data->dev_link = eth_link;PRIV (dev)->nb_mac_addr =1 ; +TAILQ_INIT (&PRIV (dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;if (params ==NULL ) {
drivers/net/failsafe/failsafe_eal.c +1 -0
@@ -78,6 +78,7 @@ fs_bus_init(struct rte_eth_dev *dev)ERROR ("sub_device %d init went wrong" , i);return -ENODEV ; } +SUB_ID (sdev) = i; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
drivers/net/failsafe/failsafe_ether.c +70 -0
90 lines not on this page · raw message
drivers/net/failsafe/failsafe_flow.c new file +216 -0
216 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +29 -0
@@ -35,6 +35,7 @@#include <stdint.h> #include <rte_ethdev.h> #include <rte_malloc.h> +#include <rte_flow.h> #include "failsafe_private.h"
@@ -628,6 +629,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); } +static int +fs_filter_ctrl (struct rte_eth_dev *dev, +enum rte_filter_type type, +enum rte_filter_op op, +void *arg) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + +if (type ==RTE_ETH_FILTER_GENERIC && + op ==RTE_ETH_FILTER_GET ) { + *(const void **)arg = &fs_flow_ops; +return 0 ; + } + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_filter_ctrl on sub_device %d" , i); + ret =rte_eth_dev_filter_ctrl (PORT_ID (sdev), type, op, arg); +if (ret) { +ERROR ("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} +const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start,
@@ -655,4 +683,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, };
drivers/net/failsafe/failsafe_private.h +18 -0
@@ -34,6 +34,8 @@#ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_#define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include <sys/queue.h> +#include <rte_dev.h> #include <rte_ethdev.h> #include <rte_devargs.h>
@@ -72,6 +74,14 @@ struct txq {struct rte_eth_txq_info info; }; +struct rte_flow { +TAILQ_ENTRY (rte_flow) next; +/* sub_flows */ +struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS ]; +/* flow description for synchronization */ +struct rte_flow_desc *fd; +}; +enum dev_state {DEV_UNDEFINED =0 ,DEV_PARSED ,
@@ -86,6 +96,7 @@ struct sub_device {struct rte_bus *bus;struct rte_device *dev;struct rte_eth_dev *edev; +uint8_t sid;/* Device state machine */ enum dev_state state;/* Some device are defined as a command line */
@@ -104,6 +115,8 @@ struct fs_priv {uint8_t subs_tail;/* first invalid */ uint8_t subs_tx;/* current emitting device */ uint8_t current_probed; +/* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list;/* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr;struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ];
@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);extern const char pmd_failsafe_driver_name[];extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops;extern uint64_t hotplug_poll;extern int mac_from_arg;
@@ -170,6 +184,10 @@ extern int mac_from_arg;#define PORT_ID (sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID (sdev) \ + ((sdev)->sid) +/** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator
Signature · 1 line
2.1.4
PATCH v7 7/11 net/failsafe: support offload capabilities
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)
doc/guides/nics/features/failsafe.ini +6 -0
@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/failsafe_ops.c +129 -2
151 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v7 8/11 net/failsafe: add fast burst functions
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_private.h | 8 +++ drivers/net/failsafe/failsafe_rxtx.c | 124 ++++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 20 deletions(-)
drivers/net/failsafe/failsafe_private.h +8 -0
@@ -141,11 +141,18 @@ int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);/* RX / TX */ +void set_burst_fn (struct rte_eth_dev *dev,int force_safe); +uint16_t failsafe_rx_burst (void *rxq,struct rte_mbuf **rx_pkts,uint16_t nb_pkts);uint16_t failsafe_tx_burst (void *txq,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +uint16_t failsafe_rx_burst_fast (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst_fast (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +/* ARGS */ int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);
@@ -299,6 +306,7 @@ fs_switch_dev(struct rte_eth_dev *dev) }else {return ; } +set_burst_fn (dev,0 );rte_wmb (); }
drivers/net/failsafe/failsafe_rxtx.c +104 -20
154 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v7 9/11 net/failsafe: support device removal
In reply to Gaetan RivetListen to INTR_RMV events issued by slaves.
Add atomic flags on slave queues to detect use of slave bursts function. If a removal is detected, set the recollection flag on this slave.
During a slave upkeep round, if its recollection flag is set and its burst functions are not in use by any thread, remove that slave.
--- doc/guides/nics/fail_safe.rst | 14 +++++ drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_args.c | 13 +++++ drivers/net/failsafe/failsafe_eal.c | 3 +- drivers/net/failsafe/failsafe_ether.c | 96 ++++++++++++++++++++++++++++++--- drivers/net/failsafe/failsafe_ops.c | 38 +++++++++++-- drivers/net/failsafe/failsafe_private.h | 72 ++++++++++++++++++++++--- drivers/net/failsafe/failsafe_rxtx.c | 17 +++++- 8 files changed, 234 insertions(+), 20 deletions(-)
doc/guides/nics/fail_safe.rst +14 -0
@@ -51,6 +51,12 @@ The Fail-safe PMD only supports a limited set of features. If you plan to use a device underneath the Fail-safe PMD with a specific feature, this feature must be supported by the Fail-safe PMD to avoid throwing any error. +A notable exception is the device removal feature. The fail-safe PMD being a +virtual device, it cannot currently be removed in the sense of a specific bus +hotplug, like for PCI for example. It will however enable this feature for its +sub-device automatically, detecting those that are capable and register the +relevant callback for such event. + Check the feature matrix for the complete set of supported features. Compilation options
@@ -170,3 +176,11 @@ emit and receive packets. It will store any applied configuration, and try to apply it upon the probing of its missing sub-device. After this configuration pass, the new sub-device will be synchronized with other sub-devices, i.e. be started if the fail-safe PMD has been started by the user before. + +Plug-out feature +---------------- + +A sub-device supporting the device removal event can be removed from its bus at +any time. The fail-safe PMD will register a callback for such event and react +accordingly. It will try to safely stop, close and uninit the sub-device having +emitted this event, allowing it to free its eventual resources.
drivers/net/failsafe/failsafe.c +1 -0
@@ -132,6 +132,7 @@ fs_hotplug_alarm(void *arg)if (!PRIV (dev)->pending_alarm)return ;PRIV (dev)->pending_alarm =0 ; +failsafe_dev_remove (dev); FOREACH_SUBDEV(sdev, i, dev)if (sdev->state !=PRIV (dev)->state)break ;
drivers/net/failsafe/failsafe_args.c +13 -0
@@ -443,6 +443,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device (struct sub_device *sdev) +{ +struct rte_devargs *da; +char devstr[DEVARGS_MAXLEN ] ="" ; + + da = &sdev->devargs; +snprintf (devstr,sizeof (devstr),"%s,%s" , da->name, da->args); +return fs_parse_device (sdev, devstr); +} +int failsafe_args_parse_subs (struct rte_eth_dev *dev) {
@@ -455,6 +466,8 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev)continue ;if (sdev->cmdline) ret =fs_execute_cmd (sdev, sdev->cmdline); +else + ret =fs_parse_sub_device (sdev);if (ret ==0 ) sdev->state =DEV_PARSED ; }
drivers/net/failsafe/failsafe_eal.c +2 -1
@@ -79,6 +79,7 @@ fs_bus_init(struct rte_eth_dev *dev)return -ENODEV ; }SUB_ID (sdev) = i; + sdev->fs_dev = dev; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
@@ -96,7 +97,7 @@ failsafe_eal_init(struct rte_eth_dev *dev)return ret;if (PRIV (dev)->state <DEV_PROBED )PRIV (dev)->state =DEV_PROBED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
drivers/net/failsafe/failsafe_ether.c +90 -6
130 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +35 -3
@@ -33,6 +33,8 @@#include <assert.h> #include <stdint.h> + +#include <rte_atomic.h> #include <rte_ethdev.h> #include <rte_malloc.h> #include <rte_flow.h>
@@ -204,9 +206,21 @@ fs_dev_configure(struct rte_eth_dev *dev) } } FOREACH_SUBDEV(sdev, i, dev) { +int rmv_interrupt =0 ; +if (sdev->state !=DEV_PROBED )continue ; + + rmv_interrupt =ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_RMV ; +if (rmv_interrupt) { +DEBUG ("Enabling RMV interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.rmv =1 ; + }else { +DEBUG ("sub_device %d does not support RMV event" , i); + }DEBUG ("Configuring sub-device %d" , i); + sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues,
@@ -215,6 +229,16 @@ fs_dev_configure(struct rte_eth_dev *dev)ERROR ("Could not configure sub_device %d" , i);return ret; } +if (rmv_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_RMV , + failsafe_eth_rmv_event_callback, + sdev); +if (ret) +WARN ("Failed to register RMV callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.rmv =0 ; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
@@ -240,7 +264,7 @@ fs_dev_start(struct rte_eth_dev *dev) }if (PRIV (dev)->state <DEV_STARTED )PRIV (dev)->state =DEV_STARTED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
@@ -351,10 +375,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,fs_rx_queue_release (rxq); dev->data->rx_queues[rx_queue_id] =NULL ; } - rxq =rte_zmalloc (NULL ,sizeof (*rxq), + rxq =rte_zmalloc (NULL , +sizeof (*rxq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (rxq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&rxq->refcnt[i]); rxq->qid = rx_queue_id; rxq->socket_id = socket_id; rxq->info.mp = mb_pool;
@@ -414,10 +442,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,fs_tx_queue_release (txq); dev->data->tx_queues[tx_queue_id] =NULL ; } - txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), + txq =rte_zmalloc ("ethdev TX queue" , +sizeof (*txq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (txq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&txq->refcnt[i]); txq->qid = tx_queue_id; txq->socket_id = socket_id; txq->info.conf = *tx_conf;
drivers/net/failsafe/failsafe_private.h +64 -8
133 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c +15 -2
@@ -33,6 +33,7 @@#include <assert.h> +#include <rte_atomic.h> #include <rte_mbuf.h> #include <rte_ethdev.h>
@@ -113,8 +114,10 @@ failsafe_rx_burst(void *queue,if (unlikely (fs_rx_unsafe (sdev)))continue ; sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -147,8 +150,10 @@ failsafe_rx_burst_fast(void *queue, sdev = &priv->subs[i];assert (!fs_rx_unsafe (sdev)); sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -165,13 +170,17 @@ failsafe_tx_burst(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);if (unlikely (fs_tx_unsafe (sdev)))return 0 ; sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }uint16_t
@@ -182,10 +191,14 @@ failsafe_tx_burst_fast(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);assert (!fs_tx_unsafe (sdev)); sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }
Signature · 1 line
2.1.4
PATCH v7 10/11 net/failsafe: support link status change event
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_ether.c | 18 ++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 23 +++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 3 +++ 5 files changed, 46 insertions(+)
doc/guides/nics/features/failsafe.ini +1 -0
@@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y
drivers/net/failsafe/failsafe.c +1 -0
@@ -240,6 +240,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) mac->addr_bytes[0 ], mac->addr_bytes[1 ], mac->addr_bytes[2 ], mac->addr_bytes[3 ], mac->addr_bytes[4], mac->addr_bytes[5]); + dev->data->dev_flags |=RTE_ETH_DEV_INTR_LSC ;return 0 ; free_args:failsafe_args_free (dev);
drivers/net/failsafe/failsafe_ether.c +18 -0
@@ -387,3 +387,21 @@ failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, sdev->remove =1 ;return 0 ; } + +int +failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, + enum rte_eth_event_type event __rte_unused, + void *cb_arg, void *out __rte_unused) +{ +struct rte_eth_dev *dev = cb_arg; +int ret; + + ret = dev->dev_ops->link_update (dev,0 ); +/* We must pass on the LSC event */ +if (ret) +return _rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC , +NULL ,NULL ); +else +return 0 ; +}
drivers/net/failsafe/failsafe_ops.c +23 -0
@@ -207,6 +207,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } FOREACH_SUBDEV(sdev, i, dev) {int rmv_interrupt =0 ; +int lsc_interrupt =0 ; +int lsc_enabled;if (sdev->state !=DEV_PROBED )continue ;
@@ -219,6 +221,17 @@ fs_dev_configure(struct rte_eth_dev *dev) }else {DEBUG ("sub_device %d does not support RMV event" , i); } + lsc_enabled = dev->data->dev_conf.intr_conf.lsc; + lsc_interrupt = lsc_enabled && + (ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_LSC ); +if (lsc_interrupt) { +DEBUG ("Enabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =1 ; + }else if (lsc_enabled && !lsc_interrupt) { +DEBUG ("Disabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =0 ; + }DEBUG ("Configuring sub-device %d" , i); sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev),
@@ -239,6 +252,16 @@ fs_dev_configure(struct rte_eth_dev *dev) SUB_ID(sdev)); } dev->data->dev_conf.intr_conf.rmv =0 ; +if (lsc_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_LSC , + failsafe_eth_lsc_event_callback, + dev); +if (ret) +WARN ("Failed to register LSC callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.lsc = lsc_enabled; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
drivers/net/failsafe/failsafe_private.h +3 -0
@@ -179,6 +179,9 @@ void failsafe_dev_remove(struct rte_eth_dev *dev);int failsafe_eth_rmv_event_callback (uint8_t port_id,enum rte_eth_event_type type,void *arg,void *out); +int failsafe_eth_lsc_event_callback (uint8_t port_id, +enum rte_eth_event_type event, +void *cb_arg,void *out);/* GLOBALS */
Signature · 1 line
2.1.4
PATCH v7 11/11 net/failsafe: support flow API isolation mode
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ether.c | 34 +++++++++++++++++++++++++++++++-- drivers/net/failsafe/failsafe_flow.c | 29 ++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ether.c +32 -2
@@ -74,6 +74,28 @@ fs_flow_complain(struct rte_flow_error *error) }static int +eth_dev_flow_isolate_set (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_flow_error ferror; +int ret; + +if (!PRIV (dev)->flow_isolated) { +DEBUG ("Flow isolation already disabled" ); + }else { +DEBUG ("Enabling flow isolation" ); + ret =rte_flow_isolate (PORT_ID (sdev), +PRIV (dev)->flow_isolated, + &ferror); +if (ret) { +fs_flow_complain (&ferror); +return ret; + } + } +return 0 ; +} + +static int fs_eth_dev_conf_apply (struct rte_eth_dev *dev,struct sub_device *sdev) {
@@ -334,9 +356,17 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)if (PRIV (dev)->state <DEV_ACTIVE )return 0 ; inactive =0 ; - FOREACH_SUBDEV(sdev, i, dev) -if (sdev->state ==DEV_PROBED ) + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state ==DEV_PROBED ) { inactive |=UINT32_C (1 ) << i; + ret =eth_dev_flow_isolate_set (dev, sdev); +if (ret) { +ERROR ("Could not apply configuration to sub_device %d" , + i); + goto err_remove; + } + } + } ret = dev->dev_ops->dev_configure (dev);if (ret) goto err_remove;
drivers/net/failsafe/failsafe_flow.c +29 -0
@@ -207,10 +207,39 @@ fs_flow_query(struct rte_eth_dev *dev,return -1 ; } +static int +fs_flow_isolate (struct rte_eth_dev *dev, +int set, +struct rte_flow_error *error) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state <DEV_PROBED ) +continue ; +DEBUG ("Calling rte_flow_isolate on sub_device %d" , i); +if (PRIV (dev)->flow_isolated != sdev->flow_isolated) +WARN ("flow isolation mode of sub_device %d in incoherent state." , + i); + ret =rte_flow_isolate (PORT_ID (sdev), set, error); +if (ret) { +ERROR ("Operation rte_flow_isolate failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + sdev->flow_isolated = set; + } +PRIV (dev)->flow_isolated = set; +return 0 ; +} +const struct rte_flow_ops fs_flow_ops = { .validate = fs_flow_validate, .create = fs_flow_create, .destroy = fs_flow_destroy, .flush = fs_flow_flush, .query = fs_flow_query, + .isolate = fs_flow_isolate, };
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -108,6 +108,8 @@ struct sub_device {struct rte_eth_dev *fs_dev;/* flag calling for recollection */ volatile unsigned int remove:1; +/* flow isolation state */ + int flow_isolated:1; };struct fs_priv {
@@ -139,6 +141,8 @@ struct fs_priv {*/ enum dev_state state; unsigned int pending_alarm:1; /* An alarm is pending */ +/* flow isolation state */ + int flow_isolated:1; };/* MISC */
Signature · 1 line
2.1.4
v8 cover introduce fail-safe PMD
In reply to Gaetan RivetThis PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
eal: complete attach / detach support
http://dpdk.org/ml/archives/dev/2017-May/066366.html
http://dpdk.org/dev/patchwork/patch/24522/
ethdev: add flow API rule copy function
http://dpdk.org/ml/archives/dev/2017-May/066145.html
http://dpdk.org/dev/patchwork/patch/24406/
ethdev: add isolated mode to flow API
http://dpdk.org/ml/archives/dev/2017-April/064327.html
http://dpdk.org/dev/patchwork/patch/23741/
v1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixes
v2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.
v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports plugin
v4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fix rte_dev hotplug API implementation.
- Introduce rte_eal_devargs_rmv API as EXPERIMENTAL.
- Use it to clean up resources on hotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.
This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.
These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Use rte_eth_dev_allocated when relevant.
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/fail_safe.rst | 199 +++++ doc/guides/nics/features/failsafe.ini | 32 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 78 ++ drivers/net/failsafe/failsafe.c | 305 ++++++++ drivers/net/failsafe/failsafe_args.c | 475 ++++++++++++ drivers/net/failsafe/failsafe_eal.c | 118 +++ drivers/net/failsafe/failsafe_ether.c | 437 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 245 ++++++ drivers/net/failsafe/failsafe_ops.c | 869 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 376 ++++++++++ drivers/net/failsafe/failsafe_rxtx.c | 204 +++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + lib/librte_ether/rte_ethdev.c | 19 +- lib/librte_ether/rte_ethdev.h | 14 +- mk/rte.app.mk | 1 + 19 files changed, 3375 insertions(+), 15 deletions(-) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ether.c create mode 100644 drivers/net/failsafe/failsafe_flow.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
Signature · 1 line
2.1.4
PATCH v8 1/11 ethdev: add deferred intermediate device state
This device state means that the device is managed externally, by whichever party has set this state (PMD or application).
Note: this new device state is only an information. The related device structure and operators are still valid and can be used normally.
It is however made private by device management helpers within ethdev, making the device invisible to applications.
--- lib/librte_ether/rte_ethdev.c | 3 ++- lib/librte_ether/rte_ethdev.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
lib/librte_ether/rte_ethdev.c +2 -1
@@ -291,7 +291,8 @@ int rte_eth_dev_is_valid_port(uint8_t port_id) {if (port_id >=RTE_MAX_ETHPORTS || - rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED ) + (rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED && + rte_eth_devices[port_id].state !=RTE_ETH_DEV_DEFERRED ))return 0 ;else return 1 ;
lib/librte_ether/rte_ethdev.h +1 -0
@@ -1607,6 +1607,7 @@ struct rte_eth_rxtx_callback {enum rte_eth_dev_state {RTE_ETH_DEV_UNUSED =0 ,RTE_ETH_DEV_ATTACHED , +RTE_ETH_DEV_DEFERRED , };/**
Signature · 1 line
2.1.4
PATCH v8 2/11 ethdev: count devices consistently
In reply to Gaetan RivetMake the rte_eth_dev_count() return the number of available devices even after some are detached by the hotplug API or put in a deferred state.
--- lib/librte_ether/rte_ethdev.c | 16 +++++++++------- lib/librte_ether/rte_ethdev.h | 13 ++++++------- 2 files changed, 15 insertions(+), 14 deletions(-)
lib/librte_ether/rte_ethdev.c +9 -7
@@ -72,7 +72,6 @@ static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS ];static struct rte_eth_dev_data *rte_eth_dev_data;static uint8_t eth_dev_last_created_port; -static uint8_t nb_ports;/* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock =RTE_SPINLOCK_INITIALIZER ;
@@ -210,7 +209,6 @@ eth_dev_get(uint8_t port_id)TAILQ_INIT (&(eth_dev->link_intr_cbs)); eth_dev_last_created_port = port_id; - nb_ports++;return eth_dev; }
@@ -283,7 +281,6 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)return -EINVAL ; eth_dev->state =RTE_ETH_DEV_UNUSED ; - nb_ports--;return 0 ; }
@@ -308,7 +305,15 @@ rte_eth_dev_socket_id(uint8_t port_id)uint8_t rte_eth_dev_count (void ) { -return nb_ports; +uint8_t p; +uint8_t count; + + count =0 ; + +RTE_ETH_FOREACH_DEV (p) + count++; + +return count; }int
@@ -341,9 +346,6 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id)return -EINVAL ; } -if (!nb_ports) -return -ENODEV ; -RTE_ETH_FOREACH_DEV (i) {if (!rte_eth_devices[i].device)continue ;
lib/librte_ether/rte_ethdev.h +6 -7
@@ -1742,13 +1742,12 @@ uint8_t rte_eth_find_next(uint8_t port_id);/** * Get the total number of Ethernet devices that have been successfully -* initialized by the [matching] Ethernet driver during the PCI probing phase. -* All devices whose port identifier is in the range -* [0, rte_eth_dev_count() - 1] can be operated on by network applications -* immediately after invoking rte_eal_init(). -* If the application unplugs a port using hotplug function, The enabled port -* numbers may be noncontiguous. In the case, the applications need to manage -* enabled port by using the ``RTE_ETH_FOREACH_DEV()`` macro. +* initialized by the matching Ethernet driver during the PCI probing phase +* and that are available for applications to use. These devices must be +* accessed by using the ``RTE_ETH_FOREACH_DEV()`` macro to deal with +* non-contiguous ranges of devices. +* These non-contiguous ranges can be created by calls to hotplug functions or +* by some PMDs. * * @return * - The total number of usable Ethernet devices.
Signature · 1 line
2.1.4
PATCH v8 3/11 net/failsafe: add fail-safe PMD
In reply to Gaetan RivetIntroduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
--- MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/fail_safe.rst | 146 +++++ doc/guides/nics/features/failsafe.ini | 24 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 76 +++ drivers/net/failsafe/failsafe.c | 231 ++++++++ drivers/net/failsafe/failsafe_args.c | 331 +++++++++++ drivers/net/failsafe/failsafe_eal.c | 138 +++++ drivers/net/failsafe/failsafe_ops.c | 663 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 227 ++++++++ drivers/net/failsafe/failsafe_rxtx.c | 107 ++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + mk/rte.app.mk | 1 + 15 files changed, 1962 insertions(+) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
MAINTAINERS +5 -0
@@ -336,6 +336,11 @@ F: drivers/net/enic/ F: doc/guides/nics/enic.rst F: doc/guides/nics/features/enic.ini +Fail-safe PMD +M: Gaetan Rivet <[email protected]> +F: drivers/net/failsafe/ +F: doc/guides/nics/fail_safe.rst + Intel e1000 M: Wenzhuo Lu <[email protected]> F: drivers/net/e1000/
config/common_base +6 -0
@@ -420,6 +420,12 @@ CONFIG_RTE_LIBRTE_PMD_XENVIRT=n CONFIG_RTE_LIBRTE_PMD_NULL=y # +# Compile fail-safe PMD +# +CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y +CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG=n + +# # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y
doc/guides/nics/fail_safe.rst new file +146 -0
146 lines not on this page · raw message
doc/guides/nics/features/failsafe.ini new file +24 -0
@@ -0,0 +1,24 @@ +; +; Supported features of the 'fail-safe' poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status = Y +Queue start/stop = Y +MTU update = Y +Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +VLAN filter = Y +Packet type parsing = Y +Basic stats = Y +Stats per queue = Y +ARMv7 = Y +ARMv8 = Y +Power8 = Y +x86-32 = Y +x86-64 = Y +Usage doc = Y
doc/guides/nics/index.rst +1 -0
@@ -64,6 +64,7 @@ Network Interface Controller Drivers vhost vmxnet3 pcap_ring + fail_safe **Figures**
drivers/net/Makefile +2 -0
@@ -59,6 +59,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena DEPDIRS-ena = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DEPDIRS-enic = $(core-libs) librte_hash +DIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe +DEPDIRS-failsafe = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DEPDIRS-fm10k = $(core-libs) librte_hash DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e
drivers/net/failsafe/Makefile new file +76 -0
76 lines not on this page · raw message
drivers/net/failsafe/failsafe.c new file +231 -0
231 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c new file +331 -0
331 lines not on this page · raw message
drivers/net/failsafe/failsafe_eal.c new file +138 -0
138 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c new file +663 -0
663 lines not on this page · raw message
drivers/net/failsafe/failsafe_private.h new file +227 -0
227 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c new file +107 -0
107 lines not on this page · raw message
drivers/net/failsafe/rte_pmd_failsafe_version.map new file +4 -0
@@ -0,0 +1,4 @@ +DPDK_17.08 { + + local: *; +};
mk/rte.app.mk +1 -0
@@ -121,6 +121,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += -lrte_pmd_ena _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += -lrte_pmd_failsafe _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
Signature · 1 line
2.1.4
Re: [PATCH v8 03/11] net/failsafe: add fail-safe PMD
11/07/2017 01:19, Gaetan Rivet:
Quoted 2 lines
drivers/net/failsafe/failsafe_args.c new file +0
-0
[...]
Quoted 1 line
+#include <
errno.h>
Do you really need errno in this file?
Re: [PATCH v8 03/11] net/failsafe: add fail-safe PMD
Quoted 7 lines · Thomas Monjalon
11/07/2017 01:19, Gaetan Rivet:
Quoted 2 lines
drivers/net/failsafe/failsafe_args.c new file +0
-0[...]
Quoted 1 line
+#include <
errno.h>Do you really need errno in this file?
It's used for error handling on strtoull and popen. Why, is it a problem to include errno.h?
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v8 03/11] net/failsafe: add fail-safe PMD
11/07/2017 23:48, Gaëtan Rivet:
Quoted 11 lines · Thomas Monjalon
Quoted 7 lines
11/07/2017 01:19, Gaetan Rivet:
Quoted 2 lines
drivers/net/failsafe/failsafe_args.c new file +0
-0[...]
Quoted 1 line
+#include <
errno.h>Do you really need errno in this file?
It's used for error handling on strtoull and popen. Why, is it a problem to include
errno.h?
I don't see errno used in this patch.
I think it is used in next patches.
Re: [PATCH v8 03/11] net/failsafe: add fail-safe PMD
Quoted 8 lines · Thomas Monjalon
11/07/2017 23:48, Gaëtan Rivet:
Quoted 7 lines · Thomas Monjalon
Quoted 6 lines
11/07/2017 01:19, Gaetan Rivet:
Quoted 2 lines
drivers/net/failsafe/failsafe_args.c new file +0
-0[...]
Quoted 1 line
+#include <
errno.h>
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
Do you really need errno in this file?
It's used for error handling on strtoull and popen. Why, is it a problem to include
errno.h?I don't see errno used in this patch.
I think it is used in next patches.
Ah, yes, you're right, sorry.
Will fix, thanks.
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v8 4/11 net/failsafe: add plug-in support
In reply to Gaetan RivetPeriodically check for the existence of a device.
If a device has not been initialized and exists on the system, then it is probed and configured.
The configuration process strives to synchronize the states between the plugged-in sub-device and the fail-safe device.
--- doc/guides/nics/fail_safe.rst | 19 +++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 71 ++++++++++ drivers/net/failsafe/failsafe_args.c | 32 +++++ drivers/net/failsafe/failsafe_eal.c | 30 +---- drivers/net/failsafe/failsafe_ether.c | 228 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 25 ++-- drivers/net/failsafe/failsafe_private.h | 60 ++++++++- 8 files changed, 423 insertions(+), 43 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c
doc/guides/nics/fail_safe.rst +19 -0
@@ -102,6 +102,11 @@ Fail-safe command line parameters address is generated, that will be subsequently applied to all sub-device once they are probed. +- **hotplug_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two slave upkeep round. + Usage example ~~~~~~~~~~~~~
@@ -144,3 +149,17 @@ Care must be taken, however, to respect the **ether** API concerning device access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate over ethernet devices, instead of directly accessing them or by writing one's own device iterator. + +Plug-in feature +--------------- + +A sub-device can be defined without existing on the system when the fail-safe +PMD is initialized. Upon probing this device, the fail-safe PMD will detect its +absence and postpone its use. It will then register for a periodic check on any +missing sub-device. + +During this time, the fail-safe PMD can be used normally, configured and told to +emit and receive packets. It will store any applied configuration, and try to +apply it upon the probing of its missing sub-device. After this configuration +pass, the new sub-device will be synchronized with other sub-devices, i.e. be +started if the fail-safe PMD has been started by the user before.
drivers/net/failsafe/Makefile +1 -0
@@ -44,6 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c # No exported include files
drivers/net/failsafe/failsafe.c +71 -0
83 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c +32 -0
@@ -45,9 +45,11 @@typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params,uint8_t head); +uint64_t hotplug_poll;int mac_from_arg;const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ,PMD_FAILSAFE_MAC_KVARG ,NULL , };
@@ -221,6 +223,24 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) }static int +fs_get_u64_arg(const char *key __rte_unused, +const char *value,void *out) +{ +uint64_t *u64 = out; +char *endptr =NULL ; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + errno =0 ; + *u64 =strtoull (value, &endptr,0 ); +if (errno !=0 ) +return -errno; +if (endptr == value) +return -1 ; +return 0 ; +} + +static int fs_get_mac_addr_arg(const char *key __rte_unused,const char *value,void *out) {
@@ -252,6 +272,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret =0 ; priv->subs_tx =FAILSAFE_MAX_ETHPORTS ;/* default parameters */ + hotplug_poll =FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS ; mac_from_arg =0 ; n =snprintf (mut_params,sizeof (mut_params),"%s" , params);if (n >=sizeof (mut_params)) {
@@ -274,6 +295,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING);return -1 ; } +/* PLUG_IN event poll timer */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG , + &fs_get_u64_arg, &hotplug_poll); +if (ret <0 ) + goto free_kvlist; + }/* MAC addr */ arg_count =rte_kvargs_count (kvlist,PMD_FAILSAFE_MAC_KVARG );
@@ -287,6 +318,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) mac_from_arg =1 ; } } +PRIV (dev)->state =DEV_PARSED ; free_kvlist:rte_kvargs_free (kvlist);return ret;
drivers/net/failsafe/failsafe_eal.c +4 -26
@@ -72,37 +72,14 @@ fs_bus_init(struct rte_eth_dev *dev)int failsafe_eal_init (struct rte_eth_dev *dev) { -struct sub_device *sdev; -uint8_t i;int ret; ret =fs_bus_init (dev);if (ret)return ret; -/* -* We only update TX_SUBDEV if we are not started. -* If a sub_device is emitting, we will switch the TX_SUBDEV to the -* preferred port only upon starting it, so that the switch is smoother. -*/ -if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && - (TX_SUBDEV (dev) ==NULL || - (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || -TX_SUBDEV (dev) ==NULL ) { -/* Using first probed device */ - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { -DEBUG ("Switching tx_dev to sub_device %d" , - i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_PROBED ) +PRIV (dev)->state =DEV_PROBED ; +fs_switch_dev (dev);return 0 ; }
@@ -134,5 +111,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret =fs_bus_uninit (dev);if (ret)return ret; +PRIV (dev)->state =DEV_PROBED -1 ;return 0 ; }
drivers/net/failsafe/failsafe_ether.c new file +228 -0
228 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +10 -15
@@ -89,6 +89,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } sdev->state =DEV_ACTIVE ; } +if (PRIV (dev)->state <DEV_ACTIVE ) +PRIV (dev)->state =DEV_ACTIVE ;return 0 ; }
@@ -108,21 +110,9 @@ fs_dev_start(struct rte_eth_dev *dev)return ret; sdev->state =DEV_STARTED ; } -if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || -TX_SUBDEV (dev) ==NULL ) { - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { -DEBUG ("Switching tx_dev to sub_device %d" , i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_STARTED ) +PRIV (dev)->state =DEV_STARTED ; +fs_switch_dev (dev);return 0 ; }
@@ -132,6 +122,7 @@ fs_dev_stop(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +PRIV (dev)->state =DEV_STARTED -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) {rte_eth_dev_stop (PORT_ID (sdev)); sdev->state =DEV_STARTED -1 ;
@@ -183,6 +174,10 @@ fs_dev_close(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +failsafe_hotplug_alarm_cancel (dev); +if (PRIV (dev)->state ==DEV_STARTED ) + dev->dev_ops->dev_stop (dev); +PRIV (dev)->state =DEV_ACTIVE -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {DEBUG ("Closing sub_device %d" , i);rte_eth_dev_close (PORT_ID (sdev));
drivers/net/failsafe/failsafe_private.h +58 -2
92 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v8 5/11 net/failsafe: add flexible device definition
In reply to Gaetan RivetAdd the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.
That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 99 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 130 insertions(+)
doc/guides/nics/fail_safe.rst +20 -0
@@ -91,6 +91,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
@@ -139,6 +152,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i + Using the Fail-safe PMD from an application -------------------------------------------
drivers/net/failsafe/failsafe_args.c +99 -0
126 lines not on this page · raw message
drivers/net/failsafe/failsafe_ether.c +7 -0
@@ -188,6 +188,13 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)int ret;uint8_t i; +if (PRIV (dev)->state <DEV_PARSED ) +return 0 ; + + ret =failsafe_args_parse_subs (dev); +if (ret) +return ret; +if (PRIV (dev)->state <DEV_PROBED )return 0 ; ret =failsafe_eal_init (dev);
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -44,6 +44,7 @@#define PMD_FAILSAFE_PLUG_IN_POLL_KVARG "hotplug_poll"#define PMD_FAILSAFE_PARAM_STRING \ "dev(<ifc>)," \ + "exec(<shell command>)," \ "mac=mac_addr," \ "hotplug_poll=u64" \ ""
@@ -87,6 +88,8 @@ struct sub_device {struct rte_eth_dev *edev;/* Device state machine */ enum dev_state state; +/* Some device are defined as a command line */ +char *cmdline; };struct fs_priv {
@@ -135,6 +138,7 @@ uint16_t failsafe_tx_burst(void *txq,int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);void failsafe_args_free (struct rte_eth_dev *dev);int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); +int failsafe_args_parse_subs (struct rte_eth_dev *dev);/* EAL */
Signature · 1 line
2.1.4
PATCH v8 6/11 net/failsafe: support flow API
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 216 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 337 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c
doc/guides/nics/features/failsafe.ini +1 -0
@@ -13,6 +13,7 @@ Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/Makefile +1 -0
@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files
drivers/net/failsafe/failsafe.c +1 -0
@@ -177,6 +177,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; dev->data->dev_link = eth_link;PRIV (dev)->nb_mac_addr =1 ; +TAILQ_INIT (&PRIV (dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;if (params ==NULL ) {
drivers/net/failsafe/failsafe_eal.c +1 -0
@@ -62,6 +62,7 @@ fs_bus_init(struct rte_eth_dev *dev)ERROR ("sub_device %d init went wrong" , i);return -ENODEV ; } +SUB_ID (sdev) = i; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
drivers/net/failsafe/failsafe_ether.c +70 -0
90 lines not on this page · raw message
drivers/net/failsafe/failsafe_flow.c new file +216 -0
216 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +29 -0
@@ -35,6 +35,7 @@#include <stdint.h> #include <rte_ethdev.h> #include <rte_malloc.h> +#include <rte_flow.h> #include "failsafe_private.h"
@@ -628,6 +629,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); } +static int +fs_filter_ctrl (struct rte_eth_dev *dev, +enum rte_filter_type type, +enum rte_filter_op op, +void *arg) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + +if (type ==RTE_ETH_FILTER_GENERIC && + op ==RTE_ETH_FILTER_GET ) { + *(const void **)arg = &fs_flow_ops; +return 0 ; + } + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_filter_ctrl on sub_device %d" , i); + ret =rte_eth_dev_filter_ctrl (PORT_ID (sdev), type, op, arg); +if (ret) { +ERROR ("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} +const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start,
@@ -655,4 +683,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, };
drivers/net/failsafe/failsafe_private.h +18 -0
@@ -34,6 +34,8 @@#ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_#define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include <sys/queue.h> +#include <rte_dev.h> #include <rte_ethdev.h> #include <rte_devargs.h>
@@ -72,6 +74,14 @@ struct txq {struct rte_eth_txq_info info; }; +struct rte_flow { +TAILQ_ENTRY (rte_flow) next; +/* sub_flows */ +struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS ]; +/* flow description for synchronization */ +struct rte_flow_desc *fd; +}; +enum dev_state {DEV_UNDEFINED =0 ,DEV_PARSED ,
@@ -86,6 +96,7 @@ struct sub_device {struct rte_bus *bus;struct rte_device *dev;struct rte_eth_dev *edev; +uint8_t sid;/* Device state machine */ enum dev_state state;/* Some device are defined as a command line */
@@ -104,6 +115,8 @@ struct fs_priv {uint8_t subs_tail;/* first invalid */ uint8_t subs_tx;/* current emitting device */ uint8_t current_probed; +/* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list;/* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr;struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ];
@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);extern const char pmd_failsafe_driver_name[];extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops;extern uint64_t hotplug_poll;extern int mac_from_arg;
@@ -170,6 +184,10 @@ extern int mac_from_arg;#define PORT_ID (sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID (sdev) \ + ((sdev)->sid) +/** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator
Signature · 1 line
2.1.4
PATCH v8 7/11 net/failsafe: support offload capabilities
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)
doc/guides/nics/features/failsafe.ini +6 -0
@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/failsafe_ops.c +129 -2
151 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v8 8/11 net/failsafe: add fast burst functions
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_private.h | 8 +++ drivers/net/failsafe/failsafe_rxtx.c | 124 ++++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 20 deletions(-)
drivers/net/failsafe/failsafe_private.h +8 -0
@@ -141,11 +141,18 @@ int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);/* RX / TX */ +void set_burst_fn (struct rte_eth_dev *dev,int force_safe); +uint16_t failsafe_rx_burst (void *rxq,struct rte_mbuf **rx_pkts,uint16_t nb_pkts);uint16_t failsafe_tx_burst (void *txq,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +uint16_t failsafe_rx_burst_fast (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst_fast (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +/* ARGS */ int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);
@@ -299,6 +306,7 @@ fs_switch_dev(struct rte_eth_dev *dev) }else {return ; } +set_burst_fn (dev,0 );rte_wmb (); }
drivers/net/failsafe/failsafe_rxtx.c +104 -20
154 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v8 9/11 net/failsafe: support device removal
In reply to Gaetan RivetListen to INTR_RMV events issued by slaves.
Add atomic flags on slave queues to detect use of slave bursts function. If a removal is detected, set the recollection flag on this slave.
During a slave upkeep round, if its recollection flag is set and its burst functions are not in use by any thread, remove that slave.
--- doc/guides/nics/fail_safe.rst | 14 +++++ drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_args.c | 13 +++++ drivers/net/failsafe/failsafe_eal.c | 3 +- drivers/net/failsafe/failsafe_ether.c | 96 ++++++++++++++++++++++++++++++--- drivers/net/failsafe/failsafe_ops.c | 38 +++++++++++-- drivers/net/failsafe/failsafe_private.h | 72 ++++++++++++++++++++++--- drivers/net/failsafe/failsafe_rxtx.c | 17 +++++- 8 files changed, 234 insertions(+), 20 deletions(-)
doc/guides/nics/fail_safe.rst +14 -0
@@ -51,6 +51,12 @@ The Fail-safe PMD only supports a limited set of features. If you plan to use a device underneath the Fail-safe PMD with a specific feature, this feature must be supported by the Fail-safe PMD to avoid throwing any error. +A notable exception is the device removal feature. The fail-safe PMD being a +virtual device, it cannot currently be removed in the sense of a specific bus +hotplug, like for PCI for example. It will however enable this feature for its +sub-device automatically, detecting those that are capable and register the +relevant callback for such event. + Check the feature matrix for the complete set of supported features. Compilation options
@@ -183,3 +189,11 @@ emit and receive packets. It will store any applied configuration, and try to apply it upon the probing of its missing sub-device. After this configuration pass, the new sub-device will be synchronized with other sub-devices, i.e. be started if the fail-safe PMD has been started by the user before. + +Plug-out feature +---------------- + +A sub-device supporting the device removal event can be removed from its bus at +any time. The fail-safe PMD will register a callback for such event and react +accordingly. It will try to safely stop, close and uninit the sub-device having +emitted this event, allowing it to free its eventual resources.
drivers/net/failsafe/failsafe.c +1 -0
@@ -132,6 +132,7 @@ fs_hotplug_alarm(void *arg)if (!PRIV (dev)->pending_alarm)return ;PRIV (dev)->pending_alarm =0 ; +failsafe_dev_remove (dev); FOREACH_SUBDEV(sdev, i, dev)if (sdev->state !=PRIV (dev)->state)break ;
drivers/net/failsafe/failsafe_args.c +13 -0
@@ -443,6 +443,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device (struct sub_device *sdev) +{ +struct rte_devargs *da; +char devstr[DEVARGS_MAXLEN ] ="" ; + + da = &sdev->devargs; +snprintf (devstr,sizeof (devstr),"%s,%s" , da->name, da->args); +return fs_parse_device (sdev, devstr); +} +int failsafe_args_parse_subs (struct rte_eth_dev *dev) {
@@ -455,6 +466,8 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev)continue ;if (sdev->cmdline) ret =fs_execute_cmd (sdev, sdev->cmdline); +else + ret =fs_parse_sub_device (sdev);if (ret ==0 ) sdev->state =DEV_PARSED ; }
drivers/net/failsafe/failsafe_eal.c +2 -1
@@ -63,6 +63,7 @@ fs_bus_init(struct rte_eth_dev *dev)return -ENODEV ; }SUB_ID (sdev) = i; + sdev->fs_dev = dev; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
@@ -80,7 +81,7 @@ failsafe_eal_init(struct rte_eth_dev *dev)return ret;if (PRIV (dev)->state <DEV_PROBED )PRIV (dev)->state =DEV_PROBED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
drivers/net/failsafe/failsafe_ether.c +90 -6
130 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +35 -3
@@ -33,6 +33,8 @@#include <assert.h> #include <stdint.h> + +#include <rte_atomic.h> #include <rte_ethdev.h> #include <rte_malloc.h> #include <rte_flow.h>
@@ -204,9 +206,21 @@ fs_dev_configure(struct rte_eth_dev *dev) } } FOREACH_SUBDEV(sdev, i, dev) { +int rmv_interrupt =0 ; +if (sdev->state !=DEV_PROBED )continue ; + + rmv_interrupt =ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_RMV ; +if (rmv_interrupt) { +DEBUG ("Enabling RMV interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.rmv =1 ; + }else { +DEBUG ("sub_device %d does not support RMV event" , i); + }DEBUG ("Configuring sub-device %d" , i); + sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues,
@@ -215,6 +229,16 @@ fs_dev_configure(struct rte_eth_dev *dev)ERROR ("Could not configure sub_device %d" , i);return ret; } +if (rmv_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_RMV , + failsafe_eth_rmv_event_callback, + sdev); +if (ret) +WARN ("Failed to register RMV callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.rmv =0 ; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
@@ -240,7 +264,7 @@ fs_dev_start(struct rte_eth_dev *dev) }if (PRIV (dev)->state <DEV_STARTED )PRIV (dev)->state =DEV_STARTED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
@@ -351,10 +375,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,fs_rx_queue_release (rxq); dev->data->rx_queues[rx_queue_id] =NULL ; } - rxq =rte_zmalloc (NULL ,sizeof (*rxq), + rxq =rte_zmalloc (NULL , +sizeof (*rxq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (rxq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&rxq->refcnt[i]); rxq->qid = rx_queue_id; rxq->socket_id = socket_id; rxq->info.mp = mb_pool;
@@ -414,10 +442,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,fs_tx_queue_release (txq); dev->data->tx_queues[tx_queue_id] =NULL ; } - txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), + txq =rte_zmalloc ("ethdev TX queue" , +sizeof (*txq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (txq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&txq->refcnt[i]); txq->qid = tx_queue_id; txq->socket_id = socket_id; txq->info.conf = *tx_conf;
drivers/net/failsafe/failsafe_private.h +64 -8
133 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c +15 -2
@@ -33,6 +33,7 @@#include <assert.h> +#include <rte_atomic.h> #include <rte_mbuf.h> #include <rte_ethdev.h>
@@ -113,8 +114,10 @@ failsafe_rx_burst(void *queue,if (unlikely (fs_rx_unsafe (sdev)))continue ; sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -147,8 +150,10 @@ failsafe_rx_burst_fast(void *queue, sdev = &priv->subs[i];assert (!fs_rx_unsafe (sdev)); sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -165,13 +170,17 @@ failsafe_tx_burst(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);if (unlikely (fs_tx_unsafe (sdev)))return 0 ; sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }uint16_t
@@ -182,10 +191,14 @@ failsafe_tx_burst_fast(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);assert (!fs_tx_unsafe (sdev)); sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }
Signature · 1 line
2.1.4
PATCH v8 10/11 net/failsafe: support link status change event
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_ether.c | 18 ++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 23 +++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 3 +++ 5 files changed, 46 insertions(+)
doc/guides/nics/features/failsafe.ini +1 -0
@@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y
drivers/net/failsafe/failsafe.c +1 -0
@@ -240,6 +240,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) mac->addr_bytes[0 ], mac->addr_bytes[1 ], mac->addr_bytes[2 ], mac->addr_bytes[3 ], mac->addr_bytes[4], mac->addr_bytes[5]); + dev->data->dev_flags |=RTE_ETH_DEV_INTR_LSC ;return 0 ; free_args:failsafe_args_free (dev);
drivers/net/failsafe/failsafe_ether.c +18 -0
@@ -387,3 +387,21 @@ failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, sdev->remove =1 ;return 0 ; } + +int +failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, + enum rte_eth_event_type event __rte_unused, + void *cb_arg, void *out __rte_unused) +{ +struct rte_eth_dev *dev = cb_arg; +int ret; + + ret = dev->dev_ops->link_update (dev,0 ); +/* We must pass on the LSC event */ +if (ret) +return _rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC , +NULL ,NULL ); +else +return 0 ; +}
drivers/net/failsafe/failsafe_ops.c +23 -0
@@ -207,6 +207,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } FOREACH_SUBDEV(sdev, i, dev) {int rmv_interrupt =0 ; +int lsc_interrupt =0 ; +int lsc_enabled;if (sdev->state !=DEV_PROBED )continue ;
@@ -219,6 +221,17 @@ fs_dev_configure(struct rte_eth_dev *dev) }else {DEBUG ("sub_device %d does not support RMV event" , i); } + lsc_enabled = dev->data->dev_conf.intr_conf.lsc; + lsc_interrupt = lsc_enabled && + (ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_LSC ); +if (lsc_interrupt) { +DEBUG ("Enabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =1 ; + }else if (lsc_enabled && !lsc_interrupt) { +DEBUG ("Disabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =0 ; + }DEBUG ("Configuring sub-device %d" , i); sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev),
@@ -239,6 +252,16 @@ fs_dev_configure(struct rte_eth_dev *dev) SUB_ID(sdev)); } dev->data->dev_conf.intr_conf.rmv =0 ; +if (lsc_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_LSC , + failsafe_eth_lsc_event_callback, + dev); +if (ret) +WARN ("Failed to register LSC callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.lsc = lsc_enabled; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
drivers/net/failsafe/failsafe_private.h +3 -0
@@ -179,6 +179,9 @@ void failsafe_dev_remove(struct rte_eth_dev *dev);int failsafe_eth_rmv_event_callback (uint8_t port_id,enum rte_eth_event_type type,void *arg,void *out); +int failsafe_eth_lsc_event_callback (uint8_t port_id, +enum rte_eth_event_type event, +void *cb_arg,void *out);/* GLOBALS */
Signature · 1 line
2.1.4
PATCH v8 11/11 net/failsafe: support flow API isolation mode
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ether.c | 34 +++++++++++++++++++++++++++++++-- drivers/net/failsafe/failsafe_flow.c | 29 ++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ether.c +32 -2
@@ -74,6 +74,28 @@ fs_flow_complain(struct rte_flow_error *error) }static int +eth_dev_flow_isolate_set (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_flow_error ferror; +int ret; + +if (!PRIV (dev)->flow_isolated) { +DEBUG ("Flow isolation already disabled" ); + }else { +DEBUG ("Enabling flow isolation" ); + ret =rte_flow_isolate (PORT_ID (sdev), +PRIV (dev)->flow_isolated, + &ferror); +if (ret) { +fs_flow_complain (&ferror); +return ret; + } + } +return 0 ; +} + +static int fs_eth_dev_conf_apply (struct rte_eth_dev *dev,struct sub_device *sdev) {
@@ -334,9 +356,17 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)if (PRIV (dev)->state <DEV_ACTIVE )return 0 ; inactive =0 ; - FOREACH_SUBDEV(sdev, i, dev) -if (sdev->state ==DEV_PROBED ) + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state ==DEV_PROBED ) { inactive |=UINT32_C (1 ) << i; + ret =eth_dev_flow_isolate_set (dev, sdev); +if (ret) { +ERROR ("Could not apply configuration to sub_device %d" , + i); + goto err_remove; + } + } + } ret = dev->dev_ops->dev_configure (dev);if (ret) goto err_remove;
drivers/net/failsafe/failsafe_flow.c +29 -0
@@ -207,10 +207,39 @@ fs_flow_query(struct rte_eth_dev *dev,return -1 ; } +static int +fs_flow_isolate (struct rte_eth_dev *dev, +int set, +struct rte_flow_error *error) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state <DEV_PROBED ) +continue ; +DEBUG ("Calling rte_flow_isolate on sub_device %d" , i); +if (PRIV (dev)->flow_isolated != sdev->flow_isolated) +WARN ("flow isolation mode of sub_device %d in incoherent state." , + i); + ret =rte_flow_isolate (PORT_ID (sdev), set, error); +if (ret) { +ERROR ("Operation rte_flow_isolate failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + sdev->flow_isolated = set; + } +PRIV (dev)->flow_isolated = set; +return 0 ; +} +const struct rte_flow_ops fs_flow_ops = { .validate = fs_flow_validate, .create = fs_flow_create, .destroy = fs_flow_destroy, .flush = fs_flow_flush, .query = fs_flow_query, + .isolate = fs_flow_isolate, };
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -108,6 +108,8 @@ struct sub_device {struct rte_eth_dev *fs_dev;/* flag calling for recollection */ volatile unsigned int remove:1; +/* flow isolation state */ + int flow_isolated:1; };struct fs_priv {
@@ -139,6 +141,8 @@ struct fs_priv {*/ enum dev_state state; unsigned int pending_alarm:1; /* An alarm is pending */ +/* flow isolation state */ + int flow_isolated:1; };/* MISC */
Signature · 1 line
2.1.4
v9 cover introduce fail-safe PMD
In reply to Gaetan RivetThis PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
eal: complete attach / detach support
http://dpdk.org/ml/archives/dev/2017-May/066366.html
http://dpdk.org/dev/patchwork/patch/24522/
ethdev: add flow API rule copy function
http://dpdk.org/ml/archives/dev/2017-May/066145.html
http://dpdk.org/dev/patchwork/patch/24406/
ethdev: add isolated mode to flow API
http://dpdk.org/ml/archives/dev/2017-April/064327.html
http://dpdk.org/dev/patchwork/patch/23741/
v1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixes
v2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.
v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports plugin
v4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fix rte_dev hotplug API implementation.
- Introduce rte_eal_devargs_rmv API as EXPERIMENTAL.
- Use it to clean up resources on hotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.
This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.
These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Use rte_eth_dev_allocated when relevant.
v8 --> v9
- Use calloc instead of rte_realloc for command line parsing.
- Include errno only when necessary.
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/fail_safe.rst | 199 +++++ doc/guides/nics/features/failsafe.ini | 32 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 78 ++ drivers/net/failsafe/failsafe.c | 305 ++++++++ drivers/net/failsafe/failsafe_args.c | 472 ++++++++++++ drivers/net/failsafe/failsafe_eal.c | 118 +++ drivers/net/failsafe/failsafe_ether.c | 437 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 245 ++++++ drivers/net/failsafe/failsafe_ops.c | 869 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 376 ++++++++++ drivers/net/failsafe/failsafe_rxtx.c | 204 +++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + lib/librte_ether/rte_ethdev.c | 19 +- lib/librte_ether/rte_ethdev.h | 14 +- mk/rte.app.mk | 1 + 19 files changed, 3372 insertions(+), 15 deletions(-) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ether.c create mode 100644 drivers/net/failsafe/failsafe_flow.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
Signature · 1 line
2.1.4
PATCH v9 1/11 ethdev: add deferred intermediate device state
This device state means that the device is managed externally, by whichever party has set this state (PMD or application).
Note: this new device state is only an information. The related device structure and operators are still valid and can be used normally.
It is however made private by device management helpers within ethdev, making the device invisible to applications.
--- lib/librte_ether/rte_ethdev.c | 3 ++- lib/librte_ether/rte_ethdev.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
lib/librte_ether/rte_ethdev.c +2 -1
@@ -291,7 +291,8 @@ int rte_eth_dev_is_valid_port(uint8_t port_id) {if (port_id >=RTE_MAX_ETHPORTS || - rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED ) + (rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED && + rte_eth_devices[port_id].state !=RTE_ETH_DEV_DEFERRED ))return 0 ;else return 1 ;
lib/librte_ether/rte_ethdev.h +1 -0
@@ -1607,6 +1607,7 @@ struct rte_eth_rxtx_callback {enum rte_eth_dev_state {RTE_ETH_DEV_UNUSED =0 ,RTE_ETH_DEV_ATTACHED , +RTE_ETH_DEV_DEFERRED , };/**
Signature · 1 line
2.1.4
PATCH v9 2/11 ethdev: count devices consistently
In reply to Gaetan RivetMake the rte_eth_dev_count() return the number of available devices even after some are detached by the hotplug API or put in a deferred state.
--- lib/librte_ether/rte_ethdev.c | 16 +++++++++------- lib/librte_ether/rte_ethdev.h | 13 ++++++------- 2 files changed, 15 insertions(+), 14 deletions(-)
lib/librte_ether/rte_ethdev.c +9 -7
@@ -72,7 +72,6 @@ static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS ];static struct rte_eth_dev_data *rte_eth_dev_data;static uint8_t eth_dev_last_created_port; -static uint8_t nb_ports;/* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock =RTE_SPINLOCK_INITIALIZER ;
@@ -210,7 +209,6 @@ eth_dev_get(uint8_t port_id)TAILQ_INIT (&(eth_dev->link_intr_cbs)); eth_dev_last_created_port = port_id; - nb_ports++;return eth_dev; }
@@ -283,7 +281,6 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)return -EINVAL ; eth_dev->state =RTE_ETH_DEV_UNUSED ; - nb_ports--;return 0 ; }
@@ -308,7 +305,15 @@ rte_eth_dev_socket_id(uint8_t port_id)uint8_t rte_eth_dev_count (void ) { -return nb_ports; +uint8_t p; +uint8_t count; + + count =0 ; + +RTE_ETH_FOREACH_DEV (p) + count++; + +return count; }int
@@ -341,9 +346,6 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id)return -EINVAL ; } -if (!nb_ports) -return -ENODEV ; -RTE_ETH_FOREACH_DEV (i) {if (!rte_eth_devices[i].device)continue ;
lib/librte_ether/rte_ethdev.h +6 -7
@@ -1742,13 +1742,12 @@ uint8_t rte_eth_find_next(uint8_t port_id);/** * Get the total number of Ethernet devices that have been successfully -* initialized by the [matching] Ethernet driver during the PCI probing phase. -* All devices whose port identifier is in the range -* [0, rte_eth_dev_count() - 1] can be operated on by network applications -* immediately after invoking rte_eal_init(). -* If the application unplugs a port using hotplug function, The enabled port -* numbers may be noncontiguous. In the case, the applications need to manage -* enabled port by using the ``RTE_ETH_FOREACH_DEV()`` macro. +* initialized by the matching Ethernet driver during the PCI probing phase +* and that are available for applications to use. These devices must be +* accessed by using the ``RTE_ETH_FOREACH_DEV()`` macro to deal with +* non-contiguous ranges of devices. +* These non-contiguous ranges can be created by calls to hotplug functions or +* by some PMDs. * * @return * - The total number of usable Ethernet devices.
Signature · 1 line
2.1.4
PATCH v9 3/11 net/failsafe: add fail-safe PMD
In reply to Gaetan RivetIntroduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
--- MAINTAINERS | 5 + config/common_base | 6 + doc/guides/nics/fail_safe.rst | 146 +++++ doc/guides/nics/features/failsafe.ini | 24 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 76 +++ drivers/net/failsafe/failsafe.c | 231 ++++++++ drivers/net/failsafe/failsafe_args.c | 331 +++++++++++ drivers/net/failsafe/failsafe_eal.c | 138 +++++ drivers/net/failsafe/failsafe_ops.c | 663 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 227 ++++++++ drivers/net/failsafe/failsafe_rxtx.c | 107 ++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + mk/rte.app.mk | 1 + 15 files changed, 1962 insertions(+) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
MAINTAINERS +5 -0
@@ -336,6 +336,11 @@ F: drivers/net/enic/ F: doc/guides/nics/enic.rst F: doc/guides/nics/features/enic.ini +Fail-safe PMD +M: Gaetan Rivet <[email protected]> +F: drivers/net/failsafe/ +F: doc/guides/nics/fail_safe.rst + Intel e1000 M: Wenzhuo Lu <[email protected]> F: drivers/net/e1000/
config/common_base +6 -0
@@ -420,6 +420,12 @@ CONFIG_RTE_LIBRTE_PMD_XENVIRT=n CONFIG_RTE_LIBRTE_PMD_NULL=y # +# Compile fail-safe PMD +# +CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y +CONFIG_RTE_LIBRTE_PMD_FAILSAFE_DEBUG=n + +# # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y
doc/guides/nics/fail_safe.rst new file +146 -0
146 lines not on this page · raw message
doc/guides/nics/features/failsafe.ini new file +24 -0
@@ -0,0 +1,24 @@ +; +; Supported features of the 'fail-safe' poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status = Y +Queue start/stop = Y +MTU update = Y +Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +VLAN filter = Y +Packet type parsing = Y +Basic stats = Y +Stats per queue = Y +ARMv7 = Y +ARMv8 = Y +Power8 = Y +x86-32 = Y +x86-64 = Y +Usage doc = Y
doc/guides/nics/index.rst +1 -0
@@ -64,6 +64,7 @@ Network Interface Controller Drivers vhost vmxnet3 pcap_ring + fail_safe **Figures**
drivers/net/Makefile +2 -0
@@ -59,6 +59,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena DEPDIRS-ena = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DEPDIRS-enic = $(core-libs) librte_hash +DIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe +DEPDIRS-failsafe = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DEPDIRS-fm10k = $(core-libs) librte_hash DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e
drivers/net/failsafe/Makefile new file +76 -0
76 lines not on this page · raw message
drivers/net/failsafe/failsafe.c new file +231 -0
231 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c new file +331 -0
331 lines not on this page · raw message
drivers/net/failsafe/failsafe_eal.c new file +138 -0
138 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c new file +663 -0
663 lines not on this page · raw message
drivers/net/failsafe/failsafe_private.h new file +227 -0
227 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c new file +107 -0
107 lines not on this page · raw message
drivers/net/failsafe/rte_pmd_failsafe_version.map new file +4 -0
@@ -0,0 +1,4 @@ +DPDK_17.08 { + + local: *; +};
mk/rte.app.mk +1 -0
@@ -121,6 +121,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += -lrte_pmd_ena _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += -lrte_pmd_failsafe _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
Signature · 1 line
2.1.4
Re: [PATCH v9 03/11] net/failsafe: add fail-safe PMD
12/07/2017 01:26, Gaetan Rivet:
Quoted 2 lines
Introduce the fail-safe poll mode driver initialization and enable its build infrastructure.
There are some assert() in this code.
It does not compile:
fatal error: use of GNU statement expression extension
Please replace them with RTE_ASSERT (and remove assert.h includes). Thanks
PATCH v9 4/11 net/failsafe: add plug-in support
In reply to Gaetan RivetPeriodically check for the existence of a device.
If a device has not been initialized and exists on the system, then it is probed and configured.
The configuration process strives to synchronize the states between the plugged-in sub-device and the fail-safe device.
--- doc/guides/nics/fail_safe.rst | 19 +++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 71 ++++++++++ drivers/net/failsafe/failsafe_args.c | 33 +++++ drivers/net/failsafe/failsafe_eal.c | 30 +---- drivers/net/failsafe/failsafe_ether.c | 228 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 25 ++-- drivers/net/failsafe/failsafe_private.h | 60 ++++++++- 8 files changed, 424 insertions(+), 43 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c
doc/guides/nics/fail_safe.rst +19 -0
@@ -102,6 +102,11 @@ Fail-safe command line parameters address is generated, that will be subsequently applied to all sub-device once they are probed. +- **hotplug_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two slave upkeep round. + Usage example ~~~~~~~~~~~~~
@@ -144,3 +149,17 @@ Care must be taken, however, to respect the **ether** API concerning device access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate over ethernet devices, instead of directly accessing them or by writing one's own device iterator. + +Plug-in feature +--------------- + +A sub-device can be defined without existing on the system when the fail-safe +PMD is initialized. Upon probing this device, the fail-safe PMD will detect its +absence and postpone its use. It will then register for a periodic check on any +missing sub-device. + +During this time, the fail-safe PMD can be used normally, configured and told to +emit and receive packets. It will store any applied configuration, and try to +apply it upon the probing of its missing sub-device. After this configuration +pass, the new sub-device will be synchronized with other sub-devices, i.e. be +started if the fail-safe PMD has been started by the user before.
drivers/net/failsafe/Makefile +1 -0
@@ -44,6 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c # No exported include files
drivers/net/failsafe/failsafe.c +71 -0
83 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c +33 -0
@@ -32,6 +32,7 @@*/ #include <string.h> +#include <errno.h> #include <rte_devargs.h> #include <rte_malloc.h>
@@ -45,9 +46,11 @@typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params,uint8_t head); +uint64_t hotplug_poll;int mac_from_arg;const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ,PMD_FAILSAFE_MAC_KVARG ,NULL , };
@@ -221,6 +224,24 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) }static int +fs_get_u64_arg(const char *key __rte_unused, +const char *value,void *out) +{ +uint64_t *u64 = out; +char *endptr =NULL ; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + errno =0 ; + *u64 =strtoull (value, &endptr,0 ); +if (errno !=0 ) +return -errno; +if (endptr == value) +return -1 ; +return 0 ; +} + +static int fs_get_mac_addr_arg(const char *key __rte_unused,const char *value,void *out) {
@@ -252,6 +273,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret =0 ; priv->subs_tx =FAILSAFE_MAX_ETHPORTS ;/* default parameters */ + hotplug_poll =FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS ; mac_from_arg =0 ; n =snprintf (mut_params,sizeof (mut_params),"%s" , params);if (n >=sizeof (mut_params)) {
@@ -274,6 +296,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING);return -1 ; } +/* PLUG_IN event poll timer */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG , + &fs_get_u64_arg, &hotplug_poll); +if (ret <0 ) + goto free_kvlist; + }/* MAC addr */ arg_count =rte_kvargs_count (kvlist,PMD_FAILSAFE_MAC_KVARG );
@@ -287,6 +319,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) mac_from_arg =1 ; } } +PRIV (dev)->state =DEV_PARSED ; free_kvlist:rte_kvargs_free (kvlist);return ret;
drivers/net/failsafe/failsafe_eal.c +4 -26
@@ -72,37 +72,14 @@ fs_bus_init(struct rte_eth_dev *dev)int failsafe_eal_init (struct rte_eth_dev *dev) { -struct sub_device *sdev; -uint8_t i;int ret; ret =fs_bus_init (dev);if (ret)return ret; -/* -* We only update TX_SUBDEV if we are not started. -* If a sub_device is emitting, we will switch the TX_SUBDEV to the -* preferred port only upon starting it, so that the switch is smoother. -*/ -if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && - (TX_SUBDEV (dev) ==NULL || - (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || -TX_SUBDEV (dev) ==NULL ) { -/* Using first probed device */ - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { -DEBUG ("Switching tx_dev to sub_device %d" , - i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_PROBED ) +PRIV (dev)->state =DEV_PROBED ; +fs_switch_dev (dev);return 0 ; }
@@ -134,5 +111,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret =fs_bus_uninit (dev);if (ret)return ret; +PRIV (dev)->state =DEV_PROBED -1 ;return 0 ; }
drivers/net/failsafe/failsafe_ether.c new file +228 -0
228 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +10 -15
@@ -89,6 +89,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } sdev->state =DEV_ACTIVE ; } +if (PRIV (dev)->state <DEV_ACTIVE ) +PRIV (dev)->state =DEV_ACTIVE ;return 0 ; }
@@ -108,21 +110,9 @@ fs_dev_start(struct rte_eth_dev *dev)return ret; sdev->state =DEV_STARTED ; } -if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || -TX_SUBDEV (dev) ==NULL ) { - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { -DEBUG ("Switching tx_dev to sub_device %d" , i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_STARTED ) +PRIV (dev)->state =DEV_STARTED ; +fs_switch_dev (dev);return 0 ; }
@@ -132,6 +122,7 @@ fs_dev_stop(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +PRIV (dev)->state =DEV_STARTED -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) {rte_eth_dev_stop (PORT_ID (sdev)); sdev->state =DEV_STARTED -1 ;
@@ -183,6 +174,10 @@ fs_dev_close(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +failsafe_hotplug_alarm_cancel (dev); +if (PRIV (dev)->state ==DEV_STARTED ) + dev->dev_ops->dev_stop (dev); +PRIV (dev)->state =DEV_ACTIVE -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {DEBUG ("Closing sub_device %d" , i);rte_eth_dev_close (PORT_ID (sdev));
drivers/net/failsafe/failsafe_private.h +58 -2
92 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v9 5/11 net/failsafe: add flexible device definition
In reply to Gaetan RivetAdd the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.
That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 95 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 126 insertions(+)
doc/guides/nics/fail_safe.rst +20 -0
@@ -91,6 +91,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
@@ -139,6 +152,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i + Using the Fail-safe PMD from an application -------------------------------------------
drivers/net/failsafe/failsafe_args.c +95 -0
122 lines not on this page · raw message
drivers/net/failsafe/failsafe_ether.c +7 -0
@@ -188,6 +188,13 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)int ret;uint8_t i; +if (PRIV (dev)->state <DEV_PARSED ) +return 0 ; + + ret =failsafe_args_parse_subs (dev); +if (ret) +return ret; +if (PRIV (dev)->state <DEV_PROBED )return 0 ; ret =failsafe_eal_init (dev);
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -44,6 +44,7 @@#define PMD_FAILSAFE_PLUG_IN_POLL_KVARG "hotplug_poll"#define PMD_FAILSAFE_PARAM_STRING \ "dev(<ifc>)," \ + "exec(<shell command>)," \ "mac=mac_addr," \ "hotplug_poll=u64" \ ""
@@ -87,6 +88,8 @@ struct sub_device {struct rte_eth_dev *edev;/* Device state machine */ enum dev_state state; +/* Some device are defined as a command line */ +char *cmdline; };struct fs_priv {
@@ -135,6 +138,7 @@ uint16_t failsafe_tx_burst(void *txq,int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);void failsafe_args_free (struct rte_eth_dev *dev);int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); +int failsafe_args_parse_subs (struct rte_eth_dev *dev);/* EAL */
Signature · 1 line
2.1.4
PATCH v9 6/11 net/failsafe: support flow API
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 216 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 337 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c
doc/guides/nics/features/failsafe.ini +1 -0
@@ -13,6 +13,7 @@ Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/Makefile +1 -0
@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files
drivers/net/failsafe/failsafe.c +1 -0
@@ -177,6 +177,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; dev->data->dev_link = eth_link;PRIV (dev)->nb_mac_addr =1 ; +TAILQ_INIT (&PRIV (dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;if (params ==NULL ) {
drivers/net/failsafe/failsafe_eal.c +1 -0
@@ -62,6 +62,7 @@ fs_bus_init(struct rte_eth_dev *dev)ERROR ("sub_device %d init went wrong" , i);return -ENODEV ; } +SUB_ID (sdev) = i; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
drivers/net/failsafe/failsafe_ether.c +70 -0
90 lines not on this page · raw message
drivers/net/failsafe/failsafe_flow.c new file +216 -0
216 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +29 -0
@@ -35,6 +35,7 @@#include <stdint.h> #include <rte_ethdev.h> #include <rte_malloc.h> +#include <rte_flow.h> #include "failsafe_private.h"
@@ -628,6 +629,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); } +static int +fs_filter_ctrl (struct rte_eth_dev *dev, +enum rte_filter_type type, +enum rte_filter_op op, +void *arg) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + +if (type ==RTE_ETH_FILTER_GENERIC && + op ==RTE_ETH_FILTER_GET ) { + *(const void **)arg = &fs_flow_ops; +return 0 ; + } + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_filter_ctrl on sub_device %d" , i); + ret =rte_eth_dev_filter_ctrl (PORT_ID (sdev), type, op, arg); +if (ret) { +ERROR ("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} +const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start,
@@ -655,4 +683,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, };
drivers/net/failsafe/failsafe_private.h +18 -0
@@ -34,6 +34,8 @@#ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_#define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include <sys/queue.h> +#include <rte_dev.h> #include <rte_ethdev.h> #include <rte_devargs.h>
@@ -72,6 +74,14 @@ struct txq {struct rte_eth_txq_info info; }; +struct rte_flow { +TAILQ_ENTRY (rte_flow) next; +/* sub_flows */ +struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS ]; +/* flow description for synchronization */ +struct rte_flow_desc *fd; +}; +enum dev_state {DEV_UNDEFINED =0 ,DEV_PARSED ,
@@ -86,6 +96,7 @@ struct sub_device {struct rte_bus *bus;struct rte_device *dev;struct rte_eth_dev *edev; +uint8_t sid;/* Device state machine */ enum dev_state state;/* Some device are defined as a command line */
@@ -104,6 +115,8 @@ struct fs_priv {uint8_t subs_tail;/* first invalid */ uint8_t subs_tx;/* current emitting device */ uint8_t current_probed; +/* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list;/* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr;struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ];
@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);extern const char pmd_failsafe_driver_name[];extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops;extern uint64_t hotplug_poll;extern int mac_from_arg;
@@ -170,6 +184,10 @@ extern int mac_from_arg;#define PORT_ID (sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID (sdev) \ + ((sdev)->sid) +/** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator
Signature · 1 line
2.1.4
PATCH v9 7/11 net/failsafe: support offload capabilities
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)
doc/guides/nics/features/failsafe.ini +6 -0
@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/failsafe_ops.c +129 -2
151 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v9 8/11 net/failsafe: add fast burst functions
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_private.h | 8 +++ drivers/net/failsafe/failsafe_rxtx.c | 124 ++++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 20 deletions(-)
drivers/net/failsafe/failsafe_private.h +8 -0
@@ -141,11 +141,18 @@ int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);/* RX / TX */ +void set_burst_fn (struct rte_eth_dev *dev,int force_safe); +uint16_t failsafe_rx_burst (void *rxq,struct rte_mbuf **rx_pkts,uint16_t nb_pkts);uint16_t failsafe_tx_burst (void *txq,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +uint16_t failsafe_rx_burst_fast (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst_fast (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +/* ARGS */ int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);
@@ -299,6 +306,7 @@ fs_switch_dev(struct rte_eth_dev *dev) }else {return ; } +set_burst_fn (dev,0 );rte_wmb (); }
drivers/net/failsafe/failsafe_rxtx.c +104 -20
154 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v9 9/11 net/failsafe: support device removal
In reply to Gaetan RivetListen to INTR_RMV events issued by slaves.
Add atomic flags on slave queues to detect use of slave bursts function. If a removal is detected, set the recollection flag on this slave.
During a slave upkeep round, if its recollection flag is set and its burst functions are not in use by any thread, remove that slave.
--- doc/guides/nics/fail_safe.rst | 14 +++++ drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_args.c | 13 +++++ drivers/net/failsafe/failsafe_eal.c | 3 +- drivers/net/failsafe/failsafe_ether.c | 96 ++++++++++++++++++++++++++++++--- drivers/net/failsafe/failsafe_ops.c | 38 +++++++++++-- drivers/net/failsafe/failsafe_private.h | 72 ++++++++++++++++++++++--- drivers/net/failsafe/failsafe_rxtx.c | 17 +++++- 8 files changed, 234 insertions(+), 20 deletions(-)
doc/guides/nics/fail_safe.rst +14 -0
@@ -51,6 +51,12 @@ The Fail-safe PMD only supports a limited set of features. If you plan to use a device underneath the Fail-safe PMD with a specific feature, this feature must be supported by the Fail-safe PMD to avoid throwing any error. +A notable exception is the device removal feature. The fail-safe PMD being a +virtual device, it cannot currently be removed in the sense of a specific bus +hotplug, like for PCI for example. It will however enable this feature for its +sub-device automatically, detecting those that are capable and register the +relevant callback for such event. + Check the feature matrix for the complete set of supported features. Compilation options
@@ -183,3 +189,11 @@ emit and receive packets. It will store any applied configuration, and try to apply it upon the probing of its missing sub-device. After this configuration pass, the new sub-device will be synchronized with other sub-devices, i.e. be started if the fail-safe PMD has been started by the user before. + +Plug-out feature +---------------- + +A sub-device supporting the device removal event can be removed from its bus at +any time. The fail-safe PMD will register a callback for such event and react +accordingly. It will try to safely stop, close and uninit the sub-device having +emitted this event, allowing it to free its eventual resources.
drivers/net/failsafe/failsafe.c +1 -0
@@ -132,6 +132,7 @@ fs_hotplug_alarm(void *arg)if (!PRIV (dev)->pending_alarm)return ;PRIV (dev)->pending_alarm =0 ; +failsafe_dev_remove (dev); FOREACH_SUBDEV(sdev, i, dev)if (sdev->state !=PRIV (dev)->state)break ;
drivers/net/failsafe/failsafe_args.c +13 -0
@@ -440,6 +440,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device (struct sub_device *sdev) +{ +struct rte_devargs *da; +char devstr[DEVARGS_MAXLEN ] ="" ; + + da = &sdev->devargs; +snprintf (devstr,sizeof (devstr),"%s,%s" , da->name, da->args); +return fs_parse_device (sdev, devstr); +} +int failsafe_args_parse_subs (struct rte_eth_dev *dev) {
@@ -452,6 +463,8 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev)continue ;if (sdev->cmdline) ret =fs_execute_cmd (sdev, sdev->cmdline); +else + ret =fs_parse_sub_device (sdev);if (ret ==0 ) sdev->state =DEV_PARSED ; }
drivers/net/failsafe/failsafe_eal.c +2 -1
@@ -63,6 +63,7 @@ fs_bus_init(struct rte_eth_dev *dev)return -ENODEV ; }SUB_ID (sdev) = i; + sdev->fs_dev = dev; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
@@ -80,7 +81,7 @@ failsafe_eal_init(struct rte_eth_dev *dev)return ret;if (PRIV (dev)->state <DEV_PROBED )PRIV (dev)->state =DEV_PROBED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
drivers/net/failsafe/failsafe_ether.c +90 -6
130 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +35 -3
@@ -33,6 +33,8 @@#include <assert.h> #include <stdint.h> + +#include <rte_atomic.h> #include <rte_ethdev.h> #include <rte_malloc.h> #include <rte_flow.h>
@@ -204,9 +206,21 @@ fs_dev_configure(struct rte_eth_dev *dev) } } FOREACH_SUBDEV(sdev, i, dev) { +int rmv_interrupt =0 ; +if (sdev->state !=DEV_PROBED )continue ; + + rmv_interrupt =ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_RMV ; +if (rmv_interrupt) { +DEBUG ("Enabling RMV interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.rmv =1 ; + }else { +DEBUG ("sub_device %d does not support RMV event" , i); + }DEBUG ("Configuring sub-device %d" , i); + sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues,
@@ -215,6 +229,16 @@ fs_dev_configure(struct rte_eth_dev *dev)ERROR ("Could not configure sub_device %d" , i);return ret; } +if (rmv_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_RMV , + failsafe_eth_rmv_event_callback, + sdev); +if (ret) +WARN ("Failed to register RMV callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.rmv =0 ; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
@@ -240,7 +264,7 @@ fs_dev_start(struct rte_eth_dev *dev) }if (PRIV (dev)->state <DEV_STARTED )PRIV (dev)->state =DEV_STARTED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
@@ -351,10 +375,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,fs_rx_queue_release (rxq); dev->data->rx_queues[rx_queue_id] =NULL ; } - rxq =rte_zmalloc (NULL ,sizeof (*rxq), + rxq =rte_zmalloc (NULL , +sizeof (*rxq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (rxq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&rxq->refcnt[i]); rxq->qid = rx_queue_id; rxq->socket_id = socket_id; rxq->info.mp = mb_pool;
@@ -414,10 +442,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,fs_tx_queue_release (txq); dev->data->tx_queues[tx_queue_id] =NULL ; } - txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), + txq =rte_zmalloc ("ethdev TX queue" , +sizeof (*txq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (txq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&txq->refcnt[i]); txq->qid = tx_queue_id; txq->socket_id = socket_id; txq->info.conf = *tx_conf;
drivers/net/failsafe/failsafe_private.h +64 -8
133 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c +15 -2
@@ -33,6 +33,7 @@#include <assert.h> +#include <rte_atomic.h> #include <rte_mbuf.h> #include <rte_ethdev.h>
@@ -113,8 +114,10 @@ failsafe_rx_burst(void *queue,if (unlikely (fs_rx_unsafe (sdev)))continue ; sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -147,8 +150,10 @@ failsafe_rx_burst_fast(void *queue, sdev = &priv->subs[i];assert (!fs_rx_unsafe (sdev)); sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -165,13 +170,17 @@ failsafe_tx_burst(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);if (unlikely (fs_tx_unsafe (sdev)))return 0 ; sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }uint16_t
@@ -182,10 +191,14 @@ failsafe_tx_burst_fast(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);assert (!fs_tx_unsafe (sdev)); sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }
Signature · 1 line
2.1.4
PATCH v9 10/11 net/failsafe: support link status change event
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_ether.c | 18 ++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 23 +++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 3 +++ 5 files changed, 46 insertions(+)
doc/guides/nics/features/failsafe.ini +1 -0
@@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y
drivers/net/failsafe/failsafe.c +1 -0
@@ -240,6 +240,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) mac->addr_bytes[0 ], mac->addr_bytes[1 ], mac->addr_bytes[2 ], mac->addr_bytes[3 ], mac->addr_bytes[4], mac->addr_bytes[5]); + dev->data->dev_flags |=RTE_ETH_DEV_INTR_LSC ;return 0 ; free_args:failsafe_args_free (dev);
drivers/net/failsafe/failsafe_ether.c +18 -0
@@ -387,3 +387,21 @@ failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, sdev->remove =1 ;return 0 ; } + +int +failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, + enum rte_eth_event_type event __rte_unused, + void *cb_arg, void *out __rte_unused) +{ +struct rte_eth_dev *dev = cb_arg; +int ret; + + ret = dev->dev_ops->link_update (dev,0 ); +/* We must pass on the LSC event */ +if (ret) +return _rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC , +NULL ,NULL ); +else +return 0 ; +}
drivers/net/failsafe/failsafe_ops.c +23 -0
@@ -207,6 +207,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } FOREACH_SUBDEV(sdev, i, dev) {int rmv_interrupt =0 ; +int lsc_interrupt =0 ; +int lsc_enabled;if (sdev->state !=DEV_PROBED )continue ;
@@ -219,6 +221,17 @@ fs_dev_configure(struct rte_eth_dev *dev) }else {DEBUG ("sub_device %d does not support RMV event" , i); } + lsc_enabled = dev->data->dev_conf.intr_conf.lsc; + lsc_interrupt = lsc_enabled && + (ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_LSC ); +if (lsc_interrupt) { +DEBUG ("Enabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =1 ; + }else if (lsc_enabled && !lsc_interrupt) { +DEBUG ("Disabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =0 ; + }DEBUG ("Configuring sub-device %d" , i); sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev),
@@ -239,6 +252,16 @@ fs_dev_configure(struct rte_eth_dev *dev) SUB_ID(sdev)); } dev->data->dev_conf.intr_conf.rmv =0 ; +if (lsc_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_LSC , + failsafe_eth_lsc_event_callback, + dev); +if (ret) +WARN ("Failed to register LSC callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.lsc = lsc_enabled; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
drivers/net/failsafe/failsafe_private.h +3 -0
@@ -179,6 +179,9 @@ void failsafe_dev_remove(struct rte_eth_dev *dev);int failsafe_eth_rmv_event_callback (uint8_t port_id,enum rte_eth_event_type type,void *arg,void *out); +int failsafe_eth_lsc_event_callback (uint8_t port_id, +enum rte_eth_event_type event, +void *cb_arg,void *out);/* GLOBALS */
Signature · 1 line
2.1.4
PATCH v9 11/11 net/failsafe: support flow API isolation mode
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ether.c | 34 +++++++++++++++++++++++++++++++-- drivers/net/failsafe/failsafe_flow.c | 29 ++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ether.c +32 -2
@@ -74,6 +74,28 @@ fs_flow_complain(struct rte_flow_error *error) }static int +eth_dev_flow_isolate_set (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_flow_error ferror; +int ret; + +if (!PRIV (dev)->flow_isolated) { +DEBUG ("Flow isolation already disabled" ); + }else { +DEBUG ("Enabling flow isolation" ); + ret =rte_flow_isolate (PORT_ID (sdev), +PRIV (dev)->flow_isolated, + &ferror); +if (ret) { +fs_flow_complain (&ferror); +return ret; + } + } +return 0 ; +} + +static int fs_eth_dev_conf_apply (struct rte_eth_dev *dev,struct sub_device *sdev) {
@@ -334,9 +356,17 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)if (PRIV (dev)->state <DEV_ACTIVE )return 0 ; inactive =0 ; - FOREACH_SUBDEV(sdev, i, dev) -if (sdev->state ==DEV_PROBED ) + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state ==DEV_PROBED ) { inactive |=UINT32_C (1 ) << i; + ret =eth_dev_flow_isolate_set (dev, sdev); +if (ret) { +ERROR ("Could not apply configuration to sub_device %d" , + i); + goto err_remove; + } + } + } ret = dev->dev_ops->dev_configure (dev);if (ret) goto err_remove;
drivers/net/failsafe/failsafe_flow.c +29 -0
@@ -207,10 +207,39 @@ fs_flow_query(struct rte_eth_dev *dev,return -1 ; } +static int +fs_flow_isolate (struct rte_eth_dev *dev, +int set, +struct rte_flow_error *error) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state <DEV_PROBED ) +continue ; +DEBUG ("Calling rte_flow_isolate on sub_device %d" , i); +if (PRIV (dev)->flow_isolated != sdev->flow_isolated) +WARN ("flow isolation mode of sub_device %d in incoherent state." , + i); + ret =rte_flow_isolate (PORT_ID (sdev), set, error); +if (ret) { +ERROR ("Operation rte_flow_isolate failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + sdev->flow_isolated = set; + } +PRIV (dev)->flow_isolated = set; +return 0 ; +} +const struct rte_flow_ops fs_flow_ops = { .validate = fs_flow_validate, .create = fs_flow_create, .destroy = fs_flow_destroy, .flush = fs_flow_flush, .query = fs_flow_query, + .isolate = fs_flow_isolate, };
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -108,6 +108,8 @@ struct sub_device {struct rte_eth_dev *fs_dev;/* flag calling for recollection */ volatile unsigned int remove:1; +/* flow isolation state */ + int flow_isolated:1; };struct fs_priv {
@@ -139,6 +141,8 @@ struct fs_priv {*/ enum dev_state state; unsigned int pending_alarm:1; /* An alarm is pending */ +/* flow isolation state */ + int flow_isolated:1; };/* MISC */
Signature · 1 line
2.1.4
v10 cover introduce fail-safe PMD
In reply to Gaetan RivetThis PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
eal: complete attach / detach support
http://dpdk.org/ml/archives/dev/2017-May/066366.html
http://dpdk.org/dev/patchwork/patch/24522/
ethdev: add flow API rule copy function
http://dpdk.org/ml/archives/dev/2017-May/066145.html
http://dpdk.org/dev/patchwork/patch/24406/
ethdev: add isolated mode to flow API
http://dpdk.org/ml/archives/dev/2017-April/064327.html
http://dpdk.org/dev/patchwork/patch/23741/
v1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixes
v2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.
v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports plugin
v4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fix rte_dev hotplug API implementation.
- Introduce rte_eal_devargs_rmv API as EXPERIMENTAL.
- Use it to clean up resources on hotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.
This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.
These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Use rte_eth_dev_allocated when relevant.
v8 --> v9
- Use calloc instead of rte_realloc for command line parsing.
- Include errno only when necessary.
v9 --> v10
- Fix rte_flow description double-free issue. Thanks Raslan for finding the issue :)
- Use RTE_ASSERT instead of assert.
Integrate the debug log of the fail-safe to RTE_LOG_DEBUG macro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
MAINTAINERS | 5 + config/common_base | 5 + doc/guides/nics/fail_safe.rst | 195 +++++ doc/guides/nics/features/failsafe.ini | 32 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 68 ++ drivers/net/failsafe/failsafe.c | 306 ++++++++ drivers/net/failsafe/failsafe_args.c | 472 ++++++++++++ drivers/net/failsafe/failsafe_eal.c | 118 +++ drivers/net/failsafe/failsafe_ether.c | 437 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 244 ++++++ drivers/net/failsafe/failsafe_ops.c | 869 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 359 +++++++++ drivers/net/failsafe/failsafe_rxtx.c | 203 +++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + lib/librte_ether/rte_ethdev.c | 19 +- lib/librte_ether/rte_ethdev.h | 14 +- mk/rte.app.mk | 1 + 19 files changed, 3339 insertions(+), 15 deletions(-) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ether.c create mode 100644 drivers/net/failsafe/failsafe_flow.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
Signature · 1 line
2.1.4
PATCH v10 1/11 ethdev: add deferred intermediate device state
This device state means that the device is managed externally, by whichever party has set this state (PMD or application).
Note: this new device state is only an information. The related device structure and operators are still valid and can be used normally.
It is however made private by device management helpers within ethdev, making the device invisible to applications.
--- lib/librte_ether/rte_ethdev.c | 3 ++- lib/librte_ether/rte_ethdev.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
lib/librte_ether/rte_ethdev.c +2 -1
@@ -291,7 +291,8 @@ int rte_eth_dev_is_valid_port(uint8_t port_id) {if (port_id >=RTE_MAX_ETHPORTS || - rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED ) + (rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED && + rte_eth_devices[port_id].state !=RTE_ETH_DEV_DEFERRED ))return 0 ;else return 1 ;
lib/librte_ether/rte_ethdev.h +1 -0
@@ -1613,6 +1613,7 @@ struct rte_eth_rxtx_callback {enum rte_eth_dev_state {RTE_ETH_DEV_UNUSED =0 ,RTE_ETH_DEV_ATTACHED , +RTE_ETH_DEV_DEFERRED , };/**
Signature · 1 line
2.1.4
PATCH v10 2/11 ethdev: count devices consistently
In reply to Gaetan RivetMake the rte_eth_dev_count() return the number of available devices even after some are detached by the hotplug API or put in a deferred state.
--- lib/librte_ether/rte_ethdev.c | 16 +++++++++------- lib/librte_ether/rte_ethdev.h | 13 ++++++------- 2 files changed, 15 insertions(+), 14 deletions(-)
lib/librte_ether/rte_ethdev.c +9 -7
@@ -72,7 +72,6 @@ static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS ];static struct rte_eth_dev_data *rte_eth_dev_data;static uint8_t eth_dev_last_created_port; -static uint8_t nb_ports;/* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock =RTE_SPINLOCK_INITIALIZER ;
@@ -210,7 +209,6 @@ eth_dev_get(uint8_t port_id)TAILQ_INIT (&(eth_dev->link_intr_cbs)); eth_dev_last_created_port = port_id; - nb_ports++;return eth_dev; }
@@ -283,7 +281,6 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)return -EINVAL ; eth_dev->state =RTE_ETH_DEV_UNUSED ; - nb_ports--;return 0 ; }
@@ -308,7 +305,15 @@ rte_eth_dev_socket_id(uint8_t port_id)uint8_t rte_eth_dev_count (void ) { -return nb_ports; +uint8_t p; +uint8_t count; + + count =0 ; + +RTE_ETH_FOREACH_DEV (p) + count++; + +return count; }int
@@ -341,9 +346,6 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id)return -EINVAL ; } -if (!nb_ports) -return -ENODEV ; -RTE_ETH_FOREACH_DEV (i) {if (!rte_eth_devices[i].device)continue ;
lib/librte_ether/rte_ethdev.h +6 -7
@@ -1748,13 +1748,12 @@ uint8_t rte_eth_find_next(uint8_t port_id);/** * Get the total number of Ethernet devices that have been successfully -* initialized by the [matching] Ethernet driver during the PCI probing phase. -* All devices whose port identifier is in the range -* [0, rte_eth_dev_count() - 1] can be operated on by network applications -* immediately after invoking rte_eal_init(). -* If the application unplugs a port using hotplug function, The enabled port -* numbers may be noncontiguous. In the case, the applications need to manage -* enabled port by using the ``RTE_ETH_FOREACH_DEV()`` macro. +* initialized by the matching Ethernet driver during the PCI probing phase +* and that are available for applications to use. These devices must be +* accessed by using the ``RTE_ETH_FOREACH_DEV()`` macro to deal with +* non-contiguous ranges of devices. +* These non-contiguous ranges can be created by calls to hotplug functions or +* by some PMDs. * * @return * - The total number of usable Ethernet devices.
Signature · 1 line
2.1.4
Re: [PATCH v10 02/11] ethdev: count devices consistently
Quoted 4 lines · Gaetan Rivet
Make the
rte_eth_dev_count()return the number of available devices even after some are detached by the hotplug API or put in a deferred state.Signed-off-by Gaetan Rivet <[email protected]>
First two patches updates ethdev, I believe to get them via next-net, an explicit ACK required.
Thanks,
ferruh
PATCH v10 3/11 net/failsafe: add fail-safe PMD
In reply to Gaetan RivetIntroduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
--- MAINTAINERS | 5 + config/common_base | 5 + doc/guides/nics/fail_safe.rst | 142 +++++ doc/guides/nics/features/failsafe.ini | 24 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 66 +++ drivers/net/failsafe/failsafe.c | 232 ++++++++ drivers/net/failsafe/failsafe_args.c | 331 +++++++++++ drivers/net/failsafe/failsafe_eal.c | 138 +++++ drivers/net/failsafe/failsafe_ops.c | 664 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 210 +++++++ drivers/net/failsafe/failsafe_rxtx.c | 107 ++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + mk/rte.app.mk | 1 + 15 files changed, 1932 insertions(+) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
MAINTAINERS +5 -0
@@ -341,6 +341,11 @@ F: drivers/net/enic/ F: doc/guides/nics/enic.rst F: doc/guides/nics/features/enic.ini +Fail-safe PMD +M: Gaetan Rivet <[email protected]> +F: drivers/net/failsafe/ +F: doc/guides/nics/fail_safe.rst + Intel e1000 M: Wenzhuo Lu <[email protected]> F: drivers/net/e1000/
config/common_base +5 -0
@@ -420,6 +420,11 @@ CONFIG_RTE_LIBRTE_PMD_XENVIRT=n CONFIG_RTE_LIBRTE_PMD_NULL=y # +# Compile fail-safe PMD +# +CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y + +# # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y
doc/guides/nics/fail_safe.rst new file +142 -0
142 lines not on this page · raw message
doc/guides/nics/features/failsafe.ini new file +24 -0
@@ -0,0 +1,24 @@ +; +; Supported features of the 'fail-safe' poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status = Y +Queue start/stop = Y +MTU update = Y +Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +VLAN filter = Y +Packet type parsing = Y +Basic stats = Y +Stats per queue = Y +ARMv7 = Y +ARMv8 = Y +Power8 = Y +x86-32 = Y +x86-64 = Y +Usage doc = Y
doc/guides/nics/index.rst +1 -0
@@ -64,6 +64,7 @@ Network Interface Controller Drivers vhost vmxnet3 pcap_ring + fail_safe **Figures**
drivers/net/Makefile +2 -0
@@ -59,6 +59,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena DEPDIRS-ena = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DEPDIRS-enic = $(core-libs) librte_hash +DIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe +DEPDIRS-failsafe = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DEPDIRS-fm10k = $(core-libs) librte_hash DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e
drivers/net/failsafe/Makefile new file +66 -0
66 lines not on this page · raw message
drivers/net/failsafe/failsafe.c new file +232 -0
232 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c new file +331 -0
331 lines not on this page · raw message
drivers/net/failsafe/failsafe_eal.c new file +138 -0
138 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c new file +664 -0
664 lines not on this page · raw message
drivers/net/failsafe/failsafe_private.h new file +210 -0
210 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c new file +107 -0
107 lines not on this page · raw message
drivers/net/failsafe/rte_pmd_failsafe_version.map new file +4 -0
@@ -0,0 +1,4 @@ +DPDK_17.08 { + + local: *; +};
mk/rte.app.mk +1 -0
@@ -121,6 +121,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += -lrte_pmd_ena _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += -lrte_pmd_failsafe _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
Signature · 1 line
2.1.4
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
Hi Gaetan,
15/07/2017 19:57, Gaetan Rivet:
doc/guides/nics/fail_safe.rst line 119
Quoted 8 lines
doc/guides/nics/fail_safe.rst new file +8
-0+#. Start testpmd. The slave device should be blacklisted from normal EAL + operations to avoid probing it twice when in PCI blacklist mode. + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 \ + -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' + -b 84:00.0 -b 00:04.0 -- -i
It is weird to use -w to declare the failsafe device. And I think it does not work with -w.
Should it be changed to --vdev?
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
Quoted 15 lines · Thomas Monjalon
Hi Gaetan,
15/07/2017 19:57, Gaetan Rivet:
doc/guides/nics/fail_safe.rst line 119
Quoted 8 lines
doc/guides/nics/fail_safe.rst new file +8
-0+#. Start testpmd. The slave device should be blacklisted from normal EAL + operations to avoid probing it twice when in PCI blacklist mode. + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 \ + -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' + -b 84:00.0 -b 00:04.0 -- -iIt is weird to use -w to declare the failsafe device. And I think it does not work with -w.
Should it be changed to --vdev?
It did work before [1], and it was a way to showcase the new format, but with [1] applied, then it should come back to --vdev indeed.
[1]: http://dpdk.org/ml/archives/dev/2017-July/071361.html
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
In reply to Gaetan RivetQuoted 6 lines · Gaetan Rivet
Introduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
Quoted 8 lines
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
All PMD in a single patch is hard to review, I am sure some details missed during the review, but taking account the histroy of the PMD I accept this as it is, but I will rely on your support to fix issues in the future.
Quoted 3 lines
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>
<...>
doc/guides/nics/fail_safe.rst line 110
Quoted 10 lines
doc/guides/nics/fail_safe.rst new file +10
-0+Usage example +~~~~~~~~~~~~~ + +This section shows some example of using **testpmd** with a fail-safe PMD. + +#. Request huge pages: + + .. code-block:: console + + echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
I think this is extra for usage sample, if you want there is generic guide [1] that you ca reference.
doc/guides/nics/fail_safe.rst line 119
Quoted 9 lines
doc/guides/nics/fail_safe.rst new file +9
-0+ +#. Start testpmd. The slave device should be blacklisted from normal EAL + operations to avoid probing it twice when in PCI blacklist mode. + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 \ + -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' + -b 84:00.0 -b 00:04.0 -- -i
Do you think does it make sense to stress sub-device shouldn't be probed by EAL, I believe it is not clear above.
Quoted 13 lines
doc/guides/nics/fail_safe.rst new file +13
-0+ + Note that PCI blacklist mode is the default PCI operating mode. In this + configuration, the fail-safe cannot proceed with its slaves if they have + been probed beforehand. + +#. Alternatively, it can be used alongside any other device in whitelist mode. + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 \ + -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' + -w 81:00.0 -- -i +
<...>
doc/guides/nics/features/failsafe.ini line 16
Quoted 9 lines
+[Features]
doc/guides/nics/features/failsafe.ini new file +6
-0+Link status = Y +MTU update = Y +Promiscuous mode = Y +Allmulticast mode = Y +VLAN filter = Y +Packet type parsing = Y
I am not sure how to document some of these features, because they depends on sub-device capability. I guess if sub-device doesn't support packet type parsing, this feature won't be supported?
Review
Quoted 7 lines
(quoted diff) +6
-0+Basic stats = Y +Stats per queue = Y +Unicast MAC filter = Y +Queue start/stop = Y +Jumbo frame = Y +Multicast MAC filter = Y
Is above ones supported by PMD, I don't see them unless I miss something.
+ "Flow Control" seems supported.
<...>
drivers/net/failsafe/Makefile line 54
Quoted 5 lines
drivers/net/failsafe/Makefile new file +5
-0+# This lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_kvargs +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += lib/librte_mbuf
DEPDIRS-y no more used, can be removed.
drivers/net/failsafe/Makefile line 57
Quoted 3 lines
drivers/net/failsafe/Makefile new file +3
-0+ +# Basic CFLAGS: +CFLAGS += -std=gnu99 -Wall -Wextra
-Wall should be coming from $(WERROR_FLAGS), no need to add here.
And are you sure about gnu99, mlx drivers tends to enforce a standard and they updated to c11, do you want to do same here.
drivers/net/failsafe/Makefile line 61
Quoted 4 lines
drivers/net/failsafe/Makefile new file +4
-0+CFLAGS += -O3 +CFLAGS += -I. +CFLAGS += -D_DEFAULT_SOURCE +CFLAGS += -D_XOPEN_SOURCE=700
Is there a reason for these variables, or are these copy-paste?
drivers/net/failsafe/Makefile line 64
Quoted 3 lines
drivers/net/failsafe/Makefile new file +3
-0+CFLAGS += $(WERROR_FLAGS) +CFLAGS += -Wno-strict-prototypes +CFLAGS += -pedantic -DPEDANTIC
Again, just question, is pedantic mode intentional, or copy-paste?
<...>
Quoted 8 lines
drivers/net/failsafe/failsafe.c new file +8
-0+static int +fs_eth_dev_create (struct rte_vdev_device *vdev) +{ +struct rte_eth_dev *dev; +struct ether_addr *mac; +struct fs_priv *priv; +struct sub_device *sdev; +const char *params;
drivers/net/failsafe/failsafe.c line 101
Quoted 10 lines
drivers/net/failsafe/failsafe.c new file +10
-0+unsigned int socket_id; +uint8_t i; +int ret; + + dev =NULL ; + priv =NULL ; + params =rte_vdev_device_args (vdev); + socket_id =rte_socket_id (); +INFO ("Creating fail-safe device on NUMA socket %u" , + socket_id);
No line break required.
drivers/net/failsafe/failsafe.c line 108
Quoted 7 lines
drivers/net/failsafe/failsafe.c new file +7
-0+ dev =rte_eth_vdev_allocate (vdev,sizeof (*priv)); +if (dev ==NULL ) { +ERROR ("Unable to allocate rte_eth_dev" ); +return -1 ; + } + priv = dev->data->dev_private; +PRIV (dev)->dev = dev;
Altough this is valid, what about?
priv = PRIV(dev);priv->dev = dev;
drivers/net/failsafe/failsafe.c line 110
Quoted 2 lines
drivers/net/failsafe/failsafe.c new file +2
-0+ dev->dev_ops = &failsafe_ops; +TAILQ_INIT (&dev->link_intr_cbs);
Not required, rte_eth_dev_allocate() initializes this.
drivers/net/failsafe/failsafe.c line 111
Quoted 1 line
drivers/net/failsafe/failsafe.c new file +1
-0+ dev->data->dev_flags =0x0 ;
Not required to set zero, dev->data already memset to zero.
drivers/net/failsafe/failsafe.c line 117
Quoted 6 lines
drivers/net/failsafe/failsafe.c new file +6
-0+ dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; + dev->data->dev_link = eth_link; +PRIV (dev)->nb_mac_addr =1 ; + dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; + dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; +if (params ==NULL ) {
I would prefer input control as first thing in the function, before allocating the device.
drivers/net/failsafe/failsafe.c line 121
Quoted 4 lines
drivers/net/failsafe/failsafe.c new file +4
-0+ERROR ("This PMD requires sub-devices, none provided" ); + goto free_dev; + } + ret =fs_sub_device_create (dev, params);
This function looks like just allocates memory for sub devices, does it make sense to rename it as fs_sub_device_alloc()?
Quoted 4 lines
drivers/net/failsafe/failsafe.c new file +4
-0+if (ret) { +ERROR ("Could not allocate sub_devices" ); + goto free_dev; + }
<...>
drivers/net/failsafe/failsafe.c line 177
Quoted 6 lines
drivers/net/failsafe/failsafe.c new file +6
-0+free_args: +failsafe_args_free (dev); +free_subs: +fs_sub_device_free (dev); +free_dev: +rte_eth_dev_release_port (dev);
Device private data should be freed.
Quoted 2 lines
(quoted diff) +2
-0+ return -1; +}
<...>
drivers/net/failsafe/failsafe.c line 207
Quoted 8 lines
drivers/net/failsafe/failsafe.c new file +8
-0+static int +rte_pmd_failsafe_probe (struct rte_vdev_device *vdev) +{ +const char *name; + + name =rte_vdev_device_name (vdev); +if (vdev ==NULL ) +return -EINVAL ;
I think you don't need this check, if name is NULL, probe shouldn't be called, same for remove().
drivers/net/failsafe/failsafe.c line 209
Quoted 2 lines
drivers/net/failsafe/failsafe.c new file +2
-0+INFO ("Initializing " FAILSAFE_DRIVER_NAME " for %s" , + name);
Line break not required.
<...>
drivers/net/failsafe/failsafe.c line 231
Quoted 2 lines
drivers/net/failsafe/failsafe.c new file +2
-0+RTE_PMD_REGISTER_VDEV (net_failsafe, failsafe_drv); +RTE_PMD_REGISTER_ALIAS (net_failsafe, eth_failsafe);
I belive alias is not required for new PMDs, this is for backward compability for old drivers.
<...>
drivers/net/failsafe/failsafe_args.c line 243
Quoted 5 lines
drivers/net/failsafe/failsafe_args.c new file +5
-0+int +failsafe_args_parse (struct rte_eth_dev *dev,const char *params) +{ +struct fs_priv *priv; +char mut_params[DEVARGS_MAXLEN ] ="" ;
Out of curiosity, what does "mut" stands for?
drivers/net/failsafe/failsafe_args.c line 250
Quoted 7 lines
drivers/net/failsafe/failsafe_args.c new file +7
-0+struct rte_kvargs *kvlist =NULL ; +unsigned int arg_count; +size_t n; +int ret; + +if (dev ==NULL || params ==NULL ) +return -EINVAL ;
This check looks like redundant.
drivers/net/failsafe/failsafe_args.c line 255
Quoted 5 lines
drivers/net/failsafe/failsafe_args.c new file +5
-0+ priv =PRIV (dev); + ret =0 ; + priv->subs_tx =FAILSAFE_MAX_ETHPORTS ; +/* default parameters */ + mac_from_arg =0 ;
This is global value, I believe it is better to set default value where variable defined with a comment. Here is easy to miss the default value.
drivers/net/failsafe/failsafe_args.c line 263
Quoted 8 lines
drivers/net/failsafe/failsafe_args.c new file +8
-0+ n =snprintf (mut_params,sizeof (mut_params),"%s" , params); +if (n >=sizeof (mut_params)) { +ERROR ("Parameter string too long (>=%zu)" , +sizeof (mut_params)); +return -ENOMEM ; + } + ret =fs_parse_sub_devices (fs_parse_device_param, + dev, params);
Why the device argument is not defined as dev=xxx, instead of current dev(xxx).
"dev=xxx" will be compatible with rest of the argument usage, and it will be possible to use kvargs to parse it, which will make this code simpler I believe.
What is the reason of using different syntax?
Quoted 15 lines
drivers/net/failsafe/failsafe_args.c new file +15
-0+if (ret <0 ) +return ret; + ret =fs_remove_sub_devices_definition (mut_params); +if (ret <0 ) +return ret; +if (strnlen (mut_params,sizeof (mut_params)) >0 ) { + kvlist =rte_kvargs_parse (mut_params, + pmd_failsafe_init_parameters); +if (kvlist ==NULL ) { +ERROR ("Error parsing parameters, usage:\n" +PMD_FAILSAFE_PARAM_STRING ); +return -1 ; + } +/* MAC addr */ + arg_count = rte_kvargs_count(kvlist,
drivers/net/failsafe/failsafe_args.c line 288
Quoted 10 lines
drivers/net/failsafe/failsafe_args.c new file +10
-0+ PMD_FAILSAFE_MAC_KVARG); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_MAC_KVARG , + &fs_get_mac_addr_arg, + &dev->data->mac_addrs[0 ]); +if (ret <0 ) + goto free_kvlist; + mac_from_arg =1 ; + }
Is ignoring the case mac defined more than once intentional?
Quoted 6 lines
drivers/net/failsafe/failsafe_args.c new file +6
-0+ } +free_kvlist: +rte_kvargs_free (kvlist); +return ret; +} +
<...>
drivers/net/failsafe/failsafe_args.c line 317
Quoted 11 lines
drivers/net/failsafe/failsafe_args.c new file +11
-0+static int +fs_count_device (struct rte_eth_dev *dev,const char *param, + uint8_t head __rte_unused) +{ +size_t b =0 ; + +while (param[b] !='(' && + param[b] !='\0' ) + b++; +if (strncmp (param,"dev" , b) && +strncmp (param,"exec" , b)) {
I believe param "exec" will be introduced in further patches?
Quoted 7 lines
drivers/net/failsafe/failsafe_args.c new file +7
-0+ERROR ("Unrecognized device type: %.*s" , (int )b, param); +return -EINVAL ; + } +PRIV (dev)->subs_tail +=1 ; +return 0 ; +} +
<...>
drivers/net/failsafe/failsafe_eal.c line 46
Quoted 9 lines
drivers/net/failsafe/failsafe_eal.c new file +9
-0+static int +fs_bus_init (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +struct rte_devargs *da; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) {
Can FOREACH_SUBDEV_ST(..., DEV_PARSED) be used here?
And what do you think renaming "FOREACH_SUBDEV_ST" to "FOREACH_SUBDEV_STATE"?
Quoted 6 lines
drivers/net/failsafe/failsafe_eal.c new file +6
-0+if (sdev->state !=DEV_PARSED ) +continue ; + da = &sdev->devargs; + ret =rte_eal_hotplug_add (da->bus->name, + da->name, + da->args);
<...>
drivers/net/failsafe/failsafe_eal.c
Quoted 6 lines
drivers/net/failsafe/failsafe_eal.c new file +6
-0+/* +* We only update TX_SUBDEV if we are not started. +* If a sub_device is emitting, we will switch the TX_SUBDEV to the +* preferred port only upon starting it, so that the switch is smoother. +*/ +if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED )
Can you please document concept of the "prefered sub device" in documentation?
Quoted 6 lines
drivers/net/failsafe/failsafe_eal.c new file +6
-0+if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && + (TX_SUBDEV (dev) ==NULL || + (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { +DEBUG ("Switching tx_dev to preferred sub_device" ); +PRIV (dev)->subs_tx =0 ; + }
<...>
drivers/net/failsafe/failsafe_ops.c line 43
Quoted 2 lines
drivers/net/failsafe/failsafe_ops.c new file +2
-0+static struct rte_eth_dev_info default_infos = { + .driver_name = pmd_failsafe_driver_name,
This should be dev->device->driver->name, but already overwriiten by rte_eth_dev_info_get() so you can drop this.
Quoted 1 line
drivers/net/failsafe/failsafe_ops.c new file +1
-0+/* Max possible number of elements */
<...>
drivers/net/failsafe/failsafe_ops.c line 190
Quoted 4 lines
drivers/net/failsafe/failsafe_ops.c new file +4
-0+ FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Closing sub_device %d" , i); +rte_eth_dev_close (PORT_ID (sdev)); + sdev->state =DEV_ACTIVE -1 ;
Should it be better to set state to DEV_PROBED? Instead of calculation.
Quoted 4 lines
drivers/net/failsafe/failsafe_ops.c new file +4
-0+ } +fs_dev_free_queues (dev); +} +
<...>
drivers/net/failsafe/failsafe_ops.c line 413
Quoted 5 lines
drivers/net/failsafe/failsafe_ops.c new file +5
-0+static void +fs_stats_get (struct rte_eth_dev *dev, +struct rte_eth_stats *stats) +{ +memset (stats,0 ,sizeof (*stats));
memset not required, done by API
Quoted 5 lines
drivers/net/failsafe/failsafe_ops.c new file +5
-0+if (TX_SUBDEV (dev) ==NULL ) +return ; +rte_eth_stats_get (PORT_ID (TX_SUBDEV (dev)), stats); +} +
<...>
drivers/net/failsafe/failsafe_ops.c line 481
Quoted 3 lines
drivers/net/failsafe/failsafe_ops.c new file +3
-0+ sdev =TX_SUBDEV (dev); +rte_eth_dev_info_get (PORT_ID (sdev), &PRIV (dev)->infos); +PRIV (dev)->infos.rx_offload_capa = rx_offload_capa;
Is intention &= ?
Quoted 7 lines
drivers/net/failsafe/failsafe_ops.c new file +7
-0+PRIV (dev)->infos.tx_offload_capa &= + default_infos.tx_offload_capa; +PRIV (dev)->infos.flow_type_rss_offloads &= + default_infos.flow_type_rss_offloads; + } +rte_memcpy (infos, &PRIV (dev)->infos,sizeof (*infos)); +}
<...>
drivers/net/failsafe/failsafe_ops.c line 525
Quoted 6 lines
drivers/net/failsafe/failsafe_ops.c new file +6
-0+ FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_set_mtu on sub_device %d" , i); + ret =rte_eth_dev_set_mtu (PORT_ID (sdev), mtu); +if (ret) { +ERROR ("Operation rte_eth_dev_set_mtu failed for sub_device %d" +" with error %d" , i, ret);
You can prefer to not break the log message.
Quoted 5 lines
drivers/net/failsafe/failsafe.c new file +5
-0+return ret; + } + } +return 0 ; +}
<...>
drivers/net/failsafe/failsafe_private.h line 49
Quoted 2 lines
drivers/net/failsafe/failsafe_private.h new file +2
-0+ +#define FAILSAFE_PLUGIN_DEFAULT_TIMEOUT_MS 2000
Is this related to next patches in the set?
<...>
drivers/net/failsafe/failsafe_private.h line 73
Quoted 2 lines
drivers/net/failsafe/failsafe_private.h new file +2
-0+enum dev_state { +DEV_UNDEFINED =0 ,
Setting value not required.
Quoted 5 lines
drivers/net/failsafe/failsafe_private.h new file +5
-0+DEV_PARSED , +DEV_PROBED , +DEV_ACTIVE , + DEV_STARTED, +};
<...>
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
Quoted 13 lines · Ferruh Yigit
Quoted 12 lines · Gaetan Rivet
Introduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Quoted 8 lines
Quoted 2 lines
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
All PMD in a single patch is hard to review, I am sure some details missed during the review, but taking account the histroy of the PMD I accept this as it is, but I will rely on your support to fix issues in the future.
Sure, sorry for having this one first big patch.
I thought about having a skeleton patch first, but found it made little sense. I tried to restrict this version to the bare functionalities, adding the others afterward.
I will fix any issues. From what I've seen I agree with almost all of your remarks and will send a new version shortly. In the meantime, I will answer in this email a few clarifying questions.
<...>
Quoted 7 lines
doc/guides/nics/features/failsafe.ini line 16
Quoted 2 lines
doc/guides/nics/features/failsafe.ini new file +2
-0+VLAN filter = Y +Packet type parsing = YI am not sure how to document some of these features, because they depends on sub-device capability. I guess if sub-device doesn't support packet type parsing, this feature won't be supported?
Yes, supporting a feature for the fail-safe means that there is some verification and synchronization code related to this feature. All sub_device should have feature parity, and the features of the fail-safe are limited to those of the sub_devices.
I thought advertizing the support made sense as there was some code related to it in the fail-safe.
Quoted 8 lines
drivers/net/failsafe/failsafe_args.c line 243
Quoted 5 lines
drivers/net/failsafe/failsafe_args.c new file +5
-0+int +failsafe_args_parse (struct rte_eth_dev *dev,const char *params) +{ +struct fs_priv *priv; +char mut_params[DEVARGS_MAXLEN ] ="" ;Out of curiosity, what does "mut" stands for?
This is the mutable version of params.
<...>
Quoted 12 lines
drivers/net/failsafe/failsafe_args.c line 263
Quoted 8 lines
drivers/net/failsafe/failsafe_args.c new file +8
-0+ n =snprintf (mut_params,sizeof (mut_params),"%s" , params); +if (n >=sizeof (mut_params)) { +ERROR ("Parameter string too long (>=%zu)" , +sizeof (mut_params)); +return -ENOMEM ; + } + ret =fs_parse_sub_devices (fs_parse_device_param, + dev, params);Why the device argument is not defined as dev=xxx, instead of current dev(xxx).
Quoted 6 lines
"dev=xxx" will be compatible with rest of the argument usage, and it will be possible to use kvargs to parse it, which will make this code simpler I believe.
What is the reason of using different syntax?
Using the dev() syntax allows the user to explicitly set the limits of the sub_device declaration, clarifying for which device each kvargs is.
The issue is that the kvargs library does not allow to set state informations in the parser depending on the position in the kvlist. An alternative would have been for example to restrict the kvargs to that of the last declared dev=, however, this means multi-stage kvargs parsing, which mean pre-processing of the parameter list, etc...
An example:
net_failsafe0,dev=net_tap0,iface=tap0,mac=00:01:02:03:04:05 net_failsafe0,dev(net_tap0,iface=tap0),mac=00:01:02:03:04:05
This is much simpler to parse this way, and much clearer I think for users.
The kvargs library was not designed with recursive PMDs in mind.
<...>
Quoted 12 lines
drivers/net/failsafe/failsafe_eal.c line 46
Quoted 9 lines
drivers/net/failsafe/failsafe_eal.c new file +9
-0+static int +fs_bus_init (struct rte_eth_dev *dev) +{ +struct sub_device *sdev; +struct rte_devargs *da; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) {Can
FOREACH_SUBDEV_ST(..., DEV_PARSED)be used here?
I could use it, this would restrict the iteration only to sub_devices being at least of the state DEV_PARSED. However, in the check just below:
+ if (sdev->state != DEV_PARSED)
+ continue;
I would have to pass on any device being in a state higher than DEV_PARSED. Thus, using FOREACH_SUBDEV_ST would not simplify the code flow. By using FOREACH_SUBDEV() directly, the reader at least has a simpler parsing to do of my intent:
foreach subdev not "parsed".
Quoted 3 lines
And what do you think renaming "
FOREACH_SUBDEV_ST" to "FOREACH_SUBDEV_STATE"?
Sure, I pushed for brievity but it might be easier to read.
<...>
Quoted 7 lines
drivers/net/failsafe/failsafe_ops.c line 190
Quoted 4 lines
drivers/net/failsafe/failsafe_ops.c new file +4
-0+ FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Closing sub_device %d" , i); +rte_eth_dev_close (PORT_ID (sdev)); + sdev->state =DEV_ACTIVE -1 ;Should it be better to set state to
DEV_PROBED? Instead of calculation.
I wanted to be able to add / remove device states without having to rewrite each of those state changes (there are a few in several places). If I insert a new device state between ACTIVE and PROBED, setting to DEV_PROBED would still be valid (no compile error), but it would be a bug. It would be very easy to miss a reference to this specific state.
Those states bugs are a little hard to find at runtime, they usually have subtle side-effects.
I can change it if you prefer, but I would probably introduce a helper in the form of fs_dev_state_prev/next, thus having a single place to check for any changes.
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
In reply to Ferruh YigitOn Mon, Jul 17, 2017 at 02:56:54PM +0100, Ferruh Yigit wrote:
<...>
Quoted 8 lines
doc/guides/nics/features/failsafe.ini line 14
Quoted 5 lines
doc/guides/nics/features/failsafe.ini new file +5
-0+Stats per queue = Y +Unicast MAC filter = Y +Queue start/stop = Y +Jumbo frame = Y +Multicast MAC filter = YIs above ones supported by PMD, I don't see them unless I miss something.
Queue start/stop was an error.
All others are supported as long as the slave support it.
<...>
Quoted 6 lines
drivers/net/failsafe/failsafe_ops.c line 481
Quoted 3 lines
drivers/net/failsafe/failsafe_ops.c new file +3
-0+ sdev =TX_SUBDEV (dev); +rte_eth_dev_info_get (PORT_ID (sdev), &PRIV (dev)->infos); +PRIV (dev)->infos.rx_offload_capa = rx_offload_capa;Is intention &= ?
rx_offload_capa is already set a little higher, and then an AND is done on it with all slaves. The "=" is correct here. Thanks for asking though, it's always useful to check :).
---
I fixed all other remarks. I will wait a little for any possible additional changes you might want to point before sending the new version.
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
On 7/18/2017 12:17 AM, Gaëtan Rivet wrote:
<...>
Quoted 4 lines
I fixed all other remarks. I will wait a little for any possible additional changes you might want to point before sending the new version.
OK, there were some patches from Thomas addition to failsafe patchset, are they all clarified, merged or rejected for this patchset?
Re: [PATCH v10 03/11] net/failsafe: add fail-safe PMD
Quoted 10 lines · Ferruh Yigit
On 7/18/2017 12:17 AM, Gaëtan Rivet wrote:
<...>Quoted 4 lines
I fixed all other remarks. I will wait a little for any possible additional changes you might want to point before sending the new version.
OK, there were some patches from Thomas addition to failsafe patchset, are they all clarified, merged or rejected for this patchset?
The patch he sent last week is postponed. It does not work as it is, and the fix requires additional API / dev. We will look into it next release.
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v10 4/11 net/failsafe: add plug-in support
In reply to Gaetan RivetPeriodically check for the existence of a device.
If a device has not been initialized and exists on the system, then it is probed and configured.
The configuration process strives to synchronize the states between the plugged-in sub-device and the fail-safe device.
--- doc/guides/nics/fail_safe.rst | 19 +++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 71 ++++++++++ drivers/net/failsafe/failsafe_args.c | 33 +++++ drivers/net/failsafe/failsafe_eal.c | 30 +---- drivers/net/failsafe/failsafe_ether.c | 228 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 25 ++-- drivers/net/failsafe/failsafe_private.h | 60 ++++++++- 8 files changed, 424 insertions(+), 43 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c
doc/guides/nics/fail_safe.rst +19 -0
@@ -98,6 +98,11 @@ Fail-safe command line parameters address is generated, that will be subsequently applied to all sub-device once they are probed. +- **hotplug_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two slave upkeep round. + Usage example ~~~~~~~~~~~~~
@@ -140,3 +145,17 @@ Care must be taken, however, to respect the **ether** API concerning device access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate over ethernet devices, instead of directly accessing them or by writing one's own device iterator. + +Plug-in feature +--------------- + +A sub-device can be defined without existing on the system when the fail-safe +PMD is initialized. Upon probing this device, the fail-safe PMD will detect its +absence and postpone its use. It will then register for a periodic check on any +missing sub-device. + +During this time, the fail-safe PMD can be used normally, configured and told to +emit and receive packets. It will store any applied configuration, and try to +apply it upon the probing of its missing sub-device. After this configuration +pass, the new sub-device will be synchronized with other sub-devices, i.e. be +started if the fail-safe PMD has been started by the user before.
drivers/net/failsafe/Makefile +1 -0
@@ -44,6 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c # No exported include files
drivers/net/failsafe/failsafe.c +71 -0
83 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c +33 -0
@@ -32,6 +32,7 @@*/ #include <string.h> +#include <errno.h> #include <rte_devargs.h> #include <rte_malloc.h>
@@ -45,9 +46,11 @@typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params,uint8_t head); +uint64_t hotplug_poll;int mac_from_arg;const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ,PMD_FAILSAFE_MAC_KVARG ,NULL , };
@@ -221,6 +224,24 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) }static int +fs_get_u64_arg(const char *key __rte_unused, +const char *value,void *out) +{ +uint64_t *u64 = out; +char *endptr =NULL ; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + errno =0 ; + *u64 =strtoull (value, &endptr,0 ); +if (errno !=0 ) +return -errno; +if (endptr == value) +return -1 ; +return 0 ; +} + +static int fs_get_mac_addr_arg(const char *key __rte_unused,const char *value,void *out) {
@@ -252,6 +273,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret =0 ; priv->subs_tx =FAILSAFE_MAX_ETHPORTS ;/* default parameters */ + hotplug_poll =FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS ; mac_from_arg =0 ; n =snprintf (mut_params,sizeof (mut_params),"%s" , params);if (n >=sizeof (mut_params)) {
@@ -274,6 +296,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING);return -1 ; } +/* PLUG_IN event poll timer */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_PLUG_IN_POLL_KVARG , + &fs_get_u64_arg, &hotplug_poll); +if (ret <0 ) + goto free_kvlist; + }/* MAC addr */ arg_count =rte_kvargs_count (kvlist,PMD_FAILSAFE_MAC_KVARG );
@@ -287,6 +319,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) mac_from_arg =1 ; } } +PRIV (dev)->state =DEV_PARSED ; free_kvlist:rte_kvargs_free (kvlist);return ret;
drivers/net/failsafe/failsafe_eal.c +4 -26
@@ -72,37 +72,14 @@ fs_bus_init(struct rte_eth_dev *dev)int failsafe_eal_init (struct rte_eth_dev *dev) { -struct sub_device *sdev; -uint8_t i;int ret; ret =fs_bus_init (dev);if (ret)return ret; -/* -* We only update TX_SUBDEV if we are not started. -* If a sub_device is emitting, we will switch the TX_SUBDEV to the -* preferred port only upon starting it, so that the switch is smoother. -*/ -if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && - (TX_SUBDEV (dev) ==NULL || - (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || -TX_SUBDEV (dev) ==NULL ) { -/* Using first probed device */ - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_PROBED) { -DEBUG ("Switching tx_dev to sub_device %d" , - i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_PROBED ) +PRIV (dev)->state =DEV_PROBED ; +fs_switch_dev (dev);return 0 ; }
@@ -134,5 +111,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret =fs_bus_uninit (dev);if (ret)return ret; +PRIV (dev)->state =DEV_PROBED -1 ;return 0 ; }
drivers/net/failsafe/failsafe_ether.c new file +228 -0
228 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +10 -15
@@ -90,6 +90,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } sdev->state =DEV_ACTIVE ; } +if (PRIV (dev)->state <DEV_ACTIVE ) +PRIV (dev)->state =DEV_ACTIVE ;return 0 ; }
@@ -109,21 +111,9 @@ fs_dev_start(struct rte_eth_dev *dev)return ret; sdev->state =DEV_STARTED ; } -if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || -TX_SUBDEV (dev) ==NULL ) { - FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) { -DEBUG ("Switching tx_dev to sub_device %d" , i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_STARTED ) +PRIV (dev)->state =DEV_STARTED ; +fs_switch_dev (dev);return 0 ; }
@@ -133,6 +123,7 @@ fs_dev_stop(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +PRIV (dev)->state =DEV_STARTED -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_STARTED) {rte_eth_dev_stop (PORT_ID (sdev)); sdev->state =DEV_STARTED -1 ;
@@ -184,6 +175,10 @@ fs_dev_close(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +failsafe_hotplug_alarm_cancel (dev); +if (PRIV (dev)->state ==DEV_STARTED ) + dev->dev_ops->dev_stop (dev); +PRIV (dev)->state =DEV_ACTIVE -1 ; FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) {DEBUG ("Closing sub_device %d" , i);rte_eth_dev_close (PORT_ID (sdev));
drivers/net/failsafe/failsafe_private.h +58 -2
92 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v10 5/11 net/failsafe: add flexible device definition
In reply to Gaetan RivetAdd the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.
That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 95 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 126 insertions(+)
doc/guides/nics/fail_safe.rst +20 -0
@@ -87,6 +87,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
@@ -135,6 +148,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i + Using the Fail-safe PMD from an application -------------------------------------------
drivers/net/failsafe/failsafe_args.c +95 -0
122 lines not on this page · raw message
drivers/net/failsafe/failsafe_ether.c +7 -0
@@ -188,6 +188,13 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)int ret;uint8_t i; +if (PRIV (dev)->state <DEV_PARSED ) +return 0 ; + + ret =failsafe_args_parse_subs (dev); +if (ret) +return ret; +if (PRIV (dev)->state <DEV_PROBED )return 0 ; ret =failsafe_eal_init (dev);
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -44,6 +44,7 @@#define PMD_FAILSAFE_PLUG_IN_POLL_KVARG "hotplug_poll"#define PMD_FAILSAFE_PARAM_STRING \ "dev(<ifc>)," \ + "exec(<shell command>)," \ "mac=mac_addr," \ "hotplug_poll=u64" \ ""
@@ -87,6 +88,8 @@ struct sub_device {struct rte_eth_dev *edev;/* Device state machine */ enum dev_state state; +/* Some device are defined as a command line */ +char *cmdline; };struct fs_priv {
@@ -135,6 +138,7 @@ uint16_t failsafe_tx_burst(void *txq,int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);void failsafe_args_free (struct rte_eth_dev *dev);int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); +int failsafe_args_parse_subs (struct rte_eth_dev *dev);/* EAL */
Signature · 1 line
2.1.4
Re: [PATCH v10 05/11] net/failsafe: add flexible device definition
Quoted 42 lines · Gaetan Rivet
Add the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 95 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 126 insertions(+)doc/guides/nics/fail_safe.rst +13
-0@@ -87,6 +87,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
doc/guides/nics/fail_safe.rst This section shows some example of using **testpmd** with a fail-safe PMD. · line 156
Quoted 9 lines
doc/guides/nics/fail_safe.rst +6
-0@@ -135,6 +148,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i
Hi Gaetan,
What is the usecase for this feature.
How this is different from --vdev='net_failsafe0,dev(echo 84:00.0)' ?
Re: [PATCH v10 05/11] net/failsafe: add flexible device definition
Hi Ferruh,
(Thanks for the review by the way, I will answer the other more lengthy emails in due time)
Quoted 55 lines · Ferruh Yigit
Quoted 42 lines · Gaetan Rivet
Add the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 95 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 126 insertions(+)doc/guides/nics/fail_safe.rst +13
-0@@ -87,6 +87,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safedoc/guides/nics/fail_safe.rst This section shows some example of using **testpmd** with a fail-safe PMD. · line 156
Quoted 9 lines
doc/guides/nics/fail_safe.rst +6
-0@@ -135,6 +148,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -iHi Gaetan,
Quoted 3 lines
What is the usecase for this feature.
How this is different from --vdev='net_failsafe0,dev(
echo 84:00.0)' ?
This version would be interpreted once, at the launch of the fail-safe PMD.
The exec option will execute the command again each time the fail-safe tries to probe the sub_device. This means that in a live VM migration context, the sub_device can change PCI address (for example), and still be matched by the command using other identifying info (MAC address, class_id, ...).
It must be reinterpreted upon plugin of the sub_device, as the output would change from the time the fail-safe was started.
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v10 05/11] net/failsafe: add flexible device definition
Quoted 68 lines · Gaëtan Rivet
Hi Ferruh,
(Thanks for the review by the way, I will answer the other more lengthy emails in due time)
Quoted 55 lines · Ferruh Yigit
Quoted 42 lines · Gaetan Rivet
Add the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 95 +++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 126 insertions(+)doc/guides/nics/fail_safe.rst +13
-0@@ -87,6 +87,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safedoc/guides/nics/fail_safe.rst This section shows some example of using **testpmd** with a fail-safe PMD. · line 156
Quoted 9 lines
doc/guides/nics/fail_safe.rst +6
-0@@ -135,6 +148,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. -w 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -iHi Gaetan,
Quoted 3 lines
What is the usecase for this feature.
How this is different from --vdev='net_failsafe0,dev(
echo 84:00.0)' ?This version would be interpreted once, at the launch of the fail-safe PMD.
Quoted 8 lines
The exec option will execute the command again each time the fail-safe tries to probe the
sub_device. This means that in a live VM migration context, thesub_devicecan change PCI address (for example), and still be matched by the command using other identifying info (MAC address,class_id, ...).It must be reinterpreted upon plugin of the
sub_device, as the output would change from the time the fail-safe was started.
Make sense, thanks for clarification.
PATCH v10 6/11 net/failsafe: support flow API
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 215 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 336 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c
doc/guides/nics/features/failsafe.ini +1 -0
@@ -13,6 +13,7 @@ Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/Makefile +1 -0
@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files
drivers/net/failsafe/failsafe.c +1 -0
@@ -178,6 +178,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; dev->data->dev_link = eth_link;PRIV (dev)->nb_mac_addr =1 ; +TAILQ_INIT (&PRIV (dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;if (params ==NULL ) {
drivers/net/failsafe/failsafe_eal.c +1 -0
@@ -62,6 +62,7 @@ fs_bus_init(struct rte_eth_dev *dev)ERROR ("sub_device %d init went wrong" , i);return -ENODEV ; } +SUB_ID (sdev) = i; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
drivers/net/failsafe/failsafe_ether.c +70 -0
90 lines not on this page · raw message
drivers/net/failsafe/failsafe_flow.c new file +215 -0
215 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +29 -0
@@ -36,6 +36,7 @@#include <rte_debug.h> #include <rte_ethdev.h> #include <rte_malloc.h> +#include <rte_flow.h> #include "failsafe_private.h"
@@ -629,6 +630,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); } +static int +fs_filter_ctrl (struct rte_eth_dev *dev, +enum rte_filter_type type, +enum rte_filter_op op, +void *arg) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + +if (type ==RTE_ETH_FILTER_GENERIC && + op ==RTE_ETH_FILTER_GET ) { + *(const void **)arg = &fs_flow_ops; +return 0 ; + } + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_filter_ctrl on sub_device %d" , i); + ret =rte_eth_dev_filter_ctrl (PORT_ID (sdev), type, op, arg); +if (ret) { +ERROR ("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} +const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start,
@@ -656,4 +684,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, };
drivers/net/failsafe/failsafe_private.h +18 -0
@@ -34,6 +34,8 @@#ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_#define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include <sys/queue.h> +#include <rte_dev.h> #include <rte_ethdev.h> #include <rte_devargs.h>
@@ -72,6 +74,14 @@ struct txq {struct rte_eth_txq_info info; }; +struct rte_flow { +TAILQ_ENTRY (rte_flow) next; +/* sub_flows */ +struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS ]; +/* flow description for synchronization */ +struct rte_flow_desc *fd; +}; +enum dev_state {DEV_UNDEFINED =0 ,DEV_PARSED ,
@@ -86,6 +96,7 @@ struct sub_device {struct rte_bus *bus;struct rte_device *dev;struct rte_eth_dev *edev; +uint8_t sid;/* Device state machine */ enum dev_state state;/* Some device are defined as a command line */
@@ -104,6 +115,8 @@ struct fs_priv {uint8_t subs_tail;/* first invalid */ uint8_t subs_tx;/* current emitting device */ uint8_t current_probed; +/* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list;/* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr;struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ];
@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);extern const char pmd_failsafe_driver_name[];extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops;extern uint64_t hotplug_poll;extern int mac_from_arg;
@@ -170,6 +184,10 @@ extern int mac_from_arg;#define PORT_ID (sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID (sdev) \ + ((sdev)->sid) +/** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator
Signature · 1 line
2.1.4
Re: [PATCH v10 06/11] net/failsafe: support flow API
Quoted 2 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>
<...>
drivers/net/failsafe/failsafe_flow.c line 113
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+ + flow =fs_flow_allocate (attr, patterns, actions); + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + flow->flows[i] =rte_flow_create (PORT_ID (sdev), + attr, patterns, actions, error);
Should SUB_ID(sdev) used here? And in related functions. flow->flows[SUB_ID(sdev)] = ...
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+if (flow->flows[i] ==NULL ) { +ERROR ("Failed to create flow on sub_device %d" , + i); + goto err; + }
<...>
Re: [PATCH v10 06/11] net/failsafe: support flow API
Quoted 6 lines · Ferruh Yigit
Quoted 2 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]><...>
Quoted 9 lines
drivers/net/failsafe/failsafe_flow.c line 113
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+ + flow =fs_flow_allocate (attr, patterns, actions); + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + flow->flows[i] =rte_flow_create (PORT_ID (sdev), + attr, patterns, actions, error);Should
SUB_ID(sdev)used here? And in related functions. flow->flows[SUB_ID(sdev)] = ...
The SUB_ID(sdev) is the index in the sub_device array allocated in private data for the fail-safe. It is also used for the sub_rte_flow in the rte_flow (which sports an array of rte_flow pointers for each sub_device).
PORT_ID(sdev) is the index in the rte_eth_devices array, meaning that the rte_flow_create function is actually called using the public API on the port.
This allows to trigger the additional operations usually done within the ether API (storing the configuration in the eth_dev_data structure, some side management), and following eventual changes automatically from the fail-safe level.
Quoted 7 lines
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+if (flow->flows[i] ==NULL ) { +ERROR ("Failed to create flow on sub_device %d" , + i); + goto err; + }<...>
Signature · 2 lines
Gaëtan Rivet 6WIND
Re: [PATCH v10 06/11] net/failsafe: support flow API
Quoted 17 lines · Gaëtan Rivet
Quoted 6 lines · Ferruh Yigit
Quoted 2 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]><...>
Quoted 9 lines
drivers/net/failsafe/failsafe_flow.c line 113
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+ + flow =fs_flow_allocate (attr, patterns, actions); + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + flow->flows[i] =rte_flow_create (PORT_ID (sdev), + attr, patterns, actions, error);Should
SUB_ID(sdev)used here? And in related functions. flow->flows[SUB_ID(sdev)] = ...
Quoted 4 lines
The
SUB_ID(sdev)is the index in thesub_devicearray allocated in private data for the fail-safe. It is also used for thesub_rte_flowin therte_flow(which sports an array ofrte_flowpointers for eachsub_device).
I got this part, let me ask another way, is it always guarantied, even after some hotplug, "i" in FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) will be same with SUB_ID(sdev) ?
Quoted 18 lines
PORT_ID(sdev)is the index in therte_eth_devicesarray, meaning that therte_flow_createfunction is actually called using the public API on the port.This allows to trigger the additional operations usually done within the ether API (storing the configuration in the
eth_dev_datastructure, some side management), and following eventual changes automatically from the fail-safe level.Quoted 7 lines
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+if (flow->flows[i] ==NULL ) { +ERROR ("Failed to create flow on sub_device %d" , + i); + goto err; + }<...>
Re: [PATCH v10 06/11] net/failsafe: support flow API
Quoted 18 lines · Ferruh Yigit
Quoted 17 lines · Gaëtan Rivet
Quoted 15 lines · Ferruh Yigit
Quoted 2 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]><...>
drivers/net/failsafe/failsafe_flow.c line 113
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+ + flow =fs_flow_allocate (attr, patterns, actions); + FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE) { + flow->flows[i] =rte_flow_create (PORT_ID (sdev), + attr, patterns, actions, error);Should
SUB_ID(sdev)used here? And in related functions. flow->flows[SUB_ID(sdev)] = ...
Quoted 9 lines
Quoted 4 lines
The
SUB_ID(sdev)is the index in thesub_devicearray allocated in private data for the fail-safe. It is also used for thesub_rte_flowin therte_flow(which sports an array ofrte_flowpointers for eachsub_device).I got this part, let me ask another way, is it always guarantied, even after some hotplug, "i" in
FOREACH_SUBDEV_ST(sdev, i, dev, DEV_ACTIVE)will be same withSUB_ID(sdev)?
Ah, yes. Sub_device slots are static, allocated once at launch and reserved for only one device corresponding to its declaration.
Thus, the PORT_ID() can change, but the SUB_ID() is always the same.
Quoted 19 lines
Quoted 18 lines
PORT_ID(sdev)is the index in therte_eth_devicesarray, meaning that therte_flow_createfunction is actually called using the public API on the port.This allows to trigger the additional operations usually done within the ether API (storing the configuration in the
eth_dev_datastructure, some side management), and following eventual changes automatically from the fail-safe level.Quoted 7 lines
Quoted 5 lines
drivers/net/failsafe/failsafe_flow.c new file +5
-0+if (flow->flows[i] ==NULL ) { +ERROR ("Failed to create flow on sub_device %d" , + i); + goto err; + }<...>
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v10 7/11 net/failsafe: support offload capabilities
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)
doc/guides/nics/features/failsafe.ini +6 -0
@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/failsafe_ops.c +129 -2
151 lines not on this page · raw message
Signature · 1 line
2.1.4
Re: [PATCH v10 07/11] net/failsafe: support offload capabilities
Quoted 12 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)doc/guides/nics/features/failsafe.ini +0
-0
doc/guides/nics/features/failsafe.ini Unicast MAC filter = Y · line 22
Quoted 9 lines
doc/guides/nics/features/failsafe.ini +6
-0@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = Y
As previous comment on features, these are advertised as supported but depends on sub-devices.
Overall I don't know what does these mean for failsafe like abstract device.
Quoted 14 lines
doc/guides/nics/features/failsafe.ini +0
-0Packet type parsing = Y Basic stats = Y Stats per queue = Ydrivers/net/failsafe/failsafe_ops.c +1
-2@@ -64,22 +64,149 @@ static struct rte_eth_dev_info default_infos = { .nb_seg_max = UINT16_MAX, .nb_mtu_seg_max = UINT16_MAX, }, -/* Set of understood capabilities */ - .rx_offload_capa = 0x0, +/*
drivers/net/failsafe/failsafe_ops.c static struct rte_eth_dev_info default_infos = { · line 77
Quoted 10 lines
drivers/net/failsafe/failsafe_ops.c +10
-0+* Set of capabilities that can be verified upon +* configuring a sub-device. +*/ + .rx_offload_capa = +DEV_RX_OFFLOAD_VLAN_STRIP | +DEV_RX_OFFLOAD_QINQ_STRIP | +DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_TCP_LRO,
These are not dynamic, even though some may be disabled via fs_port_disable_offload() same these values will be returned to the application, which is wrong.
drivers/net/failsafe/failsafe_ops.c static struct rte_eth_dev_info default_infos = { · line 78
Quoted 1 line
drivers/net/failsafe/failsafe_ops.c +0
-0.tx_offload_capa = 0x0,
Claiming support for most of the offloads means supporting it both for Rx and Tx path. This patch only takes account the Rx ones.
Quoted 3 lines
drivers/net/failsafe/failsafe_ops.c +0
-0.flow_type_rss_offloads = 0x0, };
<...>
Re: [PATCH v10 07/11] net/failsafe: support offload capabilities
Quoted 26 lines · Ferruh Yigit
Quoted 12 lines · Gaetan Rivet
Signed-off-by Gaetan Rivet <[email protected]>Acked-by Olga Shern <[email protected]>--- doc/guides/nics/features/failsafe.ini | 6 ++ drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-)doc/guides/nics/features/failsafe.ini +0
-0doc/guides/nics/features/failsafe.ini Unicast MAC filter = Y · line 22
Quoted 9 lines
doc/guides/nics/features/failsafe.ini +6
-0@@ -14,6 +14,12 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow API = Y +VLAN offload = Y +QinQ offload = Y +L3 checksum offload = Y +L4 checksum offload = Y +Inner L3 checksum = Y +Inner L4 checksum = YAs previous comment on features, these are advertised as supported but depends on sub-devices.
Quoted 2 lines
Overall I don't know what does these mean for failsafe like abstract device.
We should look into this.
The rationale for features in fail-safe was that
- If the slave supported the feature, and using it with the fail-safe did not impair the feature, then the fail-safe was transparent as far as this feature was concerned --> support = Y.
Meaning that users would be able to use this feature with the fail-safe.
- If any slave did not support the feature, it would be dynamically disabled when it made sense, or ENOTSUPP is returned if an ops is missing (checked automatically by calling the ether API).
In the end, the feature matrix is used by the user to check whether the feature is available using this PMD. Disabling all features in the matrix for the fail-safe does not help the user at all, as they should then check manually / look at the code.
On the other hand, the possible issue is that some users might expect that the fail-safe could emulate in software missing features. The usefullness of having the matrix to compare against other PMDs features outweight this possibility as I find this assumption far-fetched, but I can always remove the feature support for the moment and we will see afterward how to deal with it.
Quoted 20 lines
Quoted 20 lines
doc/guides/nics/features/failsafe.ini +0
-0Packet type parsing = Y Basic stats = Y Stats per queue = Ydrivers/net/failsafe/failsafe_ops.c +7
-2@@ -64,22 +64,149 @@ static struct rte_eth_dev_info default_infos = { .nb_seg_max = UINT16_MAX, .nb_mtu_seg_max = UINT16_MAX, }, -/* Set of understood capabilities */ - .rx_offload_capa = 0x0, +/* +* Set of capabilities that can be verified upon +* configuring a sub-device. +*/ + .rx_offload_capa = +DEV_RX_OFFLOAD_VLAN_STRIP | + DEV_RX_OFFLOAD_QINQ_STRIP |
Quoted 9 lines
drivers/net/failsafe/failsafe_ops.c static struct rte_eth_dev_info default_infos = { · line 77
Quoted 4 lines
drivers/net/failsafe/failsafe_ops.c +4
-0+DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_TCP_LRO,These are not dynamic, even though some may be disabled via
fs_port_disable_offload()same these values will be returned to the application, which is wrong.
These are the default rx_offload_capa. This flag value is AND-ed with that of the slaves before being returned. A slave is assured to be present at all time, so it will be restricted to the common set between the fail-safe and the slave features.
Quoted 5 lines
drivers/net/failsafe/failsafe_ops.c static struct rte_eth_dev_info default_infos = { · line 78
Quoted 1 line
drivers/net/failsafe/failsafe_ops.c +0
-0.tx_offload_capa = 0x0,Claiming support for most of the offloads means supporting it both for Rx and Tx path. This patch only takes account the Rx ones.
Ah I did not know. I will remove the feature support for offloads, the same work that was done with Rx will be done with Tx.
Quoted 6 lines
Quoted 3 lines
drivers/net/failsafe/failsafe_ops.c +0
-0.flow_type_rss_offloads = 0x0, };<...>
Signature · 2 lines
Gaëtan Rivet 6WIND
PATCH v10 8/11 net/failsafe: add fast burst functions
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_private.h | 8 +++ drivers/net/failsafe/failsafe_rxtx.c | 123 ++++++++++++++++++++++++++------ 2 files changed, 111 insertions(+), 20 deletions(-)
drivers/net/failsafe/failsafe_private.h +8 -0
@@ -141,11 +141,18 @@ int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);/* RX / TX */ +void set_burst_fn (struct rte_eth_dev *dev,int force_safe); +uint16_t failsafe_rx_burst (void *rxq,struct rte_mbuf **rx_pkts,uint16_t nb_pkts);uint16_t failsafe_tx_burst (void *txq,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +uint16_t failsafe_rx_burst_fast (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst_fast (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +/* ARGS */ int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);
@@ -282,6 +289,7 @@ fs_switch_dev(struct rte_eth_dev *dev) }else {return ; } +set_burst_fn (dev,0 );rte_wmb (); }
drivers/net/failsafe/failsafe_rxtx.c +103 -20
153 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v10 9/11 net/failsafe: support device removal
In reply to Gaetan RivetListen to INTR_RMV events issued by slaves.
Add atomic flags on slave queues to detect use of slave bursts function. If a removal is detected, set the recollection flag on this slave.
During a slave upkeep round, if its recollection flag is set and its burst functions are not in use by any thread, remove that slave.
--- doc/guides/nics/fail_safe.rst | 14 +++++ drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_args.c | 13 +++++ drivers/net/failsafe/failsafe_eal.c | 3 +- drivers/net/failsafe/failsafe_ether.c | 96 ++++++++++++++++++++++++++++++--- drivers/net/failsafe/failsafe_ops.c | 37 +++++++++++-- drivers/net/failsafe/failsafe_private.h | 72 ++++++++++++++++++++++--- drivers/net/failsafe/failsafe_rxtx.c | 17 +++++- 8 files changed, 233 insertions(+), 20 deletions(-)
doc/guides/nics/fail_safe.rst +14 -0
@@ -51,6 +51,12 @@ The Fail-safe PMD only supports a limited set of features. If you plan to use a device underneath the Fail-safe PMD with a specific feature, this feature must be supported by the Fail-safe PMD to avoid throwing any error. +A notable exception is the device removal feature. The fail-safe PMD being a +virtual device, it cannot currently be removed in the sense of a specific bus +hotplug, like for PCI for example. It will however enable this feature for its +sub-device automatically, detecting those that are capable and register the +relevant callback for such event. + Check the feature matrix for the complete set of supported features. Compilation option
@@ -179,3 +185,11 @@ emit and receive packets. It will store any applied configuration, and try to apply it upon the probing of its missing sub-device. After this configuration pass, the new sub-device will be synchronized with other sub-devices, i.e. be started if the fail-safe PMD has been started by the user before. + +Plug-out feature +---------------- + +A sub-device supporting the device removal event can be removed from its bus at +any time. The fail-safe PMD will register a callback for such event and react +accordingly. It will try to safely stop, close and uninit the sub-device having +emitted this event, allowing it to free its eventual resources.
drivers/net/failsafe/failsafe.c +1 -0
@@ -142,6 +142,7 @@ fs_hotplug_alarm(void *arg)if (ret)ERROR ("Unable to synchronize sub_device state" ); } +failsafe_dev_remove (dev); ret =failsafe_hotplug_alarm_install (dev);if (ret)ERROR ("Unable to set up next alarm" );
drivers/net/failsafe/failsafe_args.c +13 -0
@@ -440,6 +440,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device (struct sub_device *sdev) +{ +struct rte_devargs *da; +char devstr[DEVARGS_MAXLEN ] ="" ; + + da = &sdev->devargs; +snprintf (devstr,sizeof (devstr),"%s,%s" , da->name, da->args); +return fs_parse_device (sdev, devstr); +} +int failsafe_args_parse_subs (struct rte_eth_dev *dev) {
@@ -452,6 +463,8 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev)continue ;if (sdev->cmdline) ret =fs_execute_cmd (sdev, sdev->cmdline); +else + ret =fs_parse_sub_device (sdev);if (ret ==0 ) sdev->state =DEV_PARSED ; }
drivers/net/failsafe/failsafe_eal.c +2 -1
@@ -63,6 +63,7 @@ fs_bus_init(struct rte_eth_dev *dev)return -ENODEV ; }SUB_ID (sdev) = i; + sdev->fs_dev = dev; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
@@ -80,7 +81,7 @@ failsafe_eal_init(struct rte_eth_dev *dev)return ret;if (PRIV (dev)->state <DEV_PROBED )PRIV (dev)->state =DEV_PROBED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
drivers/net/failsafe/failsafe_ether.c +90 -6
130 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +34 -3
@@ -34,6 +34,7 @@#include <stdint.h> #include <rte_debug.h> +#include <rte_atomic.h> #include <rte_ethdev.h> #include <rte_malloc.h> #include <rte_flow.h>
@@ -205,9 +206,21 @@ fs_dev_configure(struct rte_eth_dev *dev) } } FOREACH_SUBDEV(sdev, i, dev) { +int rmv_interrupt =0 ; +if (sdev->state !=DEV_PROBED )continue ; + + rmv_interrupt =ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_RMV ; +if (rmv_interrupt) { +DEBUG ("Enabling RMV interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.rmv =1 ; + }else { +DEBUG ("sub_device %d does not support RMV event" , i); + }DEBUG ("Configuring sub-device %d" , i); + sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues,
@@ -216,6 +229,16 @@ fs_dev_configure(struct rte_eth_dev *dev)ERROR ("Could not configure sub_device %d" , i);return ret; } +if (rmv_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_RMV , + failsafe_eth_rmv_event_callback, + sdev); +if (ret) +WARN ("Failed to register RMV callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.rmv =0 ; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
@@ -241,7 +264,7 @@ fs_dev_start(struct rte_eth_dev *dev) }if (PRIV (dev)->state <DEV_STARTED )PRIV (dev)->state =DEV_STARTED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
@@ -352,10 +375,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,fs_rx_queue_release (rxq); dev->data->rx_queues[rx_queue_id] =NULL ; } - rxq =rte_zmalloc (NULL ,sizeof (*rxq), + rxq =rte_zmalloc (NULL , +sizeof (*rxq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (rxq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&rxq->refcnt[i]); rxq->qid = rx_queue_id; rxq->socket_id = socket_id; rxq->info.mp = mb_pool;
@@ -415,10 +442,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,fs_tx_queue_release (txq); dev->data->tx_queues[tx_queue_id] =NULL ; } - txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), + txq =rte_zmalloc ("ethdev TX queue" , +sizeof (*txq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (txq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&txq->refcnt[i]); txq->qid = tx_queue_id; txq->socket_id = socket_id; txq->info.conf = *tx_conf;
drivers/net/failsafe/failsafe_private.h +64 -8
133 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c +15 -2
@@ -31,6 +31,7 @@* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <rte_atomic.h> #include <rte_debug.h> #include <rte_mbuf.h> #include <rte_ethdev.h>
@@ -112,8 +113,10 @@ failsafe_rx_burst(void *queue,if (unlikely (fs_rx_unsafe (sdev)))continue ; sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -146,8 +149,10 @@ failsafe_rx_burst_fast(void *queue, sdev = &priv->subs[i];RTE_ASSERT (!fs_rx_unsafe (sdev)); sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -164,13 +169,17 @@ failsafe_tx_burst(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);if (unlikely (fs_tx_unsafe (sdev)))return 0 ; sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }uint16_t
@@ -181,10 +190,14 @@ failsafe_tx_burst_fast(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);RTE_ASSERT (!fs_tx_unsafe (sdev)); sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }
Signature · 1 line
2.1.4
PATCH v10 10/11 net/failsafe: support link status change event
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_ether.c | 18 ++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 23 +++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 3 +++ 5 files changed, 46 insertions(+)
doc/guides/nics/features/failsafe.ini +1 -0
@@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y
drivers/net/failsafe/failsafe.c +1 -0
@@ -241,6 +241,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) mac->addr_bytes[0 ], mac->addr_bytes[1 ], mac->addr_bytes[2 ], mac->addr_bytes[3 ], mac->addr_bytes[4], mac->addr_bytes[5]); + dev->data->dev_flags |=RTE_ETH_DEV_INTR_LSC ;return 0 ; free_args:failsafe_args_free (dev);
drivers/net/failsafe/failsafe_ether.c +18 -0
@@ -387,3 +387,21 @@ failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, sdev->remove =1 ;return 0 ; } + +int +failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, + enum rte_eth_event_type event __rte_unused, + void *cb_arg, void *out __rte_unused) +{ +struct rte_eth_dev *dev = cb_arg; +int ret; + + ret = dev->dev_ops->link_update (dev,0 ); +/* We must pass on the LSC event */ +if (ret) +return _rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC , +NULL ,NULL ); +else +return 0 ; +}
drivers/net/failsafe/failsafe_ops.c +23 -0
@@ -207,6 +207,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } FOREACH_SUBDEV(sdev, i, dev) {int rmv_interrupt =0 ; +int lsc_interrupt =0 ; +int lsc_enabled;if (sdev->state !=DEV_PROBED )continue ;
@@ -219,6 +221,17 @@ fs_dev_configure(struct rte_eth_dev *dev) }else {DEBUG ("sub_device %d does not support RMV event" , i); } + lsc_enabled = dev->data->dev_conf.intr_conf.lsc; + lsc_interrupt = lsc_enabled && + (ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_LSC ); +if (lsc_interrupt) { +DEBUG ("Enabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =1 ; + }else if (lsc_enabled && !lsc_interrupt) { +DEBUG ("Disabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =0 ; + }DEBUG ("Configuring sub-device %d" , i); sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev),
@@ -239,6 +252,16 @@ fs_dev_configure(struct rte_eth_dev *dev) SUB_ID(sdev)); } dev->data->dev_conf.intr_conf.rmv =0 ; +if (lsc_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_LSC , + failsafe_eth_lsc_event_callback, + dev); +if (ret) +WARN ("Failed to register LSC callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.lsc = lsc_enabled; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
drivers/net/failsafe/failsafe_private.h +3 -0
@@ -179,6 +179,9 @@ void failsafe_dev_remove(struct rte_eth_dev *dev);int failsafe_eth_rmv_event_callback (uint8_t port_id,enum rte_eth_event_type type,void *arg,void *out); +int failsafe_eth_lsc_event_callback (uint8_t port_id, +enum rte_eth_event_type event, +void *cb_arg,void *out);/* GLOBALS */
Signature · 1 line
2.1.4
PATCH v10 11/11 net/failsafe: support flow API isolation mode
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ether.c | 34 +++++++++++++++++++++++++++++++-- drivers/net/failsafe/failsafe_flow.c | 29 ++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ether.c +32 -2
@@ -74,6 +74,28 @@ fs_flow_complain(struct rte_flow_error *error) }static int +eth_dev_flow_isolate_set (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_flow_error ferror; +int ret; + +if (!PRIV (dev)->flow_isolated) { +DEBUG ("Flow isolation already disabled" ); + }else { +DEBUG ("Enabling flow isolation" ); + ret =rte_flow_isolate (PORT_ID (sdev), +PRIV (dev)->flow_isolated, + &ferror); +if (ret) { +fs_flow_complain (&ferror); +return ret; + } + } +return 0 ; +} + +static int fs_eth_dev_conf_apply (struct rte_eth_dev *dev,struct sub_device *sdev) {
@@ -334,9 +356,17 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)if (PRIV (dev)->state <DEV_ACTIVE )return 0 ; inactive =0 ; - FOREACH_SUBDEV(sdev, i, dev) -if (sdev->state ==DEV_PROBED ) + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state ==DEV_PROBED ) { inactive |=UINT32_C (1 ) << i; + ret =eth_dev_flow_isolate_set (dev, sdev); +if (ret) { +ERROR ("Could not apply configuration to sub_device %d" , + i); + goto err_remove; + } + } + } ret = dev->dev_ops->dev_configure (dev);if (ret) goto err_remove;
drivers/net/failsafe/failsafe_flow.c +29 -0
@@ -206,10 +206,39 @@ fs_flow_query(struct rte_eth_dev *dev,return -1 ; } +static int +fs_flow_isolate (struct rte_eth_dev *dev, +int set, +struct rte_flow_error *error) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state <DEV_PROBED ) +continue ; +DEBUG ("Calling rte_flow_isolate on sub_device %d" , i); +if (PRIV (dev)->flow_isolated != sdev->flow_isolated) +WARN ("flow isolation mode of sub_device %d in incoherent state." , + i); + ret =rte_flow_isolate (PORT_ID (sdev), set, error); +if (ret) { +ERROR ("Operation rte_flow_isolate failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + sdev->flow_isolated = set; + } +PRIV (dev)->flow_isolated = set; +return 0 ; +} +const struct rte_flow_ops fs_flow_ops = { .validate = fs_flow_validate, .create = fs_flow_create, .destroy = fs_flow_destroy, .flush = fs_flow_flush, .query = fs_flow_query, + .isolate = fs_flow_isolate, };
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -108,6 +108,8 @@ struct sub_device {struct rte_eth_dev *fs_dev;/* flag calling for recollection */ volatile unsigned int remove:1; +/* flow isolation state */ + int flow_isolated:1; };struct fs_priv {
@@ -139,6 +141,8 @@ struct fs_priv {*/ enum dev_state state; unsigned int pending_alarm:1; /* An alarm is pending */ +/* flow isolation state */ + int flow_isolated:1; };/* MISC */
Signature · 1 line
2.1.4
v11 cover introduce fail-safe PMD
In reply to Gaetan RivetThis PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
[dpdk-dev] [PATCH v4 0/8] fix hotplug API
http://dpdk.org/ml/archives/dev/2017-July/071340.html
v1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixes
v2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.
v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports plugin
v4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fix rte_dev hotplug API implementation.
- Introduce rte_eal_devargs_rmv API as EXPERIMENTAL.
- Use it to clean up resources on hotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.
This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.
These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Use rte_eth_dev_allocated when relevant.
v8 --> v9
- Use calloc instead of rte_realloc for command line parsing.
- Include errno only when necessary.
v9 --> v10
- Fix rte_flow description double-free issue. Thanks Raslan for finding the issue :)
- Use RTE_ASSERT instead of assert.
Integrate the debug log of the fail-safe to RTE_LOG_DEBUG macro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.
v10 --> v11
- Added Glossary in documentation.
- Fixed issues oulined in [1].
- Removed Rx offload advertizement in feature matrix.
[1]: http://dpdk.org/ml/archives/dev/2017-July/071406.html
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support Rx offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
MAINTAINERS | 5 + config/common_base | 5 + doc/guides/nics/fail_safe.rst | 221 ++++++ doc/guides/nics/features/failsafe.ini | 26 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 60 ++ drivers/net/failsafe/failsafe.c | 299 ++++++++ drivers/net/failsafe/failsafe_args.c | 468 ++++++++++++ drivers/net/failsafe/failsafe_eal.c | 118 +++ drivers/net/failsafe/failsafe_ether.c | 437 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 244 ++++++ drivers/net/failsafe/failsafe_ops.c | 867 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 359 +++++++++ drivers/net/failsafe/failsafe_rxtx.c | 203 +++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + lib/librte_ether/rte_ethdev.c | 19 +- lib/librte_ether/rte_ethdev.h | 14 +- mk/rte.app.mk | 1 + 19 files changed, 3338 insertions(+), 15 deletions(-) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ether.c create mode 100644 drivers/net/failsafe/failsafe_flow.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
Signature · 1 line
2.1.4
PATCH v11 1/11 ethdev: add deferred intermediate device state
This device state means that the device is managed externally, by whichever party has set this state (PMD or application).
Note: this new device state is only an information. The related device structure and operators are still valid and can be used normally.
It is however made private by device management helpers within ethdev, making the device invisible to applications.
--- lib/librte_ether/rte_ethdev.c | 3 ++- lib/librte_ether/rte_ethdev.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
lib/librte_ether/rte_ethdev.c +2 -1
@@ -291,7 +291,8 @@ int rte_eth_dev_is_valid_port(uint8_t port_id) {if (port_id >=RTE_MAX_ETHPORTS || - rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED ) + (rte_eth_devices[port_id].state !=RTE_ETH_DEV_ATTACHED && + rte_eth_devices[port_id].state !=RTE_ETH_DEV_DEFERRED ))return 0 ;else return 1 ;
lib/librte_ether/rte_ethdev.h +1 -0
@@ -1611,6 +1611,7 @@ struct rte_eth_rxtx_callback {enum rte_eth_dev_state {RTE_ETH_DEV_UNUSED =0 ,RTE_ETH_DEV_ATTACHED , +RTE_ETH_DEV_DEFERRED , };/**
Signature · 1 line
2.1.4
Re: [PATCH v11 01/11] ethdev: add deferred intermediate device state
18/07/2017 15:48, Gaetan Rivet:
Quoted 10 lines
This device state means that the device is managed externally, by whichever party has set this state (PMD or application).
Note: this new device state is only an information. The related device structure and operators are still valid and can be used normally.
It is however made private by device management helpers within ethdev, making the device invisible to applications.
Signed-off-by Gaetan Rivet <[email protected]>
Ferruh, it can be taken in next-net as part of failsafe series. Thanks
PATCH v11 2/11 ethdev: count devices consistently
In reply to Gaetan RivetMake the rte_eth_dev_count() return the number of available devices even after some are detached by the hotplug API or put in a deferred state.
--- lib/librte_ether/rte_ethdev.c | 16 +++++++++------- lib/librte_ether/rte_ethdev.h | 13 ++++++------- 2 files changed, 15 insertions(+), 14 deletions(-)
lib/librte_ether/rte_ethdev.c +9 -7
@@ -72,7 +72,6 @@ static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS ];static struct rte_eth_dev_data *rte_eth_dev_data;static uint8_t eth_dev_last_created_port; -static uint8_t nb_ports;/* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock =RTE_SPINLOCK_INITIALIZER ;
@@ -210,7 +209,6 @@ eth_dev_get(uint8_t port_id)TAILQ_INIT (&(eth_dev->link_intr_cbs)); eth_dev_last_created_port = port_id; - nb_ports++;return eth_dev; }
@@ -283,7 +281,6 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)return -EINVAL ; eth_dev->state =RTE_ETH_DEV_UNUSED ; - nb_ports--;return 0 ; }
@@ -308,7 +305,15 @@ rte_eth_dev_socket_id(uint8_t port_id)uint8_t rte_eth_dev_count (void ) { -return nb_ports; +uint8_t p; +uint8_t count; + + count =0 ; + +RTE_ETH_FOREACH_DEV (p) + count++; + +return count; }int
@@ -341,9 +346,6 @@ rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id)return -EINVAL ; } -if (!nb_ports) -return -ENODEV ; -RTE_ETH_FOREACH_DEV (i) {if (!rte_eth_devices[i].device)continue ;
lib/librte_ether/rte_ethdev.h +6 -7
@@ -1746,13 +1746,12 @@ uint8_t rte_eth_find_next(uint8_t port_id);/** * Get the total number of Ethernet devices that have been successfully -* initialized by the [matching] Ethernet driver during the PCI probing phase. -* All devices whose port identifier is in the range -* [0, rte_eth_dev_count() - 1] can be operated on by network applications -* immediately after invoking rte_eal_init(). -* If the application unplugs a port using hotplug function, The enabled port -* numbers may be noncontiguous. In the case, the applications need to manage -* enabled port by using the ``RTE_ETH_FOREACH_DEV()`` macro. +* initialized by the matching Ethernet driver during the PCI probing phase +* and that are available for applications to use. These devices must be +* accessed by using the ``RTE_ETH_FOREACH_DEV()`` macro to deal with +* non-contiguous ranges of devices. +* These non-contiguous ranges can be created by calls to hotplug functions or +* by some PMDs. * * @return * - The total number of usable Ethernet devices.
Signature · 1 line
2.1.4
Re: [PATCH v11 02/11] ethdev: count devices consistently
18/07/2017 15:48, Gaetan Rivet:
Quoted 4 lines
Make the
rte_eth_dev_count()return the number of available devices even after some are detached by the hotplug API or put in a deferred state.Signed-off-by Gaetan Rivet <[email protected]>
Ferruh, it can be taken in next-net as part of failsafe series. Thanks
PATCH v11 3/11 net/failsafe: add fail-safe PMD
In reply to Gaetan RivetIntroduce the fail-safe poll mode driver initialization and enable its build infrastructure.
This PMD allows for applications to benefit from true hot-plugging support without having to implement it.
It intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back. It also allows defining a contingency to the removal of a device, by designating a fail-over device that will take on transmitting operations if the preferred device is removed.
Applications only see a fail-safe instance, without caring for underlying activity ensuring their continued operations.
--- MAINTAINERS | 5 + config/common_base | 5 + doc/guides/nics/fail_safe.rst | 163 ++++++ doc/guides/nics/features/failsafe.ini | 24 + doc/guides/nics/index.rst | 1 + drivers/net/Makefile | 2 + drivers/net/failsafe/Makefile | 58 ++ drivers/net/failsafe/failsafe.c | 225 ++++++++ drivers/net/failsafe/failsafe_args.c | 327 +++++++++++ drivers/net/failsafe/failsafe_eal.c | 138 +++++ drivers/net/failsafe/failsafe_ops.c | 662 ++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 208 +++++++ drivers/net/failsafe/failsafe_rxtx.c | 107 ++++ drivers/net/failsafe/rte_pmd_failsafe_version.map | 4 + mk/rte.app.mk | 1 + 15 files changed, 1930 insertions(+) create mode 100644 doc/guides/nics/fail_safe.rst create mode 100644 doc/guides/nics/features/failsafe.ini create mode 100644 drivers/net/failsafe/Makefile create mode 100644 drivers/net/failsafe/failsafe.c create mode 100644 drivers/net/failsafe/failsafe_args.c create mode 100644 drivers/net/failsafe/failsafe_eal.c create mode 100644 drivers/net/failsafe/failsafe_ops.c create mode 100644 drivers/net/failsafe/failsafe_private.h create mode 100644 drivers/net/failsafe/failsafe_rxtx.c create mode 100644 drivers/net/failsafe/rte_pmd_failsafe_version.map
MAINTAINERS +5 -0
@@ -349,6 +349,11 @@ F: drivers/net/enic/ F: doc/guides/nics/enic.rst F: doc/guides/nics/features/enic.ini +Fail-safe PMD +M: Gaetan Rivet <[email protected]> +F: drivers/net/failsafe/ +F: doc/guides/nics/fail_safe.rst + Intel e1000 M: Wenzhuo Lu <[email protected]> F: drivers/net/e1000/
config/common_base +5 -0
@@ -420,6 +420,11 @@ CONFIG_RTE_LIBRTE_PMD_XENVIRT=n CONFIG_RTE_LIBRTE_PMD_NULL=y # +# Compile fail-safe PMD +# +CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y + +# # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y
doc/guides/nics/fail_safe.rst new file +163 -0
163 lines not on this page · raw message
doc/guides/nics/features/failsafe.ini new file +24 -0
@@ -0,0 +1,24 @@ +; +; Supported features of the 'fail-safe' poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Link status = Y +MTU update = Y +Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y +Unicast MAC filter = Y +Multicast MAC filter = Y +VLAN filter = Y +Flow control = Y +Packet type parsing = Y +Basic stats = Y +Stats per queue = Y +ARMv7 = Y +ARMv8 = Y +Power8 = Y +x86-32 = Y +x86-64 = Y +Usage doc = Y
doc/guides/nics/index.rst +1 -0
@@ -64,6 +64,7 @@ Network Interface Controller Drivers vhost vmxnet3 pcap_ring + fail_safe **Figures**
drivers/net/Makefile +2 -0
@@ -59,6 +59,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += ena DEPDIRS-ena = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DEPDIRS-enic = $(core-libs) librte_hash +DIRS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe +DEPDIRS-failsafe = $(core-libs) DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DEPDIRS-fm10k = $(core-libs) librte_hash DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e
drivers/net/failsafe/Makefile new file +58 -0
58 lines not on this page · raw message
drivers/net/failsafe/failsafe.c new file +225 -0
225 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c new file +327 -0
327 lines not on this page · raw message
drivers/net/failsafe/failsafe_eal.c new file +138 -0
138 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c new file +662 -0
662 lines not on this page · raw message
drivers/net/failsafe/failsafe_private.h new file +208 -0
208 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c new file +107 -0
107 lines not on this page · raw message
drivers/net/failsafe/rte_pmd_failsafe_version.map new file +4 -0
@@ -0,0 +1,4 @@ +DPDK_17.08 { + + local: *; +};
mk/rte.app.mk +1 -0
@@ -121,6 +121,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_ENA_PMD) += -lrte_pmd_ena _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += -lrte_pmd_failsafe _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
Signature · 1 line
2.1.4
PATCH v11 4/11 net/failsafe: add plug-in support
In reply to Gaetan RivetPeriodically check for the existence of a device.
If a device has not been initialized and exists on the system, then it is probed and configured.
The configuration process strives to synchronize the states between the plugged-in sub-device and the fail-safe device.
--- doc/guides/nics/fail_safe.rst | 23 ++++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 71 ++++++++++ drivers/net/failsafe/failsafe_args.c | 32 +++++ drivers/net/failsafe/failsafe_eal.c | 30 +---- drivers/net/failsafe/failsafe_ether.c | 228 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 25 ++-- drivers/net/failsafe/failsafe_private.h | 60 ++++++++- 8 files changed, 428 insertions(+), 42 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c
doc/guides/nics/fail_safe.rst +23 -0
@@ -98,6 +98,11 @@ Fail-safe command line parameters address is generated, that will be subsequently applied to all sub-device once they are probed. +- **hotplug_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two slave upkeep round. + Usage example ~~~~~~~~~~~~~
@@ -140,6 +145,20 @@ access, and in particular, using the ``RTE_ETH_FOREACH_DEV`` macro to iterate over ethernet devices, instead of directly accessing them or by writing one's own device iterator. +Plug-in feature +--------------- + +A sub-device can be defined without existing on the system when the fail-safe +PMD is initialized. Upon probing this device, the fail-safe PMD will detect its +absence and postpone its use. It will then register for a periodic check on any +missing sub-device. + +During this time, the fail-safe PMD can be used normally, configured and told to +emit and receive packets. It will store any applied configuration, and try to +apply it upon the probing of its missing sub-device. After this configuration +pass, the new sub-device will be synchronized with other sub-devices, i.e. be +started if the fail-safe PMD has been started by the user before. + Fail-safe glossary ------------------
@@ -153,6 +172,10 @@ Preferred device : Primary device It is the main sub-device and is used as target for configuration operations if there is any ambiguity. +Upkeep round + Periodical process when slaves are serviced. Each devices having a state + different to that of the fail-safe device itself, is synchronized with it. + Slave In the context of the fail-safe PMD, synonymous to sub-device.
drivers/net/failsafe/Makefile +1 -0
@@ -44,6 +44,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c # No exported include files
drivers/net/failsafe/failsafe.c +71 -0
83 lines not on this page · raw message
drivers/net/failsafe/failsafe_args.c +32 -0
@@ -32,6 +32,7 @@*/ #include <string.h> +#include <errno.h> #include <rte_devargs.h> #include <rte_malloc.h>
@@ -45,9 +46,11 @@typedef int (parse_cb )(struct rte_eth_dev *dev,const char *params,uint8_t head); +uint64_t hotplug_poll =FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS ;int mac_from_arg =0 ;const char *pmd_failsafe_init_parameters[] = { +PMD_FAILSAFE_HOTPLUG_POLL_KVARG ,PMD_FAILSAFE_MAC_KVARG ,NULL , };
@@ -221,6 +224,24 @@ fs_remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) }static int +fs_get_u64_arg(const char *key __rte_unused, +const char *value,void *out) +{ +uint64_t *u64 = out; +char *endptr =NULL ; + +if ((value ==NULL ) || (out ==NULL )) +return -EINVAL ; + errno =0 ; + *u64 =strtoull (value, &endptr,0 ); +if (errno !=0 ) +return -errno; +if (endptr == value) +return -1 ; +return 0 ; +} + +static int fs_get_mac_addr_arg(const char *key __rte_unused,const char *value,void *out) {
@@ -271,6 +292,16 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) PMD_FAILSAFE_PARAM_STRING);return -1 ; } +/* PLUG_IN event poll timer */ + arg_count =rte_kvargs_count (kvlist, +PMD_FAILSAFE_HOTPLUG_POLL_KVARG ); +if (arg_count ==1 ) { + ret =rte_kvargs_process (kvlist, +PMD_FAILSAFE_HOTPLUG_POLL_KVARG , + &fs_get_u64_arg, &hotplug_poll); +if (ret <0 ) + goto free_kvlist; + }/* MAC addr */ arg_count =rte_kvargs_count (kvlist,PMD_FAILSAFE_MAC_KVARG );
@@ -284,6 +315,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) mac_from_arg =1 ; } } +PRIV (dev)->state =DEV_PARSED ; free_kvlist:rte_kvargs_free (kvlist);return ret;
drivers/net/failsafe/failsafe_eal.c +4 -26
@@ -72,37 +72,14 @@ fs_bus_init(struct rte_eth_dev *dev)int failsafe_eal_init (struct rte_eth_dev *dev) { -struct sub_device *sdev; -uint8_t i;int ret; ret =fs_bus_init (dev);if (ret)return ret; -/* -* We only update TX_SUBDEV if we are not started. -* If a sub_device is emitting, we will switch the TX_SUBDEV to the -* preferred port only upon starting it, so that the switch is smoother. -*/ -if (PREFERRED_SUBDEV (dev)->state >=DEV_PROBED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev) && - (TX_SUBDEV (dev) ==NULL || - (TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ))) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_PROBED ) || -TX_SUBDEV (dev) ==NULL ) { -/* Using first probed device */ - FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { -DEBUG ("Switching tx_dev to sub_device %d" , - i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_PROBED ) +PRIV (dev)->state =DEV_PROBED ; +fs_switch_dev (dev);return 0 ; }
@@ -134,5 +111,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret =fs_bus_uninit (dev);if (ret)return ret; +PRIV (dev)->state =DEV_PROBED -1 ;return 0 ; }
drivers/net/failsafe/failsafe_ether.c new file +228 -0
228 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +10 -15
@@ -89,6 +89,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } sdev->state =DEV_ACTIVE ; } +if (PRIV (dev)->state <DEV_ACTIVE ) +PRIV (dev)->state =DEV_ACTIVE ;return 0 ; }
@@ -108,21 +110,9 @@ fs_dev_start(struct rte_eth_dev *dev)return ret; sdev->state =DEV_STARTED ; } -if (PREFERRED_SUBDEV (dev)->state ==DEV_STARTED ) { -if (TX_SUBDEV (dev) !=PREFERRED_SUBDEV (dev)) { -DEBUG ("Switching tx_dev to preferred sub_device" ); -PRIV (dev)->subs_tx =0 ; - } - }else { -if ((TX_SUBDEV (dev) &&TX_SUBDEV (dev)->state <DEV_STARTED ) || -TX_SUBDEV (dev) ==NULL ) { - FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_STARTED) { -DEBUG ("Switching tx_dev to sub_device %d" , i); -PRIV (dev)->subs_tx = i; -break ; - } - } - } +if (PRIV (dev)->state <DEV_STARTED ) +PRIV (dev)->state =DEV_STARTED ; +fs_switch_dev (dev);return 0 ; }
@@ -132,6 +122,7 @@ fs_dev_stop(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +PRIV (dev)->state =DEV_STARTED -1 ; FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_STARTED) {rte_eth_dev_stop (PORT_ID (sdev)); sdev->state =DEV_STARTED -1 ;
@@ -183,6 +174,10 @@ fs_dev_close(struct rte_eth_dev *dev)struct sub_device *sdev;uint8_t i; +failsafe_hotplug_alarm_cancel (dev); +if (PRIV (dev)->state ==DEV_STARTED ) + dev->dev_ops->dev_stop (dev); +PRIV (dev)->state =DEV_ACTIVE -1 ; FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {DEBUG ("Closing sub_device %d" , i);rte_eth_dev_close (PORT_ID (sdev));
drivers/net/failsafe/failsafe_private.h +59 -1
92 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v11 5/11 net/failsafe: add flexible device definition
In reply to Gaetan RivetAdd the "exec" device type.
The parameters given to this type of device will be executed in a shell. The output of this command is then used as a definition for a device.
That command can be re-interpreted if the related device is not plugged-in. It allows for a device definition to react to system changes (e.g. changing PCI bus for a given device).
--- doc/guides/nics/fail_safe.rst | 20 +++++++ drivers/net/failsafe/failsafe_args.c | 98 ++++++++++++++++++++++++++++++++- drivers/net/failsafe/failsafe_ether.c | 7 +++ drivers/net/failsafe/failsafe_private.h | 4 ++ 4 files changed, 128 insertions(+), 1 deletion(-)
doc/guides/nics/fail_safe.rst +20 -0
@@ -87,6 +87,19 @@ Fail-safe command line parameters additional sub-device parameters if need be. They will be passed on to the sub-device. +- **exec(<shell command>)** parameter + + This parameter allows the user to provide a command to the fail-safe PMD to + execute and define a sub-device. + It is done within a regular shell context. + The first line of its output is read by the fail-safe PMD and otherwise + interpreted as if passed by the regular **dev** parameter. + Any other line is discarded. + If the command fail or output an incorrect string, the sub-device is not + initialized. + All commas within the ``shell command`` are replaced by spaces before + executing the command. This helps using scripts to specify devices. + - **mac** parameter [MAC address] This parameter allows the user to set a default MAC address to the fail-safe
@@ -134,6 +147,13 @@ This section shows some example of using **testpmd** with a fail-safe PMD. --vdev 'net_failsafe0,mac=de:ad:be:ef:01:02,dev(84:00.0),dev(net_ring0)' -w 81:00.0 -- -i +#. Start testpmd using a flexible device definition + + .. code-block:: console + + $RTE_TARGET/build/app/testpmd -c 0xff -n 4 --no-pci \ + --vdev='net_failsafe0,exec(echo 84:00.0)' -- -i + Using the Fail-safe PMD from an application -------------------------------------------
drivers/net/failsafe/failsafe_args.c +97 -1
131 lines not on this page · raw message
drivers/net/failsafe/failsafe_ether.c +7 -0
@@ -188,6 +188,13 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)int ret;uint8_t i; +if (PRIV (dev)->state <DEV_PARSED ) +return 0 ; + + ret =failsafe_args_parse_subs (dev); +if (ret) +return ret; +if (PRIV (dev)->state <DEV_PROBED )return 0 ; ret =failsafe_eal_init (dev);
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -44,6 +44,7 @@#define PMD_FAILSAFE_HOTPLUG_POLL_KVARG "hotplug_poll"#define PMD_FAILSAFE_PARAM_STRING \ "dev(<ifc>)," \ + "exec(<shell command>)," \ "mac=mac_addr," \ "hotplug_poll=u64" \ ""
@@ -87,6 +88,8 @@ struct sub_device {struct rte_eth_dev *edev;/* Device state machine */ enum dev_state state; +/* Some device are defined as a command line */ +char *cmdline; };struct fs_priv {
@@ -135,6 +138,7 @@ uint16_t failsafe_tx_burst(void *txq,int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);void failsafe_args_free (struct rte_eth_dev *dev);int failsafe_args_count_subdevice (struct rte_eth_dev *dev,const char *params); +int failsafe_args_parse_subs (struct rte_eth_dev *dev);/* EAL */
Signature · 1 line
2.1.4
PATCH v11 6/11 net/failsafe: support flow API
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 215 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 336 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c
doc/guides/nics/features/failsafe.ini +1 -0
@@ -13,6 +13,7 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow control = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y
drivers/net/failsafe/Makefile +1 -0
@@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files
drivers/net/failsafe/failsafe.c +1 -0
@@ -179,6 +179,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV (dev)->mac_addrs[0 ]; dev->data->dev_link = eth_link;PRIV (dev)->nb_mac_addr =1 ; +TAILQ_INIT (&PRIV (dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; ret =fs_sub_device_alloc (dev, params);
drivers/net/failsafe/failsafe_eal.c +1 -0
@@ -62,6 +62,7 @@ fs_bus_init(struct rte_eth_dev *dev)ERROR ("sub_device %d init went wrong" , i);return -ENODEV ; } +SUB_ID (sdev) = i; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
drivers/net/failsafe/failsafe_ether.c +70 -0
90 lines not on this page · raw message
drivers/net/failsafe/failsafe_flow.c new file +215 -0
215 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +29 -0
@@ -36,6 +36,7 @@#include <rte_debug.h> #include <rte_ethdev.h> #include <rte_malloc.h> +#include <rte_flow.h> #include "failsafe_private.h"
@@ -627,6 +628,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)rte_eth_dev_default_mac_addr_set (PORT_ID (sdev), mac_addr); } +static int +fs_filter_ctrl (struct rte_eth_dev *dev, +enum rte_filter_type type, +enum rte_filter_op op, +void *arg) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + +if (type ==RTE_ETH_FILTER_GENERIC && + op ==RTE_ETH_FILTER_GET ) { + *(const void **)arg = &fs_flow_ops; +return 0 ; + } + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { +DEBUG ("Calling rte_eth_dev_filter_ctrl on sub_device %d" , i); + ret =rte_eth_dev_filter_ctrl (PORT_ID (sdev), type, op, arg); +if (ret) { +ERROR ("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + } +return 0 ; +} +const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start,
@@ -654,4 +682,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, };
drivers/net/failsafe/failsafe_private.h +18 -0
@@ -34,6 +34,8 @@#ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_#define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include <sys/queue.h> +#include <rte_dev.h> #include <rte_ethdev.h> #include <rte_devargs.h>
@@ -72,6 +74,14 @@ struct txq {struct rte_eth_txq_info info; }; +struct rte_flow { +TAILQ_ENTRY (rte_flow) next; +/* sub_flows */ +struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS ]; +/* flow description for synchronization */ +struct rte_flow_desc *fd; +}; +enum dev_state {DEV_UNDEFINED ,DEV_PARSED ,
@@ -86,6 +96,7 @@ struct sub_device {struct rte_bus *bus;struct rte_device *dev;struct rte_eth_dev *edev; +uint8_t sid;/* Device state machine */ enum dev_state state;/* Some device are defined as a command line */
@@ -104,6 +115,8 @@ struct fs_priv {uint8_t subs_tail;/* first invalid */ uint8_t subs_tx;/* current emitting device */ uint8_t current_probed; +/* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list;/* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr;struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR ];
@@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);extern const char pmd_failsafe_driver_name[];extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops;extern uint64_t hotplug_poll;extern int mac_from_arg;
@@ -170,6 +184,10 @@ extern int mac_from_arg;#define PORT_ID (sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID (sdev) \ + ((sdev)->sid) +/** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator
Signature · 1 line
2.1.4
PATCH v11 7/11 net/failsafe: support Rx offload capabilities
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ops.c | 131 +++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ops.c +129 -2
@@ -63,22 +63,149 @@ static struct rte_eth_dev_info default_infos = { .nb_seg_max = UINT16_MAX, .nb_mtu_seg_max = UINT16_MAX, }, - /* Set of understood capabilities */ - .rx_offload_capa = 0x0, +/* +* Set of capabilities that can be verified upon +* configuring a sub-device. +*/ + .rx_offload_capa = +DEV_RX_OFFLOAD_VLAN_STRIP | +DEV_RX_OFFLOAD_QINQ_STRIP | +DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_TCP_LRO, .tx_offload_capa = 0x0, .flow_type_rss_offloads = 0x0, }; +/** +* Check whether a specific offloading capability +* is supported by a sub_device. +* +* @return +* 0: all requested capabilities are supported by the sub_device +* positive value: This flag at least is not supported by the sub_device +*/ +static int +fs_port_offload_validate (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_eth_dev_info infos = {0 }; +struct rte_eth_conf *cf; +uint32_t cap; + + cf = &dev->data->dev_conf; +SUBOPS (sdev, dev_infos_get)(ETH (sdev), &infos); +/* RX capabilities */ + cap = infos.rx_offload_capa; +if (cf->rxmode.hw_vlan_strip && + ((cap &DEV_RX_OFFLOAD_VLAN_STRIP ) ==0 )) { +WARN ("VLAN stripping offload requested but not supported by sub_device %d" , +SUB_ID (sdev)); +return DEV_RX_OFFLOAD_VLAN_STRIP ; + } +if (cf->rxmode.hw_ip_checksum && + ((cap & (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM )) != + (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ))) { +WARN ("IP checksum offload requested but not supported by sub_device %d" , +SUB_ID (sdev)); +return DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ; + } +if (cf->rxmode.enable_lro && + ((cap &DEV_RX_OFFLOAD_TCP_LRO ) ==0 )) { +WARN ("TCP LRO offload requested but not supported by sub_device %d" , +SUB_ID (sdev)); +return DEV_RX_OFFLOAD_TCP_LRO ; + } +if (cf->rxmode.hw_vlan_extend && + ((cap &DEV_RX_OFFLOAD_QINQ_STRIP ) ==0 )) { +WARN ("Stacked VLAN stripping offload requested but not supported by sub_device %d" , +SUB_ID (sdev)); +return DEV_RX_OFFLOAD_QINQ_STRIP ; + } +/* TX capabilities */ +/* Nothing to do, no tx capa supported */ +return 0 ; +} + +/* +* Disable the dev_conf flag related to an offload capability flag +* within an ethdev configuration. +*/ +static int +fs_port_disable_offload (struct rte_eth_conf *cf, +uint32_t ol_cap) +{ +switch (ol_cap) { +case DEV_RX_OFFLOAD_VLAN_STRIP : +INFO ("Disabling VLAN stripping offload" ); + cf->rxmode.hw_vlan_strip =0 ; +break ; +case DEV_RX_OFFLOAD_IPV4_CKSUM : +case DEV_RX_OFFLOAD_UDP_CKSUM : +case DEV_RX_OFFLOAD_TCP_CKSUM : +case (DEV_RX_OFFLOAD_IPV4_CKSUM | +DEV_RX_OFFLOAD_UDP_CKSUM | +DEV_RX_OFFLOAD_TCP_CKSUM ): +INFO ("Disabling IP checksum offload" ); + cf->rxmode.hw_ip_checksum =0 ; +break ; +case DEV_RX_OFFLOAD_TCP_LRO : +INFO ("Disabling TCP LRO offload" ); + cf->rxmode.enable_lro =0 ; +break ; +case DEV_RX_OFFLOAD_QINQ_STRIP : +INFO ("Disabling stacked VLAN stripping offload" ); + cf->rxmode.hw_vlan_extend =0 ; +break ; +default : +DEBUG ("Unable to disable offload capability: %" PRIx32, + ol_cap); +return -1 ; + } +return 0 ; +} +static int fs_dev_configure (struct rte_eth_dev *dev) {struct sub_device *sdev;uint8_t i; +int capa_flag;int ret; FOREACH_SUBDEV(sdev, i, dev) {if (sdev->state !=DEV_PROBED )continue ; +DEBUG ("Checking capabilities for sub_device %d" , i); +while ((capa_flag =fs_port_offload_validate (dev, sdev))) { +/* +* Refuse to change configuration if multiple devices +* are present and we already have configured at least +* some of them. +*/ +if (PRIV (dev)->state >=DEV_ACTIVE && +PRIV (dev)->subs_tail >1 ) { +ERROR ("device already configured, cannot fix live configuration" ); +return -1 ; + } + ret =fs_port_disable_offload (&dev->data->dev_conf, + capa_flag); +if (ret) { +ERROR ("Unable to disable offload capability" ); +return ret; + } + } + } + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state !=DEV_PROBED ) +continue ;DEBUG ("Configuring sub-device %d" , i); ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues,
Signature · 1 line
2.1.4
PATCH v11 8/11 net/failsafe: add fast burst functions
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_private.h | 8 +++ drivers/net/failsafe/failsafe_rxtx.c | 123 ++++++++++++++++++++++++++------ 2 files changed, 111 insertions(+), 20 deletions(-)
drivers/net/failsafe/failsafe_private.h +8 -0
@@ -141,11 +141,18 @@ int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);/* RX / TX */ +void set_burst_fn (struct rte_eth_dev *dev,int force_safe); +uint16_t failsafe_rx_burst (void *rxq,struct rte_mbuf **rx_pkts,uint16_t nb_pkts);uint16_t failsafe_tx_burst (void *txq,struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +uint16_t failsafe_rx_burst_fast (void *rxq, +struct rte_mbuf **rx_pkts,uint16_t nb_pkts); +uint16_t failsafe_tx_burst_fast (void *txq, +struct rte_mbuf **tx_pkts,uint16_t nb_pkts); +/* ARGS */ int failsafe_args_parse (struct rte_eth_dev *dev,const char *params);
@@ -282,6 +289,7 @@ fs_switch_dev(struct rte_eth_dev *dev) }else {return ; } +set_burst_fn (dev,0 );rte_wmb (); }
drivers/net/failsafe/failsafe_rxtx.c +103 -20
153 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v11 9/11 net/failsafe: support device removal
In reply to Gaetan RivetListen to INTR_RMV events issued by slaves.
Add atomic flags on slave queues to detect use of slave bursts function. If a removal is detected, set the recollection flag on this slave.
During a slave upkeep round, if its recollection flag is set and its burst functions are not in use by any thread, remove that slave.
--- doc/guides/nics/fail_safe.rst | 15 ++++++ drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_args.c | 13 +++++ drivers/net/failsafe/failsafe_eal.c | 3 +- drivers/net/failsafe/failsafe_ether.c | 96 ++++++++++++++++++++++++++++++--- drivers/net/failsafe/failsafe_ops.c | 37 +++++++++++-- drivers/net/failsafe/failsafe_private.h | 72 ++++++++++++++++++++++--- drivers/net/failsafe/failsafe_rxtx.c | 17 +++++- 8 files changed, 234 insertions(+), 20 deletions(-)
doc/guides/nics/fail_safe.rst +15 -0
@@ -51,6 +51,12 @@ The Fail-safe PMD only supports a limited set of features. If you plan to use a device underneath the Fail-safe PMD with a specific feature, this feature must be supported by the Fail-safe PMD to avoid throwing any error. +A notable exception is the device removal feature. The fail-safe PMD being a +virtual device, it cannot currently be removed in the sense of a specific bus +hotplug, like for PCI for example. It will however enable this feature for its +sub-device automatically, detecting those that are capable and register the +relevant callback for such event. + Check the feature matrix for the complete set of supported features. Compilation option
@@ -179,6 +185,14 @@ apply it upon the probing of its missing sub-device. After this configuration pass, the new sub-device will be synchronized with other sub-devices, i.e. be started if the fail-safe PMD has been started by the user before. +Plug-out feature +---------------- + +A sub-device supporting the device removal event can be removed from its bus at +any time. The fail-safe PMD will register a callback for such event and react +accordingly. It will try to safely stop, close and uninit the sub-device having +emitted this event, allowing it to free its eventual resources. + Fail-safe glossary ------------------
@@ -195,6 +209,7 @@ Preferred device : Primary device Upkeep round Periodical process when slaves are serviced. Each devices having a state different to that of the fail-safe device itself, is synchronized with it. + Additionally, each slave having the remove flag set are cleaned-up. Slave In the context of the fail-safe PMD, synonymous to sub-device.
drivers/net/failsafe/failsafe.c +1 -0
@@ -142,6 +142,7 @@ fs_hotplug_alarm(void *arg)if (ret)ERROR ("Unable to synchronize sub_device state" ); } +failsafe_dev_remove (dev); ret =failsafe_hotplug_alarm_install (dev);if (ret)ERROR ("Unable to set up next alarm" );
drivers/net/failsafe/failsafe_args.c +13 -0
@@ -436,6 +436,17 @@ failsafe_args_count_subdevice(struct rte_eth_dev *dev, dev, params); } +static int +fs_parse_sub_device (struct sub_device *sdev) +{ +struct rte_devargs *da; +char devstr[DEVARGS_MAXLEN ] ="" ; + + da = &sdev->devargs; +snprintf (devstr,sizeof (devstr),"%s,%s" , da->name, da->args); +return fs_parse_device (sdev, devstr); +} +int failsafe_args_parse_subs (struct rte_eth_dev *dev) {
@@ -448,6 +459,8 @@ failsafe_args_parse_subs(struct rte_eth_dev *dev)continue ;if (sdev->cmdline) ret =fs_execute_cmd (sdev, sdev->cmdline); +else + ret =fs_parse_sub_device (sdev);if (ret ==0 ) sdev->state =DEV_PARSED ; }
drivers/net/failsafe/failsafe_eal.c +2 -1
@@ -63,6 +63,7 @@ fs_bus_init(struct rte_eth_dev *dev)return -ENODEV ; }SUB_ID (sdev) = i; + sdev->fs_dev = dev; sdev->dev =ETH (sdev)->device;ETH (sdev)->state =RTE_ETH_DEV_DEFERRED ; sdev->state =DEV_PROBED ;
@@ -80,7 +81,7 @@ failsafe_eal_init(struct rte_eth_dev *dev)return ret;if (PRIV (dev)->state <DEV_PROBED )PRIV (dev)->state =DEV_PROBED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
drivers/net/failsafe/failsafe_ether.c +90 -6
130 lines not on this page · raw message
drivers/net/failsafe/failsafe_ops.c +34 -3
@@ -34,6 +34,7 @@#include <stdint.h> #include <rte_debug.h> +#include <rte_atomic.h> #include <rte_ethdev.h> #include <rte_malloc.h> #include <rte_flow.h>
@@ -204,9 +205,21 @@ fs_dev_configure(struct rte_eth_dev *dev) } } FOREACH_SUBDEV(sdev, i, dev) { +int rmv_interrupt =0 ; +if (sdev->state !=DEV_PROBED )continue ; + + rmv_interrupt =ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_RMV ; +if (rmv_interrupt) { +DEBUG ("Enabling RMV interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.rmv =1 ; + }else { +DEBUG ("sub_device %d does not support RMV event" , i); + }DEBUG ("Configuring sub-device %d" , i); + sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues,
@@ -215,6 +228,16 @@ fs_dev_configure(struct rte_eth_dev *dev)ERROR ("Could not configure sub_device %d" , i);return ret; } +if (rmv_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_RMV , + failsafe_eth_rmv_event_callback, + sdev); +if (ret) +WARN ("Failed to register RMV callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.rmv =0 ; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
@@ -240,7 +263,7 @@ fs_dev_start(struct rte_eth_dev *dev) }if (PRIV (dev)->state <DEV_STARTED )PRIV (dev)->state =DEV_STARTED ; -fs_switch_dev (dev); +fs_switch_dev (dev,NULL );return 0 ; }
@@ -351,10 +374,14 @@ fs_rx_queue_setup(struct rte_eth_dev *dev,fs_rx_queue_release (rxq); dev->data->rx_queues[rx_queue_id] =NULL ; } - rxq =rte_zmalloc (NULL ,sizeof (*rxq), + rxq =rte_zmalloc (NULL , +sizeof (*rxq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (rxq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&rxq->refcnt[i]); rxq->qid = rx_queue_id; rxq->socket_id = socket_id; rxq->info.mp = mb_pool;
@@ -414,10 +441,14 @@ fs_tx_queue_setup(struct rte_eth_dev *dev,fs_tx_queue_release (txq); dev->data->tx_queues[tx_queue_id] =NULL ; } - txq =rte_zmalloc ("ethdev TX queue" ,sizeof (*txq), + txq =rte_zmalloc ("ethdev TX queue" , +sizeof (*txq) + +sizeof (rte_atomic64_t) *PRIV (dev)->subs_tail,RTE_CACHE_LINE_SIZE );if (txq ==NULL )return -ENOMEM ; + FOREACH_SUBDEV(sdev, i, dev) +rte_atomic64_init (&txq->refcnt[i]); txq->qid = tx_queue_id; txq->socket_id = socket_id; txq->info.conf = *tx_conf;
drivers/net/failsafe/failsafe_private.h +64 -8
133 lines not on this page · raw message
drivers/net/failsafe/failsafe_rxtx.c +15 -2
@@ -31,6 +31,7 @@* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <rte_atomic.h> #include <rte_debug.h> #include <rte_mbuf.h> #include <rte_ethdev.h>
@@ -112,8 +113,10 @@ failsafe_rx_burst(void *queue,if (unlikely (fs_rx_unsafe (sdev)))continue ; sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -146,8 +149,10 @@ failsafe_rx_burst_fast(void *queue, sdev = &priv->subs[i];RTE_ASSERT (!fs_rx_unsafe (sdev)); sub_rxq =ETH (sdev)->data->rx_queues[rxq->qid]; +FS_ATOMIC_P (rxq->refcnt[sdev->sid]); nb_rx =ETH (sdev)->rx_pkt_burst (sub_rxq, rx_pkts, nb_pkts); +FS_ATOMIC_V (rxq->refcnt[sdev->sid]);if (nb_rx) { rxq->last_polled = i;return nb_rx;
@@ -164,13 +169,17 @@ failsafe_tx_burst(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);if (unlikely (fs_tx_unsafe (sdev)))return 0 ; sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }uint16_t
@@ -181,10 +190,14 @@ failsafe_tx_burst_fast(void *queue,struct sub_device *sdev;struct txq *txq;void *sub_txq; +uint16_t nb_tx; txq = queue; sdev =TX_SUBDEV (txq->priv->dev);RTE_ASSERT (!fs_tx_unsafe (sdev)); sub_txq =ETH (sdev)->data->tx_queues[txq->qid]; -return ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_P (txq->refcnt[sdev->sid]); + nb_tx =ETH (sdev)->tx_pkt_burst (sub_txq, tx_pkts, nb_pkts); +FS_ATOMIC_V (txq->refcnt[sdev->sid]); +return nb_tx; }
Signature · 1 line
2.1.4
PATCH v11 10/11 net/failsafe: support link status change event
In reply to Gaetan Rivet--- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_ether.c | 18 ++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 23 +++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 3 +++ 5 files changed, 46 insertions(+)
doc/guides/nics/features/failsafe.ini +1 -0
@@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y MTU update = Y Jumbo frame = Y Promiscuous mode = Y
drivers/net/failsafe/failsafe.c +1 -0
@@ -238,6 +238,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) mac->addr_bytes[0 ], mac->addr_bytes[1 ], mac->addr_bytes[2 ], mac->addr_bytes[3 ], mac->addr_bytes[4], mac->addr_bytes[5]); + dev->data->dev_flags |=RTE_ETH_DEV_INTR_LSC ;return 0 ; free_args:failsafe_args_free (dev);
drivers/net/failsafe/failsafe_ether.c +18 -0
@@ -387,3 +387,21 @@ failsafe_eth_rmv_event_callback(uint8_t port_id __rte_unused, sdev->remove =1 ;return 0 ; } + +int +failsafe_eth_lsc_event_callback(uint8_t port_id __rte_unused, + enum rte_eth_event_type event __rte_unused, + void *cb_arg, void *out __rte_unused) +{ +struct rte_eth_dev *dev = cb_arg; +int ret; + + ret = dev->dev_ops->link_update (dev,0 ); +/* We must pass on the LSC event */ +if (ret) +return _rte_eth_dev_callback_process (dev, +RTE_ETH_EVENT_INTR_LSC , +NULL ,NULL ); +else +return 0 ; +}
drivers/net/failsafe/failsafe_ops.c +23 -0
@@ -206,6 +206,8 @@ fs_dev_configure(struct rte_eth_dev *dev) } FOREACH_SUBDEV(sdev, i, dev) {int rmv_interrupt =0 ; +int lsc_interrupt =0 ; +int lsc_enabled;if (sdev->state !=DEV_PROBED )continue ;
@@ -218,6 +220,17 @@ fs_dev_configure(struct rte_eth_dev *dev) }else {DEBUG ("sub_device %d does not support RMV event" , i); } + lsc_enabled = dev->data->dev_conf.intr_conf.lsc; + lsc_interrupt = lsc_enabled && + (ETH (sdev)->data->dev_flags & +RTE_ETH_DEV_INTR_LSC ); +if (lsc_interrupt) { +DEBUG ("Enabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =1 ; + }else if (lsc_enabled && !lsc_interrupt) { +DEBUG ("Disabling LSC interrupts for sub_device %d" , i); + dev->data->dev_conf.intr_conf.lsc =0 ; + }DEBUG ("Configuring sub-device %d" , i); sdev->remove =0 ; ret = rte_eth_dev_configure(PORT_ID(sdev),
@@ -238,6 +251,16 @@ fs_dev_configure(struct rte_eth_dev *dev) SUB_ID(sdev)); } dev->data->dev_conf.intr_conf.rmv =0 ; +if (lsc_interrupt) { + ret =rte_eth_dev_callback_register (PORT_ID (sdev), +RTE_ETH_EVENT_INTR_LSC , + failsafe_eth_lsc_event_callback, + dev); +if (ret) +WARN ("Failed to register LSC callback for sub_device %d" , +SUB_ID (sdev)); + } + dev->data->dev_conf.intr_conf.lsc = lsc_enabled; sdev->state =DEV_ACTIVE ; }if (PRIV (dev)->state <DEV_ACTIVE )
drivers/net/failsafe/failsafe_private.h +3 -0
@@ -179,6 +179,9 @@ void failsafe_dev_remove(struct rte_eth_dev *dev);int failsafe_eth_rmv_event_callback (uint8_t port_id,enum rte_eth_event_type type,void *arg,void *out); +int failsafe_eth_lsc_event_callback (uint8_t port_id, +enum rte_eth_event_type event, +void *cb_arg,void *out);/* GLOBALS */
Signature · 1 line
2.1.4
PATCH v11 11/11 net/failsafe: support flow API isolation mode
In reply to Gaetan Rivet--- drivers/net/failsafe/failsafe_ether.c | 34 +++++++++++++++++++++++++++++++-- drivers/net/failsafe/failsafe_flow.c | 29 ++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_private.h | 4 ++++ 3 files changed, 65 insertions(+), 2 deletions(-)
drivers/net/failsafe/failsafe_ether.c +32 -2
@@ -74,6 +74,28 @@ fs_flow_complain(struct rte_flow_error *error) }static int +eth_dev_flow_isolate_set (struct rte_eth_dev *dev, +struct sub_device *sdev) +{ +struct rte_flow_error ferror; +int ret; + +if (!PRIV (dev)->flow_isolated) { +DEBUG ("Flow isolation already disabled" ); + }else { +DEBUG ("Enabling flow isolation" ); + ret =rte_flow_isolate (PORT_ID (sdev), +PRIV (dev)->flow_isolated, + &ferror); +if (ret) { +fs_flow_complain (&ferror); +return ret; + } + } +return 0 ; +} + +static int fs_eth_dev_conf_apply (struct rte_eth_dev *dev,struct sub_device *sdev) {
@@ -334,9 +356,17 @@ failsafe_eth_dev_state_sync(struct rte_eth_dev *dev)if (PRIV (dev)->state <DEV_ACTIVE )return 0 ; inactive =0 ; - FOREACH_SUBDEV(sdev, i, dev) -if (sdev->state ==DEV_PROBED ) + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state ==DEV_PROBED ) { inactive |=UINT32_C (1 ) << i; + ret =eth_dev_flow_isolate_set (dev, sdev); +if (ret) { +ERROR ("Could not apply configuration to sub_device %d" , + i); + goto err_remove; + } + } + } ret = dev->dev_ops->dev_configure (dev);if (ret) goto err_remove;
drivers/net/failsafe/failsafe_flow.c +29 -0
@@ -206,10 +206,39 @@ fs_flow_query(struct rte_eth_dev *dev,return -1 ; } +static int +fs_flow_isolate (struct rte_eth_dev *dev, +int set, +struct rte_flow_error *error) +{ +struct sub_device *sdev; +uint8_t i; +int ret; + + FOREACH_SUBDEV(sdev, i, dev) { +if (sdev->state <DEV_PROBED ) +continue ; +DEBUG ("Calling rte_flow_isolate on sub_device %d" , i); +if (PRIV (dev)->flow_isolated != sdev->flow_isolated) +WARN ("flow isolation mode of sub_device %d in incoherent state." , + i); + ret =rte_flow_isolate (PORT_ID (sdev), set, error); +if (ret) { +ERROR ("Operation rte_flow_isolate failed for sub_device %d" +" with error %d" , i, ret); +return ret; + } + sdev->flow_isolated = set; + } +PRIV (dev)->flow_isolated = set; +return 0 ; +} +const struct rte_flow_ops fs_flow_ops = { .validate = fs_flow_validate, .create = fs_flow_create, .destroy = fs_flow_destroy, .flush = fs_flow_flush, .query = fs_flow_query, + .isolate = fs_flow_isolate, };
drivers/net/failsafe/failsafe_private.h +4 -0
@@ -108,6 +108,8 @@ struct sub_device {struct rte_eth_dev *fs_dev;/* flag calling for recollection */ volatile unsigned int remove:1; +/* flow isolation state */ + int flow_isolated:1; };struct fs_priv {
@@ -139,6 +141,8 @@ struct fs_priv {*/ enum dev_state state; unsigned int pending_alarm:1; /* An alarm is pending */ +/* flow isolation state */ + int flow_isolated:1; };/* MISC */
Signature · 1 line
2.1.4
Quoted 117 lines · Gaetan Rivet
This PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
[dpdk-dev] [PATCH v4 0/8] fix hotplug API
http://dpdk.org/ml/archives/dev/2017-July/071340.htmlv1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixesv2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports pluginv4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fixrte_devhotplug API implementation.
- Introducerte_eal_devargs_rmvAPI as EXPERIMENTAL.
- Use it to clean up resources onhotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Userte_eth_dev_allocatedwhen relevant.v8 --> v9
- Use calloc instead of
rte_reallocfor command line parsing.
- Include errno only when necessary.v9 --> v10
- Fix
rte_flowdescription double-free issue. Thanks Raslan for finding the issue :)
- UseRTE_ASSERTinstead of assert.
Integrate the debug log of the fail-safe toRTE_LOG_DEBUGmacro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.v10 --> v11
- Added Glossary in documentation.
- Fixed issues oulined in [1].
- Removed Rx offload advertizement in feature matrix.
Quoted 12 lines
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support Rx offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
Series applied to dpdk-next-net/master, thanks.
Quoted 131 lines · Ferruh Yigit
Quoted 117 lines · Gaetan Rivet
This PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
[dpdk-dev] [PATCH v4 0/8] fix hotplug API
http://dpdk.org/ml/archives/dev/2017-July/071340.htmlv1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixesv2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports pluginv4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fixrte_devhotplug API implementation.
- Introducerte_eal_devargs_rmvAPI as EXPERIMENTAL.
- Use it to clean up resources onhotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Userte_eth_dev_allocatedwhen relevant.v8 --> v9
- Use calloc instead of
rte_reallocfor command line parsing.
- Include errno only when necessary.v9 --> v10
- Fix
rte_flowdescription double-free issue. Thanks Raslan for finding the issue :)
- UseRTE_ASSERTinstead of assert.
Integrate the debug log of the fail-safe toRTE_LOG_DEBUGmacro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.v10 --> v11
- Added Glossary in documentation.
- Fixed issues oulined in [1].
- Removed Rx offload advertizement in feature matrix.Quoted 12 lines
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support Rx offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
Quoted 1 line
Series applied to dpdk-next-net/master, thanks.
Hi Gaetan,
Can you please send a patch to update release notes to announce the new PMD?
And can you also send a web page to list the PMD within supported NICs [1]?
Thanks,
ferruh
Quoted 132 lines · Ferruh Yigit
Quoted 131 lines · Ferruh Yigit
Quoted 129 lines · Gaetan Rivet
This PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
[dpdk-dev] [PATCH v4 0/8] fix hotplug API
http://dpdk.org/ml/archives/dev/2017-July/071340.htmlv1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixesv2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports pluginv4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fixrte_devhotplug API implementation.
- Introducerte_eal_devargs_rmvAPI as EXPERIMENTAL.
- Use it to clean up resources onhotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Userte_eth_dev_allocatedwhen relevant.v8 --> v9
- Use calloc instead of
rte_reallocfor command line parsing.
- Include errno only when necessary.v9 --> v10
- Fix
rte_flowdescription double-free issue. Thanks Raslan for finding the issue :)
- UseRTE_ASSERTinstead of assert.
Integrate the debug log of the fail-safe toRTE_LOG_DEBUGmacro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.v10 --> v11
- Added Glossary in documentation.
- Fixed issues oulined in [1].
- Removed Rx offload advertizement in feature matrix.[1]: http://dpdk.org/ml/archives/dev/2017-July/071406.html
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support Rx offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation mode
Quoted 6 lines
Quoted 1 line
Series applied to dpdk-next-net/master, thanks.
Hi Gaetan,
Can you please send a patch to update release notes to announce the new PMD?
Hi Ferruh,
Sure
Quoted 2 lines
And can you also send a web page to list the PMD within supported NICs [1]?
How can I do that? Is there a git repository for dpdk.org I can propose a patch for?
Quoted 5 lines
Thanks,
ferruh
Signature · 2 lines
Gaëtan Rivet 6WIND
Quoted 142 lines · Gaëtan Rivet
Quoted 132 lines · Ferruh Yigit
Quoted 131 lines · Ferruh Yigit
Quoted 129 lines · Gaetan Rivet
This PMD intercepts and manages Ethernet device removal events issued by slave PMDs and re-initializes them transparently when brought back so that existing applications do not need to be modified to benefit from true hot-plugging support.
The stacked PMD approach shares many similarities with the bonding PMD but with a different purpose. While bonding provides the ability to group several links into a single logical device for enhanced throughput and supports fail-over at link level, this one manages the sudden disappearance of the underlying device; it guarantees applications face a valid device in working order at all times.
Each fail-safe instance is configured to run atop one or several devices, with one defined as the preferred device. Hot-plug events are handled on all of them, and Tx is always directed to the preferred device if present or to the next available failover device (Rx is always performed on all devices for simplicity).
Moreover, the configured slaves (preferred or failover) do not need to be present at initialization time and may appear later.
Slaves configuration is continuously synchronized with that of the virtual device, which exposes their common set of capabilities to the application. Failure to apply the current configuration state to a slave for any reason simply reschedules its initialization.
This patchset depends on:
[dpdk-dev] [PATCH v4 0/8] fix hotplug API
http://dpdk.org/ml/archives/dev/2017-July/071340.htmlv1 --> v2:
- Wrote documentation
- Fixed commit logs, signed-off-by
- Added LSC event support
- A few minor fixesv2 --> v3:
- Numerous bug fixes.
- Complete sub-EAL rework to follow new bus API.
- burst protection on sub removal.
- more flexible sub definition.
- flow isolated mode support.v3 --> v4:
- Split back commits
net/failsafe: add fast burst functions net/failsafe: support device removal
That were squashed by error during a rebase
- Fix segfault on port plugin
- Fix isolate mode support for MLX4 ports pluginv4 --> v5:
- Follow new plug / unplug API.
v5 --> v6:
- Follow new hotplug API.
- Improve usability of hotplug API.
- Fixrte_devhotplug API implementation.
- Introducerte_eal_devargs_rmvAPI as EXPERIMENTAL.
- Use it to clean up resources onhotplug_remove.
- Fix hotplug implementation and support un pci bus. The scan was not idempotent, nor clean. Neither were the device fields.
- Implement plug operation for vdev bus.
This is needed for hotplug support and to make the EAL independent from vdev-specific API.
- Remove useless parameters from plug / unplug API.This patchset is fairly big and complex. The hotplug API has been rushed and has never been tested outside of the special case of vdev bus.
These evolutions are proposed alongside this PMD as only this PMD allows to test this API at the moment, and without those evolutions this PMD cannot be used.
v6 --> v7
- Split the series in three, with
vlan filter configuration store standing alone Hotplug API fixes separated
Fail-safe PMD on its own.These changes should ease integration.
v7 --> v8
- Fix usage examples in documentation.
- Userte_eth_dev_allocatedwhen relevant.v8 --> v9
- Use calloc instead of
rte_reallocfor command line parsing.
- Include errno only when necessary.v9 --> v10
- Fix
rte_flowdescription double-free issue. Thanks Raslan for finding the issue :)
- UseRTE_ASSERTinstead of assert.
Integrate the debug log of the fail-safe toRTE_LOG_DEBUGmacro as well, allowing dynamic log levels.
- Remove devices post-state-sync during slave upkeep, to avoid a useless early probe attempt.v10 --> v11
- Added Glossary in documentation.
- Fixed issues oulined in [1].
- Removed Rx offload advertizement in feature matrix.[1]: http://dpdk.org/ml/archives/dev/2017-July/071406.html
Gaetan Rivet (11):
ethdev: add deferred intermediate device state
ethdev: count devices consistently
net/failsafe: add fail-safe PMD
net/failsafe: add plug-in support
net/failsafe: add flexible device definition
net/failsafe: support flow API
net/failsafe: support Rx offload capabilities
net/failsafe: add fast burst functions
net/failsafe: support device removal
net/failsafe: support link status change event
net/failsafe: support flow API isolation modeQuoted 6 lines
Quoted 1 line
Series applied to dpdk-next-net/master, thanks.
Hi Gaetan,
Can you please send a patch to update release notes to announce the new PMD?
Hi Ferruh,
Quoted 7 lines
Sure
Quoted 2 lines
And can you also send a web page to list the PMD within supported NICs [1]?
How can I do that? Is there a git repository for dpdk.org I can propose a patch for?
Yes there is a dpdk-web repo: http://dpdk.org/browse/tools/dpdk-web/
Quoted 7 lines
Quoted 6 lines
Thanks,
ferruh