MPLS Unifom mode

- support both pipe and uniform modes for all MPLS LSP
- all API programming for output-labels requires that the mode (and associated data) is specificed
   - API changes in MPLS, BIER and IP are involved
- new DPO [sub] types for MPLS labels to handle the two modes.

Change-Id: I87b76401e996f10dfbdbe4552ff6b19af958783c
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/bier/bier.api b/src/vnet/bier/bier.api
index 446863c..d07379e 100644
--- a/src/vnet/bier/bier.api
+++ b/src/vnet/bier/bier.api
@@ -18,7 +18,7 @@
     This file defines vpp BIER control-plane API messages which are generally
     called through a shared memory interface.
 */
-option version = "1.0.0";
+option version = "1.1.0";
 import "vnet/fib/fib_types.api";
 
 /** \brief BIER Table Indentifier
@@ -84,7 +84,7 @@
   u8 br_is_replace;
   vl_api_bier_table_id_t br_tbl_id;
   u8 br_n_paths;
-  vl_api_fib_path3_t br_paths[br_n_paths];
+  vl_api_fib_path_t br_paths[br_n_paths];
 };
 
 define bier_route_dump
@@ -101,7 +101,7 @@
   u16 br_bp;
   vl_api_bier_table_id_t br_tbl_id;
   u32 br_n_paths;
-  vl_api_fib_path3_t br_paths[br_n_paths];
+  vl_api_fib_path_t br_paths[br_n_paths];
 };
 
 /** \brief BIER Imposition Add
@@ -211,7 +211,7 @@
   u8 bde_is_add;
   u8 bde_payload_proto;
   u8 bde_n_paths;
-  vl_api_fib_path3_t bde_paths[bde_n_paths];
+  vl_api_fib_path_t bde_paths[bde_n_paths];
 };
 
 define bier_disp_entry_dump
@@ -229,7 +229,7 @@
   u8 bde_is_add;
   u8 bde_payload_proto;
   u8 bde_n_paths;
-  vl_api_fib_path3_t bde_paths[bde_n_paths];
+  vl_api_fib_path_t bde_paths[bde_n_paths];
 };
 
 /*
diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c
index 4b1d1c2..77b2cab 100644
--- a/src/vnet/bier/bier_api.c
+++ b/src/vnet/bier/bier_api.c
@@ -202,8 +202,16 @@
                      mp->br_paths[ii].n_labels - 1);
         for (jj = 0; jj < mp->br_paths[ii].n_labels; jj++)
         {
-            brpath->frp_label_stack[jj] =
-                ntohl(mp->br_paths[ii].label_stack[jj]);
+            brpath->frp_label_stack[jj].fml_value =
+                ntohl(mp->br_paths[ii].label_stack[jj].label);
+            brpath->frp_label_stack[jj].fml_ttl =
+                mp->br_paths[ii].label_stack[jj].ttl;
+            brpath->frp_label_stack[jj].fml_exp =
+                mp->br_paths[ii].label_stack[jj].exp;
+            brpath->frp_label_stack[jj].fml_mode =
+                (mp->br_paths[ii].label_stack[jj].is_uniform ?
+                 FIB_MPLS_LSP_MODE_UNIFORM :
+                 FIB_MPLS_LSP_MODE_PIPE);
         }
 
         if (mp->br_paths[ii].is_udp_encap)
@@ -275,11 +283,11 @@
     fib_route_path_encode_t *api_rpaths = NULL, *api_rpath;
     bier_route_details_walk_t *ctx = args;
     vl_api_bier_route_details_t *mp;
-    vl_api_fib_path3_t *fp;
+    vl_api_fib_path_t *fp;
     u32 n_paths, m_size;
 
     n_paths = fib_path_list_get_n_paths(be->be_path_list);
-    m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path3_t));
+    m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t));
     mp = vl_msg_api_alloc(m_size);
     if (!mp)
         return;
@@ -636,7 +644,7 @@
     bier_disp_entry_details_walk_t *ctx = args;
     vl_api_bier_disp_entry_details_t *mp;
     bier_hdr_proto_id_t pproto;
-    vl_api_fib_path3_t *fp;
+    vl_api_fib_path_t *fp;
     u32 n_paths, m_size;
 
     FOR_EACH_BIER_HDR_PROTO(pproto)
@@ -645,7 +653,7 @@
         if (INDEX_INVALID != pl)
         {
             n_paths = fib_path_list_get_n_paths(pl);
-            m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path3_t));
+            m_size = sizeof(*mp) + (n_paths * sizeof(vl_api_fib_path_t));
             mp = vl_msg_api_alloc(m_size);
             if (!mp)
                 return;
diff --git a/src/vnet/bier/bier_fmask.c b/src/vnet/bier/bier_fmask.c
index 2fc24dc..31d884a 100644
--- a/src/vnet/bier/bier_fmask.c
+++ b/src/vnet/bier/bier_fmask.c
@@ -177,16 +177,13 @@
 
     if (!(bfm->bfm_flags & BIER_FMASK_FLAG_DISP))
     {
-        /*
-         * leave this label in host byte order so we can OR in the TTL
-         */
         if (NULL != rpaths->frp_label_stack)
         {
-            olabel = rpaths->frp_label_stack[0];
+            olabel = rpaths->frp_label_stack[0].fml_value;
             vnet_mpls_uc_set_label(&bfm->bfm_label, olabel);
             vnet_mpls_uc_set_exp(&bfm->bfm_label, 0);
             vnet_mpls_uc_set_s(&bfm->bfm_label, 1);
-            vnet_mpls_uc_set_ttl(&bfm->bfm_label, 0);
+            vnet_mpls_uc_set_ttl(&bfm->bfm_label, 64);
             bfm->bfm_flags |= BIER_FMASK_FLAG_MPLS;
         }
         else
