Deprecate MPLSoGRE tunnels (VPP-502) 67/3467/6
authorNeale Ranns <neale.ranns@cisco.com>
Sun, 16 Oct 2016 19:01:42 +0000 (12:01 -0700)
committerEd Warnicke <hagbard@gmail.com>
Tue, 18 Oct 2016 20:44:22 +0000 (20:44 +0000)
Add shared memory APIs for MPLS routes and MPLS to IP prefix bindings.

Change-Id: I85b074a4dadc8249c410fdabd8ea019d20479cf8
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
18 files changed:
vnet/vnet/adj/adj_midchain.c
vnet/vnet/fib/fib_entry_src_mpls.c
vnet/vnet/fib/fib_node.h
vnet/vnet/fib/fib_table.c
vnet/vnet/fib/fib_test.c
vnet/vnet/mpls/interface.c
vnet/vnet/mpls/mpls.c
vnet/vnet/mpls/mpls.h
vnet/vnet/mpls/mpls_lookup.c
vnet/vnet/mpls/mpls_output.c
vnet/vnet/mpls/node.c
vnet/vnet/mpls/pg.c
vnet/vnet/mpls/policy_encap.c
vpp-api-test/vat/api_format.c
vpp/vpp-api/api.c
vpp/vpp-api/custom_dump.c
vpp/vpp-api/test_client.c
vpp/vpp-api/vpe.api

index 2fbedae..9f6c8e4 100644 (file)
@@ -116,9 +116,6 @@ adj_mdichain_tx_inline (vlib_main_t * vm,
        vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     }
 
-    vlib_node_increment_counter (vm, gre_input_node.index,
-                                GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
     return frame->n_vectors;
 }
 
index 4f4a023..4079d8f 100644 (file)
@@ -118,6 +118,19 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
        else
        {
            fib_index = mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID);
+
+           /*
+            * if this is a change in label, reomve the old one first
+            */
+           if (src->mpls.fesm_label != label)
+           {
+               FOR_EACH_MPLS_EOS_BIT(eos)
+               {
+                   ASSERT(FIB_NODE_INDEX_INVALID != src->mpls.fesm_lfes[eos]);
+                   fib_table_entry_delete_index(src->mpls.fesm_lfes[eos],
+                                                FIB_SOURCE_SPECIAL);
+               }
+           }
        }
 
         src->mpls.fesm_label = label;
index 2f9a107..253c42d 100644 (file)
@@ -37,7 +37,6 @@ typedef enum fib_node_type_t_ {
     FIB_NODE_TYPE_MPLS_ENTRY,
     FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY,
     FIB_NODE_TYPE_LISP_ADJ,
-    FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
     FIB_NODE_TYPE_GRE_TUNNEL,
     /**
      * Marker. New types before this one. leave the test last.
@@ -57,7 +56,6 @@ typedef enum fib_node_type_t_ {
     [FIB_NODE_TYPE_ADJ] = "adj",                  \
     [FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY] = "lisp-gpe-fwd-entry", \
     [FIB_NODE_TYPE_LISP_ADJ] = "lisp-adj", \
-    [FIB_NODE_TYPE_MPLS_GRE_TUNNEL] = "mpls-gre-tunnel", \
     [FIB_NODE_TYPE_GRE_TUNNEL] = "gre-tunnel", \
 }
 
index 84c8708..d293d81 100644 (file)
@@ -805,10 +805,21 @@ fib_table_entry_local_label_add (u32 fib_index,
 {
     fib_node_index_t fib_entry_index;
  
-    fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix, 
-                                                      FIB_SOURCE_MPLS,
-                                                      FIB_ENTRY_FLAG_NONE,
-                                                      NULL);
+    fib_entry_index = fib_table_lookup_exact_match(fib_index, prefix);
+
+    if (FIB_NODE_INDEX_INVALID == fib_entry_index ||
+       !fib_entry_is_sourced(fib_entry_index, FIB_SOURCE_MPLS))
+    {
+       /*
+        * only source the prefix once. this allows the label change
+        * operation to work
+        */
+       fib_entry_index = fib_table_entry_special_dpo_add(fib_index, prefix,
+                                                         FIB_SOURCE_MPLS,
+                                                         FIB_ENTRY_FLAG_NONE,
+                                                         NULL);
+    }
+
     fib_entry_set_source_data(fib_entry_index, FIB_SOURCE_MPLS, &label);
 
     return (fib_entry_index);
index 1e459cf..bdd6e95 100644 (file)
@@ -5558,11 +5558,58 @@ fib_test_label (void)
             "label 99 over 10.10.10.1");
 
     /*
-     * remove the local label
+     * change the local label
+     */
+    fib_table_entry_local_label_add(fib_index,
+                                   &pfx_1_1_1_1_s_32,
+                                   25005);
+
+    fib_prefix_t pfx_25005_eos = {
+       .fp_proto = FIB_PROTOCOL_MPLS,
+       .fp_label = 25005,
+       .fp_eos = MPLS_EOS,
+    };
+    fib_prefix_t pfx_25005_neos = {
+       .fp_proto = FIB_PROTOCOL_MPLS,
+       .fp_label = 25005,
+       .fp_eos = MPLS_NON_EOS,
+    };
+
+    FIB_TEST((FIB_NODE_INDEX_INVALID ==
+             fib_table_lookup(fib_index, &pfx_24001_eos)),
+            "24001/eos removed after label change");
+    FIB_TEST((FIB_NODE_INDEX_INVALID ==
+             fib_table_lookup(fib_index, &pfx_24001_neos)),
+            "24001/eos removed after label change");
+
+    fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
+                          &pfx_25005_eos);
+    FIB_TEST(fib_test_validate_entry(fei,
+                                    FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+                                    2,
+                                    &l99_eos_o_10_10_10_1,
+                                    &adj_o_10_10_11_2),
+            "25005/eos LB 2 buckets via: "
+            "label 99 over 10.10.10.1, "
+            "adj over 10.10.11.2");
+
+    fei = fib_table_lookup(MPLS_FIB_DEFAULT_TABLE_ID,
+                          &pfx_25005_neos);
+    FIB_TEST(fib_test_validate_entry(fei,
+                                    FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
+                                    1,
+                                    &l99_neos_o_10_10_10_1),
+            "25005/neos LB 1 buckets via: "
+            "label 99 over 10.10.10.1");
+
+    /*
+     * remove the local label.
+     * the check that the MPLS entries are gone is done by the fact the
+     * MPLS table is no longer present.
      */
     fib_table_entry_local_label_remove(fib_index,
                                       &pfx_1_1_1_1_s_32,
-                                      24001);
+                                      25005);
 
     fei = fib_table_lookup(fib_index, &pfx_1_1_1_1_s_32);
     FIB_TEST(fib_test_validate_entry(fei, 
index 0baf2d3..fc297cd 100644 (file)
 
 #include <vnet/vnet.h>
 #include <vnet/pg/pg.h>
-#include <vnet/gre/gre.h>
 #include <vnet/mpls/mpls.h>
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/adj/adj_midchain.h>
 #include <vnet/dpo/classify_dpo.h>
 
-/* manually added to the interface output node */
-#define MPLS_GRE_OUTPUT_NEXT_POST_REWRITE      1
-
-static uword
-mpls_gre_interface_tx (vlib_main_t * vm,
-                       vlib_node_runtime_t * node,
-                       vlib_frame_t * frame)
-{
-  mpls_main_t * gm = &mpls_main;
-  vnet_main_t * vnm = gm->vnet_main;
-  u32 next_index;
-  u32 * from, * to_next, n_left_from, n_left_to_next;
-
-  /* Vector of buffer / pkt indices we're supposed to process */
-  from = vlib_frame_vector_args (frame);
-
-  /* Number of buffers / pkts */
-  n_left_from = frame->n_vectors;   
-
-  /* Speculatively send the first buffer to the last disposition we used */
-  next_index = node->cached_next_index;
-  
-  while (n_left_from > 0)
-    {
-      /* set up to enqueue to our disposition with index = next_index */
-      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
-      /* 
-       * As long as we have enough pkts left to process two pkts
-       * and prefetch two pkts...
-       */
-      while (n_left_from >= 4 && n_left_to_next >= 2)
-       {
-          vlib_buffer_t * b0, * b1;
-         u32 bi0, next0, bi1, next1;
-          mpls_gre_tunnel_t * t0, * t1;
-          u32 sw_if_index0, sw_if_index1;
-          vnet_hw_interface_t * hi0, * hi1;
-          u8 * dst0, * dst1;
-      
-         /* Prefetch the next iteration */
-         {
-           vlib_buffer_t * p2, * p3;
-
-           p2 = vlib_get_buffer (vm, from[2]);
-           p3 = vlib_get_buffer (vm, from[3]);
-
-           vlib_prefetch_buffer_header (p2, LOAD);
-           vlib_prefetch_buffer_header (p3, LOAD);
-
-            /* 
-             * Prefetch packet data. We expect to overwrite
-             * the inbound L2 header with an ip header and a
-             * gre header. Might want to prefetch the last line
-             * of rewrite space as well; need profile data
-             */
-           CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
-           CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
-         }
-
-          /* Pick up the next two buffer indices */
-         bi0 = from[0];
-         bi1 = from[1];
-
-          /* Speculatively enqueue them where we sent the last buffer */
-         to_next[0] = bi0;
-         to_next[1] = bi1;
-         from += 2;
-         to_next += 2;
-         n_left_to_next -= 2;
-         n_left_from -= 2;
-      
-         b0 = vlib_get_buffer (vm, bi0);
-         b1 = vlib_get_buffer (vm, bi1);
-
-          sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
-          sw_if_index1 = vnet_buffer(b1)->sw_if_index [VLIB_TX];
-
-          /* get h/w intfcs */
-          hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
-          hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1);
-          
-          /* hw_instance = tunnel pool index */
-          t0 = pool_elt_at_index (gm->gre_tunnels, hi0->hw_instance);
-          t1 = pool_elt_at_index (gm->gre_tunnels, hi1->hw_instance);
-
-          /* Apply rewrite - $$$$$ fixme don't use memcpy */
-          vlib_buffer_advance (b0, -(word)vec_len(t0->rewrite_data));
-          vlib_buffer_advance (b1, -(word)vec_len(t1->rewrite_data));
-
-          dst0 = vlib_buffer_get_current (b0);
-          dst1 = vlib_buffer_get_current (b1);
-
-          clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
-          clib_memcpy (dst1, t1->rewrite_data, vec_len(t1->rewrite_data));
-
-          /* Fix TX fib indices */
-          vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->outer_fib_index;
-          vnet_buffer(b1)->sw_if_index [VLIB_TX] = t1->outer_fib_index;
-
-          /* mpls-post-rewrite takes it from here... */
-          next0 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
-          next1 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
-
-          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
-            {
-              mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node, 
-                                                        b0, sizeof (*tr));
-              tr->tunnel_id = t0 - gm->gre_tunnels;
-              tr->length = b0->current_length;
-              tr->src.as_u32 = t0->tunnel_src.as_u32;
-              tr->dst.as_u32 = t0->tunnel_dst.as_u32;
-              tr->lookup_miss = 0;
-              tr->mpls_encap_index = t0->encap_index;
-            }
-          if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) 
-            {
-              mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node, 
-                                                        b1, sizeof (*tr));
-              tr->tunnel_id = t1 - gm->gre_tunnels;
-              tr->length = b1->current_length;
-              tr->src.as_u32 = t1->tunnel_src.as_u32;
-              tr->dst.as_u32 = t1->tunnel_dst.as_u32;
-              tr->lookup_miss = 0;
-              tr->mpls_encap_index = t1->encap_index;
-            }
-
-         vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
-                                          to_next, n_left_to_next,
-                                          bi0, bi1, next0, next1);
-       }
-
-      while (n_left_from > 0 && n_left_to_next > 0)
-       {
-          vlib_buffer_t * b0;
-          u32 bi0, next0;
-          mpls_gre_tunnel_t * t0;
-          u32 sw_if_index0;
-          vnet_hw_interface_t * hi0;
-          u8 * dst0;
-
-         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);
-
-          sw_if_index0 = vnet_buffer(b0)->sw_if_index [VLIB_TX];
-
-          hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
-          
-          t0 = pool_elt_at_index (gm->gre_tunnels, hi0->hw_instance);
-
-          /* Apply rewrite - $$$$$ fixme don't use memcpy */
-          vlib_buffer_advance (b0, -(word)vec_len(t0->rewrite_data));
-
-          dst0 = vlib_buffer_get_current (b0);
-
-          clib_memcpy (dst0, t0->rewrite_data, vec_len(t0->rewrite_data));
-
-          /* Fix the TX fib index */
-          vnet_buffer(b0)->sw_if_index [VLIB_TX] = t0->outer_fib_index;
-
-          /* mpls-post-rewrite takes it from here... */
-          next0 = MPLS_GRE_OUTPUT_NEXT_POST_REWRITE;
-
-          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
-            {
-              mpls_gre_tx_trace_t *tr = vlib_add_trace (vm, node, 
-                                                        b0, sizeof (*tr));
-              tr->tunnel_id = t0 - gm->gre_tunnels;
-              tr->length = b0->current_length;
-              tr->src.as_u32 = t0->tunnel_src.as_u32;
-              tr->dst.as_u32 = t0->tunnel_dst.as_u32;
-              tr->lookup_miss = 0;
-              tr->mpls_encap_index = t0->encap_index;
-            }
-
-         vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
-                                          to_next, n_left_to_next,
-                                          bi0, next0);
-       }
-  
-      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
-    }
-
-  vlib_node_increment_counter (vm, gre_input_node.index,
-                               GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
-  return frame->n_vectors;
-}
-
-static u8 * format_mpls_gre_tunnel_name (u8 * s, va_list * args)
-{
-  u32 dev_instance = va_arg (*args, u32);
-  return format (s, "mpls-gre%d", dev_instance);
-}
-
-static u8 * format_mpls_gre_device (u8 * s, va_list * args)
-{
-  u32 dev_instance = va_arg (*args, u32);
-  CLIB_UNUSED (int verbose) = va_arg (*args, int);
-
-  s = format (s, "MPLS-GRE tunnel: id %d\n", dev_instance);
-  return s;
-}
-
-VNET_DEVICE_CLASS (mpls_gre_device_class) = {
-  .name = "MPLS-GRE tunnel device",
-  .format_device_name = format_mpls_gre_tunnel_name,
-  .format_device = format_mpls_gre_device,
-  .format_tx_trace = format_mpls_gre_tx_trace,
-  .tx_function = mpls_gre_interface_tx,
-  .no_flatten_output_chains = 1,
-#ifdef SOON
-  .clear counter = 0;
-  .admin_up_down_function = 0;
-#endif
-};
-
-VLIB_DEVICE_TX_FUNCTION_MULTIARCH (mpls_gre_device_class,
-                                  mpls_gre_interface_tx)
-
-VNET_HW_INTERFACE_CLASS (mpls_gre_hw_interface_class) = {
-  .name = "MPLS-GRE",
-  .format_header = format_mpls_gre_header_with_length,
-#if 0
-  .unformat_header = unformat_mpls_gre_header,
-#endif
-  .build_rewrite = default_build_rewrite,
-  .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
-};
-
 /* manually added to the interface output node */
 #define MPLS_ETH_OUTPUT_NEXT_OUTPUT    1
 
@@ -497,63 +260,6 @@ VNET_HW_INTERFACE_CLASS (mpls_eth_hw_interface_class) = {
   .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
 };
 
-static void
-mpls_gre_fixup (vlib_main_t *vm,
-               ip_adjacency_t *adj,
-               vlib_buffer_t * b0)
-{
-    ip4_header_t * ip0;
-
-    ip0 = vlib_buffer_get_current (b0);
-
-    /* Fixup the checksum and len fields in the GRE tunnel encap
-     * that was applied at the midchain node */
-    ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
-    ip0->checksum = ip4_header_checksum (ip0);
-}
-
-static u8 * mpls_gre_rewrite (mpls_main_t *mm, mpls_gre_tunnel_t * t)
-{
-  ip4_header_t * ip0;
-  ip4_gre_and_mpls_header_t * h0;
-  u8 * rewrite_data = 0;
-  mpls_encap_t * e;
-  mpls_unicast_header_t *lp0;
-  int i;
-
- /* look up the encap label stack using the RX FIB */
-  e = mpls_encap_by_fib_and_dest (mm, t->inner_fib_index, t->tunnel_dst.as_u32);
-
-  if (e == 0)
-    {
-      clib_warning ("no label for inner fib index %d, dst %U",
-                    t->inner_fib_index, format_ip4_address, 
-                    &t->tunnel_dst);
-      return 0;
-    }
-  vec_validate (rewrite_data, sizeof (*h0) 
-                + sizeof (mpls_unicast_header_t) * vec_len(e->labels) -1);
-  memset (rewrite_data, 0, sizeof (*h0));
-
-  h0 = (ip4_gre_and_mpls_header_t *) rewrite_data;
-  /* Copy the encap label stack */
-  lp0 = h0->labels;
-  for (i = 0; i < vec_len(e->labels); i++)
-    lp0[i] = e->labels[i];
-  ip0 = &h0->ip4;
-  h0->gre.protocol = clib_host_to_net_u16(GRE_PROTOCOL_mpls_unicast);
-  ip0->ip_version_and_header_length = 0x45;
-  ip0->ttl = 254;
-  ip0->protocol = IP_PROTOCOL_GRE;
-  /* $$$ fixup ip4 header length and checksum after-the-fact */
-  ip0->src_address.as_u32 = t->tunnel_src.as_u32;
-  ip0->dst_address.as_u32 = t->tunnel_dst.as_u32;
-  ip0->checksum = ip4_header_checksum (ip0);
-
-  return (rewrite_data);
-}
-
 u8
 mpls_sw_interface_is_enabled (u32 sw_if_index)
 {
@@ -622,606 +328,6 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
   cm->config_index_by_sw_if_index[sw_if_index] = ci;
 }
 
