IPv6 Classify Forwarding Graph errors
[vpp.git] / vnet / vnet / mpls / interface.c
index 9ef4c29..af0428c 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>
 
-static uword mpls_gre_set_rewrite (vnet_main_t * vnm,
-                              u32 sw_if_index,
-                              u32 l3_type,
-                              void * dst_address,
-                              void * rewrite,
-                              uword max_rewrite_bytes)
-{
-  /*
-   * Conundrum: packets from tun/tap destined for the tunnel
-   * actually have this rewrite applied. Transit packets do not.
-   * To make the two cases equivalent, don't generate a
-   * rewrite here, build the entire header in the fast path.
-   */
-  return 0;
-}
-
-/* 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
-  .set_rewrite = mpls_gre_set_rewrite,
-};
-
-
-static uword mpls_eth_set_rewrite (vnet_main_t * vnm,
-                              u32 sw_if_index,
-                              u32 l3_type,
-                              void * dst_address,
-                              void * rewrite,
-                              uword max_rewrite_bytes)
-{
-  /*
-   * Conundrum: packets from tun/tap destined for the tunnel
-   * actually have this rewrite applied. Transit packets do not.
-   * To make the two cases equivalent, don't generate a
-   * rewrite here, build the entire header in the fast path.
-   */
-  return 0;
-}
-
 /* manually added to the interface output node */
 #define MPLS_ETH_OUTPUT_NEXT_OUTPUT    1
 
@@ -525,243 +256,10 @@ VNET_HW_INTERFACE_CLASS (mpls_eth_hw_interface_class) = {
 #if 0
   .unformat_header = unformat_mpls_eth_header,
 #endif
-  .set_rewrite = mpls_eth_set_rewrite,
-};
-
-/**
- * A conversion of DPO next object tpyes to VLIB graph next nodes from
- * the mpls_post_rewrite node
- */
-static const int dpo_next_2_mpls_post_rewrite[DPO_LAST] = {
-    [DPO_LOAD_BALANCE] = IP_LOOKUP_NEXT_LOAD_BALANCE,
+  .build_rewrite = default_build_rewrite,
+  .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
 };
 
