vnet: complete the fix for l3_hdr_offset calculation for single loop fastpass case...
[vpp.git] / src / vnet / ethernet / node.c
index 4529ca6..53d5b4e 100755 (executable)
@@ -40,6 +40,8 @@
 #include <vlib/vlib.h>
 #include <vnet/pg/pg.h>
 #include <vnet/ethernet/ethernet.h>
+#include <vnet/ethernet/p2p_ethernet.h>
+#include <vnet/devices/pipe/pipe.h>
 #include <vppinfra/sparse_vec.h>
 #include <vnet/l2/l2_bvi.h>
 
@@ -74,7 +76,7 @@ format_ethernet_input_trace (u8 * s, va_list * va)
   return s;
 }
 
-vlib_node_registration_t ethernet_input_node;
+extern vlib_node_registration_t ethernet_input_node;
 
 typedef enum
 {
@@ -101,7 +103,8 @@ parse_header (ethernet_input_variant_t variant,
 
       e0 = (void *) (b0->data + b0->current_data);
 
-      vnet_buffer (b0)->ethernet.start_of_ethernet_header = b0->current_data;
+      vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
+      b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
 
       vlib_buffer_advance (b0, sizeof (e0[0]));
 
@@ -205,9 +208,7 @@ identify_subint (vnet_hw_interface_t * hi,
       if (!(*is_l2))
        {
          ethernet_header_t *e0;
-         e0 =
-           (void *) (b0->data +
-                     vnet_buffer (b0)->ethernet.start_of_ethernet_header);
+         e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset);
 
          if (!(ethernet_address_cast (e0->dst_address)))
            {
@@ -229,6 +230,9 @@ determine_next_node (ethernet_main_t * em,
                     u32 is_l20,
                     u32 type0, vlib_buffer_t * b0, u8 * error0, u8 * next0)
 {
+  vnet_buffer (b0)->l3_hdr_offset = b0->current_data;
+  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
+
   if (PREDICT_FALSE (*error0 != ETHERNET_ERROR_NONE))
     {
       // some error occurred
@@ -236,13 +240,13 @@ determine_next_node (ethernet_main_t * em,
     }
   else if (is_l20)
     {
-      *next0 = em->l2_next;
       // record the L2 len and reset the buffer so the L2 header is preserved
-      u32 eth_start = vnet_buffer (b0)->ethernet.start_of_ethernet_header;
+      u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
       vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
+      *next0 = em->l2_next;
       ASSERT (vnet_buffer (b0)->l2.l2_len ==
              ethernet_buffer_header_size (b0));
-      vlib_buffer_advance (b0, -ethernet_buffer_header_size (b0));
+      vlib_buffer_advance (b0, -(vnet_buffer (b0)->l2.l2_len));
 
       // check for common IP/MPLS ethertypes
     }
@@ -296,7 +300,7 @@ ethernet_input_inline (vlib_main_t * vm,
   vlib_node_runtime_t *error_node;
   u32 n_left_from, next_index, *from, *to_next;
   u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
-  u32 thread_index = vlib_get_thread_index ();
+  u32 thread_index = vm->thread_index;
   u32 cached_sw_if_index = ~0;
   u32 cached_is_l2 = 0;                /* shut up gcc */
   vnet_hw_interface_t *hi = NULL;      /* used for main interface only */
@@ -375,10 +379,16 @@ ethernet_input_inline (vlib_main_t * vm,
          e1 = vlib_buffer_get_current (b1);
          type1 = clib_net_to_host_u16 (e1->type);
 
+         /* Set the L2 header offset for all packets */
+         vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
+         vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
+         b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
+         b1->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
+
          /* Speed-path for the untagged case */
          if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
-                           && !ethernet_frame_is_tagged (type0)
-                           && !ethernet_frame_is_tagged (type1)))
+                           && !ethernet_frame_is_any_tagged_x2 (type0,
+                                                                type1)))
            {
              main_intf_t *intf0;
              subint_config_t *subint0;
@@ -402,13 +412,16 @@ ethernet_input_inline (vlib_main_t * vm,
                  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
                }
 
-             vnet_buffer (b0)->ethernet.start_of_ethernet_header =
-               b0->current_data;
-             vnet_buffer (b1)->ethernet.start_of_ethernet_header =
-               b1->current_data;
-
              if (PREDICT_TRUE (is_l20 != 0))
                {
+                 vnet_buffer (b0)->l3_hdr_offset =
+                   vnet_buffer (b0)->l2_hdr_offset +
+                   sizeof (ethernet_header_t);
+                 vnet_buffer (b1)->l3_hdr_offset =
+                   vnet_buffer (b1)->l2_hdr_offset +
+                   sizeof (ethernet_header_t);
+                 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
+                 b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
                  next0 = em->l2_next;
                  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
                  next1 = em->l2_next;
@@ -424,12 +437,12 @@ ethernet_input_inline (vlib_main_t * vm,
                      (hi->hw_address != 0) &&
                      !eth_mac_equal ((u8 *) e1, hi->hw_address))
                    error1 = ETHERNET_ERROR_L3_MAC_MISMATCH;
+                 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
                  determine_next_node (em, variant, 0, type0, b0,
                                       &error0, &next0);
-                 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
+                 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
                  determine_next_node (em, variant, 0, type1, b1,
                                       &error1, &next1);
-                 vlib_buffer_advance (b1, sizeof (ethernet_header_t));
                }
              goto ship_it01;
            }
@@ -497,9 +510,9 @@ ethernet_input_inline (vlib_main_t * vm,
            {
 
              len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
-               - vnet_buffer (b0)->ethernet.start_of_ethernet_header;
+               - vnet_buffer (b0)->l2_hdr_offset;
              len1 = vlib_buffer_length_in_chain (vm, b1) + b1->current_data
-               - vnet_buffer (b1)->ethernet.start_of_ethernet_header;
+               - vnet_buffer (b1)->l2_hdr_offset;
 
              stats_n_packets += 2;
              stats_n_bytes += len0 + len1;
@@ -604,6 +617,10 @@ ethernet_input_inline (vlib_main_t * vm,
          e0 = vlib_buffer_get_current (b0);
          type0 = clib_net_to_host_u16 (e0->type);
 
+         /* Set the L2 header offset for all packets */
+         vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
+         b0->flags |= VNET_BUFFER_F_L2_HDR_OFFSET_VALID;
+
          /* Speed-path for the untagged case */
          if (PREDICT_TRUE (variant == ETHERNET_INPUT_VARIANT_ETHERNET
                            && !ethernet_frame_is_tagged (type0)))
@@ -624,11 +641,13 @@ ethernet_input_inline (vlib_main_t * vm,
                  cached_is_l2 = is_l20 = subint0->flags & SUBINT_CONFIG_L2;
                }
 
-             vnet_buffer (b0)->ethernet.start_of_ethernet_header =
-               b0->current_data;
 
              if (PREDICT_TRUE (is_l20 != 0))
                {
+                 vnet_buffer (b0)->l3_hdr_offset =
+                   vnet_buffer (b0)->l2_hdr_offset +
+                   sizeof (ethernet_header_t);
+                 b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
                  next0 = em->l2_next;
                  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
                }
@@ -638,9 +657,9 @@ ethernet_input_inline (vlib_main_t * vm,
                      (hi->hw_address != 0) &&
                      !eth_mac_equal ((u8 *) e0, hi->hw_address))
                    error0 = ETHERNET_ERROR_L3_MAC_MISMATCH;
+                 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
                  determine_next_node (em, variant, 0, type0, b0,
                                       &error0, &next0);
-                 vlib_buffer_advance (b0, sizeof (ethernet_header_t));
                }
              goto ship_it0;
            }
@@ -688,7 +707,7 @@ ethernet_input_inline (vlib_main_t * vm,
            {
 
              len0 = vlib_buffer_length_in_chain (vm, b0) + b0->current_data
-               - vnet_buffer (b0)->ethernet.start_of_ethernet_header;
+               - vnet_buffer (b0)->l2_hdr_offset;
 
              stats_n_packets += 1;
              stats_n_bytes += len0;
@@ -749,25 +768,25 @@ ethernet_input_inline (vlib_main_t * vm,
   return from_frame->n_vectors;
 }
 
-static uword
-ethernet_input (vlib_main_t * vm,
-               vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+VLIB_NODE_FN (ethernet_input_node) (vlib_main_t * vm,
+                                   vlib_node_runtime_t * node,
+                                   vlib_frame_t * from_frame)
 {
   return ethernet_input_inline (vm, node, from_frame,
                                ETHERNET_INPUT_VARIANT_ETHERNET);
 }
 
-static uword
-ethernet_input_type (vlib_main_t * vm,
-                    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+VLIB_NODE_FN (ethernet_input_type_node) (vlib_main_t * vm,
+                                        vlib_node_runtime_t * node,
+                                        vlib_frame_t * from_frame)
 {
   return ethernet_input_inline (vm, node, from_frame,
                                ETHERNET_INPUT_VARIANT_ETHERNET_TYPE);
 }
 
-static uword
-ethernet_input_not_l2 (vlib_main_t * vm,
-                      vlib_node_runtime_t * node, vlib_frame_t * from_frame)
+VLIB_NODE_FN (ethernet_input_not_l2_node) (vlib_main_t * vm,
+                                          vlib_node_runtime_t * node,
+                                          vlib_frame_t * from_frame)
 {
   return ethernet_input_inline (vm, node, from_frame,
                                ETHERNET_INPUT_VARIANT_NOT_L2);
@@ -806,11 +825,32 @@ ethernet_sw_interface_get_config (vnet_main_t * vnm,
   // Locate the subint for the given ethernet config
   si = vnet_get_sw_interface (vnm, sw_if_index);
 
-  if (si->sub.eth.flags.default_sub)
+  if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
+    {
+      p2p_ethernet_main_t *p2pm = &p2p_main;
+      u32 p2pe_sw_if_index =
+       p2p_ethernet_lookup (hi->hw_if_index, si->p2p.client_mac);
+      if (p2pe_sw_if_index == ~0)
+       {
+         pool_get (p2pm->p2p_subif_pool, subint);
+         si->p2p.pool_index = subint - p2pm->p2p_subif_pool;
+       }
+      else
+       subint = vec_elt_at_index (p2pm->p2p_subif_pool, si->p2p.pool_index);
+      *flags = SUBINT_CONFIG_P2P;
+    }
+  else if (si->type == VNET_SW_INTERFACE_TYPE_PIPE)
+    {
+      pipe_t *pipe;
+
+      pipe = pipe_get (sw_if_index);
+      subint = &pipe->subint;
+      *flags = SUBINT_CONFIG_P2P;
+    }
+  else if (si->sub.eth.flags.default_sub)
     {
       subint = &main_intf->default_subint;
-      *flags = SUBINT_CONFIG_MATCH_0_TAG |
-       SUBINT_CONFIG_MATCH_1_TAG |
+      *flags = SUBINT_CONFIG_MATCH_1_TAG |
        SUBINT_CONFIG_MATCH_2_TAG | SUBINT_CONFIG_MATCH_3_TAG;
     }
   else if ((si->sub.eth.flags.no_tags) || (si->sub.eth.raw_flags == 0))
@@ -939,7 +979,7 @@ done:
   return subint;
 }
 
-clib_error_t *
+static clib_error_t *
 ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
 {
   subint_config_t *subint;
@@ -968,6 +1008,7 @@ done:
 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_sw_interface_up_down);
 
 
+#ifndef CLIB_MARCH_VARIANT
 // Set the L2/L3 mode for the subinterface
 void
 ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2)
@@ -1055,6 +1096,7 @@ ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm,
 done:
   return;
 }
+#endif
 
 static clib_error_t *
 ethernet_sw_interface_add_del (vnet_main_t * vnm,
@@ -1095,7 +1137,7 @@ ethernet_sw_interface_add_del (vnet_main_t * vnm,
     }
   else
     {
-      // Note that config is L3 by defaulty
+      // Note that config is L3 by default
       subint->flags = SUBINT_CONFIG_VALID | match_flags;
       subint->sw_if_index = ~0;        // because interfaces are initially down
     }
@@ -1114,7 +1156,6 @@ static char *ethernet_error_strings[] = {
 
 /* *INDENT-OFF* */
 VLIB_REGISTER_NODE (ethernet_input_node) = {
-  .function = ethernet_input,
   .name = "ethernet-input",
   /* Takes a vector of packets. */
   .vector_size = sizeof (u32),
@@ -1130,15 +1171,8 @@ VLIB_REGISTER_NODE (ethernet_input_node) = {
   .format_trace = format_ethernet_input_trace,
   .unformat_buffer = unformat_ethernet_header,
 };
-/* *INDENT-ON* */
 
-/* *INDENT-OFF* */
-VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_node, ethernet_input)
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (ethernet_input_type_node, static) = {
-  .function = ethernet_input_type,
+VLIB_REGISTER_NODE (ethernet_input_type_node) = {
   .name = "ethernet-input-type",
   /* Takes a vector of packets. */
   .vector_size = sizeof (u32),
@@ -1149,15 +1183,8 @@ VLIB_REGISTER_NODE (ethernet_input_type_node, static) = {
 #undef _
   },
 };
-/* *INDENT-ON* */
 
-/* *INDENT-OFF* */
-VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_type_node, ethernet_input_type)
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (ethernet_input_not_l2_node, static) = {
-  .function = ethernet_input_not_l2,
+VLIB_REGISTER_NODE (ethernet_input_not_l2_node) = {
   .name = "ethernet-input-not-l2",
   /* Takes a vector of packets. */
   .vector_size = sizeof (u32),
@@ -1170,13 +1197,7 @@ VLIB_REGISTER_NODE (ethernet_input_not_l2_node, static) = {
 };
 /* *INDENT-ON* */
 
-
-/* *INDENT-OFF* */
-VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_not_l2_node,
-                             ethernet_input_not_l2)
-/* *INDENT-ON* */
-
-
+#ifndef CLIB_MARCH_VARIANT
 void
 ethernet_set_rx_redirect (vnet_main_t * vnm,
                          vnet_hw_interface_t * hi, u32 enable)
@@ -1377,6 +1398,7 @@ ethernet_register_l3_redirect (vlib_main_t * vm, u32 node_index)
 
   ASSERT (i == em->redirect_l3_next);
 }
+#endif
 
 /*
  * fd.io coding-style-patch-verification: ON