-static mpls_gre_tunnel_t *
-mpls_gre_tunnel_from_fib_node (fib_node_t *node)
-{
-#if (CLIB_DEBUG > 0)
-    ASSERT(FIB_NODE_TYPE_MPLS_GRE_TUNNEL == node->fn_type);
-#endif
-    return ((mpls_gre_tunnel_t*)node);
-}
-
-/*
- * mpls_gre_tunnel_stack
- *
- * 'stack' (resolve the recursion for) the tunnel's midchain adjacency
- */
-static void
-mpls_gre_tunnel_stack (mpls_gre_tunnel_t *mgt)
-{
-    /*
-     * find the adjacency that is contributed by the FIB entry
-     * that this tunnel resovles via, and use it as the next adj
-     * in the midchain
-     */
-    adj_nbr_midchain_stack(mgt->adj_index,
-                          fib_entry_contribute_ip_forwarding(mgt->fei));
-}
-
-/**
- * Function definition to backwalk a FIB node
- */
-static fib_node_back_walk_rc_t
-mpls_gre_tunnel_back_walk (fib_node_t *node,
-                          fib_node_back_walk_ctx_t *ctx)
-{
-    mpls_gre_tunnel_stack(mpls_gre_tunnel_from_fib_node(node));
-
-    return (FIB_NODE_BACK_WALK_CONTINUE);
-}
-
-/**
- * Function definition to get a FIB node from its index
- */
-static fib_node_t*
-mpls_gre_tunnel_fib_node_get (fib_node_index_t index)
-{
-    mpls_gre_tunnel_t * mgt;
-    mpls_main_t * mm;
-
-    mm  = &mpls_main;
-    mgt = pool_elt_at_index(mm->gre_tunnels, index);
-
-    return (&mgt->mgt_node);
-}
-
-/**
- * Function definition to inform the FIB node that its last lock has gone.
- */
-static void
-mpls_gre_tunnel_last_lock_gone (fib_node_t *node)
-{
-    /*
-     * The MPLS GRE tunnel is a root of the graph. As such
-     * it never has children and thus is never locked.
-     */
-    ASSERT(0);
-}
-
-/*
- * Virtual function table registered by MPLS GRE tunnels
- * for participation in the FIB object graph.
- */
-const static fib_node_vft_t mpls_gre_vft = {
-    .fnv_get = mpls_gre_tunnel_fib_node_get,
-    .fnv_last_lock = mpls_gre_tunnel_last_lock_gone,
-    .fnv_back_walk = mpls_gre_tunnel_back_walk,
-};
-static mpls_gre_tunnel_t *
-mpls_gre_tunnel_find (ip4_address_t *src,
-                     ip4_address_t *dst,
-                     ip4_address_t *intfc,
-                     u32 inner_fib_index)
-{
-    mpls_main_t * mm = &mpls_main;
-    mpls_gre_tunnel_t *tp;
-    int found_tunnel = 0;
-
-    /* suppress duplicate mpls interface generation. */
-    pool_foreach (tp, mm->gre_tunnels, 
-    ({
-       /* 
-        * If we have a tunnel which matches (src, dst, intfc/mask)
-        * AND the expected route is in the FIB, it's a dup 
-        */
-       if (!memcmp (&tp->tunnel_src, src, sizeof (*src))
-           && !memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
-           && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
-           && tp->inner_fib_index == inner_fib_index) 
-       {
-           found_tunnel = 1;
-           goto found;
-       }
-    }));
-
-found:
-    if (found_tunnel)
-    {
-       return (tp);
-    }
-    return (NULL);
-}
-
-int mpls_gre_tunnel_add (ip4_address_t *src,
-                        ip4_address_t *dst,
-                        ip4_address_t *intfc,
-                        u32 mask_width,
-                        u32 inner_fib_index,
-                        u32 outer_fib_index,
-                        u32 * tunnel_sw_if_index,
-                        u8 l2_only)
-{
-    mpls_main_t * mm = &mpls_main;
-    gre_main_t * gm = &gre_main;
-    vnet_main_t * vnm = vnet_get_main();
-    mpls_gre_tunnel_t *tp;
-    ip_adjacency_t adj;
-    u8 * rewrite_data;
-    mpls_encap_t * e = 0;
-    u32 hw_if_index = ~0;
-    vnet_hw_interface_t * hi;
-    u32 slot;
-    const ip46_address_t zero_nh = {
-       .ip4.as_u32 = 0,
-    };
-
-    tp = mpls_gre_tunnel_find(src,dst,intfc,inner_fib_index);
-
-    /* Add, duplicate */
-    if (NULL != tp)
-       return VNET_API_ERROR_NO_SUCH_ENTRY;
-
-    e = mpls_encap_by_fib_and_dest (mm, inner_fib_index, dst->as_u32);
-    if (e == 0)
-       return VNET_API_ERROR_NO_SUCH_LABEL;
-
-    pool_get(mm->gre_tunnels, tp);
-    memset (tp, 0, sizeof (*tp));
-    fib_node_init(&tp->mgt_node,
-                 FIB_NODE_TYPE_MPLS_GRE_TUNNEL);
-
-    if (vec_len (mm->free_gre_sw_if_indices) > 0)
-    {
-       hw_if_index = 
-           mm->free_gre_sw_if_indices[vec_len(mm->free_gre_sw_if_indices)-1];
-       _vec_len (mm->free_gre_sw_if_indices) -= 1;
-       hi = vnet_get_hw_interface (vnm, hw_if_index);
-       hi->dev_instance = tp - mm->gre_tunnels;
-       hi->hw_instance = tp - mm->gre_tunnels;
-    }
-    else 
-    {
-       hw_if_index = vnet_register_interface
-           (vnm, mpls_gre_device_class.index, tp - mm->gre_tunnels,
-            mpls_gre_hw_interface_class.index,
-            tp - mm->gre_tunnels);
-       hi = vnet_get_hw_interface (vnm, hw_if_index);
-
-       /* ... to make the IP and L2 x-connect cases identical */
-       slot = vlib_node_add_named_next_with_slot
-           (vnm->vlib_main, hi->tx_node_index, 
-            "mpls-post-rewrite", MPLS_GRE_OUTPUT_NEXT_POST_REWRITE);
-
-       ASSERT (slot == MPLS_GRE_OUTPUT_NEXT_POST_REWRITE);
-    }
-  
-    *tunnel_sw_if_index = hi->sw_if_index;
-    vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 
-                                VNET_SW_INTERFACE_FLAG_ADMIN_UP);      
-    vec_validate(ip4_main.fib_index_by_sw_if_index, *tunnel_sw_if_index);
-    ip4_main.fib_index_by_sw_if_index[*tunnel_sw_if_index] = outer_fib_index;
-
-    tp->hw_if_index = hw_if_index;
-
-    /* bind the MPLS and IPv4 FIBs to the interface and enable */
-    vec_validate(mm->fib_index_by_sw_if_index, hi->sw_if_index);
-    mm->fib_index_by_sw_if_index[hi->sw_if_index] = inner_fib_index;
-    mpls_sw_interface_enable_disable(mm, hi->sw_if_index, 1);
-    ip4_main.fib_index_by_sw_if_index[hi->sw_if_index] = inner_fib_index;
-    ip4_sw_interface_enable_disable(hi->sw_if_index, 1);
-
-    tp->tunnel_src.as_u32 = src->as_u32;
-    tp->tunnel_dst.as_u32 = dst->as_u32;
-    tp->intfc_address.as_u32 = intfc->as_u32;
-    tp->mask_width = mask_width;
-    tp->inner_fib_index = inner_fib_index;
-    tp->outer_fib_index = outer_fib_index;
-    tp->encap_index = e - mm->encaps;
-    tp->l2_only = l2_only;
-
-    /* Add the tunnel to the hash table of all GRE tunnels */
-    u64 key = (u64)src->as_u32 << 32 | (u64)dst->as_u32;
-
-    ASSERT(NULL == hash_get (gm->tunnel_by_key, key));
-    hash_set (gm->tunnel_by_key, key, tp - mm->gre_tunnels);
-
-    /* Create the adjacency and add to v4 fib */
-    memset(&adj, 0, sizeof (adj));
-    adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
-    
-    rewrite_data = mpls_gre_rewrite (mm, tp);
-    if (rewrite_data == 0)
-    {
-       if (*tunnel_sw_if_index != ~0)
-       {
-           hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
-           vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 
-                                        0 /* admin down */);
-           vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
-       }
-       pool_put (mm->gre_tunnels, tp);
-       return VNET_API_ERROR_NO_SUCH_LABEL;
-    }
-
-    /* Save a copy of the rewrite data for L2 x-connect */
-    vec_free (tp->rewrite_data);
-
-    tp->rewrite_data = rewrite_data;
-  
-    if (!l2_only)
-    {
-       /*
-        * source the FIB entry for the tunnel's destination
-        * and become a child thereof. The tunnel will then get poked
-        * when the forwarding for the entry updates, and the tunnel can
-        * re-stack accordingly
-        */
-       const fib_prefix_t tun_dst_pfx = {
-           .fp_len = 32,
-           .fp_proto = FIB_PROTOCOL_IP4,
-           .fp_addr = {
-               .ip4 = *dst,
-           }
-       };
-
-       tp->fei = fib_table_entry_special_add(outer_fib_index,
-                                             &tun_dst_pfx,
-                                             FIB_SOURCE_RR,
-                                             FIB_ENTRY_FLAG_NONE,
-                                             ADJ_INDEX_INVALID);
-       tp->sibling_index = fib_entry_child_add(tp->fei,
-                                               FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
-                                               tp - mm->gre_tunnels);
-
-       /*
-        * create and update the midchain adj this tunnel sources.
-        * This is the adj the route we add below will resolve to.
-        */
-       tp->adj_index = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
-                                           FIB_LINK_IP4,
-                                           &zero_nh,
-                                           hi->sw_if_index);
-
-       adj_nbr_midchain_update_rewrite(tp->adj_index,
-                                       mpls_gre_fixup,
-                                       ADJ_MIDCHAIN_FLAG_NONE,
-                                       rewrite_data);
-       mpls_gre_tunnel_stack(tp);
-
-       /*
-        * Update the route for the tunnel's subnet to point through the tunnel
-        */
-       const fib_prefix_t tun_sub_net_pfx = {
-           .fp_len = tp->mask_width,
-           .fp_proto = FIB_PROTOCOL_IP4,
-           .fp_addr = {
-               .ip4 = tp->intfc_address,
-           },
-       };
-
-       fib_table_entry_update_one_path(inner_fib_index,
-                                       &tun_sub_net_pfx,
-                                       FIB_SOURCE_INTERFACE,
-                                       (FIB_ENTRY_FLAG_CONNECTED |
-                                        FIB_ENTRY_FLAG_ATTACHED),
-                                       FIB_PROTOCOL_IP4,
-                                       &zero_nh,
-                                       hi->sw_if_index,
-                                       ~0, // invalid fib index
-                                       1,
-                                       MPLS_LABEL_INVALID,
-                                       FIB_ROUTE_PATH_FLAG_NONE);
-    }
-
-    return 0;
-}
-
-static int
-mpls_gre_tunnel_del (ip4_address_t *src,
-                    ip4_address_t *dst,
-                    ip4_address_t *intfc,
-                    u32 mask_width,
-                    u32 inner_fib_index,
-                    u32 outer_fib_index,
-                    u32 * tunnel_sw_if_index,
-                    u8 l2_only)
-{
-    mpls_main_t * mm = &mpls_main;
-    vnet_main_t * vnm = vnet_get_main();
-    gre_main_t * gm = &gre_main;
-    mpls_gre_tunnel_t *tp;
-    vnet_hw_interface_t * hi;
-  
-    tp = mpls_gre_tunnel_find(src,dst,intfc,inner_fib_index);
-
-    /* Delete, and we can't find the tunnel */
-    if (NULL == tp)
-       return VNET_API_ERROR_NO_SUCH_ENTRY;
-
-    hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
-
-    if (!l2_only)
-    {
-       /*
-        * unsource the FIB entry for the tunnel's destination
-        */
-       const fib_prefix_t tun_dst_pfx = {
-           .fp_len = 32,
-           .fp_proto = FIB_PROTOCOL_IP4,
-           .fp_addr = {
-               .ip4 = *dst,
-           }
-       };
-
-       fib_entry_child_remove(tp->fei,
-                              tp->sibling_index);
-       fib_table_entry_special_remove(outer_fib_index,
-                                      &tun_dst_pfx,
-                                      FIB_SOURCE_RR);
-       tp->fei = FIB_NODE_INDEX_INVALID;
-       adj_unlock(tp->adj_index);
-       /*
-        * unsource the route for the tunnel's subnet
-        */
-       const fib_prefix_t tun_sub_net_pfx = {
-           .fp_len = tp->mask_width,
-           .fp_proto = FIB_PROTOCOL_IP4,
-           .fp_addr = {
-               .ip4 = tp->intfc_address,
-           },
-       };
-
-       fib_table_entry_delete(inner_fib_index,
-                              &tun_sub_net_pfx,
-                              FIB_SOURCE_INTERFACE);
-    }
-
-    u64 key = ((u64)tp->tunnel_src.as_u32 << 32 |
-               (u64)tp->tunnel_src.as_u32);
-
-    hash_unset (gm->tunnel_by_key, key);
-    mpls_sw_interface_enable_disable(mm, hi->sw_if_index, 0);
-    ip4_sw_interface_enable_disable(hi->sw_if_index, 0);
-
-    vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 
-                                0 /* admin down */);
-    vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
-    vec_free (tp->rewrite_data);
-    fib_node_deinit(&tp->mgt_node);
-    pool_put (mm->gre_tunnels, tp);
-
-    return 0;
-}
-
-int
-vnet_mpls_gre_add_del_tunnel (ip4_address_t *src,
-                             ip4_address_t *dst,
-                             ip4_address_t *intfc,
-                             u32 mask_width,
-                             u32 inner_fib_id, u32 outer_fib_id,
-                             u32 * tunnel_sw_if_index,
-                             u8 l2_only,
-                             u8 is_add)
-{
-    u32 inner_fib_index = 0;
-    u32 outer_fib_index = 0;
-    u32 dummy;
-    ip4_main_t * im = &ip4_main;
-  
-    /* No questions, no answers */
-    if (NULL == tunnel_sw_if_index)
-       tunnel_sw_if_index = &dummy;
-
-    *tunnel_sw_if_index = ~0;
-
-    if (inner_fib_id != (u32)~0)
-    {
-       uword * p;
-      
-       p = hash_get (im->fib_index_by_table_id, inner_fib_id);
-       if (! p)
-           return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-       inner_fib_index = p[0];
-    }
-
-    if (outer_fib_id != 0)
-    {
-       uword * p;
-      
-       p = hash_get (im->fib_index_by_table_id, outer_fib_id);
-       if (! p)
-           return VNET_API_ERROR_NO_SUCH_FIB;
-       outer_fib_index = p[0];
-    }
-
-    if (is_add)
-    {
-       return (mpls_gre_tunnel_add(src,dst,intfc, mask_width,
-                                   inner_fib_index,
-                                   outer_fib_index,
-                                   tunnel_sw_if_index,
-                                   l2_only));
-    }
-    else
-    {
-       return (mpls_gre_tunnel_del(src,dst,intfc, mask_width,
-                                   inner_fib_index,
-                                   outer_fib_index,
-                                   tunnel_sw_if_index,
-                                   l2_only));
-    }
-}
-
-/*
- * Remove all mpls tunnels in the specified fib
- */
-int vnet_mpls_gre_delete_fib_tunnels (u32 fib_id)
-{
-  mpls_main_t * mm = &mpls_main;
-  vnet_main_t * vnm = mm->vnet_main;
-  mpls_gre_tunnel_t *tp;
-  u32 fib_index = 0;
-  u32 * tunnels_to_delete = 0;
-  vnet_hw_interface_t * hi;
-  int i;
-
-  fib_index = ip4_fib_index_from_table_id(fib_id);
-  if (~0 == fib_index)
-      return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-
-  pool_foreach (tp, mm->gre_tunnels, 
-    ({
-      if (tp->inner_fib_index == fib_index) 
-        vec_add1 (tunnels_to_delete, tp - mm->gre_tunnels);
-    }));
-  
-  for (i = 0; i < vec_len(tunnels_to_delete); i++) {
-      tp = pool_elt_at_index (mm->gre_tunnels, tunnels_to_delete[i]);
-
-      /* Delete, the route if not already gone */
-      if (FIB_NODE_INDEX_INVALID != tp->fei && !tp->l2_only) 
-      {
-         const fib_prefix_t tun_dst_pfx = {
-             .fp_len = 32,
-             .fp_proto = FIB_PROTOCOL_IP4,
-             .fp_addr = {
-                 .ip4 = tp->tunnel_dst,
-             }
-         };
-
-         fib_entry_child_remove(tp->fei,
-                                tp->sibling_index);
-         fib_table_entry_special_remove(tp->outer_fib_index,
-                                        &tun_dst_pfx,
-                                        FIB_SOURCE_RR);
-         tp->fei = FIB_NODE_INDEX_INVALID;
-         adj_unlock(tp->adj_index);
-         const fib_prefix_t tun_sub_net_pfx = {
-             .fp_len = tp->mask_width,
-             .fp_proto = FIB_PROTOCOL_IP4,
-             .fp_addr = {
-                 .ip4 = tp->intfc_address,
-             },
-         };
-
-         fib_table_entry_delete(tp->inner_fib_index,
-                                &tun_sub_net_pfx,
-                                FIB_SOURCE_INTERFACE);
-      }
-      
-      hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
-      vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 
-                                   0 /* admin down */);
-      vec_add1 (mm->free_gre_sw_if_indices, tp->hw_if_index);
-      vec_free (tp->rewrite_data);
-      pool_put (mm->gre_tunnels, tp);
-  }
-  
-  vec_free(tunnels_to_delete);
-  
-  return (0);
-}
-
-static clib_error_t *
-create_mpls_gre_tunnel_command_fn (vlib_main_t * vm,
-                unformat_input_t * input,
-                vlib_cli_command_t * cmd)
-{
-  unformat_input_t _line_input, * line_input = &_line_input;
-  ip4_address_t src, dst, intfc;
-  int src_set = 0, dst_set = 0, intfc_set = 0;
-  u32 mask_width;
-  u32 inner_fib_id = (u32)~0;
-  u32 outer_fib_id = 0;
-  int rv;
-  u8 is_del = 0;
-  u8 l2_only = 0;
-  u32 tunnel_intfc_sw_if_index = ~0;
-  
-  /* Get a line of input. */
-  if (! unformat_user (input, unformat_line_input, line_input))
-    return 0;
-
-  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (line_input, "src %U", 
-                    unformat_ip4_address, &src))
-        src_set = 1;
-      else if (unformat (line_input, "dst %U", 
-                         unformat_ip4_address, &dst))
-        dst_set = 1;
-      else if (unformat (line_input, "intfc %U/%d", 
-                         unformat_ip4_address, &intfc, &mask_width))
-        intfc_set = 1;
-      else if (unformat (line_input, "inner-fib-id %d", &inner_fib_id))
-        ;
-      else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
-        ;
-      else if (unformat (line_input, "del"))
-        is_del = 1;
-      else if (unformat (line_input, "l2-only"))
-        l2_only = 1;
-      else
-        return clib_error_return (0, "unknown input '%U'",
-                                  format_unformat_error, line_input);
-    }
-
-  if (!src_set)
-    return clib_error_return (0, "missing: src <ip-address>");
-          
-  if (!dst_set)
-    return clib_error_return (0, "missing: dst <ip-address>");
-          
-  if (!intfc_set)
-    return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
-          
-
-  rv = vnet_mpls_gre_add_del_tunnel (&src, &dst, &intfc, mask_width, 
-                                     inner_fib_id, outer_fib_id, 
-                                     &tunnel_intfc_sw_if_index, 
-                                     l2_only, !is_del);
-
-  switch (rv) 
-    {
-    case 0:
-      if (!is_del)
-        vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), tunnel_intfc_sw_if_index);
-      break;
-
-    case VNET_API_ERROR_NO_SUCH_INNER_FIB:
-      return clib_error_return (0, "inner fib ID %d doesn't exist\n",
-                                inner_fib_id);
-    case VNET_API_ERROR_NO_SUCH_FIB:
-      return clib_error_return (0, "outer fib ID %d doesn't exist\n",
-                                outer_fib_id);
-
-    case VNET_API_ERROR_NO_SUCH_ENTRY:
-      return clib_error_return (0, "tunnel not found\n");
-
-    case VNET_API_ERROR_NO_SUCH_LABEL:
-      /* 
-       * This happens when there's no MPLS label for the dst address
-       * no need for two error messages.
-       */
-      break;
-      
-    default:
-      return clib_error_return (0, "vnet_mpls_gre_add_del_tunnel returned %d",
-                                rv);
-    }
-  return 0;
-}
-
-VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = {
-  .path = "create mpls gre tunnel",
-  .short_help = 
-  "create mpls gre tunnel [del] src <addr> dst <addr> intfc <addr>/<mw>",
-  .function = create_mpls_gre_tunnel_command_fn,
-};
-
 u8 * format_mpls_encap_index (u8 * s, va_list * args)
 {
   mpls_main_t * mm = va_arg (*args, mpls_main_t *);
@@ -1239,40 +345,6 @@ u8 * format_mpls_encap_index (u8 * s, va_list * args)
   return s;
 }
 
