FIB: encode the label stack in the FIB path during table dump

Change-Id: I28e8a99b980ad343a4209e673201791b91ceab4e
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/fib/fib_api.c b/src/vnet/fib/fib_api.c
index d46b9e2..98f92c3 100644
--- a/src/vnet/fib/fib_api.c
+++ b/src/vnet/fib/fib_api.c
@@ -17,6 +17,7 @@
 #include <vlibmemory/api.h>
 #include <vnet/fib/fib_api.h>
 #include <vnet/fib/fib_table.h>
+#include <vnet/mfib/mfib_table.h>
 #include <vnet/bier/bier_disp_table.h>
 #include <vnet/dpo/ip_null_dpo.h>
 
@@ -207,6 +208,8 @@
 fib_api_path_encode (const fib_route_path_encode_t * api_rpath,
                      vl_api_fib_path_t *out)
 {
+    int ii;
+
     clib_memset (out, 0, sizeof (*out));
     switch (api_rpath->dpo.dpoi_type)
     {
@@ -246,12 +249,20 @@
         if ((DPO_PROTO_IP6 == api_rpath->rpath.frp_proto) ||
             (DPO_PROTO_IP4 == api_rpath->rpath.frp_proto))
         {
-            fib_table_t *fib;
-
-            fib = fib_table_get (api_rpath->rpath.frp_fib_index,
-                                 dpo_proto_to_fib(api_rpath->rpath.frp_proto));
-
-            out->table_id = htonl (fib->ft_table_id);
+            if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RPF_ID)
+            {
+                out->table_id =
+                    htonl(mfib_table_get_table_id(
+                              api_rpath->rpath.frp_fib_index,
+                              dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
+            }
+            else
+            {
+                out->table_id =
+                    htonl(fib_table_get_table_id(
+                              api_rpath->rpath.frp_fib_index,
+                              dpo_proto_to_fib(api_rpath->rpath.frp_proto)));
+            }
         }
     }
 
@@ -264,6 +275,41 @@
         out->is_udp_encap = 1;
         out->next_hop_id = api_rpath->rpath.frp_udp_encap_id;
     }
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_INTF_RX)
+    {
+        out->is_interface_rx = 1;
+    }
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_LOCAL)
+    {
+        out->is_local = 1;
+    }
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
+    {
+        out->is_resolve_host = 1;
+    }
+    if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
+    {
+        out->is_resolve_attached = 1;
+    }
+    /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_ATTACHED) { */
+    /*     out->is_attached = 1; */
+    /* } */
+    /* if (api_rpath->rpath.frp_flags & FIB_ROUTE_PATH_CONNECTED) { */
+    /*     out->is_connected = 1; */
+    /* } */
+    if (api_rpath->rpath.frp_label_stack)
+    {
+        for (ii = 0; ii < vec_len(api_rpath->rpath.frp_label_stack); ii++)
+        {
+            out->label_stack[ii].label =
+                htonl(api_rpath->rpath.frp_label_stack[ii].fml_value);
+            out->label_stack[ii].ttl =
+                api_rpath->rpath.frp_label_stack[ii].fml_ttl;
+            out->label_stack[ii].exp =
+                api_rpath->rpath.frp_label_stack[ii].fml_exp;
+        }
+        out->n_labels = ii;
+    }
 }
 
 fib_protocol_t
diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c
index eaedc50..32e45f2 100644
--- a/src/vnet/fib/fib_entry.c
+++ b/src/vnet/fib/fib_entry.c
@@ -1652,12 +1652,25 @@
 fib_entry_encode (fib_node_index_t fib_entry_index,
 		  fib_route_path_encode_t **api_rpaths)
 {
+    fib_path_ext_list_t *ext_list;
     fib_entry_t *fib_entry;
+    fib_entry_src_t *bsrc;
 
+    ext_list = NULL;
     fib_entry = fib_entry_get(fib_entry_index);
+    bsrc = fib_entry_get_best_src_i(fib_entry);
+
+    if (bsrc)
+    {
+	ext_list = &bsrc->fes_path_exts;
+    }
+
     if (FIB_NODE_INDEX_INVALID != fib_entry->fe_parent)
     {
-        fib_path_list_walk(fib_entry->fe_parent, fib_path_encode, api_rpaths);
+        fib_path_list_walk_w_ext(fib_entry->fe_parent,
+                                 ext_list,
+                                 fib_path_encode,
+                                 api_rpaths);
     }
 }
 
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index f528c67..d4a701d 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -37,6 +37,7 @@
 #include <vnet/fib/fib_internal.h>
 #include <vnet/fib/fib_urpf_list.h>
 #include <vnet/fib/mpls_fib.h>
+#include <vnet/fib/fib_path_ext.h>
 #include <vnet/udp/udp_encap.h>
 #include <vnet/bier/bier_fmask.h>
 #include <vnet/bier/bier_table.h>
@@ -605,10 +606,14 @@
                         vnm,
                         path->dvr.fp_interface));
         break;
+    case FIB_PATH_TYPE_DEAG:
+        s = format (s, " %sfib-index:%d",
+                    (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?  "m" : ""),
+                    path->deag.fp_tbl_id);
+        break;
     case FIB_PATH_TYPE_RECEIVE:
     case FIB_PATH_TYPE_INTF_RX:
     case FIB_PATH_TYPE_SPECIAL:
