L2 BD: introduce a BD interface on which to send UU packets
[vpp.git] / src / vnet / interface.c
index 7a2c3ab..5cbbbf9 100644 (file)
@@ -42,6 +42,7 @@
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/adj/adj.h>
 #include <vnet/adj/adj_mcast.h>
+#include <vnet/l2/l2_input.h>
 
 #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
 #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
@@ -424,7 +425,7 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index,
            }
        }
 
-      /* Donot change state for slave link of bonded interfaces */
+      /* Do not change state for slave link of bonded interfaces */
       if (si->flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE)
        {
          error = clib_error_return
@@ -649,10 +650,11 @@ vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
     {
       config = vec_elt_at_index (l2input_main.configs, sw_if_index);
       if (config->xconnect)
-       set_int_l2_mode (vm, vnm, MODE_L3, config->output_sw_if_index, 0, 0,
-                        0, 0);
+       set_int_l2_mode (vm, vnm, MODE_L3, config->output_sw_if_index, 0,
+                        L2_BD_PORT_TYPE_NORMAL, 0, 0);
       if (config->xconnect || config->bridge)
-       set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0, 0, 0, 0);
+       set_int_l2_mode (vm, vnm, MODE_L3, sw_if_index, 0,
+                        L2_BD_PORT_TYPE_NORMAL, 0, 0);
     }
   vnet_clear_sw_interface_tag (vnm, sw_if_index);
 
@@ -705,6 +707,22 @@ vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
     call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
 }
 
+void
+vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
+                                        u32 sw_if_index, u8 enable)
+{
+  vnet_sw_interface_t *si;
+
+  si = vnet_get_sw_interface (vnm, sw_if_index);
+
+  if (enable)
+    si->flags |= VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+  else
+    si->flags &= ~VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+
+  ip4_directed_broadcast (sw_if_index, enable);
+}
+
 /*
  * Reflect a change in hardware MTU on protocol MTUs
  */
@@ -1042,8 +1060,9 @@ vnet_hw_interface_walk_sw (vnet_main_t * vnm,
   u32 id, sw_if_index;
 
   hi = vnet_get_hw_interface (vnm, hw_if_index);
-  /* the super first, then the and sub interfaces */
-  fn (vnm, hi->sw_if_index, ctx);
+  /* the super first, then the sub interfaces */
+  if (WALK_STOP == fn (vnm, hi->sw_if_index, ctx))
+    return;
 
   /* *INDENT-OFF* */
   hash_foreach (id, sw_if_index,
@@ -1055,6 +1074,24 @@ vnet_hw_interface_walk_sw (vnet_main_t * vnm,
   /* *INDENT-ON* */
 }
 
+void
+vnet_hw_interface_walk (vnet_main_t * vnm,
+                       vnet_hw_interface_walk_t fn, void *ctx)
+{
+  vnet_interface_main_t *im;
+  vnet_hw_interface_t *hi;
+
+  im = &vnm->interface_main;
+
+  /* *INDENT-OFF* */
+  pool_foreach (hi, im->hw_interfaces,
+  ({
+    if (WALK_STOP == fn(vnm, hi->hw_if_index, ctx))
+      break;
+  }));
+  /* *INDENT-ON* */
+}
+
 void
 vnet_sw_interface_walk (vnet_main_t * vnm,
                        vnet_sw_interface_walk_t fn, void *ctx)
@@ -1257,7 +1294,8 @@ int
 vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index)
 {
   vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
-  if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
+  if ((si->type == VNET_SW_INTERFACE_TYPE_P2P) ||
+      (si->type == VNET_SW_INTERFACE_TYPE_PIPE))
     return 1;
 
   vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
@@ -1297,38 +1335,20 @@ vnet_interface_init (vlib_main_t * vm)
                                                   CLIB_CACHE_LINE_BYTES);
   im->sw_if_counter_lock[0] = 1;       /* should be no need */
 
-  /*
-   * $$$$ add stat segment name(s) if desired
-   * set xxx.stat_segment_name = "whatever"...
-   */
   vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1);
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP].name = "drops";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_PUNT].name = "punts";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_IP4].name = "ip4";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_IP6].name = "ip6";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_NO_BUF].name = "rx-no-buf";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_MISS].name = "rx-miss";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_ERROR].name = "rx-error";
-  im->sw_if_counters[VNET_INTERFACE_COUNTER_TX_ERROR].name = "tx-error";
-
-  vec_validate (im->combined_sw_if_counters,
-               VNET_N_COMBINED_INTERFACE_COUNTER - 1);
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX].name = "rx";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_UNICAST].name =
-    "rx-unicast";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_MULTICAST].name =
-    "rx-multicast";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_BROADCAST].name =
-    "rx-broadcast";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX].name = "tx";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_UNICAST].name =
-    "tx-unicast";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_MULTICAST].name =
-    "tx-multicast";
-  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_BROADCAST].name =
-    "tx-broadcast";
-
-  im->sw_if_counter_lock[0] = 0;
+#define _(E,n,p)                                                       \
+  im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n;            \
+  im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
+  foreach_simple_interface_counter_name
+#undef _
+    vec_validate (im->combined_sw_if_counters,
+                 VNET_N_COMBINED_INTERFACE_COUNTER - 1);
+#define _(E,n,p)                                                       \
+  im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n;   \
+  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;
 
   im->device_class_by_name = hash_create_string ( /* size */ 0,
                                                 sizeof (uword));
@@ -1341,6 +1361,27 @@ vnet_interface_init (vlib_main_t * vm)
       {
        c->index = vec_len (im->device_classes);
        hash_set_mem (im->device_class_by_name, c->name, c->index);
+
+       if (c->tx_fn_registrations)
+         {
+           vlib_node_fn_registration_t *fnr = c->tx_fn_registrations;
+           int priority = -1;
+
+           /* to avoid confusion, please remove ".tx_function" statement
+              from VNET_DEVICE_CLASS() if using function candidates */
+           ASSERT (c->tx_function == 0);
+
+           while (fnr)
+             {
+               if (fnr->priority > priority)
+                 {
+                   priority = fnr->priority;
+                   c->tx_function = fnr->function;
+                 }
+               fnr = fnr->next_registration;
+             }
+         }
+
        vec_add1 (im->device_classes, c[0]);
        c = c->next_class_registration;
       }
@@ -1462,12 +1503,14 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
 
   if (hi->hw_address)
     {
+      u8 *old_address = vec_dup (hi->hw_address);
       vnet_device_class_t *dev_class =
        vnet_get_device_class (vnm, hi->dev_class_index);
       if (dev_class->mac_addr_change_function)
        {
          error =
-           dev_class->mac_addr_change_function (hi, (char *) mac_address);
+           dev_class->mac_addr_change_function (hi, old_address,
+                                                mac_address);
        }
       if (!error)
        {
@@ -1476,7 +1519,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
          hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
 
          if (NULL != hw_class->mac_addr_change_function)
-           hw_class->mac_addr_change_function (hi, (char *) mac_address);
+           hw_class->mac_addr_change_function (hi, old_address, mac_address);
        }
       else
        {
@@ -1484,6 +1527,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
            clib_error_return (0,
                               "MAC Address Change is not supported on this interface");
        }
+      vec_free (old_address);
     }
   else
     {
@@ -1607,8 +1651,9 @@ default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
       adj_glean_update_rewrite (ai);
       break;
     case IP_LOOKUP_NEXT_ARP:
+    case IP_LOOKUP_NEXT_BCAST:
       /*
-       * default rewirte in neighbour adj
+       * default rewrite in neighbour adj
        */
       adj_nbr_update_rewrite
        (ai,