-u8 * format_mpls_gre_tunnel (u8 * s, va_list * args)
-{
-  mpls_gre_tunnel_t * t = va_arg (*args, mpls_gre_tunnel_t *);
-  mpls_main_t * mm = &mpls_main;
-  
-  if (t->l2_only == 0)
-    {
-      s = format (s, "[%d]: src %U, dst %U, adj %U/%d, labels %U\n",
-                  t - mm->gre_tunnels, 
-                  format_ip4_address, &t->tunnel_src,
-                  format_ip4_address, &t->tunnel_dst,
-                  format_ip4_address, &t->intfc_address,
-                  t->mask_width, 
-                  format_mpls_encap_index, mm, t->encap_index);
-
-      s = format (s, "      inner fib index %d, outer fib index %d",
-                  t->inner_fib_index, t->outer_fib_index);
-    }
-  else
-    {
-      s = format (s, "[%d]: src %U, dst %U, key %U, labels %U\n",
-                  t - mm->gre_tunnels, 
-                  format_ip4_address, &t->tunnel_src,
-                  format_ip4_address, &t->tunnel_dst,
-                  format_ip4_address, &t->intfc_address,
-                  format_mpls_encap_index, mm, t->encap_index);
-
-      s = format (s, "      l2 interface %d, outer fib index %d",
-                  t->hw_if_index, t->outer_fib_index);
-    }
-
-  return s;
-}
-
 u8 * format_mpls_ethernet_tunnel (u8 * s, va_list * args)
 {
   mpls_eth_tunnel_t * t = va_arg (*args, mpls_eth_tunnel_t *);
@@ -1299,20 +371,8 @@ show_mpls_tunnel_command_fn (vlib_main_t * vm,
                              vlib_cli_command_t * cmd)
 {
   mpls_main_t * mm = &mpls_main;
-  mpls_gre_tunnel_t * gt;
   mpls_eth_tunnel_t * et;
 
-  if (pool_elts (mm->gre_tunnels))
-    {
-      vlib_cli_output (vm, "MPLS-GRE tunnels");
-      pool_foreach (gt, mm->gre_tunnels,
-      ({
-        vlib_cli_output (vm, "%U", format_mpls_gre_tunnel, gt);
-      }));
-    }
-  else
-    vlib_cli_output (vm, "No MPLS-GRE tunnels");
-
   if (pool_elts (mm->eth_tunnels))
     {
       vlib_cli_output (vm, "MPLS-Ethernet tunnels");
@@ -1339,9 +399,6 @@ clib_error_t *mpls_interface_init (vlib_main_t *vm)
 {
   clib_error_t * error;
 
-  fib_node_register_type(FIB_NODE_TYPE_MPLS_GRE_TUNNEL,
-                        &mpls_gre_vft);
-
   if ((error = vlib_call_init_function (vm, mpls_policy_encap_init)))
       return error;
 
index b28736b..ac35e5d 100644 (file)
@@ -96,25 +96,29 @@ u8 * format_mpls_header (u8 * s, va_list * args)
                 vnet_mpls_uc_get_s(hdr.label_exp_s_ttl)));
 }
 
-u8 * format_mpls_gre_tx_trace (u8 * s, va_list * args)
+uword
+unformat_mpls_header (unformat_input_t * input, va_list * args)
 {
-  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
-  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
-  mpls_gre_tx_trace_t * t = va_arg (*args, mpls_gre_tx_trace_t *);
-  mpls_main_t * mm = &mpls_main;
-    
-  if (t->lookup_miss)
-    s = format (s, "MPLS: lookup miss");
-  else
-    {
-      s = format (s, "MPLS: tunnel %d labels %U len %d src %U dst %U",
-                  t->tunnel_id,
-                  format_mpls_encap_index, mm, t->mpls_encap_index, 
-                  clib_net_to_host_u16 (t->length),
-                  format_ip4_address, &t->src.as_u8,
-                  format_ip4_address, &t->dst.as_u8);
-    }
-  return s;
+  u8 ** result = va_arg (*args, u8 **);
+  mpls_unicast_header_t _h, * h = &_h;
+  u32 label, label_exp_s_ttl;
+
+  if (! unformat (input, "MPLS %d", &label))
+    return 0;
+
+  label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
+  h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
+
+  /* Add gre, mpls headers to result. */
+  {
+    void * p;
+    u32 h_n_bytes = sizeof (h[0]);
+
+    vec_add2 (*result, p, h_n_bytes);
+    clib_memcpy (p, h, h_n_bytes);
+  }
+
+  return 1;
 }
 
 u8 * format_mpls_eth_tx_trace (u8 * s, va_list * args)
@@ -156,62 +160,6 @@ u8 * format_mpls_eth_header_with_length (u8 * s, va_list * args)
   return s;
 }
 
-u8 * format_mpls_gre_header_with_length (u8 * s, va_list * args)
-{
-  gre_header_t * h = va_arg (*args, gre_header_t *);
-  mpls_unicast_header_t * m = (mpls_unicast_header_t *)(h+1);
-  u32 max_header_bytes = va_arg (*args, u32);
-  uword header_bytes;
-
-  header_bytes = sizeof (h[0]);
-  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
-    return format (s, "gre header truncated");
-
-  s = format 
-    (s, "GRE-MPLS label %d", 
-     vnet_mpls_uc_get_label (clib_net_to_host_u32 (m->label_exp_s_ttl)));
-
-  return s;
-}
-
-u8 * format_mpls_gre_header (u8 * s, va_list * args)
-{
-  gre_header_t * h = va_arg (*args, gre_header_t *);
-  return format (s, "%U", format_mpls_gre_header_with_length, h, 0);
-}
-
-uword
-unformat_mpls_gre_header (unformat_input_t * input, va_list * args)
-{
-  u8 ** result = va_arg (*args, u8 **);
-  gre_header_t _g, * g = &_g;
-  mpls_unicast_header_t _h, * h = &_h;
-  u32 label, label_exp_s_ttl;
-  
-  if (! unformat (input, "MPLS %d", &label))
-    return 0;
-
-  g->protocol = clib_host_to_net_u16 (GRE_PROTOCOL_mpls_unicast);
-
-  label_exp_s_ttl = (label<<12) | (1<<8) /* s-bit */ | 0xFF;
-  h->label_exp_s_ttl = clib_host_to_net_u32 (label_exp_s_ttl);
-
-  /* Add gre, mpls headers to result. */
-  {
-    void * p;
-    u32 g_n_bytes = sizeof (g[0]);
-    u32 h_n_bytes = sizeof (h[0]);
-
-    vec_add2 (*result, p, g_n_bytes);
-    clib_memcpy (p, g, g_n_bytes);
-
-    vec_add2 (*result, p, h_n_bytes);
-    clib_memcpy (p, h, h_n_bytes);
-  }
-  
-  return 1;
-}
-
 uword
 unformat_mpls_label_net_byte_order (unformat_input_t * input,
                                         va_list * args)
@@ -443,217 +391,6 @@ VLIB_CLI_COMMAND (mpls_del_encap_command, static) = {
   .function = mpls_del_encap_command_fn,
 };
 
-int vnet_mpls_add_del_decap (u32 rx_fib_id, 
-                             u32 tx_fib_id,
-                             u32 label_host_byte_order, 
-                             int s_bit, int next_index, int is_add)
-{
-  mpls_main_t * mm = &mpls_main;
-  ip4_main_t * im = &ip4_main;
-  mpls_decap_t * d;
-  u32 rx_fib_index, tx_fib_index_or_output_swif_index;
-  uword *p;
-  u64 key;
-  
-  p = hash_get (im->fib_index_by_table_id, rx_fib_id);
-  if (! p)
-    return VNET_API_ERROR_NO_SUCH_FIB;
-
-  rx_fib_index = p[0];
-
-  /* L3 decap => transform fib ID to fib index */
-  if (next_index == MPLS_LOOKUP_NEXT_IP4_INPUT)
-    {
-      p = hash_get (im->fib_index_by_table_id, tx_fib_id);
-      if (! p)
-        return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-      
-      tx_fib_index_or_output_swif_index = p[0];
-    }
-  else
-    {
-      /* L2 decap, tx_fib_id is actually the output sw_if_index */
-      tx_fib_index_or_output_swif_index = tx_fib_id;
-    }
-
-  key = ((u64) rx_fib_index<<32) | ((u64) label_host_byte_order<<12)
-    | ((u64) s_bit<<8);
-
-  p = hash_get (mm->mpls_decap_by_rx_fib_and_label, key);
-
-  /* If deleting, or replacing an old entry */
-  if (is_add == 0 || p)
-    {
-      if (is_add == 0 && p == 0)
-        return VNET_API_ERROR_NO_SUCH_LABEL;
-
-      d = pool_elt_at_index (mm->decaps, p[0]);
-      hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
-      pool_put (mm->decaps, d);
-      /* Deleting, we're done... */
-      if (is_add == 0)
-        return 0;
-    }
-
-  /* add decap entry... */
-  pool_get (mm->decaps, d);
-  memset (d, 0, sizeof (*d));
-  d->tx_fib_index = tx_fib_index_or_output_swif_index;
-  d->next_index = next_index;
-
-  hash_set (mm->mpls_decap_by_rx_fib_and_label, key, d - mm->decaps);
-
-  return 0;
-}
-
-uword
-unformat_mpls_gre_input_next (unformat_input_t * input, va_list * args)
-{
-  u32 * result = va_arg (*args, u32 *);
-  int rv = 0;
-
-  if (unformat (input, "lookup"))
-    {
-      *result = MPLS_LOOKUP_NEXT_IP4_INPUT;
-      rv = 1;
-    }
-  else if (unformat (input, "output"))
-    {
-      *result = MPLS_LOOKUP_NEXT_L2_OUTPUT;
-      rv = 1;
-    }
-  return rv;
-}
-
-static clib_error_t *
-mpls_add_decap_command_fn (vlib_main_t * vm,
-                           unformat_input_t * input,
-                           vlib_cli_command_t * cmd)
-{
-  vnet_main_t * vnm = vnet_get_main();
-  u32 rx_fib_id = 0;
-  u32 tx_fib_or_sw_if_index;
-  u32 label;
-  int s_bit = 1;
-  u32 next_index = 1;           /* ip4_lookup, see node.c */
-  int tx_fib_id_set = 0;
-  int label_set = 0;
-  int rv;
-
-  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (input, "fib %d", &tx_fib_or_sw_if_index))
-        tx_fib_id_set = 1;
-      else if (unformat (input, "sw_if_index %d", &tx_fib_or_sw_if_index))
-        tx_fib_id_set = 1;
-      else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
-                         &tx_fib_or_sw_if_index))
-        tx_fib_id_set = 1;
-      else if (unformat (input, "rx-fib %d", &rx_fib_id))
-        ;
-      else if (unformat (input, "label %d", &label))
-        label_set = 1;
-      else if (unformat (input, "s-bit-clear"))
-        s_bit = 0;
-      else if (unformat (input, "next %U", unformat_mpls_gre_input_next, 
-                         &next_index))
-        ;
-      else
-        break;
-    }
-
-  if (tx_fib_id_set == 0)
-    return clib_error_return (0, "lookup FIB ID not set");
-  if (label_set == 0)
-    return clib_error_return (0, "missing label");
-  
-  rv = vnet_mpls_add_del_decap (rx_fib_id, tx_fib_or_sw_if_index, 
-                                label, s_bit, next_index, 1 /* is_add */);
-  switch (rv)
-    {
-    case 0:
-      break;
-
-    case VNET_API_ERROR_NO_SUCH_FIB:
-      return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
-    case VNET_API_ERROR_NO_SUCH_INNER_FIB:
-      return clib_error_return (0, "no such tx fib / swif %d", 
-                                tx_fib_or_sw_if_index);
-
-    default:
-      return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
-                                rv);
-    }
-  return 0;
-}
-
-VLIB_CLI_COMMAND (mpls_add_decap_command, static) = {
-    .path = "mpls decap add",
-    .short_help = 
-    "mpls decap add fib <id> label <nn> [s-bit-clear] [next-index <nn>]",
-    .function = mpls_add_decap_command_fn, 
-};
-
-static clib_error_t *
-mpls_del_decap_command_fn (vlib_main_t * vm,
-                           unformat_input_t * input,
-                           vlib_cli_command_t * cmd)
-{
-  u32 rx_fib_id = 0;
-  u32 tx_fib_id = 0;
-  u32 label;
-  int s_bit = 1;
-  int label_set = 0;
-  int rv;
-
-  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (input, "rx-fib %d", &rx_fib_id))
-        ;
-      else if (unformat (input, "label %d", &label))
-        label_set = 1;
-      else if (unformat (input, "s-bit-clear"))
-        s_bit = 0;
-    }
-
-  if (!label_set)
-    return clib_error_return (0, "label not set");
-
-  rv = vnet_mpls_add_del_decap (rx_fib_id, 
-                                tx_fib_id /* not interesting */,
-                                label, s_bit, 
-                                0 /* next_index not interesting */,
-                                0 /* is_add */);
-  switch (rv)
-    {
-    case 0:
-      break;
-
-    case VNET_API_ERROR_NO_SUCH_FIB:
-      return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
-    case VNET_API_ERROR_NO_SUCH_INNER_FIB:
-      return clib_error_return (0, "no such lookup fib id %d", tx_fib_id);
-
-    case VNET_API_ERROR_NO_SUCH_LABEL:
-      return clib_error_return (0, "no such label %d rx fib id %d", 
-                                label, rx_fib_id);
-
-    default:
-      return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
-                                rv);
-    }
-  return 0;
-}
-
-
-VLIB_CLI_COMMAND (mpls_del_decap_command, static) = {
-  .path = "mpls decap delete",
-  .short_help = "mpls decap delete label <label> rx-fib <id> [s-bit-clear]",
-  .function = mpls_del_decap_command_fn,
-};
-
 int
 mpls_dest_cmp(void * a1, void * a2)
 {
@@ -943,28 +680,6 @@ int mpls_fib_reset_labels (u32 fib_id)
       pool_put_index (mm->encaps, s->entry_index);
     }
                 
