ip: Replace Sematics for Interface IP addresses
[vpp.git] / src / plugins / gbp / gbp_vxlan.c
index 846ea0f..643089e 100644 (file)
  */
 
 #include <plugins/gbp/gbp_vxlan.h>
-#include <plugins/gbp/gbp_itf.h>
 #include <plugins/gbp/gbp_learn.h>
 #include <plugins/gbp/gbp_bridge_domain.h>
 #include <plugins/gbp/gbp_route_domain.h>
-#include <plugins/gbp/gbp_sclass.h>
 
 #include <vnet/vxlan-gbp/vxlan_gbp.h>
 #include <vlibmemory/api.h>
 #include <vnet/fib/fib_table.h>
+#include <vlib/punt.h>
 
 /**
  * A reference to a VXLAN-GBP tunnel created as a child/dependent tunnel
@@ -30,9 +29,8 @@
  */
 typedef struct vxlan_tunnel_ref_t_
 {
+  gbp_itf_hdl_t vxr_itf;
   u32 vxr_sw_if_index;
-  index_t vxr_itf;
-  u32 vxr_locks;
   index_t vxr_parent;
   gbp_vxlan_tunnel_layer_t vxr_layer;
 } vxlan_tunnel_ref_t;
@@ -45,28 +43,32 @@ uword *gv_db;
 /**
  * Logger
  */
-vlib_log_class_t gt_logger;
+static vlib_log_class_t gt_logger;
 
 /**
  * Pool of template tunnels
  */
-gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_pool;
+static gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_pool;
 
 /**
  * Pool of child tunnels
  */
-vxlan_tunnel_ref_t *vxlan_tunnel_ref_pool;
+static vxlan_tunnel_ref_t *vxlan_tunnel_ref_pool;
 
 /**
  * DB of template interfaces by SW interface index
  */
-index_t *gbp_vxlan_tunnel_db;
+static index_t *gbp_vxlan_tunnel_db;
 
 /**
  * DB of child interfaces by SW interface index
  */
-index_t *vxlan_tunnel_ref_db;
+static index_t *vxlan_tunnel_ref_db;
 
