Add DPDK 16.07 support (rc3 based)
[vpp.git] / vnet / vnet / l2 / l2_output.c
index 3128764..acca349 100644 (file)
@@ -62,31 +62,12 @@ static u8 * format_l2output_trace (u8 * s, va_list * args)
 }
 
 
-#define foreach_l2output_error                         \
-_(L2OUTPUT,     "L2 output packets")                   \
-_(EFP_DROP,     "L2 EFP filter pre-rewrite drops")     \
-_(VTR_DROP,     "L2 output tag rewrite drops")         \
-_(SHG_DROP,     "L2 split horizon drops")              \
-_(DROP,         "L2 output drops")
-
-typedef enum {
-#define _(sym,str) L2OUTPUT_ERROR_##sym,
-  foreach_l2output_error
-#undef _
-  L2OUTPUT_N_ERROR,
-} l2output_error_t;
-
 static char * l2output_error_strings[] = {
 #define _(sym,string) string,
   foreach_l2output_error
 #undef _
 };
 
-typedef enum {
-  L2OUTPUT_NEXT_DROP,
-  L2OUTPUT_N_NEXT,
-} l2output_next_t;
-
 // Return 0 if split horizon check passes, otherwise return non-zero
 // Packets should not be transmitted out an interface with the same
 // split-horizon group as the input interface, except if the shg is 0
@@ -102,6 +83,8 @@ split_horizon_violation (u8 shg1, u8 shg2)
 }
 
 
+static vlib_node_registration_t l2output_node;
+
 static uword
 l2output_node_fn (vlib_main_t * vm,
                  vlib_node_runtime_t * node,
@@ -190,16 +173,16 @@ l2output_node_fn (vlib_main_t * vm,
                     l2output_trace_t *t = 
                       vlib_add_trace (vm, node, b0, sizeof (*t));
                     t->sw_if_index = sw_if_index0;
-                    memcpy(t->src, h0->src_address, 6);
-                    memcpy(t->dst, h0->dst_address, 6);
+                    clib_memcpy(t->src, h0->src_address, 6);
+                    clib_memcpy(t->dst, h0->dst_address, 6);
                   }
                 if (b1->flags & VLIB_BUFFER_IS_TRACED) 
                   {
                     l2output_trace_t *t = 
                       vlib_add_trace (vm, node, b1, sizeof (*t));
                     t->sw_if_index = sw_if_index1;
-                    memcpy(t->src, h1->src_address, 6);
-                    memcpy(t->dst, h1->dst_address, 6);
+                    clib_memcpy(t->src, h1->src_address, 6);
+                    clib_memcpy(t->dst, h1->dst_address, 6);
                   }
               }
 
@@ -327,8 +310,8 @@ l2output_node_fn (vlib_main_t * vm,
                vlib_add_trace (vm, node, b0, sizeof (*t));
             t->sw_if_index = sw_if_index0;
             h0 = vlib_buffer_get_current (b0);
-            memcpy(t->src, h0->src_address, 6);
-            memcpy(t->dst, h0->dst_address, 6);
+            clib_memcpy(t->src, h0->src_address, 6);
+            clib_memcpy(t->dst, h0->dst_address, 6);
             }
 
           em->counters[node_counter_base_index + L2OUTPUT_ERROR_L2OUTPUT] += 1;
@@ -394,7 +377,7 @@ l2output_node_fn (vlib_main_t * vm,
 }
 
 
