diff options
author | 2016-02-25 12:56:03 -0500 | |
---|---|---|
committer | 2016-03-01 01:22:42 +0000 | |
commit | 3a03598aab24500568ecd1e80b1b0d6bb66eb59d (patch) | |
tree | b5cce4c0379b79612a765dbd189c0bed4e9f1e4d | |
parent | 679ea7951514736e8c8318b434ad7162b27eea84 (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.c | 16 | ||||
-rw-r--r-- | vnet/vnet/interface.c | 34 |
2 files changed, 38 insertions, 12 deletions
diff --git a/vnet/vnet/devices/dpdk/device.c b/vnet/vnet/devices/dpdk/device.c index 3107fe80..d68c5abb 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 ffe0b672..6c8823f1 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) |