API refactoring : gre
[vpp.git] / vnet / vnet / gre / node.c
index 97f9dac..86f7a6e 100644 (file)
 #include <vlib/vlib.h>
 #include <vnet/pg/pg.h>
 #include <vnet/gre/gre.h>
+#include <vnet/mpls/mpls.h>
 #include <vppinfra/sparse_vec.h>
 
 #define foreach_gre_input_next                 \
 _(PUNT, "error-punt")                           \
 _(DROP, "error-drop")                           \
+_(ETHERNET_INPUT, "ethernet-input")             \
 _(IP4_INPUT, "ip4-input")                       \
-_(IP6_INPUT, "ip6-input")                      
+_(IP6_INPUT, "ip6-input")                      \
+_(MPLS_INPUT, "mpls-input")
 
 typedef enum {
 #define _(s,n) GRE_INPUT_NEXT_##s,
@@ -68,10 +71,11 @@ gre_input (vlib_main_t * vm,
   gre_input_runtime_t * rt = (void *) node->runtime_data;
   __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next;
   u64 cached_tunnel_key = (u64) ~0;
-  u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index;
-  u32 cached_tunnel_fib_index = 0, tunnel_fib_index;
+  u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0;
 
   u32 cpu_index = os_get_cpu_number();
+  u32 len;
+  vnet_interface_main_t *im = &gm->vnet_main->interface_main;
 
   from = vlib_frame_vector_args (from_frame);
   n_left_from = from_frame->n_vectors;
@@ -140,7 +144,7 @@ gre_input (vlib_main_t * vm,
          /* Index sparse array with network byte order. */
          protocol0 = h0->protocol;
          protocol1 = h1->protocol;
-         sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1, 
+         sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1,
                              &i0, &i1);
           next0 = vec_elt(rt->next_by_protocol, i0);
           next1 = vec_elt(rt->next_by_protocol, i1);
@@ -153,16 +157,19 @@ gre_input (vlib_main_t * vm,
           version1 = clib_net_to_host_u16 (h1->flags_and_version);
           verr1 =  version1 & GRE_VERSION_MASK;
 
-          b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] 
+          b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
               : b0->error;
           next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
-          b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] 
+          b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
               : b1->error;
           next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;
 
+
           /* RPF check for ip4/ip6 input */
-          if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT 
-                            || next0 == GRE_INPUT_NEXT_IP6_INPUT))
+          if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_IP4_INPUT
+                          || next0 == GRE_INPUT_NEXT_IP6_INPUT
+                          || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT
+                          || next0 == GRE_INPUT_NEXT_MPLS_INPUT))
             {
               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
                          (u64)(vnet_buffer(b0)->gre.src);
@@ -173,7 +180,6 @@ gre_input (vlib_main_t * vm,
                   gre_tunnel_t * t;
                   uword * p;
 
-                  ip4_main_t * ip4m = &ip4_main;
                   p = hash_get (gm->tunnel_by_key, key);
                   if (!p)
                     {
@@ -185,33 +191,34 @@ gre_input (vlib_main_t * vm,
                   hi = vnet_get_hw_interface (gm->vnet_main,
                             t->hw_if_index);
                   tunnel_sw_if_index = hi->sw_if_index;
-                  tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
-                                              tunnel_sw_if_index);
 
                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
-                  cached_tunnel_fib_index = tunnel_fib_index;
                 }
               else
                 {
                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
-                  tunnel_fib_index = cached_tunnel_fib_index;
                 }
-
-              u32 len = vlib_buffer_length_in_chain (vm, b0);
-              vnet_interface_main_t *im = &gm->vnet_main->interface_main;
-              vlib_increment_combined_counter (im->combined_sw_if_counters
-                                               + VNET_INTERFACE_COUNTER_RX,
-                                               cpu_index,
-                                               tunnel_sw_if_index,
-                                               1 /* packets */,
-                                               len /* bytes */);
-
-              vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_index;
             }
+          else
+            {
+               next0 = GRE_INPUT_NEXT_DROP;
+                goto drop0;
+            }
+          len = vlib_buffer_length_in_chain (vm, b0);
+          vlib_increment_combined_counter (im->combined_sw_if_counters
+                                           + VNET_INTERFACE_COUNTER_RX,
+                                           cpu_index,
+                                           tunnel_sw_if_index,
+                                           1 /* packets */,
+                                           len /* bytes */);
+
+          vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
 
 drop0:
-          if (PREDICT_FALSE(next1 == GRE_INPUT_NEXT_IP4_INPUT 
-                            || next1 == GRE_INPUT_NEXT_IP6_INPUT))
+          if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_IP4_INPUT
+                          || next1 == GRE_INPUT_NEXT_IP6_INPUT
+                          || next1 == GRE_INPUT_NEXT_ETHERNET_INPUT
+                          || next1 == GRE_INPUT_NEXT_MPLS_INPUT))
             {
               u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
                          (u64)(vnet_buffer(b1)->gre.src);
@@ -222,7 +229,6 @@ drop0:
                   gre_tunnel_t * t;
                   uword * p;
 
-                  ip4_main_t * ip4m = &ip4_main;
                   p = hash_get (gm->tunnel_by_key, key);
                   if (!p)
                     {
@@ -234,45 +240,45 @@ drop0:
                   hi = vnet_get_hw_interface (gm->vnet_main,
                             t->hw_if_index);
                   tunnel_sw_if_index = hi->sw_if_index;
-                  tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
-                                              tunnel_sw_if_index);
 
                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
-                  cached_tunnel_fib_index = tunnel_fib_index;
                 }
               else
                 {
                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
-                  tunnel_fib_index = cached_tunnel_fib_index;
                 }