-  vec_reset_length(records);
-
-  hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label, 
-  ({
-    if (fib_index == (u32) (key>>32)) {
-        vec_add2 (records, s, 1);
-        s->entry_index = value;
-        s->fib_index = fib_index;
-        s->s_bit = key & (1<<8);
-        s->dest = (u32)((key & 0xFFFFFFFF)>>12);
-    }
-  }));
-  
-  vec_foreach (s, records)
-    {
-       key = ((u64) fib_index <<32) | ((u64) s->dest<<12) |
-        ((u64) s->s_bit);
-      
-      hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
-      pool_put_index (mm->decaps, s->entry_index);
-    }
-
   vec_free(records);
   return 0;
 }
@@ -981,7 +696,6 @@ static clib_error_t * mpls_init (vlib_main_t * vm)
     return error;
 
   mm->mpls_encap_by_fib_and_dest = hash_create (0, sizeof (uword));
-  mm->mpls_decap_by_rx_fib_and_label = hash_create (0, sizeof (uword));
 
   return vlib_call_init_function (vm, mpls_input_init);
 }
index 3575533..da663b0 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef included_vnet_mpls_gre_h
-#define included_vnet_mpls_gre_h
+#ifndef included_vnet_mpls_h
+#define included_vnet_mpls_h
 
 #include <vnet/vnet.h>
-#include <vnet/gre/gre.h>
 #include <vnet/mpls/packet.h>
 #include <vnet/mpls/mpls_types.h>
 #include <vnet/ip/ip4_packet.h>
 #include <vnet/fib/fib_node.h>
 #include <vnet/adj/adj.h>
 
-typedef CLIB_PACKED (struct {
-  ip4_header_t ip4;             /* 20 bytes */
-  gre_header_t gre;             /* 4 bytes */
-  mpls_unicast_header_t labels[0];   /* 4 bytes each */
-}) ip4_gre_and_mpls_header_t;
-
-extern vnet_hw_interface_class_t mpls_gre_hw_interface_class;
-
 typedef enum {
 #define mpls_error(n,s) MPLS_ERROR_##n,
 #include <vnet/mpls/error.def>
 #undef mpls_error
   MPLS_N_ERROR,
-} mpls_gre_error_t;
+} mpls_error_t;
 
 /*
  * No protocol info, MPLS labels don't have a next-header field
  * presumably the label field tells all...
  */