@@ -207,7 +204,9 @@
             vnet_mpls_uc_set_label(&bfm->bfm_label, id);
             vnet_mpls_uc_set_s(&bfm->bfm_label, 1);
             vnet_mpls_uc_set_exp(&bfm->bfm_label, 0);
+            vnet_mpls_uc_set_ttl(&bfm->bfm_label, 64);
         }
+        bfm->bfm_label = clib_host_to_net_u32(bfm->bfm_label);
     }
 
     bfm->bfm_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED |
diff --git a/src/vnet/bier/bier_output.c b/src/vnet/bier/bier_output.c
index db115d3..01eeffe 100644
--- a/src/vnet/bier/bier_output.c
+++ b/src/vnet/bier/bier_output.c
@@ -140,8 +140,8 @@
                 h0 = vlib_buffer_get_current(b0);
                 
                 h0[0] = bfm0->bfm_label;
-                vnet_mpls_uc_set_ttl(h0, vnet_buffer(b0)->mpls.ttl - 1);
-                h0[0] = clib_host_to_net_u32(h0[0]);
+
+                ((char*)h0)[3]= vnet_buffer(b0)->mpls.ttl - 1;
             }
 
             /*
diff --git a/src/vnet/bier/bier_test.c b/src/vnet/bier/bier_test.c
index 08a8c55..6c7af82 100644
--- a/src/vnet/bier/bier_test.c
+++ b/src/vnet/bier/bier_test.c
@@ -316,7 +316,10 @@
         .frp_bier_fib_index = bti,
         .frp_sw_if_index = ~0,
     };
-    vec_add1(path_1_1_1_1.frp_label_stack, 500);
+    fib_mpls_label_t fml_500 = {
+        .fml_value = 500,
+    };
+    vec_add1(path_1_1_1_1.frp_label_stack, fml_500);
     vec_add1(paths_1_1_1_1, path_1_1_1_1);
     const fib_prefix_t pfx_1_1_1_1_s_32 = {
         .fp_addr = nh_1_1_1_1,
@@ -389,8 +392,10 @@
             .ttl = 255,
         },
     };
-    mpls_label_t *out_lbl_99 = NULL;
-    vec_add1(out_lbl_99, 99);
+    fib_mpls_label_t *out_lbl_99 = NULL, fml_99 = {
+        .fml_value = 99,
+    };
+    vec_add1(out_lbl_99, fml_99);
 
     fei = fib_table_entry_update_one_path(0,
                                           &pfx_1_1_1_1_s_32,
@@ -443,8 +448,10 @@
             .ttl = 255,
         },
     };
-    mpls_label_t *out_lbl_100 = NULL;
-    vec_add1(out_lbl_100, 100);
+    fib_mpls_label_t *out_lbl_100 = NULL, fml_100 = {
+        .fml_value = 100,
+    };
+    vec_add1(out_lbl_100, fml_100);
 
     fei = fib_table_entry_path_add(0,
                                    &pfx_1_1_1_1_s_32,
@@ -505,13 +512,18 @@
         .frp_bier_fib_index = bti,
         .frp_sw_if_index = ~0,
     };
-    vec_add1(path_1_1_1_2.frp_label_stack, 501);
+    fib_mpls_label_t fml_501 = {
+        .fml_value = 501,
+    };
+    vec_add1(path_1_1_1_2.frp_label_stack, fml_501);
     vec_add1(paths_1_1_1_2, path_1_1_1_2);
     input_paths_1_1_1_2 = vec_dup(paths_1_1_1_2);
     index_t bei_3;
 
-    mpls_label_t *out_lbl_101 = NULL;
-    vec_add1(out_lbl_101, 101);
+    fib_mpls_label_t *out_lbl_101 = NULL, fml_101 = {
+        .fml_value = 101,
+    };
+    vec_add1(out_lbl_101, fml_101);
     fei = fib_table_entry_path_add(0,
                                    &pfx_1_1_1_2_s_32,
                                    FIB_SOURCE_API,
@@ -605,7 +617,7 @@
      * add the via back
      */
     out_lbl_101 = NULL;
-    vec_add1(out_lbl_101, 101);
+    vec_add1(out_lbl_101, fml_101);
     fei = fib_table_entry_path_add(0,
                                    &pfx_1_1_1_2_s_32,
                                    FIB_SOURCE_API,