From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f44.google.com (mail-wm0-f44.google.com [74.125.82.44]) by dpdk.org (Postfix) with ESMTP id EF6523DC for ; Wed, 8 Mar 2017 16:16:09 +0100 (CET) Received: by mail-wm0-f44.google.com with SMTP id n11so33463545wma.0 for ; Wed, 08 Mar 2017 07:16:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references:in-reply-to :references; bh=MsMJDiwCe8FxUZ1rCMFFgYlbvzs2DuSXcwYkDRA0UAs=; b=k06py8deIiXkq6k9Heq/4MnRimPycduxkFYYx7p2r+l1wGgKmNFicgmqajPjlfjner 9rYoqNhnRZ2C0VQnJ8gUMlJo2eWb1Os1WG/DTeSJUMjx4Ex2hyQJe9jgASPESk09FLmY S6LNOHfaBoxEj6CZEvoVwprvgWy9j1NhD5J8ggxK/Aj619z/DtBT1cpgBdoyBu8NutF6 PlutEmFlJFkYkJu34fK4rjyTv6EMp2Pua3Dj1KiRn4XekFNd2/hkB8ddDN73gJxsAutB JPxAj3+j5ryBSq1/+4MFOrNxwP61jqLSpq70luE4FM/fCE6439R+PweAfJRQy23mMSgV MP8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=MsMJDiwCe8FxUZ1rCMFFgYlbvzs2DuSXcwYkDRA0UAs=; b=s9frwXKVRE+c+DqZcS9P3Y7OtiYlnEZJNd/1I4SnR/xWZuracQ0D/PE1guUYHWBrhf pObDPLwzBjkG7kzKH9QLEzrNeKFeexwQw3Bl4pMu1vIkMZlJ7SRG/JAIkJQzQqom8JE1 w/V4iEMRGFx6ljSOII5xMJdJ9mFWJS/Fe0NTo48SlXpcN55O6LkkbAIjSucz0bKH+eML /XxfjMc6LG350cP9fml0TtNY4+Fc+Ylvb3/B8rGU6HlXSIezSxmZV8GBI/3YyTqJAw/r H8Ziv5ptf8W1wDB5Bn6FObr4KE2du13lItfxgpxX2VVfrXgBiw+yOc3rHCMPXjRue/po +2qA== X-Gm-Message-State: AMke39lqwe/KEv65a01yIRrcZmUfa4LB+rbQMP6Wl0H/n59FKzf9bkMRZZX7Wc7hASltrgYk X-Received: by 10.28.8.147 with SMTP id 141mr16938731wmi.43.1488986169068; Wed, 08 Mar 2017 07:16:09 -0800 (PST) Received: from bidouze.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id t103sm4553592wrc.43.2017.03.08.07.16.08 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 08 Mar 2017 07:16:08 -0800 (PST) From: Gaetan Rivet To: dev@dpdk.org Date: Wed, 8 Mar 2017 16:15:40 +0100 Message-Id: <2a07a105a64a88cd6d6d9e9f167c7ad7661b331f.1488985489.git.gaetan.rivet@6wind.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v2 07/13] net/failsafe: add plug-in support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Mar 2017 15:16:10 -0000 Periodically 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. Signed-off-by: Gaetan Rivet Acked-by: Olga Shern --- doc/guides/nics/fail_safe.rst | 19 +++ drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 68 ++++++++++ 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 | 57 +++++++- 8 files changed, 418 insertions(+), 42 deletions(-) create mode 100644 drivers/net/failsafe/failsafe_ether.c diff --git a/doc/guides/nics/fail_safe.rst b/doc/guides/nics/fail_safe.rst index 056f85f..74bd807 100644 --- a/doc/guides/nics/fail_safe.rst +++ b/doc/guides/nics/fail_safe.rst @@ -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. +- **plug_in_poll** parameter [UINT64] (default **2000**) + + This parameter allows the user to configure the amount of time in milliseconds + between two sub-device probing attempt. + 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. diff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile index 06199ad..4567961 100644 --- a/drivers/net/failsafe/Makefile +++ b/drivers/net/failsafe/Makefile @@ -40,6 +40,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 diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c index cd60193..2063393 100644 --- a/drivers/net/failsafe/failsafe.c +++ b/drivers/net/failsafe/failsafe.c @@ -79,6 +79,69 @@ sub_device_free(struct rte_eth_dev *dev) rte_free(PRIV(dev)->subs); } +static void failsafe_plugin_alarm(void *arg); + +int +failsafe_plugin_alarm_install(struct rte_eth_dev *dev) +{ + struct sub_device *sdev; + uint8_t i; + int ret; + + if (PRIV(dev)->pending_alarm) + return 0; + FOREACH_SUBDEV(sdev, i, dev) + if (sdev->state != PRIV(dev)->state) + break; + if (i != PRIV(dev)->subs_tail) { + ret = rte_eal_alarm_set(plug_in_poll * 1000, + failsafe_plugin_alarm, + dev); + if (ret) { + ERROR("Could not set up plug-in event detection"); + return ret; + } + PRIV(dev)->pending_alarm = 1; + } + return 0; +} + +int +failsafe_plugin_alarm_cancel(struct rte_eth_dev *dev) +{ + int ret = 0; + + if (PRIV(dev)->pending_alarm) { + rte_errno = 0; + rte_eal_alarm_cancel(failsafe_plugin_alarm, dev); + if (rte_errno) { + ERROR("rte_eal_alarm_cancel failed (errno: %s)", + strerror(rte_errno)); + ret = -rte_errno; + } else { + PRIV(dev)->pending_alarm = 0; + } + } + return ret; +} + +static void +failsafe_plugin_alarm(void *arg) +{ + struct rte_eth_dev *dev = arg; + int ret; + + if (!PRIV(dev)->pending_alarm) + return; + PRIV(dev)->pending_alarm = 0; + ret = failsafe_eth_dev_state_sync(dev); + if (ret) + ERROR("Unable to synchronize sub_device state"); + ret = failsafe_plugin_alarm_install(dev); + if (ret) + ERROR("Unable to set up next alarm"); +} + static int eth_dev_create(const char *name, const unsigned socket_id, @@ -134,6 +197,11 @@ eth_dev_create(const char *name, ret = failsafe_eal_init(dev); if (ret) goto free_args; + ret = failsafe_plugin_alarm_install(dev); + if (ret) { + ERROR("Could not set up plug-in event detection"); + goto free_subs; + } mac = &dev->data->mac_addrs[0]; if (!mac_from_arg) { struct sub_device *sdev; diff --git a/drivers/net/failsafe/failsafe_args.c b/drivers/net/failsafe/failsafe_args.c index faa48f4..773b322 100644 --- a/drivers/net/failsafe/failsafe_args.c +++ b/drivers/net/failsafe/failsafe_args.c @@ -45,9 +45,11 @@ typedef int (parse_cb)(struct rte_eth_dev *dev, const char *params, uint8_t head); +uint64_t plug_in_poll; int mac_from_arg; const char *pmd_failsafe_init_parameters[] = { + PMD_FAILSAFE_PLUG_IN_POLL_KVARG, PMD_FAILSAFE_MAC_KVARG, NULL, }; @@ -237,6 +239,24 @@ remove_sub_devices_definition(char params[DEVARGS_MAXLEN]) } static int +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 get_mac_addr_arg(const char *key __rte_unused, const char *value, void *out) { @@ -268,6 +288,7 @@ failsafe_args_parse(struct rte_eth_dev *dev, const char *params) ret = 0; priv->subs_tx = FAILSAFE_MAX_ETHPORTS; /* default parameters */ + plug_in_poll = FAILSAFE_PLUGIN_DEFAULT_TIMEOUT_MS; mac_from_arg = 0; n = snprintf(mut_params, sizeof(mut_params), "%s", params); if (n >= sizeof(mut_params)) { @@ -290,6 +311,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, + &get_u64_arg, &plug_in_poll); + if (ret < 0) + goto free_kvlist; + } /* MAC addr */ arg_count = rte_kvargs_count(kvlist, PMD_FAILSAFE_MAC_KVARG); @@ -303,6 +334,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; diff --git a/drivers/net/failsafe/failsafe_eal.c b/drivers/net/failsafe/failsafe_eal.c index fcee500..a5e8c3c 100644 --- a/drivers/net/failsafe/failsafe_eal.c +++ b/drivers/net/failsafe/failsafe_eal.c @@ -198,8 +198,6 @@ pci_probe(struct rte_eth_dev *dev) int failsafe_eal_init(struct rte_eth_dev *dev) { - struct sub_device *sdev; - uint8_t i; int ret; ret = pci_scan(dev); @@ -211,30 +209,9 @@ failsafe_eal_init(struct rte_eth_dev *dev) ret = dev_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; } @@ -314,5 +291,6 @@ failsafe_eal_uninit(struct rte_eth_dev *dev) ret = dev_uninit(dev); if (ret) return ret; + PRIV(dev)->state = DEV_PROBED - 1; return 0; } diff --git a/drivers/net/failsafe/failsafe_ether.c b/drivers/net/failsafe/failsafe_ether.c new file mode 100644 index 0000000..ccdd471 --- /dev/null +++ b/drivers/net/failsafe/failsafe_ether.c @@ -0,0 +1,228 @@ +/*- + * 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 + +#include "failsafe_private.h" + +static int +eth_dev_conf_apply(struct rte_eth_dev *dev, + struct sub_device *sdev) +{ + struct rte_eth_dev *edev; + struct rte_vlan_filter_conf *vfc1; + struct rte_vlan_filter_conf *vfc2; + uint32_t i; + int ret; + + edev = ETH(sdev); + /* RX queue setup */ + for (i = 0; i < dev->data->nb_rx_queues; i++) { + struct rxq *rxq; + + rxq = dev->data->rx_queues[i]; + ret = rte_eth_rx_queue_setup(PORT_ID(sdev), i, + rxq->info.nb_desc, rxq->socket_id, + &rxq->info.conf, rxq->info.mp); + if (ret) { + ERROR("rx_queue_setup failed"); + return ret; + } + } + /* TX queue setup */ + for (i = 0; i < dev->data->nb_tx_queues; i++) { + struct txq *txq; + + txq = dev->data->tx_queues[i]; + ret = rte_eth_tx_queue_setup(PORT_ID(sdev), i, + txq->info.nb_desc, txq->socket_id, + &txq->info.conf); + if (ret) { + ERROR("tx_queue_setup failed"); + return ret; + } + } + /* dev_link.link_status */ + if (dev->data->dev_link.link_status != + edev->data->dev_link.link_status) { + DEBUG("Configuring link_status"); + if (dev->data->dev_link.link_status) + ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); + else + ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); + if (ret) { + ERROR("Failed to apply link_status"); + return ret; + } + } else { + DEBUG("link_status already set"); + } + /* promiscuous */ + if (dev->data->promiscuous != edev->data->promiscuous) { + DEBUG("Configuring promiscuous"); + if (dev->data->promiscuous) + rte_eth_promiscuous_enable(PORT_ID(sdev)); + else + rte_eth_promiscuous_disable(PORT_ID(sdev)); + } else { + DEBUG("promiscuous already set"); + } + /* all_multicast */ + if (dev->data->all_multicast != edev->data->all_multicast) { + DEBUG("Configuring all_multicast"); + if (dev->data->all_multicast) + rte_eth_allmulticast_enable(PORT_ID(sdev)); + else + rte_eth_allmulticast_disable(PORT_ID(sdev)); + } else { + DEBUG("all_multicast already set"); + } + /* MTU */ + if (dev->data->mtu != edev->data->mtu) { + DEBUG("Configuring MTU"); + ret = rte_eth_dev_set_mtu(PORT_ID(sdev), dev->data->mtu); + if (ret) { + ERROR("Failed to apply MTU"); + return ret; + } + } else { + DEBUG("MTU already set"); + } + /* default MAC */ + DEBUG("Configuring default MAC address"); + ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), + &dev->data->mac_addrs[0]); + if (ret) { + ERROR("Setting default MAC address failed"); + return ret; + } + /* additional MAC */ + if (PRIV(dev)->nb_mac_addr > 1) + DEBUG("Configure additional MAC address%s", + (PRIV(dev)->nb_mac_addr > 2 ? "es" : "")); + for (i = 1; i < PRIV(dev)->nb_mac_addr; i++) { + struct ether_addr *ea; + + ea = &dev->data->mac_addrs[i]; + ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), ea, + PRIV(dev)->mac_addr_pool[i]); + if (ret) { + char ea_fmt[ETHER_ADDR_FMT_SIZE]; + + ether_format_addr(ea_fmt, ETHER_ADDR_FMT_SIZE, ea); + ERROR("Adding MAC address %s failed", ea_fmt); + } + } + /* VLAN filter */ + vfc1 = &dev->data->vlan_filter_conf; + vfc2 = &edev->data->vlan_filter_conf; + if (memcmp(vfc1, vfc2, sizeof(struct rte_vlan_filter_conf))) { + uint64_t vbit; + uint64_t ids; + size_t i; + uint16_t vlan_id; + + DEBUG("Configuring VLAN filter"); + for (i = 0; i < RTE_DIM(vfc1->ids); i++) { + if (vfc1->ids[i] == 0) + continue; + ids = vfc1->ids[i]; + while (ids) { + vlan_id = 64 * i; + /* count trailing zeroes */ + vbit = ~ids & (ids - 1); + /* clear least significant bit set */ + ids ^= (ids ^ (ids - 1)) ^ vbit; + for (; vbit; vlan_id++) + vbit >>= 1; + ret = rte_eth_dev_vlan_filter( + PORT_ID(sdev), vlan_id, 1); + if (ret) { + ERROR("Failed to apply VLAN filter %hu", + vlan_id); + return ret; + } + } + } + } else { + DEBUG("VLAN filter already set"); + } + return 0; +} + +int +failsafe_eth_dev_state_sync(struct rte_eth_dev *dev) +{ + struct sub_device *sdev; + uint32_t inactive; + int ret; + uint8_t i; + + if (PRIV(dev)->state < DEV_PROBED) + return 0; + ret = failsafe_eal_init(dev); + if (ret) + return ret; + if (PRIV(dev)->state < DEV_ACTIVE) + return 0; + inactive = 0; + FOREACH_SUBDEV(sdev, i, dev) + if (sdev->state == DEV_PROBED) + inactive |= UINT32_C(1) << i; + ret = dev->dev_ops->dev_configure(dev); + if (ret) + return ret; + FOREACH_SUBDEV(sdev, i, dev) { + if (inactive & (UINT32_C(1) << i)) { + ret = eth_dev_conf_apply(dev, sdev); + if (ret) { + ERROR("Could not apply configuration to sub_device %d", + i); + /* TODO: disable device */ + return ret; + } + } + } + /* + * If new devices have been configured, check if + * the link state has changed. + */ + if (inactive) + dev->dev_ops->link_update(dev, 1); + if (PRIV(dev)->state < DEV_STARTED) + return 0; + ret = dev->dev_ops->dev_start(dev); + if (ret) + return ret; + return 0; +} diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c index 470fea4..b408877 100644 --- a/drivers/net/failsafe/failsafe_ops.c +++ b/drivers/net/failsafe/failsafe_ops.c @@ -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_plugin_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)); diff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h index 84a4d3a..bb27223 100644 --- a/drivers/net/failsafe/failsafe_private.h +++ b/drivers/net/failsafe/failsafe_private.h @@ -42,9 +42,11 @@ #define FAILSAFE_DRIVER_NAME "Fail-safe PMD" #define PMD_FAILSAFE_MAC_KVARG "mac" +#define PMD_FAILSAFE_PLUG_IN_POLL_KVARG "plug_in_poll" #define PMD_FAILSAFE_PARAM_STRING \ "dev()," \ - "mac=mac_addr" \ + "mac=mac_addr," \ + "plug_in_poll=u64" \ "" #define FAILSAFE_PLUGIN_DEFAULT_TIMEOUT_MS 2000 @@ -110,8 +112,22 @@ struct fs_priv { uint32_t mac_addr_pool[FAILSAFE_MAX_ETHADDR]; /* current capabilities */ struct rte_eth_dev_info infos; + /* + * Fail-safe state machine. + * This level will be tracking state of the EAL and eth + * layer at large as defined by the user application. + * It will then steer the sub_devices toward the same + * synchronized state. + */ + enum dev_state state; + unsigned int pending_alarm:1; /* An alarm is pending */ }; +/* MISC */ + +int failsafe_plugin_alarm_install(struct rte_eth_dev *dev); +int failsafe_plugin_alarm_cancel(struct rte_eth_dev *dev); + /* RX / TX */ uint16_t failsafe_rx_burst(void *rxq, @@ -130,10 +146,15 @@ int failsafe_args_count_subdevice(struct rte_eth_dev *dev, const char *params); int failsafe_eal_init(struct rte_eth_dev *dev); int failsafe_eal_uninit(struct rte_eth_dev *dev); +/* ETH_DEV */ + +int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev); + /* GLOBALS */ extern const char pmd_failsafe_driver_name[]; extern const struct eth_dev_ops failsafe_ops; +extern uint64_t plug_in_poll; extern int mac_from_arg; /* HELPERS */ @@ -229,4 +250,38 @@ fs_find_next(struct rte_eth_dev *dev, uint8_t sid, return sid; } +static inline void +fs_switch_dev(struct rte_eth_dev *dev) +{ + enum dev_state req_state; + + req_state = PRIV(dev)->state; + if (PREFERRED_SUBDEV(dev)->state >= req_state) { + if (TX_SUBDEV(dev) != PREFERRED_SUBDEV(dev) && + (TX_SUBDEV(dev) == NULL || + (req_state == DEV_STARTED) || + (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 < req_state) || + TX_SUBDEV(dev) == NULL) { + struct sub_device *sdev; + uint8_t i; + + /* Using acceptable device */ + FOREACH_SUBDEV_ST(sdev, i, dev, req_state) { + DEBUG("Switching tx_dev to sub_device %d", + i); + PRIV(dev)->subs_tx = i; + break; + } + } else if (TX_SUBDEV(dev) && TX_SUBDEV(dev)->state < req_state) { + DEBUG("No device ready, deactivating tx_dev"); + PRIV(dev)->subs_tx = PRIV(dev)->subs_tail; + } else { + return; + } +} + #endif /* _RTE_ETH_FAILSAFE_PRIVATE_H_ */ -- 2.1.4