-    case FIB_PATH_TYPE_DEAG:
     case FIB_PATH_TYPE_EXCLUSIVE:
 	if (dpo_id_is_valid(&path->fp_dpo))
 	{
@@ -2609,7 +2614,8 @@
 
 fib_path_list_walk_rc_t
 fib_path_encode (fib_node_index_t path_list_index,
-		 fib_node_index_t path_index,
+                 fib_node_index_t path_index,
+                 const fib_path_ext_t *path_ext,
                  void *ctx)
 {
     fib_route_path_encode_t **api_rpaths = ctx;
@@ -2628,7 +2634,7 @@
     api_rpath->dpo = path->fp_dpo;
 
     switch (path->fp_type)
-      {
+    {
       case FIB_PATH_TYPE_RECEIVE:
         api_rpath->rpath.frp_addr = path->receive.fp_addr;
         api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
@@ -2647,6 +2653,10 @@
         break;
       case FIB_PATH_TYPE_DEAG:
         api_rpath->rpath.frp_fib_index = path->deag.fp_tbl_id;
+        if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
+        {
+            api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_RPF_ID;
+        }
         break;
       case FIB_PATH_TYPE_RECURSIVE:
         api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip;
@@ -2660,9 +2670,18 @@
           api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id;
           api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
           break;
+      case FIB_PATH_TYPE_INTF_RX:
+	  api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
+	  api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_INTF_RX;
+	  break;
       default:
         break;
-      }
+    }
+
+    if (path_ext && path_ext->fpe_type == FIB_PATH_EXT_MPLS) 
+    {
+        api_rpath->rpath.frp_label_stack = path_ext->fpe_path.frp_label_stack;
+    }
 
     return (FIB_PATH_LIST_WALK_CONTINUE);
 }
diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h
index e162f4d..57dec6d 100644
--- a/src/vnet/fib/fib_path.h
+++ b/src/vnet/fib/fib_path.h
@@ -183,6 +183,7 @@
 extern void fib_path_module_init(void);
 extern fib_path_list_walk_rc_t fib_path_encode(fib_node_index_t path_list_index,
                                                fib_node_index_t path_index,
+                                               const struct fib_path_ext_t_ *ext_list,
                                                void *ctx);
 
 #endif
diff --git a/src/vnet/fib/fib_path_ext.c b/src/vnet/fib/fib_path_ext.c
index 5ecf3a9..209b627 100644
--- a/src/vnet/fib/fib_path_ext.c
+++ b/src/vnet/fib/fib_path_ext.c
@@ -328,11 +328,14 @@
 {
     fib_path_ext_t *path_ext;
 
-    vec_foreach(path_ext, list->fpel_exts)
+    if (NULL != list)
     {
-        if (path_ext->fpe_path_index == path_index)
+        vec_foreach(path_ext, list->fpel_exts)
         {
-            return (path_ext);
+            if (path_ext->fpe_path_index == path_index)
+            {
+                return (path_ext);
+            }
         }
     }
     return (NULL);
diff --git a/src/vnet/fib/fib_path_list.c b/src/vnet/fib/fib_path_list.c
index 568886a..4e110fb 100644
--- a/src/vnet/fib/fib_path_list.c
+++ b/src/vnet/fib/fib_path_list.c
@@ -24,6 +24,7 @@
 #include <vnet/fib/fib_node_list.h>
 #include <vnet/fib/fib_walk.h>
 #include <vnet/fib/fib_urpf_list.h>
+#include <vnet/fib/fib_path_ext.h>
 
 /**
  * The magic number of child entries that make a path-list popular.
@@ -722,7 +723,7 @@
 	if (FIB_NODE_INDEX_INVALID != old_path_list_index)
 	{
 	    fib_path_list_destroy(path_list);
-	
+
 	    path_list_index = old_path_list_index;
 	}
 	else
@@ -747,7 +748,7 @@
     return (path_list_index);
 }
 
-static fib_path_cfg_flags_t 
+static fib_path_cfg_flags_t
 fib_path_list_flags_2_path_flags (fib_path_list_flags_t plf)
 {
     fib_path_cfg_flags_t pf = FIB_PATH_CFG_FLAG_NONE;
@@ -1343,6 +1344,29 @@
     }
 }
 
+void
+fib_path_list_walk_w_ext (fib_node_index_t path_list_index,
+                          const fib_path_ext_list_t *ext_list,
+                          fib_path_list_walk_w_ext_fn_t func,
+                          void *ctx)
+{
+    fib_node_index_t *path_index;
+    fib_path_list_t *path_list;
+    fib_path_ext_t *path_ext;
+
+    path_list = fib_path_list_get(path_list_index);
+
+    vec_foreach(path_index, path_list->fpl_paths)
+    {
+        path_ext = fib_path_ext_list_find_by_path_index(ext_list, *path_index);
+
+        if (FIB_PATH_LIST_WALK_STOP == func(path_list_index,
+                                            *path_index,
+                                            path_ext,
+                                            ctx))
+            break;
+    }
+}
 
 void
 fib_path_list_module_init (void)
diff --git a/src/vnet/fib/fib_path_list.h b/src/vnet/fib/fib_path_list.h
index 18835a6..380eb1a 100644
--- a/src/vnet/fib/fib_path_list.h
+++ b/src/vnet/fib/fib_path_list.h
@@ -183,6 +183,17 @@
 			       fib_path_list_walk_fn_t func,
 			       void *ctx);
 
+typedef fib_path_list_walk_rc_t (*fib_path_list_walk_w_ext_fn_t)(
+    fib_node_index_t pl_index,
+    fib_node_index_t path_index,
+    const struct fib_path_ext_t_ *ext_list,
+    void *ctx);
+
+extern void fib_path_list_walk_w_ext(fib_node_index_t pl_index,
+                                     const fib_path_ext_list_t *ext_list,
+                                     fib_path_list_walk_w_ext_fn_t func,
+                                     void *ctx);
+
 extern void fib_path_list_module_init(void);
 
 extern void fib_path_list_module_init(void);
diff --git a/src/vnet/fib/fib_types.api b/src/vnet/fib/fib_types.api
index d946ed7..8268870 100644
--- a/src/vnet/fib/fib_types.api
+++ b/src/vnet/fib/fib_types.api
@@ -59,6 +59,7 @@
   u8 is_resolve_attached;
   u8 is_dvr;
   u8 is_source_lookup;
+  u8 is_interface_rx;
   u8 afi;
   u8 next_hop[16];
   u32 next_hop_id;