-VLIB_REGISTER_NODE (l2output_node) = {
+VLIB_REGISTER_NODE (l2output_node,static) = {
   .function = l2output_node_fn,
   .name = "l2-output",
   .vector_size = sizeof (u32),
@@ -409,9 +392,116 @@ VLIB_REGISTER_NODE (l2output_node) = {
   /* edit / add dispositions here */
   .next_nodes = {
         [L2OUTPUT_NEXT_DROP] = "error-drop",
+        [L2OUTPUT_NEXT_DEL_TUNNEL] = "l2-output-del-tunnel",
+  },
+};
+
+
+#define foreach_l2output_del_tunnel_error      \
+_(DROP,     "L2 output to deleted tunnel")
+
+static char * l2output_del_tunnel_error_strings[] = {
+#define _(sym,string) string,
+  foreach_l2output_del_tunnel_error
+#undef _
+};
+
+typedef enum {
+#define _(sym,str) L2OUTPUT_DEL_TUNNEL_ERROR_##sym,
+  foreach_l2output_del_tunnel_error
+#undef _
+  L2OUTPUT_DEL_TUNNEL_N_ERROR,
+} l2output_del_tunnel_error_t;
+
+
+// Output node for tunnels which was in L2 BD's but were deleted.
+// On deletion of any tunnel which was on a L2 BD, its entry in 
+// l2_output_main table next_nodes.output_node_index_vec[sw_if_index] 
+// MUST be set to the value of L2OUTPUT_NEXT_DEL_TUNNEL. Thus, if there
+// are stale entries in the L2FIB for this tunnel sw_if_index, l2-output 
+// will send packets for this sw_if_index to the l2-output-tunnel-del
+// node which just setup the proper drop reason before sending packets
+// to the error-drop node to drop the packet. Then, stale L2FIB entries
+// for delted tunnels won't cause possible packet or memory corrpution.
+static vlib_node_registration_t l2output_del_tunnel_node;
+
+static uword
+l2output_del_tunnel_node_fn (vlib_main_t * vm,
+                            vlib_node_runtime_t * node,
+                            vlib_frame_t * frame)
+{
+  u32 n_left_from, * from, * to_next;
+  l2output_next_t next_index = 0;
+
+  from = vlib_frame_vector_args (frame);
+  n_left_from = frame->n_vectors; // number of packets to process
+
+  while (n_left_from > 0)
+    {
+      u32 n_left_to_next;
+
+      // get space to enqueue frame to graph node "next_index"
+      vlib_get_next_frame (vm, node, next_index,
+                          to_next, n_left_to_next);
+
+      while (n_left_from >= 4 && n_left_to_next >= 2)
+       {
+          u32 bi0, bi1;
+         vlib_buffer_t * b0, * b1;
+
+         to_next[0] = bi0 = from[0];
+         to_next[1] = bi1 = from[1];
+         from += 2;
+         to_next += 2;
+         n_left_from -= 2;
+         n_left_to_next -= 2;
+         b0 = vlib_get_buffer (vm, bi0);
+         b1 = vlib_get_buffer (vm, bi1);
+         b0->error = node->errors[L2OUTPUT_DEL_TUNNEL_ERROR_DROP];
+         b1->error = node->errors[L2OUTPUT_DEL_TUNNEL_ERROR_DROP];
+        }
+      
+      while (n_left_from > 0 && n_left_to_next > 0)
+       {
+          u32 bi0;
+         vlib_buffer_t * b0;
+
+         bi0 = from[0];
+         to_next[0] = bi0;
+         from += 1;
+         to_next += 1;
+         n_left_from -= 1;
+         n_left_to_next -= 1;
+         b0 = vlib_get_buffer (vm, bi0);
+         b0->error = node->errors[L2OUTPUT_DEL_TUNNEL_ERROR_DROP];
+       }
+
+      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+    }
+
+  return frame->n_vectors;
+}
+
+VLIB_REGISTER_NODE (l2output_del_tunnel_node,static) = {
+  .function = l2output_del_tunnel_node_fn,
+  .name = "l2-output-del-tunnel",
+  .vector_size = sizeof (u32),
+  .type = VLIB_NODE_TYPE_INTERNAL,
+  
+  .n_errors =  ARRAY_LEN(l2output_del_tunnel_error_strings),
+  .error_strings = l2output_del_tunnel_error_strings,
+
+  .n_next_nodes = 1,
+
+  /* edit / add dispositions here */
+  .next_nodes = {
+       [0] = "error-drop",
   },
 };
 
+
+VLIB_NODE_FUNCTION_MULTIARCH (l2output_node, l2output_node_fn)
+
 clib_error_t *l2output_init (vlib_main_t *vm)
 {
   l2output_main_t * mp = &l2output_main;
@@ -485,17 +575,15 @@ u32 l2output_create_output_node_mapping (
   if (cpu_number)
     {
       u32 oldflags;
-      vlib_node_t  *error_drop_node;
 
-      error_drop_node = vlib_get_node_by_name (vlib_main, (u8 *) "error-drop");
       oldflags = __sync_fetch_and_or(&hw0->flags,
                                      VNET_HW_INTERFACE_FLAG_L2OUTPUT_MAPPED);
 
       if ((oldflags & VNET_HW_INTERFACE_FLAG_L2OUTPUT_MAPPED) )
-      return error_drop_node->index;
+        return L2OUTPUT_NEXT_DROP;
 
       output_node_mapping_send_rpc (node_index, sw_if_index);
-      return error_drop_node->index;
+        return L2OUTPUT_NEXT_DROP;
     }
 #endif