-static uword
-mpls_post_rewrite (vlib_main_t * vm,
-                   vlib_node_runtime_t * node,
-                   vlib_frame_t * from_frame)
-{
-  ip4_main_t * im = &ip4_main;
-  ip_lookup_main_t * lm = &im->lookup_main;
-  u32 n_left_from, next_index, * from, * to_next;
-  u16 old_l0 = 0; //, old_l1 = 0;
-
-  from = vlib_frame_vector_args (from_frame);
-  n_left_from = from_frame->n_vectors;
-
-  next_index = node->cached_next_index;
-
-  while (n_left_from > 0)
-    {
-      u32 n_left_to_next;
-
-      vlib_get_next_frame (vm, node, next_index,
-                          to_next, n_left_to_next);
-
-      /* while (n_left_from >= 4 && n_left_to_next >= 2) */
-      /*       { */
-      /*         u32 bi0, bi1; */
-      /*         vlib_buffer_t * b0, * b1; */
-      /*     ip4_header_t * ip0, * ip1; */
-      /*         u32 next0; */
-      /*         u32 next1; */
-      /*     u16 new_l0, new_l1, adj_index0, adj_index1; */
-      /*     ip_csum_t sum0, sum1; */
-      /*         ip_adjacency_t *adj0, *adj1; */
-
-      /*         /\* Prefetch 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); */
-
-      /*           CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); */
-      /*           CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); */
-      /*         } */
-
-      /*         bi0 = from[0]; */
-      /*         bi1 = from[1]; */
-      /*         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); */
-      /*     ip0 = vlib_buffer_get_current (b0); */
-      /*     ip1 = vlib_buffer_get_current (b1); */
-          
-      /*     /\* Note: the tunnel rewrite sets up sw_if_index[VLIB_TX] *\/ */
-
-      /*     /\* set the GRE (outer) ip packet length, fix the bloody checksum *\/ */
-      /*     sum0 = ip0->checksum; */
-      /*     sum1 = ip1->checksum; */
-
-      /*     /\* old_l0, old_l1 always 0, see the rewrite setup *\/ */
-      /*     new_l0 =  */
-      /*       clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); */
-      /*     new_l1 =  */
-      /*       clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)); */
-          
-      /*     sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, */
-      /*                            length /\* changed member *\/); */
-      /*     sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t, */
-      /*                            length /\* changed member *\/); */
-      /*     ip0->checksum = ip_csum_fold (sum0); */
-      /*     ip1->checksum = ip_csum_fold (sum1); */
-      /*     ip0->length = new_l0; */
-      /*     ip1->length = new_l1; */
-
-      /*         /\* replace the TX adj in the packet with the next in the chain *\/ */
-      /*         adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; */
-      /*         adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; */
-
-      /*         adj0 = ip_get_adjacency (lm, adj_index0); */
-      /*         adj1 = ip_get_adjacency (lm, adj_index1); */
-
-      /*         ASSERT(adj0->sub_type.midchain.adj_index != ADJ_INDEX_INVALID); */
-      /*         ASSERT(adj1->sub_type.midchain.adj_index != ADJ_INDEX_INVALID); */
-
-      /*         adj_index0 = adj0->sub_type.midchain.adj_index; */
-      /*         adj_index1 = adj1->sub_type.midchain.adj_index; */
-
-      /*         vnet_buffer (b0)->ip.adj_index[VLIB_TX] = adj_index0; */
-      /*         vnet_buffer (b1)->ip.adj_index[VLIB_TX] = adj_index1; */
-
-      /*         /\* get the next adj in the chain to determine the next graph node *\/ */
-      /*         adj0 = ip_get_adjacency (lm, adj_index0); */
-      /*         adj1 = ip_get_adjacency (lm, adj_index1); */
-
-      /*         next0 = adj0->lookup_next_index; */
-      /*         next1 = adj1->lookup_next_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)
-       {
-         ip_adjacency_t * adj0;
-         u32 bi0;
-         vlib_buffer_t * b0;
-          ip4_header_t * ip0;
-         u32 next0;
-          u16 new_l0, adj_index0;
-          ip_csum_t sum0;
-
-         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);
-          ip0 = vlib_buffer_get_current (b0);
-          
-          /* Note: the tunnel rewrite sets up sw_if_index[VLIB_TX] */
-
-          /* set the GRE (outer) ip packet length, fix the bloody checksum */
-          sum0 = ip0->checksum;
-          /* old_l0 always 0, see the rewrite setup */
-          new_l0 = 
-            clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
-          
-          sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
-                                 length /* changed member */);
-          ip0->checksum = ip_csum_fold (sum0);
-          ip0->length = new_l0;
-
-         /* replace the TX adj in the packet with the next in the chain */
-         adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
-
-          ASSERT(adj_index0);
-
-         adj0 = ip_get_adjacency (lm, adj_index0);
-         ASSERT(adj0->sub_type.midchain.next_dpo.dpoi_index != ADJ_INDEX_INVALID);
-         adj_index0 = adj0->sub_type.midchain.next_dpo.dpoi_index;
-         vnet_buffer (b0)->ip.adj_index[VLIB_TX] = adj_index0;
-
-         /* get the next adj in the chain to determine the next graph node */
-         ASSERT(0);
-         next0 = 0; //adj0->sub_type.midchain.next_dpo.dpoi_next;
-
-         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, mpls_input_node.index,
-                               MPLS_ERROR_PKTS_ENCAP, from_frame->n_vectors);
-  return from_frame->n_vectors;
-}
-
-VLIB_REGISTER_NODE (mpls_post_rewrite_node) = {
-  .function = mpls_post_rewrite,
-  .name = "mpls-post-rewrite",
-  /* Takes a vector of packets. */
-  .vector_size = sizeof (u32),
-
-  .runtime_data_bytes = 0,
-
-  .n_next_nodes = IP_LOOKUP_N_NEXT,
-  .next_nodes = IP4_LOOKUP_NEXT_NODES,
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (mpls_post_rewrite_node, mpls_post_rewrite)
-
-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)
 {
@@ -778,9 +276,8 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
                                   u32 sw_if_index,
                                   u8 is_enable)
 {
-  mpls_interface_state_change_callback_t *callback;
   vlib_main_t * vm = vlib_get_main();
-  ip_config_main_t * cm = &mm->rx_config_mains;
+  ip_config_main_t * cm = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
   vnet_config_main_t * vcm = &cm->config_main;
   u32 lookup_feature_index;
   fib_node_index_t lfib_index;
@@ -829,615 +326,8 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
                                   /* # bytes of config data */ 0);
 
   cm->config_index_by_sw_if_index[sw_if_index] = ci;
-
-  /*
-   * notify all interested clients of the change of state.
-   */
-  vec_foreach(callback, mm->mpls_interface_state_change_callbacks)
-  {
-      (*callback)(sw_if_index, is_enable);
-  }
-}
-
-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_post_rewrite_node.index,
-                                       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 *);
@@ -1455,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 *);
@@ -1515,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");
@@ -1555,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;
 
@@ -1746,7 +587,7 @@ int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
   
   vnet_rewrite_for_sw_interface
     (vnm,
-     VNET_L3_PACKET_TYPE_MPLS_UNICAST
+     VNET_LINK_MPLS
      tx_sw_if_index,
      ip4_rewrite_node.index,
      tp->tunnel_dst,
@@ -1931,7 +772,7 @@ int vnet_mpls_policy_tunnel_add_rewrite (mpls_main_t * mm,
   /* Build L2 encap */
   vnet_rewrite_for_sw_interface
     (mm->vnet_main, 
-     VNET_L3_PACKET_TYPE_MPLS_UNICAST
+     VNET_LINK_MPLS
      t->tx_sw_if_index,
      mpls_policy_encap_node.index,
      t->tunnel_dst,
@@ -2093,14 +934,14 @@ int vnet_mpls_ethernet_add_del_policy_tunnel (u8 *dst,
          .fp_len = tp->mask_width,
          .fp_proto = FIB_PROTOCOL_IP4,
       };
-      dpo_id_t dpo = DPO_NULL;
+      dpo_id_t dpo = DPO_INVALID;
 
       if (is_add)
         {
           dpo_set(&dpo,
                   DPO_CLASSIFY,
                   DPO_PROTO_IP4,
-                  classify_dpo_create(FIB_PROTOCOL_IP4,
+                  classify_dpo_create(DPO_PROTO_IP4,
                                       classify_table_index));
 
           tp->fei = fib_table_entry_special_dpo_add(tp->inner_fib_index,