-
-typedef struct {
-  fib_node_t mgt_node;
-  ip4_address_t tunnel_src;
-  ip4_address_t tunnel_dst;
-  ip4_address_t intfc_address;
-  u32 mask_width;
-  u32 inner_fib_index;
-  u32 outer_fib_index;
-  u32 encap_index;
-  u32 hw_if_index;              /* L2 x-connect capable tunnel intfc */
-  u8 * rewrite_data;
-  u8 l2_only;
-  fib_node_index_t fei; /* FIB Entry index for the tunnel's destination */
-  adj_index_t adj_index; /* The midchain adj this tunnel creates */
-  u32 sibling_index;
-} mpls_gre_tunnel_t;
-
 typedef struct {
   u8 tunnel_dst[6];
   ip4_address_t intfc_address;
@@ -81,11 +54,6 @@ typedef struct {
   u32 output_next_index;
 } mpls_encap_t;
 
-typedef struct {
-  u32 tx_fib_index;
-  u32 next_index;               /* e.g. ip4/6-input, l2-input */
-} mpls_decap_t;
-
 #define MPLS_FIB_DEFAULT_TABLE_ID 0
 
 /**
@@ -134,10 +102,6 @@ typedef struct {
   u32 mpls_rx_feature_not_enabled;
   u32 mpls_tx_feature_interface_output;
 
-  /* pool of gre tunnel instances */
-  mpls_gre_tunnel_t *gre_tunnels;
-  u32 * free_gre_sw_if_indices;
-
   /* pool of ethernet tunnel instances */
   mpls_eth_tunnel_t *eth_tunnels;
   u32 * free_eth_sw_if_indices;
@@ -146,10 +110,6 @@ typedef struct {
   mpls_encap_t * encaps;
   uword * mpls_encap_by_fib_and_dest;
 
-  /* Decap side: map rx label to FIB */
-  mpls_decap_t * decaps;
-  uword * mpls_decap_by_rx_fib_and_label;
-
   /* mpls-o-e policy tunnel next index for ip4/ip6-classify */
   u32 ip4_classify_mpls_policy_encap_next_index;
   u32 ip6_classify_mpls_policy_encap_next_index;
@@ -197,7 +157,6 @@ __VA_ARGS__ vnet_feature_registration_t tx_##x
 extern clib_error_t * mpls_feature_init(vlib_main_t * vm);
 
 format_function_t format_mpls_protocol;
-format_function_t format_mpls_gre_header_with_length;
 format_function_t format_mpls_eth_header_with_length;
 format_function_t format_mpls_encap_index;
 
@@ -211,25 +170,17 @@ extern vlib_node_registration_t mpls_policy_encap_node;
 extern vlib_node_registration_t mpls_output_node;
 extern vlib_node_registration_t mpls_midchain_node;
 
-extern vnet_device_class_t mpls_gre_device_class;
-
 /* Parse mpls protocol as 0xXXXX or protocol name.
    In either host or network byte order. */
 unformat_function_t unformat_mpls_protocol_host_byte_order;
 unformat_function_t unformat_mpls_protocol_net_byte_order;
 unformat_function_t unformat_mpls_label_net_byte_order;
-unformat_function_t unformat_mpls_gre_header;
-unformat_function_t unformat_pg_mpls_gre_header;
 unformat_function_t unformat_mpls_unicast_label;
 
 /* Parse mpls header. */
 unformat_function_t unformat_mpls_header;
 unformat_function_t unformat_pg_mpls_header;
 
-/* manually added to the interface output node in mpls.c */
-#define MPLS_GRE_OUTPUT_NEXT_LOOKUP    1
-#define MPLS_GRE_OUTPUT_NEXT_DROP      VNET_INTERFACE_TX_NEXT_DROP
-
 void mpls_sw_interface_enable_disable (mpls_main_t * mm,
                                       u32 sw_if_index,
                                       u8 is_enable);
@@ -239,18 +190,6 @@ u8 mpls_sw_interface_is_enabled (u32 sw_if_index);
 mpls_encap_t *
 mpls_encap_by_fib_and_dest (mpls_main_t * mm, u32 rx_fib, u32 dst_address);
 
-int mpls_label_from_fib_id_and_dest (mpls_main_t *gm, u32 fib_id,
-                                     u32 dst_address, u32 *labelp);
-
-int vnet_mpls_gre_add_del_tunnel (ip4_address_t *src,
-                                  ip4_address_t *dst,
-                                  ip4_address_t *intfc,
-                                  u32 mask_width,
-                                  u32 inner_fib_id, u32 outer_fib_id,
-                                  u32 * tunnel_intfc_sw_if_index,
-                                  u8 l2_only,
-                                  u8 is_add);
-
 int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
                                        ip4_address_t *intfc,
                                        u32 mask_width,
@@ -260,15 +199,8 @@ int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
                                        u8 l2_only,
                                        u8 is_add);
 
-int vnet_mpls_gre_delete_fib_tunnels (u32 fib_id);
-
 int mpls_fib_reset_labels (u32 fib_id);
 
-int vnet_mpls_add_del_decap (u32 rx_fib_id,
-                             u32 tx_fib_id,
-                             u32 label_host_byte_order,
-                             int s_bit, int next_index, int is_add);
-
 int vnet_mpls_add_del_encap (ip4_address_t *dest, u32 fib_id,
                              u32 *labels_host_byte_order,
                              u32 policy_tunnel_index,
@@ -278,26 +210,6 @@ int vnet_mpls_policy_tunnel_add_rewrite (mpls_main_t * mm,
                                          mpls_encap_t * e,
                                          u32 policy_tunnel_index);
 
-typedef struct {
-  u32 lookup_miss;
-
-  /* Tunnel-id / index in tunnel vector */
-  u32 tunnel_id;
-
-  /* mpls encap index */
-  u32 mpls_encap_index;
-
-  /* pkt length */
-  u32 length;
-
-  /* tunnel ip4 addresses */
-  ip4_address_t src;
-  ip4_address_t dst;
-} mpls_gre_tx_trace_t;
-
-u8 * format_mpls_gre_tx_trace (u8 * s, va_list * args);
-u8 * format_mpls_gre_header (u8 * s, va_list * args);
-
 #define foreach_mpls_input_next                        \
 _(DROP, "error-drop")                           \
 _(LOOKUP, "mpls-lookup")
@@ -369,4 +281,4 @@ mpls_fib_index_cmp(void * a1, void * a2);
 int
 mpls_label_cmp(void * a1, void * a2);
 
-#endif /* included_vnet_mpls_gre_h */
+#endif /* included_vnet_mpls_h */
index 31ad68c..9d29cec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * node.c: mpls-o-gre decap processing
+ * mpls_lookup.c: MPLS lookup
  *
  * Copyright (c) 2012-2014 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -167,9 +167,9 @@ VLIB_REGISTER_NODE (mpls_lookup_node) = {
 
   .sibling_of = "ip4-lookup",
 
-  .format_buffer = format_mpls_gre_header_with_length,
+  .format_buffer = format_mpls_header,
   .format_trace = format_mpls_lookup_trace,
-  .unformat_buffer = unformat_mpls_gre_header,
+  .unformat_buffer = unformat_mpls_header,
 };
 
 VLIB_NODE_FUNCTION_MULTIARCH (mpls_lookup_node, mpls_lookup)
index 1d5d182..739e85d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <vlib/vlib.h>
 #include <vnet/pg/pg.h>
+#include <vnet/ip/ip.h>
 #include <vnet/mpls/mpls.h>
 
 typedef struct {
index 1b435f3..5b8f256 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * node.c: mpls-o-gre decap processing
+ * node.c: MPLS input
  *
  * Copyright (c) 2012-2014 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
index f04b530..6ff86e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * pg.c: packet generator mpls/gre interface
+ * pg.c: packet generator mpls interface
  *
  * Copyright (c) 2012 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
index 278e8e6..d48a153 100644 (file)
@@ -18,6 +18,7 @@
 #include <vlib/vlib.h>
 #include <vnet/pg/pg.h>
 #include <vnet/mpls/mpls.h>
+#include <vnet/classify/vnet_classify.h>
 
 typedef struct {
   u32 next_index;
index 71c6f24..0e55732 100644 (file)
@@ -1093,40 +1093,6 @@ static void vl_api_add_node_next_reply_t_handler_json
   vam->result_ready = 1;
 }
 
-static void vl_api_mpls_gre_add_del_tunnel_reply_t_handler
-  (vl_api_mpls_gre_add_del_tunnel_reply_t * mp)
-{
-  vat_main_t *vam = &vat_main;
-  i32 retval = ntohl (mp->retval);
-  u32 sw_if_index = ntohl (mp->tunnel_sw_if_index);
-
-  if (retval >= 0 && sw_if_index != (u32) ~ 0)
-    {
-      errmsg ("tunnel_sw_if_index %d\n", sw_if_index);
-    }
-  vam->retval = retval;
-  vam->result_ready = 1;
-}
-
-static void vl_api_mpls_gre_add_del_tunnel_reply_t_handler_json
-  (vl_api_mpls_gre_add_del_tunnel_reply_t * mp)
-{
-  vat_main_t *vam = &vat_main;
-  vat_json_node_t node;
-
-  vat_json_init_object (&node);
-  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
-  vat_json_object_add_uint (&node, "tunnel_sw_if_index",
-                           ntohl (mp->tunnel_sw_if_index));
-
-  vat_json_print (vam->ofp, &node);
-  vat_json_free (&node);
-
-  vam->retval = ntohl (mp->retval);
-  vam->result_ready = 1;
-}
-
-
 static void vl_api_show_version_reply_t_handler
   (vl_api_show_version_reply_t * mp)
 {
@@ -3518,10 +3484,11 @@ _(bridge_domain_add_del_reply)                          \
 _(sw_interface_set_l2_xconnect_reply)                   \
 _(l2fib_add_del_reply)                                  \
 _(ip_add_del_route_reply)                               \
+_(mpls_route_add_del_reply)                             \
+_(mpls_ip_bind_unbind_reply)                            \
 _(proxy_arp_add_del_reply)                              \
 _(proxy_arp_intfc_enable_disable_reply)                 \
 _(mpls_add_del_encap_reply)                             \
-_(mpls_add_del_decap_reply)                             \
 _(mpls_ethernet_add_del_tunnel_2_reply)                 \
 _(sw_interface_set_unnumbered_reply)                    \
 _(ip_neighbor_add_del_reply)                            \
@@ -3676,12 +3643,12 @@ _(TAP_MODIFY_REPLY, tap_modify_reply)                                   \
 _(TAP_DELETE_REPLY, tap_delete_reply)                                  \
 _(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details)                   \
 _(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply)                      \
+_(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                  \
+_(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                        \
 _(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply)                     \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY,                                 \
   proxy_arp_intfc_enable_disable_reply)                                 \
 _(MPLS_ADD_DEL_ENCAP_REPLY, mpls_add_del_encap_reply)                   \
-_(MPLS_ADD_DEL_DECAP_REPLY, mpls_add_del_decap_reply)                   \
-_(MPLS_GRE_ADD_DEL_TUNNEL_REPLY, mpls_gre_add_del_tunnel_reply)         \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,                                   \
   mpls_ethernet_add_del_tunnel_reply)                                   \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY,                                 \
@@ -3815,10 +3782,9 @@ _(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \
 _(POLICER_CLASSIFY_DETAILS, policer_classify_details)                   \
 _(NETMAP_CREATE_REPLY, netmap_create_reply)                             \
 _(NETMAP_DELETE_REPLY, netmap_delete_reply)                             \
-_(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details)                     \
 _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details)                     \
 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details)                       \
-_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details)                       \
+_(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
 _(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply)                   \
 _(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
 _(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply)                 \
@@ -5752,7 +5718,7 @@ api_ip_add_del_route (vat_main_t * vam)
   u8 is_multipath = 0;
   u8 address_set = 0;
   u8 address_length_set = 0;
-  u32 lookup_in_vrf = 0;
+  u32 next_hop_table_id = 0;
   u32 resolve_attempts = 0;
   u32 dst_address_length = 0;
   u8 next_hop_set = 0;
@@ -5768,6 +5734,7 @@ api_ip_add_del_route (vat_main_t * vam)
   u32 classify_table_index = ~0;
   u8 is_classify = 0;
   u8 resolve_host = 0, resolve_attached = 0;
+  mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
 
   /* Parse args required to build the message */
   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
@@ -5835,7 +5802,11 @@ api_ip_add_del_route (vat_main_t * vam)
        create_vrf_if_needed = 1;
       else if (unformat (i, "count %d", &count))
        ;
-      else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
+      else if (unformat (i, "lookup-in-vrf %d", &next_hop_table_id))
+       ;
+      else if (unformat (i, "next-hop-table %d", &next_hop_table_id))
+       ;
+      else if (unformat (i, "out-label %d", &next_hop_out_label))
        ;
       else if (unformat (i, "random"))
        random_add_del = 1;
@@ -5909,7 +5880,7 @@ api_ip_add_del_route (vat_main_t * vam)
       M (IP_ADD_DEL_ROUTE, ip_add_del_route);
 
       mp->next_hop_sw_if_index = ntohl (sw_if_index);
-      mp->vrf_id = ntohl (vrf_id);
+      mp->table_id = ntohl (vrf_id);
       if (resolve_attempts > 0)
        {
          mp->resolve_attempts = ntohl (resolve_attempts);
@@ -5928,8 +5899,9 @@ api_ip_add_del_route (vat_main_t * vam)
       mp->not_last = not_last;
       mp->next_hop_weight = next_hop_weight;
       mp->dst_address_length = dst_address_length;
-      mp->lookup_in_vrf = ntohl (lookup_in_vrf);
+      mp->next_hop_table_id = ntohl (next_hop_table_id);
       mp->classify_table_index = ntohl (classify_table_index);
+      mp->next_hop_out_label = ntohl (next_hop_out_label);
 
       if (is_ipv6)
        {
@@ -6006,6 +5978,299 @@ api_ip_add_del_route (vat_main_t * vam)
   return (vam->retval);
 }
 
+static int
+api_mpls_route_add_del (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_mpls_route_add_del_t *mp;
+  f64 timeout;
+  u32 sw_if_index = ~0, table_id = 0;
+  u8 create_table_if_needed = 0;
+  u8 is_add = 1;
+  u8 next_hop_weight = 1;
+  u8 is_multipath = 0;
+  u32 next_hop_table_id = 0;
+  u8 next_hop_set = 0;
+  ip4_address_t v4_next_hop_address = {
+    .as_u32 = 0,
+  };
+  ip6_address_t v6_next_hop_address = { {0} };
+  int count = 1;
+  int j;
+  f64 before = 0;
+  u32 classify_table_index = ~0;
+  u8 is_classify = 0;
+  u8 resolve_host = 0, resolve_attached = 0;
+  mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
+  mpls_label_t local_label = MPLS_LABEL_INVALID;
+  u8 is_eos = 1;
+  u8 next_hop_proto_is_ip4 = 1;
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+       ;
+      else if (unformat (i, "sw_if_index %d", &sw_if_index))
+       ;
+      else if (unformat (i, "%d", &local_label))
+       ;
+      else if (unformat (i, "eos"))
+       is_eos = 1;
+      else if (unformat (i, "non-eos"))
+       is_eos = 0;
+      else if (unformat (i, "via %U", unformat_ip4_address,
+                        &v4_next_hop_address))
+       {
+         next_hop_set = 1;
+         next_hop_proto_is_ip4 = 1;
+       }
+      else if (unformat (i, "via %U", unformat_ip6_address,
+                        &v6_next_hop_address))
+       {
+         next_hop_set = 1;
+         next_hop_proto_is_ip4 = 0;
+       }
+      else if (unformat (i, "weight %d", &next_hop_weight))
+       ;
+      else if (unformat (i, "create-table"))
+       create_table_if_needed = 1;
+      else if (unformat (i, "classify %d", &classify_table_index))
+       {
+         is_classify = 1;
+       }
+      else if (unformat (i, "del"))
+       is_add = 0;
+      else if (unformat (i, "add"))
+       is_add = 1;
+      else if (unformat (i, "resolve-via-host"))
+       resolve_host = 1;
+      else if (unformat (i, "resolve-via-attached"))
+       resolve_attached = 1;
+      else if (unformat (i, "multipath"))
+       is_multipath = 1;
+      else if (unformat (i, "count %d", &count))
+       ;
+      else if (unformat (i, "lookup-in-ip4-table %d", &next_hop_table_id))
+       {
+         next_hop_set = 1;
+         next_hop_proto_is_ip4 = 1;
+       }
+      else if (unformat (i, "lookup-in-ip6-table %d", &next_hop_table_id))
+       {
+         next_hop_set = 1;
+         next_hop_proto_is_ip4 = 0;
+       }
+      else if (unformat (i, "next-hop-table %d", &next_hop_table_id))
+       ;
+      else if (unformat (i, "out-label %d", &next_hop_out_label))
+       ;
+      else
+       {
+         clib_warning ("parse error '%U'", format_unformat_error, i);
+         return -99;
+       }
+    }
+
+  if (!next_hop_set && !is_classify)
+    {
+      errmsg ("next hop / classify not set\n");
+      return -99;
+    }
+
+  if (MPLS_LABEL_INVALID == local_label)
+    {
+      errmsg ("missing label\n");
+      return -99;
+    }
+
+  if (count > 1)
+    {
+      /* Turn on async mode */
+      vam->async_mode = 1;
+      vam->async_errors = 0;
+      before = vat_time_now (vam);
+    }
+
+  for (j = 0; j < count; j++)
+    {
+      /* Construct the API message */
+      M (MPLS_ROUTE_ADD_DEL, mpls_route_add_del);
+
+      mp->mr_next_hop_sw_if_index = ntohl (sw_if_index);
+      mp->mr_table_id = ntohl (table_id);
+      mp->mr_create_table_if_needed = create_table_if_needed;
+
+      mp->mr_is_add = is_add;
+      mp->mr_next_hop_proto_is_ip4 = next_hop_proto_is_ip4;
+      mp->mr_is_classify = is_classify;
+      mp->mr_is_multipath = is_multipath;
+      mp->mr_is_resolve_host = resolve_host;
+      mp->mr_is_resolve_attached = resolve_attached;
+      mp->mr_next_hop_weight = next_hop_weight;
+      mp->mr_next_hop_table_id = ntohl (next_hop_table_id);
+      mp->mr_classify_table_index = ntohl (classify_table_index);
+      mp->mr_next_hop_out_label = ntohl (next_hop_out_label);
+      mp->mr_label = ntohl (local_label);
+      mp->mr_eos = is_eos;
+
+      if (next_hop_set)
+       {
+         if (next_hop_proto_is_ip4)
+           {
+             clib_memcpy (mp->mr_next_hop,
+                          &v4_next_hop_address,
+                          sizeof (v4_next_hop_address));
+           }
+         else
+           {
+             clib_memcpy (mp->mr_next_hop,
+                          &v6_next_hop_address,
+                          sizeof (v6_next_hop_address));
+           }
+       }
+      local_label++;
+
+      /* send it... */
+      S;
+      /* If we receive SIGTERM, stop now... */
+      if (vam->do_exit)
+       break;
+    }
+
+  /* When testing multiple add/del ops, use a control-ping to sync */
+  if (count > 1)
+    {
+      vl_api_control_ping_t *mp;
+      f64 after;
+
+      /* Shut off async mode */
+      vam->async_mode = 0;
+
+      M (CONTROL_PING, control_ping);
+      S;
+
+      timeout = vat_time_now (vam) + 1.0;
+      while (vat_time_now (vam) < timeout)
+       if (vam->result_ready == 1)
+         goto out;
+      vam->retval = -99;
+
+    out:
+      if (vam->retval == -99)
+       errmsg ("timeout\n");
+
+      if (vam->async_errors > 0)
+       {
+         errmsg ("%d asynchronous errors\n", vam->async_errors);
+         vam->retval = -98;
+       }
+      vam->async_errors = 0;
+      after = vat_time_now (vam);
+
+      /* slim chance, but we might have eaten SIGTERM on the first iteration */
+      if (j > 0)
+       count = j;
+
+      fformat (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
+              count, after - before, count / (after - before));
+    }
+  else
+    {
+      /* Wait for a reply... */
+      W;
+    }
+
+  /* Return the good/bad news */
+  return (vam->retval);
+}
+
+static int
+api_mpls_ip_bind_unbind (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_mpls_ip_bind_unbind_t *mp;
+  f64 timeout;
+  u32 ip_table_id = 0;
+  u8 create_table_if_needed = 0;
+  u8 is_bind = 1;
+  u8 is_ip4 = 1;
+  ip4_address_t v4_address;
+  ip6_address_t v6_address;
+  u32 address_length;
+  u8 address_set = 0;
+  mpls_label_t local_label = MPLS_LABEL_INVALID;
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "%U/%d", unformat_ip4_address,
+                   &v4_address, &address_length))
+       {
+         is_ip4 = 1;
+         address_set = 1;
+       }
+      else if (unformat (i, "%U/%d", unformat_ip6_address,
+                        &v6_address, &address_length))
+       {
+         is_ip4 = 0;
+         address_set = 1;
+       }
+      else if (unformat (i, "%d", &local_label))
+       ;
+      else if (unformat (i, "create-table"))
+       create_table_if_needed = 1;
+      else if (unformat (i, "table-id %d", &ip_table_id))
+       ;
+      else if (unformat (i, "unbind"))
+       is_bind = 0;
+      else if (unformat (i, "bind"))
+       is_bind = 1;
+      else
+       {
+         clib_warning ("parse error '%U'", format_unformat_error, i);
+         return -99;
+       }
+    }
+
+  if (!address_set)
+    {
+      errmsg ("IP addres not set\n");
+      return -99;
+    }
+
+  if (MPLS_LABEL_INVALID == local_label)
+    {
+      errmsg ("missing label\n");
+      return -99;
+    }
+
+  /* Construct the API message */
+  M (MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind);
+
+  mp->mb_create_table_if_needed = create_table_if_needed;
+  mp->mb_is_bind = is_bind;
+  mp->mb_is_ip4 = is_ip4;
+  mp->mb_ip_table_id = ntohl (ip_table_id);
+  mp->mb_mpls_table_id = 0;
+  mp->mb_label = ntohl (local_label);
+  mp->mb_address_length = address_length;
+
+  if (is_ip4)
+    clib_memcpy (mp->mb_address, &v4_address, sizeof (v4_address));
+  else
+    clib_memcpy (mp->mb_address, &v6_address, sizeof (v6_address));
+
+  /* send it... */
+  S;
+
+  /* Wait for a reply... */
+  W;
+
+  /* Return the good/bad news */
+  return (vam->retval);
+}
+
 static int
 api_proxy_arp_add_del (vat_main_t * vam)
 {
@@ -6096,55 +6361,6 @@ api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
   return 0;
 }
 
-static int
-api_mpls_add_del_decap (vat_main_t * vam)
-{
-  unformat_input_t *i = vam->input;
-  vl_api_mpls_add_del_decap_t *mp;
-  f64 timeout;
-  u32 rx_vrf_id = 0;
-  u32 tx_vrf_id = 0;
-  u32 label = 0;
-  u8 is_add = 1;
-  u8 s_bit = 1;
-  u32 next_index = 1;
-
-  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
-       ;
-      else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
-       ;
-      else if (unformat (i, "label %d", &label))
-       ;
-      else if (unformat (i, "next-index %d", &next_index))
-       ;
-      else if (unformat (i, "del"))
-       is_add = 0;
-      else if (unformat (i, "s-bit-clear"))
-       s_bit = 0;
-      else
-       {
-         clib_warning ("parse error '%U'", format_unformat_error, i);
-         return -99;
-       }
-    }
-
-  M (MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
-
-  mp->rx_vrf_id = ntohl (rx_vrf_id);
-  mp->tx_vrf_id = ntohl (tx_vrf_id);
-  mp->label = ntohl (label);
-  mp->next_index = ntohl (next_index);
-  mp->s_bit = s_bit;
-  mp->is_add = is_add;
-
-  S;
-  W;
-  /* NOTREACHED */
-  return 0;
-}
-
 static int
 api_mpls_add_del_encap (vat_main_t * vam)
 {
@@ -6197,63 +6413,6 @@ api_mpls_add_del_encap (vat_main_t * vam)
   return 0;
 }
 
-static int
-api_mpls_gre_add_del_tunnel (vat_main_t * vam)
-{
-  unformat_input_t *i = vam->input;
-  vl_api_mpls_gre_add_del_tunnel_t *mp;
-  f64 timeout;
-  u32 inner_vrf_id = 0;
-  u32 outer_vrf_id = 0;
-  ip4_address_t src_address;
-  ip4_address_t dst_address;
-  ip4_address_t intfc_address;
-  u32 tmp;
-  u8 intfc_address_length = 0;
-  u8 is_add = 1;
-  u8 l2_only = 0;
-
-  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
-    {
-      if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
-       ;
-      else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
-       ;
-      else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
-       ;
-      else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
-       ;
-      else if (unformat (i, "adj %U/%d", unformat_ip4_address,
-                        &intfc_address, &tmp))
-       intfc_address_length = tmp;
-      else if (unformat (i, "l2-only"))
-       l2_only = 1;
-      else if (unformat (i, "del"))
-       is_add = 0;
-      else
-       {
-         clib_warning ("parse error '%U'", format_unformat_error, i);
-         return -99;
-       }
-    }
-
-  M (MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
-
-  mp->inner_vrf_id = ntohl (inner_vrf_id);
-  mp->outer_vrf_id = ntohl (outer_vrf_id);
-  clib_memcpy (mp->src_address, &src_address, sizeof (src_address));
-  clib_memcpy (mp->dst_address, &dst_address, sizeof (dst_address));
-  clib_memcpy (mp->intfc_address, &intfc_address, sizeof (intfc_address));
-  mp->intfc_address_length = intfc_address_length;
-  mp->l2_only = l2_only;
-  mp->is_add = is_add;
-
-  S;
-  W;
-  /* NOTREACHED */
-  return 0;
-}
-
 static int
 api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
 {
@@ -14491,117 +14650,6 @@ api_netmap_delete (vat_main_t * vam)
   return 0;
 }
 
-static void vl_api_mpls_gre_tunnel_details_t_handler
-  (vl_api_mpls_gre_tunnel_details_t * mp)
-{
-  vat_main_t *vam = &vat_main;
-  i32 i;
-  i32 len = ntohl (mp->nlabels);
-
-  if (mp->l2_only == 0)
-    {
-      fformat (vam->ofp, "[%d]: src %U, dst %U, adj %U/%d, labels ",
-              ntohl (mp->tunnel_index),
-              format_ip4_address, &mp->tunnel_src,
-              format_ip4_address, &mp->tunnel_dst,
-              format_ip4_address, &mp->intfc_address,
-              ntohl (mp->mask_width));
-      for (i = 0; i < len; i++)
-       {
-         fformat (vam->ofp, "%u ", ntohl (mp->labels[i]));
-       }
-      fformat (vam->ofp, "\n");
-      fformat (vam->ofp, "      inner fib index %d, outer fib index %d\n",
-              ntohl (mp->inner_fib_index), ntohl (mp->outer_fib_index));
-    }
-  else
-    {
-      fformat (vam->ofp, "[%d]: src %U, dst %U, key %U, labels ",
-              ntohl (mp->tunnel_index),
-              format_ip4_address, &mp->tunnel_src,
-              format_ip4_address, &mp->tunnel_dst,
-              format_ip4_address, &mp->intfc_address);
-      for (i = 0; i < len; i++)
-       {
-         fformat (vam->ofp, "%u ", ntohl (mp->labels[i]));
-       }
-      fformat (vam->ofp, "\n");
-      fformat (vam->ofp, "      l2 interface %d, outer fib index %d\n",
-              ntohl (mp->hw_if_index), ntohl (mp->outer_fib_index));
-    }
-}
-
-static void vl_api_mpls_gre_tunnel_details_t_handler_json
-  (vl_api_mpls_gre_tunnel_details_t * mp)
-{
-  vat_main_t *vam = &vat_main;
-  vat_json_node_t *node = NULL;
-  struct in_addr ip4;
-  i32 i;
-  i32 len = ntohl (mp->nlabels);
-
-  if (VAT_JSON_ARRAY != vam->json_tree.type)
-    {
-      ASSERT (VAT_JSON_NONE == vam->json_tree.type);
-      vat_json_init_array (&vam->json_tree);
-    }
-  node = vat_json_array_add (&vam->json_tree);
-
-  vat_json_init_object (node);
-  vat_json_object_add_uint (node, "tunnel_index", ntohl (mp->tunnel_index));
-  clib_memcpy (&ip4, &(mp->intfc_address), sizeof (ip4));
-  vat_json_object_add_ip4 (node, "intfc_address", ip4);
-  vat_json_object_add_uint (node, "inner_fib_index",
-                           ntohl (mp->inner_fib_index));
-  vat_json_object_add_uint (node, "mask_width", ntohl (mp->mask_width));
-  vat_json_object_add_uint (node, "encap_index", ntohl (mp->encap_index));
-  vat_json_object_add_uint (node, "hw_if_index", ntohl (mp->hw_if_index));
-  vat_json_object_add_uint (node, "l2_only", ntohl (mp->l2_only));
-  clib_memcpy (&ip4, &(mp->tunnel_src), sizeof (ip4));
-  vat_json_object_add_ip4 (node, "tunnel_src", ip4);
-  clib_memcpy (&ip4, &(mp->tunnel_dst), sizeof (ip4));
-  vat_json_object_add_ip4 (node, "tunnel_dst", ip4);
-  vat_json_object_add_uint (node, "outer_fib_index",
-                           ntohl (mp->outer_fib_index));
-  vat_json_object_add_uint (node, "label_count", len);
-  for (i = 0; i < len; i++)
-    {
-      vat_json_object_add_uint (node, "label", ntohl (mp->labels[i]));
-    }
-}
-
-static int
-api_mpls_gre_tunnel_dump (vat_main_t * vam)
-{
-  vl_api_mpls_gre_tunnel_dump_t *mp;
-  f64 timeout;
-  i32 index = -1;
-
-  /* Parse args required to build the message */
-  while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT)
-    {
-      if (!unformat (vam->input, "tunnel_index %d", &index))
-       {
-         index = -1;
-         break;
-       }
-    }
-
-  fformat (vam->ofp, "  tunnel_index %d\n", index);
-
-  M (MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump);
-  mp->tunnel_index = htonl (index);
-  S;
-
-  /* Use a control ping for synchronization */
-  {
-    vl_api_control_ping_t *mp;
-    M (CONTROL_PING, control_ping);
-    S;
-  }
-  W;
-}
-
 static void vl_api_mpls_eth_tunnel_details_t_handler
   (vl_api_mpls_eth_tunnel_details_t * mp)
 {
@@ -14755,23 +14803,21 @@ api_mpls_fib_encap_dump (vat_main_t * vam)
   W;
 }
 
-static void vl_api_mpls_fib_decap_details_t_handler
-  (vl_api_mpls_fib_decap_details_t * mp)
+static void
+vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
 {
   vat_main_t *vam = &vat_main;
 
   fformat (vam->ofp,
-          "RX table %d, TX table/intfc %u, swif_tag '%s', label %u, s_bit %u\n",
-          ntohl (mp->rx_table_id), ntohl (mp->tx_table_id), mp->swif_tag,
-          ntohl (mp->label), ntohl (mp->s_bit));
+          "table-id %d, label %u, ess_bit %u\n",
+          ntohl (mp->table_id), ntohl (mp->label), mp->eos_bit);
 }
 