+/**
+ * handle registered with the ;unt infra
+ */
+static vlib_punt_hdl_t punt_hdl;
 
 static char *gbp_vxlan_tunnel_layer_strings[] = {
 #define _(n,s) [GBP_VXLAN_TUN_##n] = s,
@@ -78,7 +80,6 @@ static char *gbp_vxlan_tunnel_layer_strings[] = {
     vlib_log_debug (gt_logger, __VA_ARGS__);
 
 
-
 gbp_vxlan_tunnel_t *
 gbp_vxlan_tunnel_get (index_t gti)
 {
@@ -99,13 +100,37 @@ format_vxlan_tunnel_ref (u8 * s, va_list * args)
 
   vxr = vxlan_tunnel_ref_get (vxri);
 
-  s = format (s, "[%U locks:%d]", format_vnet_sw_if_index_name,
-             vnet_get_main (), vxr->vxr_sw_if_index, vxr->vxr_locks);
+  s = format (s, "[%U]", format_gbp_itf_hdl, vxr->vxr_itf);
 
   return (s);
 }
 
-static u32
+static void
+gdb_vxlan_dep_del (u32 sw_if_index)
+{
+  vxlan_tunnel_ref_t *vxr;
+  gbp_vxlan_tunnel_t *gt;
+  index_t vxri;
+  u32 pos;
+
+  vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]);
+  vxri = vxr - vxlan_tunnel_ref_pool;
+  gt = gbp_vxlan_tunnel_get (vxr->vxr_parent);
+
+  GBP_VXLAN_TUN_DBG ("del-dep:%U", format_vxlan_tunnel_ref, vxri);
+
+  vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = INDEX_INVALID;
+  pos = vec_search (gt->gt_tuns, vxri);
+
+  ASSERT (~0 != pos);
+  vec_del1 (gt->gt_tuns, pos);
+
+  vnet_vxlan_gbp_tunnel_del (vxr->vxr_sw_if_index);
+
+  pool_put (vxlan_tunnel_ref_pool, vxr);
+}
+
+static gbp_itf_hdl_t
 gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt,
                   const ip46_address_t * src, const ip46_address_t * dst)
 {
@@ -132,7 +157,7 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt,
       vxri = vxlan_tunnel_ref_db[sw_if_index];
 
       vxr = vxlan_tunnel_ref_get (vxri);
-      vxr->vxr_locks++;
+      gbp_itf_lock (vxr->vxr_itf);
     }
   else if (0 == rv)
     {
@@ -147,7 +172,6 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt,
       vxri = (vxr - vxlan_tunnel_ref_pool);
       vxr->vxr_parent = gt - gbp_vxlan_tunnel_pool;
       vxr->vxr_sw_if_index = sw_if_index;
-      vxr->vxr_locks = 1;
       vxr->vxr_layer = gt->gt_layer;
 
       /*
@@ -166,38 +190,32 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt,
          gbp_bridge_domain_t *gbd;
 
          gbd = gbp_bridge_domain_get (gt->gt_gbd);
-         vxr->vxr_itf = gbp_itf_add_and_lock (vxr->vxr_sw_if_index,
-                                              gt->gt_bd_index);
+         vxr->vxr_itf = gbp_itf_l2_add_and_lock_w_free
+           (vxr->vxr_sw_if_index, gt->gt_gbd, gdb_vxlan_dep_del);
 
-         ofeat = (L2OUTPUT_FEAT_GBP_POLICY_MAC |
-                  L2OUTPUT_FEAT_GBP_ID_2_SCLASS);
-         ifeat = L2INPUT_FEAT_GBP_SCLASS_2_ID;
+         ofeat = L2OUTPUT_FEAT_GBP_POLICY_MAC;
+         ifeat = L2INPUT_FEAT_NONE;
 
          if (!(gbd->gb_flags & GBP_BD_FLAG_DO_NOT_LEARN))
            ifeat |= L2INPUT_FEAT_GBP_LEARN;
 
-         gbp_itf_set_l2_output_feature (vxr->vxr_itf,
-                                        vxr->vxr_sw_if_index, ofeat);
-         gbp_itf_set_l2_input_feature (vxr->vxr_itf,
-                                       vxr->vxr_sw_if_index, ifeat);
+         gbp_itf_l2_set_output_feature (vxr->vxr_itf, ofeat);
+         gbp_itf_l2_set_input_feature (vxr->vxr_itf, ifeat);
        }
       else
        {
-         const gbp_route_domain_t *grd;
-         fib_protocol_t fproto;
-
-         grd = gbp_route_domain_get (gt->gt_grd);
+         vxr->vxr_itf = gbp_itf_l3_add_and_lock_w_free
+           (vxr->vxr_sw_if_index, gt->gt_grd, gdb_vxlan_dep_del);
 
-         FOR_EACH_FIB_IP_PROTOCOL (fproto)
-           ip_table_bind (fproto, vxr->vxr_sw_if_index,
-                          grd->grd_table_id[fproto], 1);
-
-         gbp_learn_enable (vxr->vxr_sw_if_index, GBP_LEARN_MODE_L3);
-         gbp_sclass_enable_ip (vxr->vxr_sw_if_index);
+         gbp_itf_l3_set_input_feature (vxr->vxr_itf, GBP_ITF_L3_FEAT_LEARN);
        }
     }
+  else
+    {
+      return (GBP_ITF_HDL_INVALID);
+    }
 
-  return (sw_if_index);
+  return (vxr->vxr_itf);
 }
 
 u32
@@ -215,6 +233,22 @@ vxlan_gbp_tunnel_get_parent (u32 sw_if_index)
   return (gt->gt_sw_if_index);
 }
 
+gbp_itf_hdl_t
+vxlan_gbp_tunnel_lock_itf (u32 sw_if_index)
+{
+  ASSERT ((sw_if_index < vec_len (vxlan_tunnel_ref_db)) &&
+         (INDEX_INVALID != vxlan_tunnel_ref_db[sw_if_index]));
+
+  vxlan_tunnel_ref_t *vxr;
+
+  vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]);
+
+  gbp_itf_lock (vxr->vxr_itf);
+
+  return (vxr->vxr_itf);
+}
+
+
 gbp_vxlan_tunnel_type_t
 gbp_vxlan_tunnel_get_type (u32 sw_if_index)
 {
@@ -233,7 +267,7 @@ gbp_vxlan_tunnel_get_type (u32 sw_if_index)
   return (GBP_VXLAN_TEMPLATE_TUNNEL);
 }
 
-u32
+gbp_itf_hdl_t
 gbp_vxlan_tunnel_clone_and_lock (u32 sw_if_index,
                                 const ip46_address_t * src,
                                 const ip46_address_t * dst)
@@ -244,85 +278,26 @@ gbp_vxlan_tunnel_clone_and_lock (u32 sw_if_index,
   gti = gbp_vxlan_tunnel_db[sw_if_index];
 
   if (INDEX_INVALID == gti)
-    return (~0);
+    return (GBP_ITF_HDL_INVALID);
 
   gt = pool_elt_at_index (gbp_vxlan_tunnel_pool, gti);
 
   return (gdb_vxlan_dep_add (gt, src, dst));
 }
 
-static void
-gdb_vxlan_dep_del (index_t vxri)
-{
-  vxlan_tunnel_ref_t *vxr;
-  gbp_vxlan_tunnel_t *gt;
-  u32 pos;
-
-  vxr = vxlan_tunnel_ref_get (vxri);
-  gt = gbp_vxlan_tunnel_get (vxr->vxr_parent);
-
-  GBP_VXLAN_TUN_DBG ("del-dep:%U", format_vxlan_tunnel_ref, vxri);
-
-  vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = INDEX_INVALID;
-  pos = vec_search (gt->gt_tuns, vxri);
-
-  ASSERT (~0 != pos);
-  vec_del1 (gt->gt_tuns, pos);
-
-  if (GBP_VXLAN_TUN_L2 == vxr->vxr_layer)
-    {
-      gbp_itf_set_l2_output_feature (vxr->vxr_itf, vxr->vxr_sw_if_index,
-                                    L2OUTPUT_FEAT_NONE);
-      gbp_itf_set_l2_input_feature (vxr->vxr_itf, vxr->vxr_sw_if_index,
-                                   L2INPUT_FEAT_NONE);
-      gbp_itf_unlock (vxr->vxr_itf);
-    }
-  else
-    {
-      fib_protocol_t fproto;
-
-      FOR_EACH_FIB_IP_PROTOCOL (fproto)
-       ip_table_bind (fproto, vxr->vxr_sw_if_index, 0, 0);
-      gbp_sclass_disable_ip (vxr->vxr_sw_if_index);
-      gbp_learn_disable (vxr->vxr_sw_if_index, GBP_LEARN_MODE_L3);
-    }
-
-  vnet_vxlan_gbp_tunnel_del (vxr->vxr_sw_if_index);
-
-  pool_put (vxlan_tunnel_ref_pool, vxr);
-}
-
 void
 vxlan_gbp_tunnel_unlock (u32 sw_if_index)
 {
-  vxlan_tunnel_ref_t *vxr;
-  index_t vxri;
-
-  vxri = vxlan_tunnel_ref_db[sw_if_index];
-
-  ASSERT (vxri != INDEX_INVALID);
-
-  vxr = vxlan_tunnel_ref_get (vxri);
-  vxr->vxr_locks--;
-
-  if (0 == vxr->vxr_locks)
-    {
-      gdb_vxlan_dep_del (vxri);
-    }
-}
+  /* vxlan_tunnel_ref_t *vxr; */
+  /* index_t vxri; */
 
-void
-vxlan_gbp_tunnel_lock (u32 sw_if_index)
-{
-  vxlan_tunnel_ref_t *vxr;
-  index_t vxri;
+  /* vxri = vxlan_tunnel_ref_db[sw_if_index]; */
 
-  vxri = vxlan_tunnel_ref_db[sw_if_index];
+  /* ASSERT (vxri != INDEX_INVALID); */
 
-  ASSERT (vxri != INDEX_INVALID);
+  /* vxr = vxlan_tunnel_ref_get (vxri); */
 
-  vxr = vxlan_tunnel_ref_get (vxri);
-  vxr->vxr_locks++;
+  /* gdb_vxlan_dep_del (vxri); */
 }
 
 void
@@ -373,23 +348,20 @@ format_gbp_vxlan_tunnel (u8 * s, va_list * args)
   gbp_vxlan_tunnel_t *gt = gbp_vxlan_tunnel_get (dev_instance);
   index_t *vxri;
 
-  s = format (s, "GBP VXLAN tunnel: hw:%d sw:%d vni:%d %U",
-             gt->gt_hw_if_index, gt->gt_sw_if_index, gt->gt_vni,
+  s = format (s, " [%d] gbp-vxlan-tunnel: hw:%d sw:%d vni:%d %U",
+             dev_instance, gt->gt_hw_if_index,
+             gt->gt_sw_if_index, gt->gt_vni,
              format_gbp_vxlan_tunnel_layer, gt->gt_layer);
   if (GBP_VXLAN_TUN_L2 == gt->gt_layer)
-    s = format (s, " BD:%d bd-index:%d", gt->gt_bd_rd_id, gt->gt_bd_index);
+    s = format (s, " BD:%d gbd-index:%d", gt->gt_bd_rd_id, gt->gt_gbd);
   else
-    s = format (s, " RD:%d fib-index:[%d,%d]",
-               gt->gt_bd_rd_id,
-               gt->gt_fib_index[FIB_PROTOCOL_IP4],
-               gt->gt_fib_index[FIB_PROTOCOL_IP6]);
+    s = format (s, " RD:%d grd-index:%d", gt->gt_bd_rd_id, gt->gt_grd);
 
-  s = format (s, " children:[");
+  s = format (s, "   dependents:");
   vec_foreach (vxri, gt->gt_tuns)
   {
-    s = format (s, "%U, ", format_vxlan_tunnel_ref, *vxri);
+    s = format (s, "\n    %U, ", format_vxlan_tunnel_ref, *vxri);
   }
-  s = format (s, "]");
 
   return s;
 }
@@ -465,7 +437,8 @@ VNET_HW_INTERFACE_CLASS (gbp_vxlan_hw_interface_class) = {
 
 int
 gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer,
-                     u32 bd_rd_id, u32 * sw_if_indexp)
+                     u32 bd_rd_id,
+                     const ip4_address_t * src, u32 * sw_if_indexp)
 {
   gbp_vxlan_tunnel_t *gt;
   index_t gti;
@@ -512,6 +485,7 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer,
       gt->gt_vni = vni;
       gt->gt_layer = layer;
       gt->gt_bd_rd_id = bd_rd_id;
+      gt->gt_src.ip4.as_u32 = src->as_u32;
       gt->gt_hw_if_index = vnet_register_interface (vnm,
                                                    gbp_vxlan_device_class.index,
                                                    gti,
@@ -533,37 +507,18 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer,
          gb = gbp_bridge_domain_get (gbi);
 
          gt->gt_gbd = gbi;
-         gt->gt_bd_index = gb->gb_bd_index;
-         gb->gb_vni_sw_if_index = gt->gt_sw_if_index;
+         gb->gb_vni = gti;
          /* set it up as a GBP interface */
-         gt->gt_itf = gbp_itf_add_and_lock (gt->gt_sw_if_index,
-                                            gt->gt_bd_index);
-         gbp_learn_enable (gt->gt_sw_if_index, GBP_LEARN_MODE_L2);
-         gbp_sclass_enable_l2 (gt->gt_sw_if_index);
+         gt->gt_itf = gbp_itf_l2_add_and_lock (gt->gt_sw_if_index,
+                                               gt->gt_gbd);
+         gbp_itf_l2_set_input_feature (gt->gt_itf, L2INPUT_FEAT_GBP_LEARN);
        }
       else
        {
-         gbp_route_domain_t *grd;
-         fib_protocol_t fproto;
-
-         grd = gbp_route_domain_get (grdi);
-
          gt->gt_grd = grdi;
-         grd->grd_vni_sw_if_index = gt->gt_sw_if_index;
-
-         gbp_learn_enable (gt->gt_sw_if_index, GBP_LEARN_MODE_L3);
-         gbp_sclass_enable_ip (gt->gt_sw_if_index);
-
-         ip4_sw_interface_enable_disable (gt->gt_sw_if_index, 1);
-         ip6_sw_interface_enable_disable (gt->gt_sw_if_index, 1);
-
-         FOR_EACH_FIB_IP_PROTOCOL (fproto)
-         {
-           gt->gt_fib_index[fproto] = grd->grd_fib_index[fproto];
-
-           ip_table_bind (fproto, gt->gt_sw_if_index,
-                          grd->grd_table_id[fproto], 1);
-         }
+         gt->gt_itf = gbp_itf_l3_add_and_lock (gt->gt_sw_if_index,
+                                               gt->gt_grd);
+         gbp_itf_l3_set_input_feature (gt->gt_itf, GBP_ITF_L3_FEAT_LEARN);
        }
 
       /*
@@ -571,7 +526,8 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer,
        */
       hash_set (gv_db, vni, gti);
 
-      vec_validate (gbp_vxlan_tunnel_db, gt->gt_sw_if_index);
+      vec_validate_init_empty (gbp_vxlan_tunnel_db,
+                              gt->gt_sw_if_index, INDEX_INVALID);
       gbp_vxlan_tunnel_db[gt->gt_sw_if_index] = gti;
 
       if (sw_if_indexp)
@@ -614,25 +570,14 @@ gbp_vxlan_tunnel_del (u32 vni)
       ASSERT (0 == vec_len (gt->gt_tuns));
       vec_free (gt->gt_tuns);
 
+      gbp_itf_unlock (&gt->gt_itf);
+
       if (GBP_VXLAN_TUN_L2 == gt->gt_layer)
        {
-         gbp_learn_disable (gt->gt_sw_if_index, GBP_LEARN_MODE_L2);
-         gbp_sclass_disable_l2 (gt->gt_sw_if_index);
-         gbp_itf_unlock (gt->gt_itf);
          gbp_bridge_domain_unlock (gt->gt_gbd);
        }
       else
        {
-         fib_protocol_t fproto;
-
-         FOR_EACH_FIB_IP_PROTOCOL (fproto)
-           ip_table_bind (fproto, gt->gt_sw_if_index, 0, 0);
-
-         ip4_sw_interface_enable_disable (gt->gt_sw_if_index, 0);
-         ip6_sw_interface_enable_disable (gt->gt_sw_if_index, 0);
-
-         gbp_learn_disable (gt->gt_sw_if_index, GBP_LEARN_MODE_L3);
-         gbp_sclass_disable_ip (gt->gt_sw_if_index);
          gbp_route_domain_unlock (gt->gt_grd);
        }
 
@@ -654,6 +599,9 @@ static clib_error_t *
 gbp_vxlan_show (vlib_main_t * vm,
                unformat_input_t * input, vlib_cli_command_t * cmd)
 {
+
+  vlib_cli_output (vm, "GBP-VXLAN Interfaces:");
+
   gbp_vxlan_walk (gbp_vxlan_tunnel_show_one, vm);
 
   return (NULL);
@@ -677,31 +625,25 @@ VLIB_CLI_COMMAND (gbp_vxlan_show_node, static) = {
 static clib_error_t *
 gbp_vxlan_init (vlib_main_t * vm)
 {
-  u32 slot4;
-  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "gbp-vxlan4");
-
-  /*
-   * insert ourselves into the VXLAN-GBP arc to collect the no-tunnel
-   * packets.
-   */
-  slot4 = vlib_node_add_next_with_slot (vm,
-                                       vxlan4_gbp_input_node.index,
-                                       node->index,
-                                       VXLAN_GBP_INPUT_NEXT_NO_TUNNEL);
-  ASSERT (slot4 == VXLAN_GBP_INPUT_NEXT_NO_TUNNEL);
-
-  /* slot6 = vlib_node_add_next_with_slot (vm, */
-  /*                                    vxlan6_gbp_input_node.index, */
-  /*                                    gbp_vxlan6_input_node.index, */
-  /*                                    VXLAN_GBP_INPUT_NEXT_NO_TUNNEL); */
-  /* ASSERT (slot6 == VXLAN_GBP_INPUT_NEXT_NO_TUNNEL); */
+  vxlan_gbp_main_t *vxm = &vxlan_gbp_main;
 
   gt_logger = vlib_log_register_class ("gbp", "tun");
 
-  return (NULL);
+  punt_hdl = vlib_punt_client_register ("gbp-vxlan");
+
+  vlib_punt_register (punt_hdl,
+                     vxm->punt_no_such_tunnel[FIB_PROTOCOL_IP4],
+                     "gbp-vxlan4");
+
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (gbp_vxlan_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (gbp_vxlan_init) =
+{
+  .runs_after = VLIB_INITS("punt_init", "vxlan_gbp_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON