interface: callback to manage extra MAC addresses
[vpp.git] / src / vnet / interface.c
index 12204bd..0b4d78a 100644 (file)
@@ -287,9 +287,6 @@ call_sw_interface_add_del_callbacks (vnet_main_t * vnm, u32 sw_if_index,
     (vnm, sw_if_index, is_create, vnm->sw_interface_add_del_functions);
 }
 
-#define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
-#define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
-
 static clib_error_t *
 vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index,
                                    vnet_hw_interface_flags_t flags,
@@ -397,15 +394,6 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index,
            }
        }
 
-      /* Do not 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;
@@ -518,6 +506,30 @@ vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index,
      VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE);
 }
 
+void
+vnet_sw_interface_admin_up (vnet_main_t * vnm, u32 sw_if_index)
+{
+  u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
+
+  if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
+    {
+      flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
+      vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
+    }
+}
+
+void
+vnet_sw_interface_admin_down (vnet_main_t * vnm, u32 sw_if_index)
+{
+  u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
+
+  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
+    {
+      flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
+      vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
+    }
+}
+
 static u32
 vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm,
                                       vnet_sw_interface_t * template)
@@ -756,6 +768,7 @@ vnet_register_interface (vnet_main_t * vnm,
 
   pool_get (im->hw_interfaces, hw);
   clib_memset (hw, 0, sizeof (*hw));
+  hw->trace_classify_table_index = ~0;
 
   hw_index = hw - im->hw_interfaces;
   hw->hw_if_index = hw_index;
@@ -894,6 +907,7 @@ vnet_register_interface (vnet_main_t * vnm,
        static char *e[] = {
          "interface is down",
          "interface is deleted",
+         "no buffers to segment GSO",
        };
 
        r.n_errors = ARRAY_LEN (e);
@@ -1247,9 +1261,8 @@ vnet_interface_init (vlib_main_t * vm)
         sizeof (b->opaque), sizeof (vnet_buffer_opaque_t));
     }
 
-  im->sw_if_counter_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
-                                                  CLIB_CACHE_LINE_BYTES);
-  im->sw_if_counter_lock[0] = 1;       /* should be no need */
+  clib_spinlock_init (&im->sw_if_counter_lock);
+  clib_spinlock_lock (&im->sw_if_counter_lock);        /* should be no need */
 
   vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1);
 #define _(E,n,p)                                                       \
@@ -1264,7 +1277,7 @@ vnet_interface_init (vlib_main_t * vm)
   im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
   foreach_combined_interface_counter_name
 #undef _
-    im->sw_if_counter_lock[0] = 0;
+    clib_spinlock_unlock (&im->sw_if_counter_lock);
 
   im->device_class_by_name = hash_create_string ( /* size */ 0,
                                                 sizeof (uword));
@@ -1328,6 +1341,11 @@ vnet_interface_init (vlib_main_t * vm)
       }
   }
 
+  im->gso_interface_count = 0;
+  /* init per-thread data */
+  vec_validate_aligned (im->per_thread_data, vlib_num_workers (),
+                       CLIB_CACHE_LINE_BYTES);
+
   if ((error = vlib_call_init_function (vm, vnet_interface_cli_init)))
     return error;
 
@@ -1409,6 +1427,48 @@ vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name)
   return error;
 }
 
+clib_error_t *
+vnet_hw_interface_add_del_mac_address (vnet_main_t * vnm,
+                                      u32 hw_if_index,
+                                      const u8 * mac_address, u8 is_add)
+{
+  clib_error_t *error = 0;
+  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+
+  vnet_device_class_t *dev_class =
+    vnet_get_device_class (vnm, hi->dev_class_index);
+
+  if (!hi->hw_address)
+    {
+      error =
+       clib_error_return
+       (0, "Secondary MAC Addresses not supported for interface index %u",
+        hw_if_index);
+      goto done;
+    }
+
+  if (dev_class->mac_addr_add_del_function)
+    error = dev_class->mac_addr_add_del_function (hi, mac_address, is_add);
+
+  if (!error)
+    {
+      vnet_hw_interface_class_t *hw_class;
+
+      hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
+
+      if (NULL != hw_class->mac_addr_add_del_function)
+       error = hw_class->mac_addr_add_del_function (hi, mac_address, is_add);
+    }
+
+  /* If no errors, add to the list of secondary MACs on the ethernet intf */
+  if (!error)
+    ethernet_interface_add_del_address (&ethernet_main, hw_if_index,
+                                       mac_address, is_add);
+
+done:
+  return error;
+}
+
 static clib_error_t *
 vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
                                             u32 hw_if_index,