-static void vl_api_mpls_fib_decap_details_t_handler_json
-  (vl_api_mpls_fib_decap_details_t * mp)
+static void vl_api_mpls_fib_details_t_handler_json
+  (vl_api_mpls_fib_details_t * mp)
 {
   vat_main_t *vam = &vat_main;
   vat_json_node_t *node = NULL;
-  struct in_addr ip4;
 
   if (VAT_JSON_ARRAY != vam->json_tree.type)
     {
@@ -14781,24 +14827,18 @@ static void vl_api_mpls_fib_decap_details_t_handler_json
   node = vat_json_array_add (&vam->json_tree);
 
   vat_json_init_object (node);
-  vat_json_object_add_uint (node, "table", ntohl (mp->fib_index));
-  vat_json_object_add_uint (node, "entry_index", ntohl (mp->entry_index));
-  clib_memcpy (&ip4, &(mp->dest), sizeof (ip4));
-  vat_json_object_add_ip4 (node, "dest", ip4);
-  vat_json_object_add_uint (node, "s_bit", ntohl (mp->s_bit));
+  vat_json_object_add_uint (node, "table", ntohl (mp->table_id));
+  vat_json_object_add_uint (node, "s_bit", mp->eos_bit);
   vat_json_object_add_uint (node, "label", ntohl (mp->label));
-  vat_json_object_add_uint (node, "rx_table_id", ntohl (mp->rx_table_id));
-  vat_json_object_add_uint (node, "tx_table_id", ntohl (mp->tx_table_id));
-  vat_json_object_add_string_copy (node, "swif_tag", mp->swif_tag);
 }
 
 static int
-api_mpls_fib_decap_dump (vat_main_t * vam)
+api_mpls_fib_dump (vat_main_t * vam)
 {
-  vl_api_mpls_fib_decap_dump_t *mp;
+  vl_api_mpls_fib_dump_t *mp;
   f64 timeout;
 
-  M (MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump);
+  M (MPLS_FIB_DUMP, mpls_fib_dump);
   S;
 
   /* Use a control ping for synchronization */
@@ -16149,21 +16189,23 @@ _(tap_delete,                                                           \
   "<vpp-if-name> | sw_if_index <id>")                                   \
 _(sw_interface_tap_dump, "")                                            \
 _(ip_add_del_route,                                                     \
-  "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
+  "<addr>/<mask> via <addr> [table-id <n>]\n"                           \
+  "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
+  "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
+  "[multipath] [count <n>]")                                            \
+_(mpls_route_add_del,                                                   \
+  "<label> <eos> via <addr> [table-id <n>]\n"                           \
   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
   "[multipath] [count <n>]")                                            \
+_(mpls_ip_bind_unbind,                                                  \
+  "<label> <addr/len>")                                                 \
 _(proxy_arp_add_del,                                                    \
   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
 _(proxy_arp_intfc_enable_disable,                                       \
   "<intfc> | sw_if_index <id> enable | disable")                        \
 _(mpls_add_del_encap,                                                   \
   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
-_(mpls_add_del_decap,                                                   \
-  "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
-_(mpls_gre_add_del_tunnel,                                              \
-  "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
-  "adj <ip4-address>/<mask-width> [del]")                               \
 _(sw_interface_set_unnumbered,                                          \
   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
 _(ip_neighbor_add_del,                                                  \
@@ -16374,10 +16416,9 @@ _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
 _(netmap_create, "name <interface name> [hw-addr <mac>] [pipe] "        \
     "[master|slave]")                                                   \
 _(netmap_delete, "name <interface name>")                               \
-_(mpls_gre_tunnel_dump, "tunnel_index <tunnel-id>")                     \
 _(mpls_eth_tunnel_dump, "tunnel_index <tunnel-id>")                     \
 _(mpls_fib_encap_dump, "")                                              \
-_(mpls_fib_decap_dump, "")                                              \
+_(mpls_fib_dump, "")                                                    \
 _(classify_table_ids, "")                                               \
 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
 _(classify_table_info, "table_id <nn>")                                 \
index b0e0412..33f8770 100644 (file)
@@ -282,6 +282,8 @@ _(SW_INTERFACE_DUMP, sw_interface_dump)                                 \
 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                       \
 _(IP_ADD_DEL_ROUTE, ip_add_del_route)                                   \
+_(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
+_(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address)           \
 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table)                       \
@@ -305,11 +307,9 @@ _(TAP_DELETE, tap_delete)                                               \
 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump)                         \
 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
 _(CREATE_SUBIF, create_subif)                                           \
-_(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel)                     \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel)           \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2)       \
 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap)                               \
-_(MPLS_ADD_DEL_DECAP, mpls_add_del_decap)                               \
 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del)                             \
@@ -426,14 +426,12 @@ _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
 _(NETMAP_CREATE, netmap_create)                                         \
 _(NETMAP_DELETE, netmap_delete)                                         \
-_(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump)                           \
-_(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details)                     \
 _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump)                           \
 _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details)                     \
 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump)                             \
 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details)                       \
-_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump)                             \
-_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details)                       \
+_(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
+_(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
@@ -1031,44 +1029,57 @@ VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
 /* *INDENT-ON* */
 
 static int
-ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
-                           u32 fib_index,
-                           const fib_prefix_t * prefix,
-                           const ip46_address_t * next_hop,
-                           u32 next_hop_sw_if_index,
-                           u32 next_hop_fib_index, u32 next_hop_weight)
+add_del_route_t_handler (u8 is_multipath,
+                        u8 is_add,
+                        u8 is_drop,
+                        u8 is_local,
+                        u8 is_classify,
+                        u32 classify_table_index,
+                        u8 is_resolve_host,
+                        u8 is_resolve_attached,
+                        u32 fib_index,
+                        const fib_prefix_t * prefix,
+                        u8 next_hop_proto_is_ip4,
+                        const ip46_address_t * next_hop,
+                        u32 next_hop_sw_if_index,
+                        u8 next_hop_fib_index,
+                        u32 next_hop_weight, u32 next_hop_out_label)
 {
   vnet_classify_main_t *cm = &vnet_classify_main;
   fib_protocol_t proto = prefix->fp_proto;
   stats_main_t *sm = &stats_main;
 
-  if (mp->is_multipath)
+  if (is_multipath)
     {
       fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
 
       dslock (sm, 1 /* release hint */ , 10 /* tag */ );
 
-      if (mp->is_resolve_host)
+      if (is_resolve_host)
        path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
-      if (mp->is_resolve_attached)
+      if (is_resolve_attached)
        path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
 
-      if (mp->is_add)
+      if (is_add)
        fib_table_entry_path_add (fib_index,
                                  prefix,
                                  FIB_SOURCE_API,
                                  FIB_ENTRY_FLAG_NONE,
-                                 prefix->fp_proto,
+                                 (next_hop_proto_is_ip4 ?
+                                  FIB_PROTOCOL_IP4 :
+                                  FIB_PROTOCOL_IP6),
                                  next_hop,
                                  next_hop_sw_if_index,
                                  next_hop_fib_index,
                                  next_hop_weight,
-                                 MPLS_LABEL_INVALID, path_flags);
+                                 next_hop_out_label, path_flags);
       else
        fib_table_entry_path_remove (fib_index,
                                     prefix,
                                     FIB_SOURCE_API,
-                                    prefix->fp_proto,
+                                    (next_hop_proto_is_ip4 ?
+                                     FIB_PROTOCOL_IP4 :
+                                     FIB_PROTOCOL_IP6),
                                     next_hop,
                                     next_hop_sw_if_index,
                                     next_hop_fib_index,
@@ -1080,26 +1091,26 @@ ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
 
   dslock (sm, 1 /* release hint */ , 2 /* tag */ );
 
-  if (mp->is_drop || mp->is_local || mp->is_classify || mp->lookup_in_vrf)
+  if (is_drop || is_local || is_classify)
     {
       /*
        * special route types that link directly to the adj
        */
-      if (mp->is_add)
+      if (is_add)
        {
          dpo_id_t dpo = DPO_NULL;
          dpo_proto_t dproto;
 
          dproto = fib_proto_to_dpo (prefix->fp_proto);
 
-         if (mp->is_drop)
+         if (is_drop)
            dpo_copy (&dpo, drop_dpo_get (dproto));
-         else if (mp->is_local)
+         else if (is_local)
            receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
-         else if (mp->is_classify)
+         else if (is_classify)
            {
              if (pool_is_free_index (cm->tables,
-                                     ntohl (mp->classify_table_index)))
+                                     ntohl (classify_table_index)))
                {
                  dsunlock (sm);
                  return VNET_API_ERROR_NO_SUCH_TABLE;
@@ -1107,25 +1118,7 @@ ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
 
              dpo_set (&dpo, DPO_CLASSIFY, proto,
                       classify_dpo_create (prefix->fp_proto,
-                                           ntohl
-                                           (mp->classify_table_index)));
-           }
-         else if (mp->lookup_in_vrf)
-           {
-             next_hop_fib_index =
-               fib_table_id_find_fib_index (dproto,
-                                            ntohl (mp->lookup_in_vrf));
-             if (~0 == next_hop_fib_index)
-               {
-                 dsunlock (sm);
-                 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-               }
-
-             lookup_dpo_add_or_lock_w_fib_index (next_hop_fib_index,
-                                                 dproto,
-                                                 LOOKUP_INPUT_DST_ADDR,
-                                                 LOOKUP_TABLE_FROM_CONFIG,
-                                                 &dpo);
+                                           ntohl (classify_table_index)));
            }
          else
            {
@@ -1146,25 +1139,27 @@ ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
     }
   else
     {
-      if (mp->is_add)
+      if (is_add)
        {
          fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
 
-         if (mp->is_resolve_host)
+         if (is_resolve_host)
            path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
-         if (mp->is_resolve_attached)
+         if (is_resolve_attached)
            path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
 
          fib_table_entry_update_one_path (fib_index,
                                           prefix,
                                           FIB_SOURCE_API,
                                           FIB_ENTRY_FLAG_NONE,
-                                          prefix->fp_proto,
+                                          (next_hop_proto_is_ip4 ?
+                                           FIB_PROTOCOL_IP4 :
+                                           FIB_PROTOCOL_IP6),
                                           next_hop,
                                           next_hop_sw_if_index,
                                           next_hop_fib_index,
                                           next_hop_weight,
-                                          MPLS_LABEL_INVALID, path_flags);
+                                          next_hop_out_label, path_flags);
        }
       else
        {
@@ -1177,19 +1172,23 @@ ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
 }
 
 static int
-ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
+add_del_route_check (fib_protocol_t table_proto,
+                    u32 table_id,
+                    u32 next_hop_sw_if_index,
+                    fib_protocol_t next_hop_table_proto,
+                    u32 next_hop_table_id,
+                    u8 create_missing_tables,
+                    u32 * fib_index, u32 * next_hop_fib_index)
 {
-  vpe_api_main_t *vam = &vpe_api_main;
-  vnet_main_t *vnm = vam->vnet_main;
-  u32 fib_index;
+  vnet_main_t *vnm = vnet_get_main ();
 
-  fib_index = ip4_fib_index_from_table_id (ntohl (mp->vrf_id));
-  if (~0 == fib_index)
+  *fib_index = fib_table_find (table_proto, ntohl (table_id));
+  if (~0 == *fib_index)
     {
-      if (mp->create_vrf_if_needed)
+      if (create_missing_tables)
        {
-         fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                        ntohl (mp->vrf_id));
+         *fib_index = fib_table_find_or_create_and_lock (table_proto,
+                                                         ntohl (table_id));
        }
       else
        {
@@ -1198,10 +1197,54 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
        }
     }
 
-  if (~0 != ntohl (mp->next_hop_sw_if_index) &&
-      pool_is_free_index (vnm->interface_main.sw_interfaces,
-                         ntohl (mp->next_hop_sw_if_index)))
-    return VNET_API_ERROR_NO_MATCHING_INTERFACE;
+  if (~0 != ntohl (next_hop_sw_if_index))
+    {
+      if (pool_is_free_index (vnm->interface_main.sw_interfaces,
+                             ntohl (next_hop_sw_if_index)))
+       {
+         return VNET_API_ERROR_NO_MATCHING_INTERFACE;
+       }
+    }
+  else
+    {
+      *next_hop_fib_index = fib_table_find (next_hop_table_proto,
+                                           ntohl (next_hop_table_id));
+
+      if (~0 == *next_hop_fib_index)
+       {
+         if (create_missing_tables)
+           {
+             *next_hop_fib_index =
+               fib_table_find_or_create_and_lock (next_hop_table_proto,
+                                                  ntohl (next_hop_table_id));
+           }
+         else
+           {
+             /* No such VRF, and we weren't asked to create one */
+             return VNET_API_ERROR_NO_SUCH_FIB;
+           }
+       }
+    }
+
+  return (0);
+}
+
+static int
+ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
+{
+  u32 fib_index, next_hop_fib_index;
+  int rv;
+
+  rv = add_del_route_check (FIB_PROTOCOL_IP4,
+                           mp->table_id,
+                           mp->next_hop_sw_if_index,
+                           FIB_PROTOCOL_IP4,
+                           mp->next_hop_table_id,
+                           mp->create_vrf_if_needed,
+                           &fib_index, &next_hop_fib_index);
+
+  if (0 != rv)
+    return (rv);
 
   fib_prefix_t pfx = {
     .fp_len = mp->dst_address_length,
@@ -1213,50 +1256,109 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
   memset (&nh, 0, sizeof (nh));
   memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
 
-  return (ip_add_del_route_t_handler (mp, fib_index, &pfx, &nh,
-                                     ntohl (mp->next_hop_sw_if_index),
-                                     fib_index, (u32) mp->next_hop_weight));
+  return (add_del_route_t_handler (mp->is_multipath, mp->is_add, mp->is_drop, mp->is_local, mp->is_classify, mp->classify_table_index, mp->is_resolve_host, mp->is_resolve_attached, fib_index, &pfx, 1,       // is_ip4
+                                  &nh,
+                                  ntohl (mp->next_hop_sw_if_index),
+                                  next_hop_fib_index,
+                                  mp->next_hop_weight,
+                                  ntohl (mp->next_hop_out_label)));
 }
 
 static int
 ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
 {
-  vnet_main_t *vnm = vnet_get_main ();
-  u32 fib_index;
+  u32 fib_index, next_hop_fib_index;
+  int rv;
+
+  rv = add_del_route_check (FIB_PROTOCOL_IP6,
+                           mp->table_id,
+                           mp->next_hop_sw_if_index,
+                           FIB_PROTOCOL_IP6,
+                           mp->next_hop_table_id,
+                           mp->create_vrf_if_needed,
+                           &fib_index, &next_hop_fib_index);
+
+  if (0 != rv)
+    return (rv);
+
+  fib_prefix_t pfx = {
+    .fp_len = mp->dst_address_length,
+    .fp_proto = FIB_PROTOCOL_IP6,
+  };
+  clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
+
+  ip46_address_t nh;
+  memset (&nh, 0, sizeof (nh));
+  memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
+
+  return (add_del_route_t_handler (mp->is_multipath, mp->is_add, mp->is_drop, mp->is_local, mp->is_classify, mp->classify_table_index, mp->is_resolve_host, mp->is_resolve_attached, fib_index, &pfx, 0,       // is_ip4
+                                  &nh, ntohl (mp->next_hop_sw_if_index),
+                                  next_hop_fib_index,
+                                  mp->next_hop_weight,
+                                  ntohl (mp->next_hop_out_label)));
+}
+
+static int
+mpls_route_add_del_t_handler (vnet_main_t * vnm,
+                             vl_api_mpls_route_add_del_t * mp)
+{
+  u32 fib_index, next_hop_fib_index;
 
-  fib_index = ip6_fib_index_from_table_id (ntohl (mp->vrf_id));
-  if (~0 == fib_index)
+  int rv;
+
+  fib_prefix_t pfx = {
+    .fp_len = 21,
+    .fp_proto = FIB_PROTOCOL_MPLS,
+    .fp_eos = mp->mr_eos,
+    .fp_label = ntohl (mp->mr_label),
+  };
+  if (pfx.fp_eos)
     {
-      if (mp->create_vrf_if_needed)
+      if (mp->mr_next_hop_proto_is_ip4)
        {
-         fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                        ntohl (mp->vrf_id));
+         pfx.fp_payload_proto = DPO_PROTO_IP4;
        }
       else
        {
-         /* No such VRF, and we weren't asked to create one */
-         return VNET_API_ERROR_NO_SUCH_FIB;
+         pfx.fp_payload_proto = DPO_PROTO_IP6;
        }
     }
+  else
+    {
+      pfx.fp_payload_proto = DPO_PROTO_MPLS;
+    }
 
-  if (~0 != ntohl (mp->next_hop_sw_if_index) &&
-      pool_is_free_index (vnm->interface_main.sw_interfaces,
-                         ntohl (mp->next_hop_sw_if_index)))
-    return VNET_API_ERROR_NO_MATCHING_INTERFACE;
+  rv = add_del_route_check (FIB_PROTOCOL_MPLS,
+                           mp->mr_table_id,
+                           mp->mr_next_hop_sw_if_index,
+                           dpo_proto_to_fib (pfx.fp_payload_proto),
+                           mp->mr_next_hop_table_id,
+                           mp->mr_create_table_if_needed,
+                           &fib_index, &next_hop_fib_index);
 
-  fib_prefix_t pfx = {
-    .fp_len = mp->dst_address_length,
-    .fp_proto = FIB_PROTOCOL_IP6,
-  };
-  clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
+  if (0 != rv)
+    return (rv);
 
   ip46_address_t nh;
   memset (&nh, 0, sizeof (nh));
-  memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
 
-  return (ip_add_del_route_t_handler (mp, fib_index, &pfx,
-                                     &nh, ntohl (mp->next_hop_sw_if_index),
-                                     fib_index, (u32) mp->next_hop_weight));
+  if (mp->mr_next_hop_proto_is_ip4)
+    memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
+  else
+    memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
+
+  return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,      // mp->is_drop,
+                                  0,   // mp->is_local,
+                                  mp->mr_is_classify,
+                                  mp->mr_classify_table_index,
+                                  mp->mr_is_resolve_host,
+                                  mp->mr_is_resolve_attached,
+                                  fib_index, &pfx,
+                                  mp->mr_next_hop_proto_is_ip4,
+                                  &nh, ntohl (mp->mr_next_hop_sw_if_index),
+                                  next_hop_fib_index,
+                                  mp->mr_next_hop_weight,
+                                  ntohl (mp->mr_next_hop_out_label)));
 }
 
 void