+            }
+          else
+            {
+               next1 = GRE_INPUT_NEXT_DROP;
+                goto drop1;
+            }
+          len = vlib_buffer_length_in_chain (vm, b1);
+          vlib_increment_combined_counter (im->combined_sw_if_counters
+                                           + VNET_INTERFACE_COUNTER_RX,
+                                           cpu_index,
+                                           tunnel_sw_if_index,
+                                           1 /* packets */,
+                                           len /* bytes */);
 
-              u32 len = vlib_buffer_length_in_chain (vm, b1);
-              vnet_interface_main_t *im = &gm->vnet_main->interface_main;
-              vlib_increment_combined_counter (im->combined_sw_if_counters
-                                               + VNET_INTERFACE_COUNTER_RX,
-                                               cpu_index,
-                                               tunnel_sw_if_index,
-                                               1 /* packets */,
-                                               len /* bytes */);
+          vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
 
-              vnet_buffer(b1)->sw_if_index[VLIB_TX] = tunnel_fib_index;
-            }
 drop1:
-          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
+          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
             {
-              gre_rx_trace_t *tr = vlib_add_trace (vm, node, 
+              gre_rx_trace_t *tr = vlib_add_trace (vm, node,
                                                    b0, sizeof (*tr));
-              tr->tunnel_id = ~0;
+              tr->tunnel_id = tunnel_sw_if_index;
               tr->length = ip0->length;
               tr->src.as_u32 = ip0->src_address.as_u32;
               tr->dst.as_u32 = ip0->dst_address.as_u32;
             }
 
-          if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) 
+          if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
             {
-              gre_rx_trace_t *tr = vlib_add_trace (vm, node, 
+              gre_rx_trace_t *tr = vlib_add_trace (vm, node,
                                                    b1, sizeof (*tr));
-              tr->tunnel_id = ~0;
+              tr->tunnel_id = tunnel_sw_if_index;
               tr->length = ip1->length;
               tr->src.as_u32 = ip1->src_address.as_u32;
               tr->dst.as_u32 = ip1->dst_address.as_u32;
@@ -326,11 +332,15 @@ drop1:
               : b0->error;
           next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
 
+
           /* For IP payload we need to find source interface
              so we can increase counters and help forward node to
              pick right FIB */
-          if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT 
-                            || next0 == GRE_INPUT_NEXT_IP6_INPUT))
+          /* RPF check for ip4/ip6 input */
+          if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_IP4_INPUT
+                          || next0 == GRE_INPUT_NEXT_IP6_INPUT
+                          || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT
+                          || next0 == GRE_INPUT_NEXT_MPLS_INPUT))
             {
               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
                          (u64)(vnet_buffer(b0)->gre.src);
@@ -341,7 +351,6 @@ drop1:
                   gre_tunnel_t * t;
                   uword * p;
 
-                  ip4_main_t * ip4m = &ip4_main;
                   p = hash_get (gm->tunnel_by_key, key);
                   if (!p)
                     {
@@ -353,36 +362,35 @@ drop1:
                   hi = vnet_get_hw_interface (gm->vnet_main,
                             t->hw_if_index);
                   tunnel_sw_if_index = hi->sw_if_index;
-                  tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
-                                              tunnel_sw_if_index);
 
                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
-                  cached_tunnel_fib_index = tunnel_fib_index;
                 }
               else
                 {
                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
-                  tunnel_fib_index = cached_tunnel_fib_index;
                 }
-
-              u32 len = vlib_buffer_length_in_chain (vm, b0);
-              vnet_interface_main_t *im = &gm->vnet_main->interface_main;
-              vlib_increment_combined_counter (im->combined_sw_if_counters
-                                               + VNET_INTERFACE_COUNTER_RX,
-                                               cpu_index,
-                                               tunnel_sw_if_index,
-                                               1 /* packets */,
-                                               len /* bytes */);
-
-              vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_index;
             }
+          else
+            {
+               next0 = GRE_INPUT_NEXT_DROP;
+                goto drop;
+            }
+          len = vlib_buffer_length_in_chain (vm, b0);
+          vlib_increment_combined_counter (im->combined_sw_if_counters
+                                           + VNET_INTERFACE_COUNTER_RX,
+                                           cpu_index,
+                                           tunnel_sw_if_index,
+                                           1 /* packets */,
+                                           len /* bytes */);
+
+          vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
 
 drop:
           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
             {
               gre_rx_trace_t *tr = vlib_add_trace (vm, node, 
                                                    b0, sizeof (*tr));
-              tr->tunnel_id = ~0;
+              tr->tunnel_id = tunnel_sw_if_index;
               tr->length = ip0->length;
               tr->src.as_u32 = ip0->src_address.as_u32;
               tr->dst.as_u32 = ip0->dst_address.as_u32;
@@ -476,7 +484,7 @@ gre_setup_node (vlib_main_t * vm, u32 node_index)
 static clib_error_t * gre_input_init (vlib_main_t * vm)
 {
   gre_input_runtime_t * rt;
-  vlib_node_t *ip4_input, *ip6_input, *mpls_unicast_input;
+  vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input;
 
   {
     clib_error_t * error; 
@@ -494,13 +502,18 @@ static clib_error_t * gre_input_init (vlib_main_t * vm)
      /* bits in index */ BITS (((gre_header_t *) 0)->protocol));
 
   /* These could be moved to the supported protocol input node defn's */
+  ethernet_input = vlib_get_node_by_name (vm, (u8 *)"ethernet-input");
+  ASSERT(ethernet_input);
   ip4_input = vlib_get_node_by_name (vm, (u8 *)"ip4-input");
   ASSERT(ip4_input);
   ip6_input = vlib_get_node_by_name (vm, (u8 *)"ip6-input");
   ASSERT(ip6_input);
-  mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-gre-input");
+  mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-input");
   ASSERT(mpls_unicast_input);
 
+  gre_register_input_protocol (vm, GRE_PROTOCOL_teb,
+                               ethernet_input->index);
+
   gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, 
                                ip4_input->index);