l2: coverity complains dead codes
[vpp.git] / src / vnet / l2 / l2_bd.c
index 207ef4d..9c81b0f 100644 (file)
@@ -88,6 +88,9 @@ bd_add_bd_index (bd_main_t * bdm, u32 bd_id)
 
   vec_validate (l2input_main.bd_configs, rv);
   l2input_main.bd_configs[rv].bd_id = bd_id;
+  l2input_main.bd_configs[rv].learn_limit =
+    l2learn_main.bd_default_learn_limit;
+  l2input_main.bd_configs[rv].learn_count = 0;
 
   return rv;
 }
@@ -124,6 +127,8 @@ bd_delete (bd_main_t * bdm, u32 bd_index)
   /* clear BD config for reuse: bd_id to -1 and clear feature_bitmap */
   bd->bd_id = ~0;
   bd->feature_bitmap = 0;
+  bd->learn_limit = 0;
+  bd->learn_count = ~0;
 
   /* free BD tag */
   vec_free (bd->bd_tag);
@@ -229,7 +234,7 @@ l2bd_init (vlib_main_t * vm)
   bd_main_t *bdm = &bd_main;
   bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword));
   /*
-   * create a dummy bd with bd_id of 0 and bd_index of 0 with feature set
+   * create a placeholder bd with bd_id of 0 and bd_index of 0 with feature set
    * to packet drop only. Thus, packets received from any L2 interface with
    * uninitialized bd_index of 0 can be dropped safely.
    */
@@ -243,6 +248,43 @@ l2bd_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (l2bd_init);
 
+l2_bridge_domain_t *
+bd_get (u32 bd_index)
+{
+  if (bd_index < vec_len (l2input_main.bd_configs))
+    return (vec_elt_at_index (l2input_main.bd_configs, bd_index));
+  return (NULL);
+}
+
+u32
+bd_input_walk (u32 bd_index, bd_input_walk_fn_t fn, void *data)
+{
+  l2_flood_member_t *member;
+  l2_bridge_domain_t *bd;
+  u32 sw_if_index;
+
+  sw_if_index = ~0;
+  bd = bd_get (bd_index);
+
+  ASSERT (bd);
+
+  vec_foreach (member, bd->members)
+  {
+    if (WALK_STOP == fn (bd_index, member->sw_if_index))
+      {
+       sw_if_index = member->sw_if_index;
+       break;
+      }
+  }
+
+  return (sw_if_index);
+}
+
+static void
+b2_input_recache (u32 bd_index)
+{
+  bd_input_walk (bd_index, l2input_recache, NULL);
+}
 
 /**
     Set the learn/forward/flood flags for the bridge domain.
@@ -290,6 +332,8 @@ bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, u32 enable)
       bd_config->feature_bitmap &= ~feature_bitmap;
     }
 
+  b2_input_recache (bd_index);
+
   return bd_config->feature_bitmap;
 }
 
@@ -305,6 +349,7 @@ bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age)
   vec_validate (l2input_main.bd_configs, bd_index);
   bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
   bd_config->mac_age = age;
+  b2_input_recache (bd_index);
 
   /* check if there is at least one bd with mac aging enabled */
   vec_foreach (bd_config, l2input_main.bd_configs)
@@ -316,9 +361,20 @@ bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age)
 }
 
 /**
-    Set the tag for the bridge domain.
+    Set learn limit for the bridge domain.
 */
+void
+bd_set_learn_limit (vlib_main_t *vm, u32 bd_index, u32 learn_limit)
+{
+  l2_bridge_domain_t *bd_config;
+  vec_validate (l2input_main.bd_configs, bd_index);
+  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
+  bd_config->learn_limit = learn_limit;
+}
 
