Fix crash with worker threads on 4K VXLAN/BD setup (VPP-907)
[vpp.git] / src / vnet / l2 / l2_input.c
index e5d6878..9a3148c 100644 (file)
@@ -202,8 +202,14 @@ classify_and_dispatch (vlib_main_t * vm,
       /* Get config for the bridge domain interface */
       bd_config = vec_elt_at_index (msm->bd_configs, bd_index0);
 
-      /* Save bridge domain seq_num */
-      vnet_buffer (b0)->l2.bd_sn = bd_config->seq_num;
+      /* Save bridge domain and interface seq_num */
+      /* *INDENT-OFF* */
+      l2fib_seq_num_t sn = {
+        .swif = *l2fib_swif_seq_num(sw_if_index0),
+       .bd = bd_config->seq_num,
+      };
+      /* *INDENT-ON* */
+      vnet_buffer (b0)->l2.l2fib_sn = sn.as_u16;;
 
       /*
        * Process bridge domain feature enables.
@@ -218,9 +224,6 @@ classify_and_dispatch (vlib_main_t * vm,
   /* mask out features from bitmap using packet type and bd config */
   feature_bitmap = config->feature_bitmap & feat_mask;
 
-  /* Save interface seq_num */
-  vnet_buffer (b0)->l2.int_sn = config->seq_num;
-
   /* save for next feature graph nodes */
   vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap;
 
@@ -481,20 +484,12 @@ l2input_intf_config (u32 sw_if_index)
 u32
 l2input_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable)
 {
-  l2input_main_t *mp = &l2input_main;
-  l2_input_config_t *config;
-
-  vec_validate (mp->configs, sw_if_index);
-  config = vec_elt_at_index (mp->configs, sw_if_index);
+  l2_input_config_t *config = l2input_intf_config (sw_if_index);
 
   if (enable)
-    {
-      config->feature_bitmap |= feature_bitmap;
-    }
+    config->feature_bitmap |= feature_bitmap;
   else
-    {
-      config->feature_bitmap &= ~feature_bitmap;
-    }
+    config->feature_bitmap &= ~feature_bitmap;
 
   return config->feature_bitmap;
 }
@@ -502,9 +497,7 @@ l2input_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable)
 u32
 l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value)
 {
-  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);
+  l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);;
   bd_validate (bd_config);
   bd_config->feature_bitmap =
     (bd_config->feature_bitmap & ~feat_mask) | feat_value;
@@ -535,7 +528,6 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
   l2_output_config_t *out_config;
   l2_input_config_t *config;
   l2_bridge_domain_t *bd_config;
-  l2_flood_member_t member;
   u64 mac;
   i32 l2_if_adjust = 0;
   u32 slot;
@@ -570,8 +562,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
        }
 
       /* Clear MACs learned on the interface */
-      if ((config->feature_bitmap | L2INPUT_FEAT_LEARN) ||
-         (bd_config->feature_bitmap | L2INPUT_FEAT_LEARN))
+      if ((config->feature_bitmap & L2INPUT_FEAT_LEARN) ||
+         (bd_config->feature_bitmap & L2INPUT_FEAT_LEARN))
        l2fib_flush_int_mac (vm, sw_if_index);
 
       l2_if_adjust--;
@@ -581,13 +573,9 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,        /*           */
       l2_if_adjust--;
     }
 
-  /*
-   * Directs the l2 output path to work out the interface
-   * output next-arc itself. Needed when recycling a sw_if_index.
-   */
+  /* Make sure vector is big enough */
   vec_validate_init_empty (l2om->next_nodes.output_node_index_vec,
-                          sw_if_index, ~0);
-  l2om->next_nodes.output_node_index_vec[sw_if_index] = ~0;
+                          sw_if_index, L2OUTPUT_NEXT_DROP);
 
   /* Initialize the l2-input configuration for the interface */
   if (mode == MODE_L3)
@@ -609,26 +597,11 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,       /*           */
       l2om->next_nodes.output_node_index_vec[sw_if_index] =
        L2OUTPUT_NEXT_BAD_INTF;
     }
