Enforce Bridge Domain ID range to match 24-bit VNI range
[vpp.git] / src / vnet / lisp-gpe / interface.c
index 2142e09..94703ab 100644 (file)
@@ -23,7 +23,7 @@
 #include <vppinfra/hash.h>
 #include <vnet/vnet.h>
 #include <vnet/ip/ip.h>
-#include <vnet/ip/udp.h>
+#include <vnet/udp/udp.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/lisp-gpe/lisp_gpe.h>
 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
@@ -185,7 +185,8 @@ format_lisp_gpe_header_with_length (u8 * s, va_list * args)
 
   s = format (s, "\n  ver_res %d res %d next_protocol %d iid %d(%x)",
              h->ver_res, h->res, h->next_protocol,
-             clib_net_to_host_u32 (h->iid), clib_net_to_host_u32 (h->iid));
+             clib_net_to_host_u32 (h->iid << 8),
+             clib_net_to_host_u32 (h->iid << 8));
   return s;
 }
 
@@ -652,6 +653,12 @@ lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
   uword *hip, *si;
   u16 bd_index;
 
+  if (bd_id > L2_BD_ID_MAX)
+    {
+      clib_warning ("bridge domain ID %d exceed 16M limit", bd_id);
+      return ~0;
+    }
+
   bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
   hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
 
@@ -704,11 +711,11 @@ void
 lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
 {
   tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces;
-  u16 bd_index;
-  uword *hip;
+  vnet_hw_interface_t *hi;
 
-  bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
-  hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
+  u32 bd_index = bd_find_index (&bd_main, bd_id);
+  ASSERT (bd_index != ~0);
+  uword *hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
 
   if (hip == 0)
     {
@@ -716,6 +723,11 @@ lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
                    bd_id);
       return;
     }
+
+  /* Remove interface from bridge .. by enabling L3 mode */
+  hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]);
+  set_int_l2_mode (lgm->vlib_main, lgm->vnet_main, MODE_L3, hi->sw_if_index,
+                  0, 0, 0, 0);
   lisp_gpe_remove_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces);
 }
 
@@ -794,6 +806,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
   u32 table_id, vni, bd_id;
   u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0;
   u8 nsh_iface = 0;
+  clib_error_t *error = NULL;
 
   if (vnet_lisp_gpe_enable_disable_status () == 0)
     {
@@ -828,8 +841,9 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
        }
       else
        {
-         return clib_error_return (0, "parse error: '%U'",
-                                   format_unformat_error, line_input);
+         error = clib_error_return (0, "parse error: '%U'",
+                                    format_unformat_error, line_input);
+         goto done;
        }
     }
 
@@ -839,32 +853,46 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
        {
          if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main))
            {
-             return clib_error_return (0, "NSH interface not created");
+             error = clib_error_return (0, "NSH interface not created");
+             goto done;
            }
        }
       else
        {
          lisp_gpe_del_nsh_iface (&lisp_gpe_main);
        }
-      return (NULL);
+      goto done;
     }
 
   if (vrf_is_set && bd_index_is_set)
-    return clib_error_return (0,
-                             "Cannot set both vrf and brdige domain index!");
+    {
+      error = clib_error_return
+       (0, "Cannot set both vrf and brdige domain index!");
+      goto done;
+    }
 
   if (!vni_is_set)
-    return clib_error_return (0, "vni must be set!");
+    {
+      error = clib_error_return (0, "vni must be set!");
+      goto done;
+    }
 
   if (!vrf_is_set && !bd_index_is_set)
-    return clib_error_return (0, "vrf or bridge domain index must be set!");
+    {
+      error =
+       clib_error_return (0, "vrf or bridge domain index must be set!");
+      goto done;
+    }
 
   if (bd_index_is_set)
     {
       if (is_add)
        {
          if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, bd_id))
-           return clib_error_return (0, "L2 interface not created");
+           {
+             error = clib_error_return (0, "L2 interface not created");
+             goto done;
+           }
        }
       else
        lisp_gpe_tenant_l2_iface_unlock (vni);
@@ -874,13 +902,19 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
       if (is_add)
        {
          if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id))
-           return clib_error_return (0, "L3 interface not created");
+           {
+             error = clib_error_return (0, "L3 interface not created");
+             goto done;
+           }
        }
       else
        lisp_gpe_tenant_l3_iface_unlock (vni);
     }
 
-  return (NULL);
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */