Support MPLSoGRE with the new FIB 2.0 31/3431/3
authorJohn Lo <loj@cisco.com>
Sat, 15 Oct 2016 21:45:35 +0000 (17:45 -0400)
committerChris Luke <chris_luke@comcast.com>
Mon, 17 Oct 2016 14:15:37 +0000 (14:15 +0000)
Note that the new way to provision MPLSoGRE is using the "normal"
GRE tunnel such as in the following example:
  create gre tunnel src 10.0.3.1 dst 10.0.3.3
  set in state gre0 up
  set int ip addr gre0 10.0.4.1/30
  set int mpls gre0 enable
  ip route table 4 6.0.0.0/24 via 10.0.4.2 gre0 out-label 30
  mpls local-label add 30 eos ip4-lookup-in-table 4

The previous CLIs/APIs used to configure MPLSoGRE tunnel such as
"create mpls gre tunnel...", "mpls encap|decap add label .." and
"show mpls tunnel", etc. can not be used. They will be deprecated
in a later update to the VPP code base.

Change-Id: I244916841924dc2b87d2143691cd8476716c06b1
Signed-off-by: John Lo <loj@cisco.com>
vnet/vnet/gre/node.c
vnet/vnet/mpls/mpls.c
vnet/vnet/mpls/mpls_output.c

index b55f551..556f1a8 100644 (file)
@@ -68,7 +68,6 @@ gre_input (vlib_main_t * vm,
           vlib_frame_t * from_frame)
 {
   gre_main_t * gm = &gre_main;
-  mpls_main_t * mm = &mpls_main;
   ip4_main_t * ip4m = &ip4_main;
   gre_input_runtime_t * rt = (void *) node->runtime_data;
   __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next;
@@ -169,9 +168,10 @@ gre_input (vlib_main_t * vm,
 
 
           /* RPF check for ip4/ip6 input */
-          if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
-                            || next0 == GRE_INPUT_NEXT_IP6_INPUT
-                            || next0 == GRE_INPUT_NEXT_ETHERNET_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);
@@ -205,40 +205,6 @@ gre_input (vlib_main_t * vm,
                   tunnel_fib_index = cached_tunnel_fib_index;
                 }
             }
-          else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT))
-            {
-              u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
-                         (u64)(vnet_buffer(b0)->gre.src);
-
-              if (cached_tunnel_key != key)
-                {
-                  vnet_hw_interface_t * hi;
-                  mpls_gre_tunnel_t * t;
-                  uword * p;
-
-                  p = hash_get (gm->tunnel_by_key, key);
-                  if (!p)
-                    {
-                      next0 = GRE_INPUT_NEXT_DROP;
-                      b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
-                      goto drop0;
-                    }
-                  t = pool_elt_at_index (mm->gre_tunnels, p[0]);
-                  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
             {
                next0 = GRE_INPUT_NEXT_DROP;
@@ -256,9 +222,10 @@ gre_input (vlib_main_t * vm,
           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
-                            || next1 == GRE_INPUT_NEXT_ETHERNET_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);
@@ -292,41 +259,6 @@ drop0:
                   tunnel_fib_index = cached_tunnel_fib_index;
                 }
             }
-          else if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_MPLS_INPUT))
-            {
-              u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
-                         (u64)(vnet_buffer(b1)->gre.src);
-
-              if (cached_tunnel_key != key)
-                {
-                  vnet_hw_interface_t * hi;
-                  mpls_gre_tunnel_t * t;
-                  uword * p;
-
-                  ip4_main_t * ip4m = &ip4_main;
-                  p = hash_get (gm->tunnel_by_key, key);
-                  if (!p)
-                    {
-                      next1 = GRE_INPUT_NEXT_DROP;
-                      b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
-                      goto drop1;
-                    }
-                  t = pool_elt_at_index (mm->gre_tunnels, p[0]);
-                  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;
@@ -417,9 +349,10 @@ drop1:
              so we can increase counters and help forward node to
              pick right FIB */
           /* RPF check for ip4/ip6 input */
-          if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
-                            || next0 == GRE_INPUT_NEXT_IP6_INPUT
-                            || next0 == GRE_INPUT_NEXT_ETHERNET_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);
@@ -453,40 +386,6 @@ drop1:
                   tunnel_fib_index = cached_tunnel_fib_index;
                 }
             }
-          else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT))
-            {
-              u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
-                         (u64)(vnet_buffer(b0)->gre.src);
-
-              if (cached_tunnel_key != key)
-                {
-                  vnet_hw_interface_t * hi;
-                  mpls_gre_tunnel_t * t;
-                  uword * p;
-
-                  p = hash_get (gm->tunnel_by_key, key);
-                  if (!p)
-                    {
-                      next0 = GRE_INPUT_NEXT_DROP;
-                      b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
-                      goto drop;
-                    }
-                  t = pool_elt_at_index (mm->gre_tunnels, p[0]);
-                  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
             {
                next0 = GRE_INPUT_NEXT_DROP;
index de57da8..b28736b 100644 (file)
@@ -746,6 +746,7 @@ vnet_mpls_local_label (vlib_main_t * vm,
   eos = MPLS_EOS;
   is_del = 0;
   local_label = MPLS_LABEL_INVALID;
+  memset(&pfx, 0, sizeof(pfx));
 
    /* Get a line of input. */
   if (! unformat_user (input, unformat_line_input, line_input))
@@ -754,7 +755,6 @@ vnet_mpls_local_label (vlib_main_t * vm,
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
       memset(&rpath, 0, sizeof(rpath));
-      memset(&pfx, 0, sizeof(pfx));
 
       if (unformat (line_input, "table %d", &table_id))
        ;
@@ -763,9 +763,9 @@ vnet_mpls_local_label (vlib_main_t * vm,
       else if (unformat (line_input, "add"))
        is_del = 0;
       else if (unformat (line_input, "eos"))
-       eos = MPLS_EOS;
+       pfx.fp_eos = MPLS_EOS;
       else if (unformat (line_input, "non-eos"))
-       eos = MPLS_NON_EOS;
+       pfx.fp_eos = MPLS_NON_EOS;
       else if (unformat (line_input, "%U/%d",
                         unformat_ip4_address,
                         &pfx.fp_addr.ip4,
@@ -791,6 +791,7 @@ vnet_mpls_local_label (vlib_main_t * vm,
          rpath.frp_label = MPLS_LABEL_INVALID;
           rpath.frp_proto = FIB_PROTOCOL_IP4;
           rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
+         pfx.fp_payload_proto = FIB_PROTOCOL_IP4;
          vec_add1(rpaths, rpath);
       }
       else if (unformat (line_input,
@@ -801,14 +802,16 @@ vnet_mpls_local_label (vlib_main_t * vm,
           rpath.frp_proto = FIB_PROTOCOL_IP6;
           rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
          vec_add1(rpaths, rpath);
+         pfx.fp_payload_proto = FIB_PROTOCOL_IP6;
       }
       else if (unformat (line_input,
                         "mpls-lookup-in-table %d",
                         &rpath.frp_fib_index))
       {
          rpath.frp_label = MPLS_LABEL_INVALID;
-          rpath.frp_proto = FIB_PROTOCOL_IP4;
+          rpath.frp_proto = FIB_PROTOCOL_MPLS;
           rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID;
+         pfx.fp_payload_proto = FIB_PROTOCOL_MPLS;
          vec_add1(rpaths, rpath);
       }
       else
@@ -851,11 +854,26 @@ vnet_mpls_local_label (vlib_main_t * vm,
   else
   {
       fib_node_index_t lfe, fib_index;
-      fib_prefix_t prefix = {
-         .fp_proto = FIB_PROTOCOL_MPLS,
-         .fp_label = local_label,
-         .fp_eos = eos,
-      };
+      u32 fi;
+
+      pfx.fp_proto = FIB_PROTOCOL_MPLS;
+      pfx.fp_len = 21;
+      pfx.fp_label = local_label;
+
+      /*
+       * the CLI parsing stored table Ids, swap to FIB indicies
+       */
+      fi = fib_table_id_find_fib_index(pfx.fp_payload_proto,
+                                      rpaths[0].frp_fib_index);
+
+      if (~0 == fi)
+      {
+         error = clib_error_return(0 , "%U Via table %d does not exist",
+                                   format_fib_protocol, pfx.fp_payload_proto,
+                                   rpaths[0].frp_fib_index);
+         goto done;
+      }
+      rpaths[0].frp_fib_index = fi;
 
       fib_index = mpls_fib_index_from_table_id(table_id);
 
@@ -867,7 +885,7 @@ vnet_mpls_local_label (vlib_main_t * vm,
       }
 
       lfe = fib_table_entry_path_add2(fib_index,
-                                     &prefix,
+                                     &pfx,
                                      FIB_SOURCE_CLI,
                                      FIB_ENTRY_FLAG_NONE,
                                      rpaths);
index 299e1dd..1d5d182 100644 (file)
@@ -52,7 +52,8 @@ format_mpls_output_trace (u8 * s, va_list * args)
 static inline uword
 mpls_output_inline (vlib_main_t * vm,
                     vlib_node_runtime_t * node,
-                    vlib_frame_t * from_frame)
+                    vlib_frame_t * from_frame,
+                   int is_midchain)
 {
   u32 n_left_from, next_index, * from, * to_next, cpu_index;
   vlib_node_runtime_t * error_node;
@@ -121,6 +122,11 @@ mpls_output_inline (vlib_main_t * vm,
               vnet_buffer (p0)->sw_if_index[VLIB_TX] =
                   adj0[0].rewrite_header.sw_if_index;
               next0 = adj0[0].rewrite_header.next_index;
+
+             if (is_midchain)
+               {
+                 adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
+               }
             }
           else
             {
@@ -165,7 +171,7 @@ mpls_output (vlib_main_t * vm,
              vlib_node_runtime_t * node,
              vlib_frame_t * from_frame)
 {
-    return (mpls_output_inline(vm, node, from_frame));
+    return (mpls_output_inline(vm, node, from_frame, /* is_midchain */ 0));
 }
 
 VLIB_REGISTER_NODE (mpls_output_node) = {
@@ -193,11 +199,11 @@ mpls_midchain (vlib_main_t * vm,
                vlib_node_runtime_t * node,
                vlib_frame_t * from_frame)
 {
-    return (mpls_output_inline(vm, node, from_frame));
+    return (mpls_output_inline(vm, node, from_frame, /* is_midchain */ 1));
 }
 
 VLIB_REGISTER_NODE (mpls_midchain_node) = {
-  .function = mpls_output,
+  .function = mpls_midchain,
   .name = "mpls-midchain",
   .vector_size = sizeof (u32),