-  else if (mode == MODE_L2_CLASSIFY)
-    {
-      config->xconnect = 1;
-      config->bridge = 0;
-      config->output_sw_if_index = xc_sw_if_index;
-
-      /* Make sure last-chance drop is configured */
-      config->feature_bitmap |=
-       L2INPUT_FEAT_DROP | L2INPUT_FEAT_INPUT_CLASSIFY;
-
-      /* Make sure bridging features are disabled */
-      config->feature_bitmap &=
-       ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD);
-      shg = 0;                 /* not used in xconnect */
-
-      /* Insure all packets go to ethernet-input */
-      ethernet_set_rx_redirect (vnet_main, hi, 1);
-    }
   else
     {
+      /* Add or update l2-output node next-arc and output_node_index_vec table
+       * for the interface */
+      l2output_create_output_node_mapping (vm, vnet_main, sw_if_index);
 
       if (mode == MODE_L2_BRIDGE)
        {
@@ -645,7 +618,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
          config->xconnect = 0;
          config->bridge = 1;
          config->bd_index = bd_index;
-         config->seq_num += 1;
+         *l2fib_swif_seq_num (sw_if_index) += 1;
 
          /*
           * Enable forwarding, flooding, learning and ARP termination by default
@@ -661,8 +634,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
          config->feature_bitmap &= ~L2INPUT_FEAT_XCONNECT;
 
          /* Set up bridge domain */
-         vec_validate (mp->bd_configs, bd_index);
-         bd_config = vec_elt_at_index (mp->bd_configs, bd_index);
+         bd_config = l2input_bd_config (bd_index);
          bd_validate (bd_config);
 
          /* TODO: think: add l2fib entry even for non-bvi interface? */
@@ -680,7 +652,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
 
              /* create the l2fib entry for the bvi interface */
              mac = *((u64 *) hi->hw_address);
-             l2fib_add_entry (mac, bd_index, sw_if_index, 1, 0, 1);    /* static + bvi */
+             l2fib_add_fwd_entry (mac, bd_index, sw_if_index, 1, 1);   /* static + bvi */
 
              /* Disable learning by default. no use since l2fib entry is static. */
              config->feature_bitmap &= ~L2INPUT_FEAT_LEARN;
@@ -694,13 +666,15 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,       /*           */
            }
 
          /* Add interface to bridge-domain flood vector */
-         member.sw_if_index = sw_if_index;
-         member.flags = bvi ? L2_FLOOD_MEMBER_BVI : L2_FLOOD_MEMBER_NORMAL;
-         member.shg = shg;
+         l2_flood_member_t member = {
+           .sw_if_index = sw_if_index,
+           .flags = bvi ? L2_FLOOD_MEMBER_BVI : L2_FLOOD_MEMBER_NORMAL,
+           .shg = shg,
+         };
          bd_add_member (bd_config, &member);
 
        }
-      else
+      else if (mode == MODE_L2_XC)
        {
          config->xconnect = 1;
          config->bridge = 0;
@@ -716,6 +690,24 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,        /*           */
          config->feature_bitmap |= L2INPUT_FEAT_XCONNECT;
          shg = 0;              /* not used in xconnect */
        }
+      else if (mode == MODE_L2_CLASSIFY)
+       {
+         config->xconnect = 1;
+         config->bridge = 0;
+         config->output_sw_if_index = xc_sw_if_index;
+
+         /* Make sure last-chance drop is configured */
+         config->feature_bitmap |=
+           L2INPUT_FEAT_DROP | L2INPUT_FEAT_INPUT_CLASSIFY;
+
+         /* Make sure bridging features are disabled */
+         config->feature_bitmap &=
+           ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD);
+         shg = 0;              /* not used in xconnect */
+
+         /* Insure all packets go to ethernet-input */
+         ethernet_set_rx_redirect (vnet_main, hi, 1);
+       }
 
       /* set up split-horizon group and set output feature bit */
       config->shg = shg;
@@ -798,6 +790,12 @@ int_l2_bridge (vlib_main_t * vm,
       goto done;
     }
 
+  if (bd_id > L2_BD_ID_MAX)
+    {
+      error = clib_error_return (0, "bridge domain ID exceed 16M limit",
+                                format_unformat_error, input);
+      goto done;
+    }
   bd_index = bd_find_or_add_bd_index (&bd_main, bd_id);
 
   /* optional bvi  */
@@ -997,10 +995,8 @@ show_int_mode (vlib_main_t * vm,
   char *mode;
   u8 *args;
   vnet_interface_main_t *im = &vnm->interface_main;
-  vnet_sw_interface_t *si, *sis = 0;
-  l2input_main_t *mp = &l2input_main;
-  l2_input_config_t *config;
 
+  vnet_sw_interface_t *si, *sis = 0;
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       u32 sw_if_index;
@@ -1018,7 +1014,6 @@ show_int_mode (vlib_main_t * vm,
                                     format_unformat_error, input);
          goto done;
        }
-
     }
 
   if (vec_len (sis) == 0)      /* Get all interfaces */
@@ -1033,8 +1028,7 @@ show_int_mode (vlib_main_t * vm,
 
   vec_foreach (si, sis)
   {
-    vec_validate (mp->configs, si->sw_if_index);
-    config = vec_elt_at_index (mp->configs, si->sw_if_index);
+    l2_input_config_t *config = l2input_intf_config (si->sw_if_index);
     if (config->bridge)
       {
        u32 bd_id;