+/**
+    Set the tag for the bridge domain.
+*/
 static void
 bd_set_bd_tag (vlib_main_t * vm, u32 bd_index, u8 * bd_tag)
 {
@@ -406,6 +462,34 @@ VLIB_CLI_COMMAND (bd_learn_cli, static) = {
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+bd_default_learn_limit (vlib_main_t *vm, unformat_input_t *input,
+                       vlib_cli_command_t *cmd)
+{
+  l2learn_main_t *l2m = &l2learn_main;
+  clib_error_t *error = 0;
+  u32 learn_limit;
+
+  if (!unformat (input, "%d", &learn_limit))
+    {
+      error = clib_error_return (
+       0, "expecting per bridge-domain max entry number got`%U'",
+       format_unformat_error, input);
+      goto done;
+    }
+
+  l2m->bd_default_learn_limit = learn_limit;
+
+done:
+  return error;
+}
+
+VLIB_CLI_COMMAND (bd_default_learn_limit_cli, static) = {
+  .path = "set bridge-domain default-learn-limit",
+  .short_help = "set bridge-domain default-learn-limit <maxentries>",
+  .function = bd_default_learn_limit,
+};
+
 /**
     Set bridge-domain forward enable/disable.
     The CLI format is:
@@ -778,6 +862,55 @@ VLIB_CLI_COMMAND (bd_mac_age_cli, static) = {
 };
 /* *INDENT-ON* */
 
+static clib_error_t *
+bd_learn_limit (vlib_main_t *vm, unformat_input_t *input,
+               vlib_cli_command_t *cmd)
+{
+  bd_main_t *bdm = &bd_main;
+  clib_error_t *error = 0;
+  u32 bd_index, bd_id;
+  u32 learn_limit;
+  uword *p;
+
+  if (!unformat (input, "%d", &bd_id))
+    {
+      error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
+                                format_unformat_error, input);
+      goto done;
+    }
+
+  if (bd_id == 0)
+    return clib_error_return (
+      0, "No operations on the default bridge domain are supported");
+
+  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
+
+  if (p == 0)
+    return clib_error_return (0, "No such bridge domain %d", bd_id);
+
+  bd_index = p[0];
+
+  if (!unformat (input, "%u", &learn_limit))
+    {
+      error = clib_error_return (
+       0, "expecting maxium number of learned entries but got `%U'",
+       format_unformat_error, input);
+      goto done;
+    }
+
+  bd_set_learn_limit (vm, bd_index, learn_limit);
+
+done:
+  return error;
+}
+
+VLIB_CLI_COMMAND (bd_learn_limit_cli, static) = {
+  .path = "set bridge-domain learn-limit",
+  .short_help =
+    "set bridge-domain learn-limit <bridge-domain-id> <learn-limit>",
+  .function = bd_learn_limit,
+};
+
 /*?
  * Modify whether or not an existing bridge-domain should terminate and respond
  * to ARP Requests. ARP Termination is disabled by default.
@@ -994,41 +1127,6 @@ VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = {
 };
 /* *INDENT-ON* */
 
-static u8 *
-format_vtr (u8 * s, va_list * args)
-{
-  u32 vtr_op = va_arg (*args, u32);
-  u32 dot1q = va_arg (*args, u32);
-  u32 tag1 = va_arg (*args, u32);
-  u32 tag2 = va_arg (*args, u32);
-  switch (vtr_op)
-    {
-    case L2_VTR_DISABLED:
-      return format (s, "none");
-    case L2_VTR_PUSH_1:
-      return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
-    case L2_VTR_PUSH_2:
-      return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1,
-                    tag2);
-    case L2_VTR_POP_1:
-      return format (s, "pop-1");
-    case L2_VTR_POP_2:
-      return format (s, "pop-2");
-    case L2_VTR_TRANSLATE_1_1:
-      return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
-    case L2_VTR_TRANSLATE_1_2:
-      return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
-                    tag1, tag2);
-    case L2_VTR_TRANSLATE_2_1:
-      return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
-    case L2_VTR_TRANSLATE_2_2:
-      return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
-                    tag1, tag2);
-    default:
-      return format (s, "none");
-    }
-}
-
 static u8 *
 format_uu_cfg (u8 * s, va_list * args)
 {
@@ -1116,10 +1214,11 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
            {
              printed = 1;
              vlib_cli_output (vm,
-                              "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=9s %=11s",
-                              "BD-ID", "Index", "BSN", "Age(min)",
-                              "Learning", "U-Forwrd", "UU-Flood",
-                              "Flooding", "ARP-Term", "arp-ufwd",
+                              "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s "
+                              "%=9s %=8s %=8s %=11s",
+                              "BD-ID", "Index", "BSN", "Age(min)", "Learning",
+                              "U-Forwrd", "UU-Flood", "Flooding", "ARP-Term",
+                              "arp-ufwd", "Learn-count", "Learn-limit",
                               "BVI-Intf");
            }
 
@@ -1127,22 +1226,23 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
            as = format (as, "%d", bd_config->mac_age);
          else
            as = format (as, "off");
-         vlib_cli_output (vm,
-                          "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=11U",
-                          bd_config->bd_id, bd_index, bd_config->seq_num, as,
-                          bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
-                          "on" : "off",
-                          bd_config->feature_bitmap & L2INPUT_FEAT_FWD ?
-                          "on" : "off",
-                          format_uu_cfg, bd_config,
-                          bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
-                          "on" : "off",
-                          bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
-                          "on" : "off",
-                          bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ?
-                          "on" : "off",
-                          format_vnet_sw_if_index_name_with_NA,
-                          vnm, bd_config->bvi_sw_if_index);
+         vlib_cli_output (
+           vm,
+           "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=8d %=8d "
+           "%=11U",
+           bd_config->bd_id, bd_index, bd_config->seq_num, as,
+           bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ? "on" : "off",
+           bd_config->feature_bitmap & L2INPUT_FEAT_FWD ? "on" : "off",
+           format_uu_cfg, bd_config,
+           bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ? "on" : "off",
+           bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ? "on" : "off",
+           bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ? "on" : "off",
+           bd_config->learn_count, bd_config->learn_limit,
+           format_vnet_sw_if_index_name_with_NA, vnm,
+           bd_config->bvi_sw_if_index);
+         if (detail)
+           vlib_cli_output (vm, "%U", format_l2_input_feature_bitmap,
+                            bd_config->feature_bitmap);
          vec_reset_length (as);
 
          if (detail || intf)
@@ -1153,7 +1253,7 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
              {
                l2_flood_member_t *member =
                  vec_elt_at_index (bd_config->members, i);
-               u8 swif_seq_num = *l2fib_swif_seq_num (member->sw_if_index);
+               u8 swif_seq_num = l2_input_seq_num (member->sw_if_index);
                u32 vtr_opr, dot1q, tag1, tag2;
                if (i == 0)
                  {
@@ -1261,9 +1361,13 @@ int
 bd_add_del (l2_bridge_domain_add_del_args_t * a)
 {
   bd_main_t *bdm = &bd_main;
+  l2fib_main_t *fm = &l2fib_main;
   vlib_main_t *vm = bdm->vlib_main;
   int rv = 0;
 
+  if (fm->mac_table_initialized == 0)
+    l2fib_table_init ();
+
   u32 bd_index = bd_find_index (bdm, a->bd_id);
   if (a->is_add)
     {
@@ -1315,6 +1419,8 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a)
       if (a->bd_tag)
        bd_set_bd_tag (vm, bd_index, a->bd_tag);
 
+      bd_set_learn_limit (vm, bd_index, l2learn_main.bd_default_learn_limit);
+      vec_elt_at_index (l2input_main.bd_configs, bd_index)->learn_count = 0;
     }
   else
     {
@@ -1387,8 +1493,15 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
   if (bd_id == ~0)
     {
-      error = clib_error_return (0, "bridge-domain-id not specified");
-      goto done;
+      if (is_add)
+       {
+         bd_id = bd_get_unused_id ();
+       }
+      else
+       {
+         error = clib_error_return (0, "bridge-domain-id not specified");
+         goto done;
+       }
     }
 
   if (bd_id == 0)
@@ -1491,7 +1604,37 @@ VLIB_CLI_COMMAND (bd_create_cli, static) = {
 };
 /* *INDENT-ON* */
 
+/*
+ * Returns an unused bridge domain id, and ~0 if it can't find one.
+ */
+u32
+bd_get_unused_id (void)
+{
+  bd_main_t *bdm = &bd_main;
+  int i, j;
+  static u32 seed = 0;
 
+  /* limit to 1M tries */
+  for (j = 0; j < 1 << 10; j++)
+    {
+      seed = random_u32 (&seed);
+      for (i = 0; i < 1 << 10; i++)
+       {
+         /*
+          * iterate seed+0, seed+1, seed-1, seed+2, seed-2, ... to generate id
+          */
+         seed += (2 * (i % 2) - 1) * i;
+         /* bd_id must be (1 <= bd_id <= L2_BD_ID_MAX) */
+         seed &= L2_BD_ID_MAX;
+         if (seed == 0)
+           continue;
+         if (bd_find_index (bdm, seed) == ~0)
+           return seed;
+       }
+    }
+
+  return ~0;
+}
 
 /*
  * fd.io coding-style-patch-verification: ON