Fix double-enqueued packet in interface-output dual-loop, fixes VPP-116
[vpp.git] / vnet / vnet / interface.c
index ffe0b67..2fb9374 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;
@@ -362,6 +363,15 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, u32 flag
            }
        }
 
+      /* Donot change state for slave link of bonded interfaces */
+      if (si->flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE)
+        {
+         error = clib_error_return 
+             (0, "not allowed as %U belong to a BondEthernet interface",
+              format_vnet_sw_interface_name, vnm, si);
+         goto done;
+        }
+
       /* Already in the desired state? */
       if ((si->flags & mask) == flags)
        goto done;
@@ -397,13 +407,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)
@@ -660,8 +689,8 @@ vnet_register_interface (vnet_main_t * vnm,
       r.flags = 0;
       r.name = output_node_name;
       r.function =  dev_class->no_flatten_output_chains ?
-          vnet_interface_output_node_no_flatten : 
-          vnet_interface_output_node;
+          vnet_interface_output_node_no_flatten_multiarch_select() :
+          vnet_interface_output_node_multiarch_select() ;
       r.format_trace = format_vnet_interface_output_trace;
 
       {
@@ -1049,3 +1078,40 @@ int vnet_interface_add_del_feature(vnet_main_t * vnm,
   return 0;
 }
 
+clib_error_t *
+vnet_rename_interface (vnet_main_t * vnm,
+                       u32           hw_if_index,
+                       char *        new_name)
+{
+  vnet_interface_main_t * im = &vnm->interface_main;
+  vlib_main_t * vm = vnm->vlib_main;
+  vnet_hw_interface_t* hw;
+  u8* old_name;
+  clib_error_t * error = 0;
+
+  hw = vnet_get_hw_interface(vnm, hw_if_index);
+  if (!hw)
+    {
+      return clib_error_return (0,
+                                "unable to find hw interface for index %u",
+                                 hw_if_index);
+    }
+
+  old_name = hw->name;
+
+  // set new hw->name
+  hw->name = format (0, "%s", new_name);
+
+  // remove the old name to hw_if_index mapping and install the new one
+  hash_unset_mem (im->hw_interface_by_name, old_name);
+  hash_set_mem (im->hw_interface_by_name, hw->name, hw_if_index);
+
+  // rename tx/output nodes
+  vlib_node_rename (vm, hw->tx_node_index, "%v-tx", hw->name);
+  vlib_node_rename (vm, hw->output_node_index, "%v-output", hw->name);
+
+  // free the old name vector
+  vec_free (old_name);
+
+  return error;
+}