Fix for TX and RX descriptor queue lockup 45/445/2
authorGeorgi Savov <gsavov@cisco.com>
Thu, 25 Feb 2016 17:56:03 +0000 (12:56 -0500)
committerGerrit Code Review <gerrit@fd.io>
Tue, 1 Mar 2016 01:22:42 +0000 (01:22 +0000)
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>
vnet/vnet/devices/dpdk/device.c
vnet/vnet/interface.c

index 3107fe8..d68c5ab 100644 (file)
@@ -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)
index ffe0b67..6c8823f 100644 (file)
@@ -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)