@@ -1278,6 +1380,95 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
   REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
 }
 
+void
+vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
+{
+  vl_api_mpls_route_add_del_reply_t *rmp;
+  vnet_main_t *vnm;
+  int rv;
+
+  vnm = vnet_get_main ();
+  vnm->api_errno = 0;
+
+  rv = mpls_route_add_del_t_handler (vnm, mp);
+
+  rv = (rv == 0) ? vnm->api_errno : rv;
+
+  REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
+}
+
+static int
+mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
+                            vl_api_mpls_ip_bind_unbind_t * mp)
+{
+  u32 mpls_fib_index, ip_fib_index;
+
+  mpls_fib_index =
+    fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
+
+  if (~0 == mpls_fib_index)
+    {
+      if (mp->mb_create_table_if_needed)
+       {
+         mpls_fib_index =
+           fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
+                                              ntohl (mp->mb_mpls_table_id));
+       }
+      else
+       return VNET_API_ERROR_NO_SUCH_FIB;
+    }
+
+  ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
+                                 FIB_PROTOCOL_IP4 :
+                                 FIB_PROTOCOL_IP6),
+                                ntohl (mp->mb_ip_table_id));
+  if (~0 == ip_fib_index)
+    return VNET_API_ERROR_NO_SUCH_FIB;
+
+  fib_prefix_t pfx = {
+    .fp_len = mp->mb_address_length,
+  };
+
+  if (mp->mb_is_ip4)
+    {
+      pfx.fp_proto = FIB_PROTOCOL_IP4;
+      clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
+                  sizeof (pfx.fp_addr.ip4));
+    }
+  else
+    {
+      pfx.fp_proto = FIB_PROTOCOL_IP6;
+      clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
+                  sizeof (pfx.fp_addr.ip6));
+    }
+
+  if (mp->mb_is_bind)
+    fib_table_entry_local_label_add (ip_fib_index, &pfx,
+                                    ntohl (mp->mb_label));
+  else
+    fib_table_entry_local_label_remove (ip_fib_index, &pfx,
+                                       ntohl (mp->mb_label));
+
+  return (0);
+}
+
+void
+vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
+{
+  vl_api_mpls_route_add_del_reply_t *rmp;
+  vnet_main_t *vnm;
+  int rv;
+
+  vnm = vnet_get_main ();
+  vnm->api_errno = 0;
+
+  rv = mpls_ip_bind_unbind_handler (vnm, mp);
+
+  rv = (rv == 0) ? vnm->api_errno : rv;
+
+  REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
+}
+
 static void
   vl_api_sw_interface_add_del_address_t_handler
   (vl_api_sw_interface_add_del_address_t * mp)
@@ -2168,35 +2359,6 @@ out:
   /* *INDENT-ON* */
 }
 
-static void
-vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t *
-                                         mp)
-{
-  vl_api_mpls_gre_add_del_tunnel_reply_t *rmp;
-  int rv = 0;
-  stats_main_t *sm = &stats_main;
-  u32 tunnel_sw_if_index = ~0;
-
-  dslock (sm, 1 /* release hint */ , 5 /* tag */ );
-
-  rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *) (mp->src_address),
-                                    (ip4_address_t *) (mp->dst_address),
-                                    (ip4_address_t *) (mp->intfc_address),
-                                    (u32) (mp->intfc_address_length),
-                                    ntohl (mp->inner_vrf_id),
-                                    ntohl (mp->outer_vrf_id),
-                                    &tunnel_sw_if_index,
-                                    mp->l2_only, mp->is_add);
-  dsunlock (sm);
-
-  /* *INDENT-OFF* */
-  REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
-  ({
-    rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
-  }));
-  /* *INDENT-ON* */
-}
-
 static void
   vl_api_mpls_ethernet_add_del_tunnel_t_handler
   (vl_api_mpls_ethernet_add_del_tunnel_t * mp)
@@ -2363,19 +2525,6 @@ vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t * mp)
   REPLY_MACRO (VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
 }
 
-static void
-vl_api_mpls_add_del_decap_t_handler (vl_api_mpls_add_del_decap_t * mp)
-{
-  vl_api_mpls_add_del_decap_reply_t *rmp;
-  int rv;
-
-  rv = vnet_mpls_add_del_decap (ntohl (mp->rx_vrf_id), ntohl (mp->tx_vrf_id),
-                               ntohl (mp->label), ntohl (mp->next_index),
-                               mp->s_bit, mp->is_add);
-
-  REPLY_MACRO (VL_API_MPLS_ADD_DEL_DECAP_REPLY);
-}
-
 static void
 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
 {
@@ -2967,9 +3116,6 @@ ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
     if (fib->table_id != target_fib_id)
       continue;
 
-    /* remove any mpls/gre tunnels in this fib */
-    vnet_mpls_gre_delete_fib_tunnels (fib->table_id);
-
     /* remove any mpls encap/decap labels */
     mpls_fib_reset_labels (fib->table_id);
 
@@ -7387,41 +7533,40 @@ vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp)
 }
 
 static void
-vl_api_mpls_gre_tunnel_details_t_handler (vl_api_mpls_gre_tunnel_details_t *
+vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t *
                                          mp)
 {
   clib_warning ("BUG");
 }
 
 static void
-send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
+send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
                            unix_shared_memory_queue_t * q,
-                           mpls_gre_tunnel_t * gt, u32 index, u32 context)
+                           mpls_eth_tunnel_t * et, u32 index, u32 context)
 {
-  vl_api_mpls_gre_tunnel_details_t *mp;
   mpls_main_t *mm = &mpls_main;
   mpls_encap_t *e;
   int i;
   u32 nlabels;
+  vl_api_mpls_eth_tunnel_details_t *mp;
 
-  e = pool_elt_at_index (mm->encaps, gt->encap_index);
+  e = pool_elt_at_index (mm->encaps, et->encap_index);
   nlabels = vec_len (e->labels);
 
   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
   memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_TUNNEL_DETAILS);
+  mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
   mp->context = context;
 
   mp->tunnel_index = htonl (index);
-  mp->tunnel_src = gt->tunnel_src.as_u32;
-  mp->tunnel_dst = gt->tunnel_dst.as_u32;
-  mp->intfc_address = gt->intfc_address.as_u32;
-  mp->mask_width = htonl (gt->mask_width);
-  mp->inner_fib_index = htonl (gt->inner_fib_index);
-  mp->outer_fib_index = htonl (gt->outer_fib_index);
-  mp->encap_index = htonl (gt->encap_index);
-  mp->hw_if_index = htonl (gt->hw_if_index);
-  mp->l2_only = htonl (gt->l2_only);
+  memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
+  mp->intfc_address = et->intfc_address.as_u32;
+  mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
+  mp->inner_fib_index = htonl (et->inner_fib_index);
+  mp->mask_width = htonl (et->mask_width);
+  mp->encap_index = htonl (et->encap_index);
+  mp->hw_if_index = htonl (et->hw_if_index);
+  mp->l2_only = htonl (et->l2_only);
   mp->nlabels = htonl (nlabels);
 
   for (i = 0; i < nlabels; i++)
@@ -7435,12 +7580,12 @@ send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
 }
 
 static void
-vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
+vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
   unix_shared_memory_queue_t *q;
   mpls_main_t *mm = &mpls_main;
-  mpls_gre_tunnel_t *gt;
+  mpls_eth_tunnel_t *et;
   u32 index = ntohl (mp->tunnel_index);
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
@@ -7449,19 +7594,19 @@ vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
 
   if (index != ~0)
     {
-      if (!pool_is_free_index (mm->gre_tunnels, index))
+      if (!pool_is_free_index (mm->eth_tunnels, index))
        {
-         gt = pool_elt_at_index (mm->gre_tunnels, index);
-         send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
+         et = pool_elt_at_index (mm->eth_tunnels, index);
+         send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
                                      mp->context);
        }
     }
   else
     {
       /* *INDENT-OFF* */
-      pool_foreach (gt, mm->gre_tunnels,
+      pool_foreach (et, mm->eth_tunnels,
       ({
-        send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
+        send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
                                     mp->context);
       }));
       /* *INDENT-ON* */
@@ -7469,84 +7614,71 @@ vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
 }
 
 static void
-vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t *
-                                         mp)
+vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
 {
   clib_warning ("BUG");
 }
 
 static void
-send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
-                           unix_shared_memory_queue_t * q,
-                           mpls_eth_tunnel_t * et, u32 index, u32 context)
+send_mpls_fib_details (vpe_api_main_t * am,
+                      unix_shared_memory_queue_t * q,
+                      u32 table_id, u32 label, u32 eos, u32 context)
 {
-  mpls_main_t *mm = &mpls_main;
-  mpls_encap_t *e;
-  int i;
-  u32 nlabels;
-  vl_api_mpls_eth_tunnel_details_t *mp;
+  vl_api_mpls_fib_details_t *mp;
 
-  e = pool_elt_at_index (mm->encaps, et->encap_index);
-  nlabels = vec_len (e->labels);
-
-  mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
+  mp = vl_msg_api_alloc (sizeof (*mp));
   memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
+  mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
   mp->context = context;
 
-  mp->tunnel_index = htonl (index);
-  memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
-  mp->intfc_address = et->intfc_address.as_u32;
-  mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
-  mp->inner_fib_index = htonl (et->inner_fib_index);
-  mp->mask_width = htonl (et->mask_width);
-  mp->encap_index = htonl (et->encap_index);
-  mp->hw_if_index = htonl (et->hw_if_index);
-  mp->l2_only = htonl (et->l2_only);
-  mp->nlabels = htonl (nlabels);
-
-  for (i = 0; i < nlabels; i++)
-    {
-      mp->labels[i] =
-       htonl (vnet_mpls_uc_get_label
-              (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
-    }
+  mp->table_id = htonl (table_id);
+  mp->eos_bit = eos;
+  mp->label = htonl (label);
 
   vl_msg_api_send_shmem (q, (u8 *) & mp);
 }
 
 static void
-vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
+vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
   unix_shared_memory_queue_t *q;
   mpls_main_t *mm = &mpls_main;
-  mpls_eth_tunnel_t *et;
-  u32 index = ntohl (mp->tunnel_index);
+  fib_table_t *fib_table;
+  fib_node_index_t lfei, *lfeip, *lfeis = NULL;
+  mpls_label_t key;
+  fib_prefix_t pfx;
+  u32 fib_index;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
   if (q == 0)
     return;
 
-  if (index != ~0)
-    {
-      if (!pool_is_free_index (mm->eth_tunnels, index))
-       {
-         et = pool_elt_at_index (mm->eth_tunnels, index);
-         send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
-                                     mp->context);
-       }
-    }
-  else
-    {
-      /* *INDENT-OFF* */
-      pool_foreach (et, mm->eth_tunnels,
-      ({
-        send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
-                                    mp->context);
-      }));
-      /* *INDENT-ON* */
-    }
+  /* *INDENT-OFF* */
+  pool_foreach (fib_table, mm->fibs,
+  ({
+    hash_foreach(key, lfei, fib_table->mpls.mf_entries,
+    ({
+       vec_add1(lfeis, lfei);
+    }));
+  }));
+  vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
+
+  vec_foreach(lfeip, lfeis)
+  {
+    fib_entry_get_prefix(*lfeip, &pfx);
+    fib_index = fib_entry_get_fib_index(*lfeip);
+
+    fib_table = fib_table_get(fib_index, pfx.fp_proto);
+
+    send_mpls_fib_details (am, q,
+                          fib_table->ft_table_id,
+                          pfx.fp_label,
+                          pfx.fp_eos,
+                          mp->context);
+  }
+
+  vec_free (lfeis);
 }
 
 static void
@@ -7642,108 +7774,6 @@ out:
   vec_free (records);
 }
 
-static void
-vl_api_mpls_fib_decap_details_t_handler (vl_api_mpls_fib_decap_details_t * mp)
-{
-  clib_warning ("BUG");
-}
-
-static void
-send_mpls_fib_decap_details (vpe_api_main_t * am,
-                            unix_shared_memory_queue_t * q,
-                            show_mpls_fib_t * s,
-                            u32 rx_table_id,
-                            u32 tx_table_id, char *swif_tag, u32 context)
-{
-  vl_api_mpls_fib_decap_details_t *mp;
-
-  mp = vl_msg_api_alloc (sizeof (*mp));
-  memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DECAP_DETAILS);
-  mp->context = context;
-
-  mp->fib_index = htonl (s->fib_index);
-  mp->entry_index = htonl (s->entry_index);
-  mp->dest = s->dest;
-  mp->s_bit = htonl (s->s_bit);
-  mp->label = htonl (s->label);
-  mp->rx_table_id = htonl (rx_table_id);
-  mp->tx_table_id = htonl (tx_table_id);
-  strncpy ((char *) mp->swif_tag,
-          (char *) swif_tag, ARRAY_LEN (mp->swif_tag) - 1);
-
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
-}
-
-static void
-vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t * mp)
-{
-  vpe_api_main_t *am = &vpe_api_main;
-  unix_shared_memory_queue_t *q;
-  vlib_main_t *vm = &vlib_global_main;
-  u64 key;
-  u32 value;
-  show_mpls_fib_t *records = 0;
-  show_mpls_fib_t *s;
-  mpls_main_t *mm = &mpls_main;
-  ip4_fib_t *rx_fib;
-  ip4_fib_t *tx_fib;
-  u32 tx_table_id;
-  char *swif_tag;
-
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    return;
-
-  /* *INDENT-OFF* */
-  hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
-  ({
-    vec_add2 (records, s, 1);
-    s->fib_index = (u32)(key>>32);
-    s->entry_index = (u32) value;
-    s->label = ((u32) key)>>12;
-    s->s_bit = (key & (1<<8)) != 0;
-  }));
-  /* *INDENT-ON* */
-
-  if (!vec_len (records))
-    {
-      vlib_cli_output (vm, "MPLS decap table empty");
-      goto out;
-    }
-
-  vec_sort_with_function (records, mpls_label_cmp);
-  vlib_cli_output (vm, "MPLS decap table");
-  vlib_cli_output (vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc",
-                  "Label", "S-bit");
-  vec_foreach (s, records)
-  {
-    mpls_decap_t *d;
-    d = pool_elt_at_index (mm->decaps, s->entry_index);
-    if (d->next_index == MPLS_LOOKUP_NEXT_IP4_INPUT)
-      {
-       tx_fib = ip4_fib_get (d->tx_fib_index);
-       tx_table_id = tx_fib->table_id;
-       swif_tag = "     ";
-      }
-    else
-      {
-       tx_table_id = d->tx_fib_index;
-       swif_tag = "(i)  ";
-      }
-    rx_fib = ip4_fib_get (s->fib_index);
-
-    vlib_cli_output (vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id,
-                    tx_table_id, swif_tag, s->label, s->s_bit);
-
-    send_mpls_fib_decap_details (am, q, s, rx_fib->table_id,
-                                tx_table_id, swif_tag, mp->context);
-  }
-
-out:
-  vec_free (records);
-}
-
 static void
 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
 {
index 887c9fc..cce6bb8 100644 (file)
@@ -477,8 +477,8 @@ static void *vl_api_ip_add_del_route_t_print
        s = format (s, "via %U ", format_ip4_address, mp->next_hop_address);
     }
 
-  if (mp->vrf_id != 0)
-    s = format (s, "vrf %d ", ntohl (mp->vrf_id));
+  if (mp->table_id != 0)
+    s = format (s, "vrf %d ", ntohl (mp->table_id));
 
   if (mp->create_vrf_if_needed)
     s = format (s, "create-vrf ");
@@ -498,8 +498,8 @@ static void *vl_api_ip_add_del_route_t_print
   if (mp->is_multipath)
     s = format (s, "multipath ");
 
-  if (mp->lookup_in_vrf)
-    s = format (s, "lookup-in-vrf %d ", ntohl (mp->lookup_in_vrf));
+  if (mp->next_hop_table_id)
+    s = format (s, "lookup-in-vrf %d ", ntohl (mp->next_hop_table_id));
 
   FINISH;
 }
@@ -537,30 +537,6 @@ static void *vl_api_proxy_arp_intfc_enable_disable_t_print
   FINISH;
 }
 
-static void *vl_api_mpls_add_del_decap_t_print
-  (vl_api_mpls_add_del_decap_t * mp, void *handle)
-{
-  u8 *s;
-
-  s = format (0, "SCRIPT: mpls_add_del_decap ");
-
-  s = format (s, "rx_vrf_id %d ", ntohl (mp->rx_vrf_id));
-
-  s = format (s, "tx_vrf_id %d ", ntohl (mp->tx_vrf_id));
-
-  s = format (s, "label %d ", ntohl (mp->label));
-
-  s = format (s, "next-index %d ", ntohl (mp->next_index));
-
-  if (mp->s_bit == 0)
-    s = format (s, "s-bit-clear ");
-
-  if (mp->is_add == 0)
-    s = format (s, "del ");
-
-  FINISH;
-}
-
 static void *vl_api_mpls_add_del_encap_t_print
   (vl_api_mpls_add_del_encap_t * mp, void *handle)
 {
@@ -582,33 +558,6 @@ static void *vl_api_mpls_add_del_encap_t_print
   FINISH;
 }
 
-static void *vl_api_mpls_gre_add_del_tunnel_t_print
-  (vl_api_mpls_gre_add_del_tunnel_t * mp, void *handle)
-{
-  u8 *s;
-
-  s = format (0, "SCRIPT: mpls_gre_add_del_tunnel ");
-
-  s = format (s, "src %U ", format_ip4_address, mp->src_address);
-
-  s = format (s, "dst %U ", format_ip4_address, mp->dst_address);
-
-  s = format (s, "adj %U/%d ", format_ip4_address,
-             (ip4_address_t *) mp->intfc_address, mp->intfc_address_length);
-
-  s = format (s, "inner-vrf_id %d ", ntohl (mp->inner_vrf_id));
-
-  s = format (s, "outer-vrf_id %d ", ntohl (mp->outer_vrf_id));
-
-  if (mp->is_add == 0)
-    s = format (s, "del ");
-
-  if (mp->l2_only)
-    s = format (s, "l2-only ");
-
-  FINISH;
-}
-
 static void *vl_api_mpls_ethernet_add_del_tunnel_t_print
   (vl_api_mpls_ethernet_add_del_tunnel_t * mp, void *handle)
 {
@@ -2060,18 +2009,6 @@ static void *vl_api_sw_interface_clear_stats_t_print
   FINISH;
 }
 
-static void *vl_api_mpls_gre_tunnel_dump_t_print
-  (vl_api_mpls_gre_tunnel_dump_t * mp, void *handle)
-{
-  u8 *s;
-
-  s = format (0, "SCRIPT: mpls_gre_tunnel_dump ");
-
-  s = format (s, "tunnel_index %d ", ntohl (mp->tunnel_index));
-
-  FINISH;
-}
-
 static void *vl_api_mpls_eth_tunnel_dump_t_print
   (vl_api_mpls_eth_tunnel_dump_t * mp, void *handle)
 {
@@ -2094,8 +2031,8 @@ static void *vl_api_mpls_fib_encap_dump_t_print
   FINISH;
 }
 
-static void *vl_api_mpls_fib_decap_dump_t_print
-  (vl_api_mpls_fib_decap_dump_t * mp, void *handle)
+static void *vl_api_mpls_fib_dump_t_print
+  (vl_api_mpls_fib_dump_t * mp, void *handle)
 {
   u8 *s;
 
@@ -2871,9 +2808,7 @@ _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump)                         \
 _(IP_ADD_DEL_ROUTE, ip_add_del_route)                                   \
 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
-_(MPLS_ADD_DEL_DECAP, mpls_add_del_decap)                               \
 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap)                               \
-_(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel)                     \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel)          \
 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2)      \
 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)             \
@@ -2951,10 +2886,9 @@ _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
 _(AF_PACKET_CREATE, af_packet_create)                                  \
 _(AF_PACKET_DELETE, af_packet_delete)                                  \
 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                   \
-_(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump)                           \
 _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump)                           \
 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump)                             \
-_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump)                             \
+_(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
index 8ca7a4b..d619249 100644 (file)
@@ -224,13 +224,6 @@ vl_api_create_vlan_subif_reply_t_handler (vl_api_create_vlan_subif_reply_t *
           ntohl (mp->retval), ntohl (mp->sw_if_index));
 }
 
-static void
-  vl_api_mpls_gre_add_del_tunnel_reply_t_handler
-  (vl_api_mpls_gre_add_del_tunnel_reply_t * mp)
-{
-  fformat (stdout, "add_del mpls gre tunnel reply %d\n", ntohl (mp->retval));
-}
-
 static void
 vl_api_mpls_add_del_encap_reply_t_handler (vl_api_mpls_add_del_encap_reply_t *
                                           mp)
@@ -238,13 +231,6 @@ vl_api_mpls_add_del_encap_reply_t_handler (vl_api_mpls_add_del_encap_reply_t *
   fformat (stdout, "add del mpls label reply %d\n", ntohl (mp->retval));
 }
 
-static void
-vl_api_mpls_add_del_decap_reply_t_handler (vl_api_mpls_add_del_decap_reply_t *
-                                          mp)
-{
-  fformat (stdout, "add del mpls decap label reply %d\n", ntohl (mp->retval));
-}
-
 static void vl_api_proxy_arp_add_del_reply_t_handler
   (vl_api_proxy_arp_add_del_reply_t * mp)
 {
@@ -604,9 +590,7 @@ _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, sw_interface_add_del_address_reply) \
 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
 _(TAP_CONNECT_REPLY, tap_connect_reply)                                 \
 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
-_(MPLS_GRE_ADD_DEL_TUNNEL_REPLY, mpls_gre_add_del_tunnel_reply)         \
 _(MPLS_ADD_DEL_ENCAP_REPLY, mpls_add_del_encap_reply)                   \
-_(MPLS_ADD_DEL_DECAP_REPLY, mpls_add_del_decap_reply)                   \
 _(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply)                    \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY, proxy_arp_intfc_enable_disable_reply) \
 _(IP_NEIGHBOR_ADD_DEL_REPLY, ip_neighbor_add_del_reply)                 \
@@ -751,7 +735,7 @@ add_del_ip4_route (test_main_t * tm, int enable_disable)
   mp->_vl_msg_id = ntohs (VL_API_IP_ADD_DEL_ROUTE);
   mp->client_index = tm->my_client_index;
   mp->context = 0xdeadbeef;
-  mp->vrf_id = ntohl (0);
+  mp->table_id = ntohl (0);
   mp->create_vrf_if_needed = 1;
   /* Arp, please, if needed */
   mp->resolve_if_needed = 1;
@@ -915,63 +899,6 @@ create_vlan_subif (test_main_t * tm, u32 vlan_id)
   vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp);
 }
 
-void
-create_mpls_gre_tunnel (test_main_t * tm, u32 vrf_id, u32 label, u8 is_add)
-{
-  vl_api_mpls_add_del_encap_t *lp;
-  vl_api_mpls_add_del_decap_t *dlp;
-  vl_api_mpls_gre_add_del_tunnel_t *mp;
-  u32 tmp;
-
-  dlp = vl_msg_api_alloc (sizeof (*dlp));
-  memset (dlp, 0, sizeof (*dlp));
-  dlp->_vl_msg_id = ntohs (VL_API_MPLS_ADD_DEL_DECAP);
-  dlp->client_index = tm->my_client_index;
-  dlp->context = 0xdeadbeef;
-  dlp->tx_vrf_id = ntohl (vrf_id);
-  dlp->label = ntohl (label);
-  dlp->s_bit = 1;
-  dlp->is_add = is_add;
-  vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & dlp);
-
-  lp = vl_msg_api_alloc (sizeof (*lp) + sizeof (u32));
-  memset (lp, 0, sizeof (*lp) + sizeof (u32));
-  lp->_vl_msg_id = ntohs (VL_API_MPLS_ADD_DEL_ENCAP);
-  lp->client_index = tm->my_client_index;
-  lp->context = 0xdeadbeef;
-  lp->vrf_id = ntohl (vrf_id);
-  lp->labels[0] = ntohl (label);
-  lp->nlabels = 1;
-  lp->is_add = is_add;
-  /* dst: 5.0.0.1 */
-  tmp = ntohl (0x05000001);
-  clib_memcpy (lp->dst_address, &tmp, 4);
-
-  vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & lp);
-
-  mp = vl_msg_api_alloc (sizeof (*mp));
-  memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_ADD_DEL_TUNNEL);
-  mp->client_index = tm->my_client_index;
-  mp->context = 0xdeadbeef;
-  mp->inner_vrf_id = ntohl (vrf_id);
-  mp->outer_vrf_id = 0;
-  mp->is_add = is_add;
-
-  /* src: 6.0.0.1 */
-  tmp = ntohl (0x06000001);
-  clib_memcpy (mp->src_address, &tmp, 4);
-  /* dst: 5.0.0.1 */
-  tmp = ntohl (0x05000001);
-  clib_memcpy (mp->dst_address, &tmp, 4);
-  /* intfc: 5.0.0.1/24 */
-  tmp = ntohl (0x05000001);
-  clib_memcpy (mp->intfc_address, &tmp, 4);
-  mp->intfc_address_length = 24;
-
-  vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp);
-}
-
 void
 add_del_proxy_arp (test_main_t * tm, int is_add)
 {
@@ -1441,16 +1368,6 @@ main (int argc, char **argv)
          connect_unix_tap (tm, "foo");
          break;
 
-       case 'M':
-         create_mpls_gre_tunnel (tm, 11 /* fib */ , 123 /* label */ ,
-                                 1 /* is_add */ );
-         break;
-
-       case 'm':
-         create_mpls_gre_tunnel (tm, 11 /* fib */ , 123 /* label */ ,
-                                 0 /* is_add */ );
-         break;
-
        case 'n':
          add_ip4_neighbor (tm, 1 /* is_add */ );
          add_ip6_neighbor (tm, 1 /* is_add */ );
index 0fe9d20..ac84bdc 100644 (file)
@@ -367,6 +367,120 @@ define create_vlan_subif_reply
   u32 sw_if_index;
 };
 
+/** \brief MPLS Route Add / del route
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param mr_label - The MPLS label value
+    @param mr_eos - The End of stack bit
+    @param mr_table_id - The MPLS table-id the route is added in
+    @param mr_classify_table_index - If this is a classify route, 
+                                     this is the classify table index
+    @param  mr_create_table_if_needed - If the MPLS or IP tables do not exist,
+                                        create them
+    @param mr_is_add - Is this a route add or delete
+    @param mr_is_classify - Is this route result a classify
+    @param mr_is_multipath - Is this route update a multipath - i.e. is this
+                             a path addition to an existing route
+    @param mr_is_resolve_host - Recurse resolution constraint via a host prefix
+    @param mr_is_resolve_attached - Recurse resolution constraint via attached prefix
+    @param mr_next_hop_proto_is_ip4 - The next-hop is IPV4
+    @param mr_next_hop_weight - The weight, for UCMP
+    @param mr_next_hop[16] - the nextop address
+    @param mr_next_hop_sw_if_index - the next-hop SW interface
+    @param mr_next_hop_table_id - the next-hop table-id (if appropriate)
+    @param mr_next_hop_out_label - the next-hop output label
+*/
+define mpls_route_add_del
+{
+  u32 client_index;
+  u32 context;
+  u32 mr_label;
+  u8 mr_eos;
+  u32 mr_table_id;
+  u32 mr_classify_table_index;
+  u8 mr_create_table_if_needed;
+  u8 mr_is_add;
+  u8 mr_is_classify;
+  u8 mr_is_multipath;
+  u8 mr_is_resolve_host;
+  u8 mr_is_resolve_attached;
+  u8 mr_next_hop_proto_is_ip4;
+  u8 mr_next_hop_weight;
+  u8 mr_next_hop[16];
+  u32 mr_next_hop_sw_if_index;
+  u32 mr_next_hop_table_id;
+  u32 mr_next_hop_out_label;
+};
+
+/** \brief Reply for MPLS route add / del request
+    @param context - returned sender context, to match reply w/ request
+    @param retval - return code
+*/
+define mpls_route_add_del_reply
+{
+  u32 context;
+  i32 retval;
+};
+
+/** \brief Dump MPLS fib table
+    @param client_index - opaque cookie to identify the sender
+*/
+define mpls_fib_dump
+{
+  u32 client_index;
+  u32 context;
+};
+
+/** \brief mpls FIB table response
+    @param table_id - MPLS fib table id
+    @param s_bit - End-of-stack bit
+    @param label - MPLS label value
+*/
+define mpls_fib_details
+{
+  u32 context;
+  u32 table_id;
+  u8  eos_bit;
+  u32 label;
+};
+
+/** \brief Bind/Unbind an MPLS local label to an IP prefix. i.e. create
+           a per-prefix label entry.
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param mb_mpls_table_id - The MPLS table-id the MPLS entry will be added in
+    @param mb_label - The MPLS label value to bind
+    @param mb_ip_table_id - The IP table-id of the IP prefix to bind to.
+    @param mb_create_table_if_needed - Create either/both tables if required.
+    @param mb_is_bind - Bind or unbind
+    @param mb_is_ip4 - The prefix to bind to is IPv4
+    @param mb_address_length - Length of IP prefix
+    @param mb_address[16] - IP prefix/
+*/
+define mpls_ip_bind_unbind
+{
+  u32 client_index;
+  u32 context;
+  u32 mb_mpls_table_id;
+  u32 mb_label;
+  u32 mb_ip_table_id;
+  u8 mb_create_table_if_needed;
+  u8 mb_is_bind;
+  u8 mb_is_ip4;
+  u8 mb_address_length;
+  u8 mb_address[16];
+};
+
+/** \brief Reply for MPLS IP bind/unbind request
+    @param context - returned sender context, to match reply w/ request
+    @param retval - return code
+*/
+define mpls_ip_bind_unbind_reply
+{
+  u32 context;
+  i32 retval;
+};
+
 /** \brief Add / del route request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -394,10 +508,11 @@ define ip_add_del_route
   u32 client_index;
   u32 context;
   u32 next_hop_sw_if_index;
-  u32 vrf_id;
-  u32 lookup_in_vrf;
+  u32 table_id;
   u32 resolve_attempts;
   u32 classify_table_index;
+  u32 next_hop_out_label;
+  u32 next_hop_table_id;
   u8 create_vrf_if_needed;
   u8 resolve_if_needed;
   u8 is_add;
@@ -426,44 +541,6 @@ define ip_add_del_route_reply
   i32 retval;
 };
 
-/* works */
-/** \brief Add / del gre tunnel request
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
-    @param sw_if_index - software index of the new vlan's parent interface
-    @param inner_vrf_id -
-    @param outer_vrf_id - 
-    @param is_add - 1 if adding the tunnel, 0 if deleting
-    @param src_address[4] - tunnel source address
-    @param dst_address[4] - tunnel destination address
-    @param intf_address - 
-    @param intf_address_length - 
-*/
-define mpls_gre_add_del_tunnel
-{
-  u32 client_index;
-  u32 context;
-  u32 inner_vrf_id;
-  u32 outer_vrf_id;
-  u8 is_add;
-  u8 l2_only;
-  u8 src_address[4];
-  u8 dst_address[4];
-  u8 intfc_address[4];
-  u8 intfc_address_length;
-};
-
-/** \brief Reply for add / del tunnel request
-    @param context - returned sender context, to match reply w/ request
-    @param retval - return code
-*/
-define mpls_gre_add_del_tunnel_reply
-{
-  u32 context;
-  i32 retval;
-  u32 tunnel_sw_if_index;
-};
-
 /** \brief Add / del MPLS encapsulation request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -495,38 +572,6 @@ define mpls_add_del_encap_reply
   i32 retval;
 };
 
-/** \brief Add / del MPLS decapsulation request
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
-    @param rx_vrf_id - receive vrf
-    @param tx_vrf_id - transmit vrf
-    @param label - 
-    @param next_index - 
-    @param s_bit - 
-    @param is_add - 1 if adding the encap, 0 if deleting
-*/
-define mpls_add_del_decap
-{
-  u32 client_index;
-  u32 context;
-  u32 rx_vrf_id;
-  u32 tx_vrf_id;
-  u32 label;
-  u32 next_index;
-  u8 s_bit;
-  u8 is_add;
-};
-
-/** \brief Reply for MPLS decap add / del request
-    @param context - returned sender context, to match reply w/ request
-    @param retval - return code
-*/
-define mpls_add_del_decap_reply
-{
-  u32 context;
-  i32 retval;
-};
-
 /** \brief Proxy ARP add / del request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -4522,40 +4567,6 @@ define mpls_fib_encap_details
   u32 labels[nlabels];
 };
 
-/** \brief Dump mpls fib decap table
-    @param client_index - opaque cookie to identify the sender
-    @param fib_index    - mpls fib entry identifier or -1 in case of all entries
-*/
-define mpls_fib_decap_dump
-{
-  u32 client_index;
-  u32 context;
-};
-
-/** \brief mpls fib decap table response
-    @param fib_index - fib table id
-    @param entry_index - reference to mpls label table
-    @param dest - destination ipv4 addr
-    @param s_bit -
-    @param label - mpls labels
-    @param rx_table_id - rx fib id
-    @param tx_table_id - tx fib id
-    @param swif_tag -
-*/
-define mpls_fib_decap_details
-{
-  u32 context;
-
-  u32 fib_index;
-  u32 entry_index;
-  u32 dest;
-  u32 s_bit;
-  u32 label;
-  u32 rx_table_id;
-  u32 tx_table_id;
-  u8 swif_tag[8];
-};
-
 /** \brief Classify get table IDs request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request