summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorgi Savov <gsavov@cisco.com>2016-02-25 12:56:03 -0500
committerGerrit Code Review <gerrit@fd.io>2016-03-01 01:22:42 +0000
commit3a03598aab24500568ecd1e80b1b0d6bb66eb59d (patch)
treeb5cce4c0379b79612a765dbd189c0bed4e9f1e4d
parent679ea7951514736e8c8318b434ad7162b27eea84 (diff)
Fix for TX and RX descriptor queue lockup
On admin up/down changes the TX and RX queues were getting locked up for VNET_DPDK_PMD_VMXNET3 interfaces. The fix is to ensure the interface is in admin down before touching the hardware. Change-Id: Ia264d95355a860607bff7ada00d2be48f91e6dd9 Signed-off-by: Todd Foggoa (tfoggoa) <tfoggoa@cisco.com>
-rw-r--r--vnet/vnet/devices/dpdk/device.c16
-rw-r--r--vnet/vnet/interface.c34
2 files changed, 38 insertions, 12 deletions
diff --git a/vnet/vnet/devices/dpdk/device.c b/vnet/vnet/devices/dpdk/device.c
index 3107fe80daf..d68c5abb4f0 100644
--- a/vnet/vnet/devices/dpdk/device.c
+++ b/vnet/vnet/devices/dpdk/device.c
@@ -930,6 +930,17 @@ dpdk_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
}
else
{
+ /*
+ * DAW-FIXME: VMXNET3 device stop/start doesn't work,
+ * therefore fake the stop in the dpdk driver by
+ * silently dropping all of the incoming pkts instead of
+ * stopping the driver / hardware.
+ */
+ if (xd->pmd != VNET_DPDK_PMD_VMXNET3)
+ xd->admin_up = 0;
+ else
+ xd->admin_up = ~0;
+
rte_eth_allmulticast_disable (xd->device_index);
vnet_hw_interface_set_flags (vnm, xd->vlib_hw_if_index, 0);
@@ -940,12 +951,7 @@ dpdk_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
* stopping the driver / hardware.
*/
if (xd->pmd != VNET_DPDK_PMD_VMXNET3)
- {
rte_eth_dev_stop (xd->device_index);
- xd->admin_up = 0;
- }
- else
- xd->admin_up = ~0;
}
if (rv < 0)
diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c
index ffe0b672acd..6c8823f14bc 100644
--- a/vnet/vnet/interface.c
+++ b/vnet/vnet/interface.c
@@ -325,6 +325,7 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, u32 flag
u32 mask;
clib_error_t * error = 0;
u32 is_create = (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0;
+ u32 old_flags;
mask = VNET_SW_INTERFACE_FLAG_ADMIN_UP | VNET_SW_INTERFACE_FLAG_PUNT;
flags &= mask;
@@ -397,13 +398,32 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, u32 flag
vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
vnet_device_class_t * dev_class = vnet_get_device_class (vnm, hi->dev_class_index);
- if (dev_class->admin_up_down_function
- && (error = dev_class->admin_up_down_function (vnm, si->hw_if_index, flags)))
- goto done;
-
- if (hw_class->admin_up_down_function
- && (error = hw_class->admin_up_down_function (vnm, si->hw_if_index, flags)))
- goto done;
+ /* save the si admin up flag */
+ old_flags = si->flags;
+
+ /* update si admin up flag in advance if we are going admin down */
+ if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
+ si->flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
+
+ if (dev_class->admin_up_down_function
+ && (error = dev_class->admin_up_down_function(vnm,
+ si->hw_if_index,
+ flags)))
+ {
+ /* restore si admin up flag to it's original state on errors */
+ si->flags = old_flags;
+ goto done;
+ }
+
+ if (hw_class->admin_up_down_function
+ && (error = hw_class->admin_up_down_function(vnm,
+ si->hw_if_index,
+ flags)))
+ {
+ /* restore si admin up flag to it's original state on errors */
+ si->flags = old_flags;
+ goto done;
+ }
/* Admin down implies link down. */
if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)