Route counters in the stats segment

route ADD API changed to return the stats segment index to use to read the counters

Change-Id: I2ef41e01eaa2f9cfaa49d9c88968897793825925
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/dpo/load_balance.c b/src/vnet/dpo/load_balance.c
index ae95b6e..37f8ca1 100644
--- a/src/vnet/dpo/load_balance.c
+++ b/src/vnet/dpo/load_balance.c
@@ -53,7 +53,16 @@
 /**
  * The one instance of load-balance main
  */
-load_balance_main_t load_balance_main;
+load_balance_main_t load_balance_main = {
+    .lbm_to_counters = {
+        .name = "route-to",
+        .stat_segment_name = "/net/route/to",
+    },
+    .lbm_via_counters = {
+        .name = "route-via",
+        .stat_segment_name = "/net/route/via",
+    }
+};
 
 f64
 load_balance_get_multipath_tolerance (void)
diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c
index 6555265..8d7ce00 100644
--- a/src/vnet/fib/fib_entry.c
+++ b/src/vnet/fib/fib_entry.c
@@ -1495,6 +1495,16 @@
     }
 }
 
+u32
+fib_entry_get_stats_index (fib_node_index_t fib_entry_index)
+{
+    fib_entry_t *fib_entry;
+
+    fib_entry = fib_entry_get(fib_entry_index);
+
+    return (fib_entry->fe_lb.dpoi_index);
+}
+
 static int
 fib_ip4_address_compare (const ip4_address_t * a1,
                          const ip4_address_t * a2)
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index 61b8149..9175a57 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -623,6 +623,8 @@
 
 extern void fib_entry_module_init(void);
 
+extern u32 fib_entry_get_stats_index(fib_node_index_t fib_entry_index);
+
 /*
  * unsafe... beware the raw pointer.
  */
diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c
index f63edaa..d8e8d63 100644
--- a/src/vnet/fib/fib_table.c
+++ b/src/vnet/fib/fib_table.c
@@ -885,6 +885,14 @@
                              fib_entry_index, prefix, source);
 }
 
+u32
+fib_table_entry_get_stats_index(u32 fib_index,
+                                const fib_prefix_t *prefix)
+{
+    return (fib_entry_get_stats_index(
+                fib_table_lookup_exact_match(fib_index, prefix)));
+}
+
 fib_node_index_t
 fib_table_entry_local_label_add (u32 fib_index,
 				 const fib_prefix_t *prefix,
diff --git a/src/vnet/fib/fib_table.h b/src/vnet/fib/fib_table.h
index 8b86f8d..f13dd77 100644
--- a/src/vnet/fib/fib_table.h
+++ b/src/vnet/fib/fib_table.h
@@ -596,6 +596,17 @@
 
 /**
  * @brief
+ *  Return the stats index for a FIB entry
+ * @param fib_index
+ *  The table's FIB index
+ * @param prefix
+ *  The entry's prefix's
+ */
+extern u32 fib_table_entry_get_stats_index(u32 fib_index,
+                                           const fib_prefix_t *prefix);
+
+/**
+ * @brief
  *  Flush all entries from a table for the source
  *
  * @param fib_index
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api
index 616d621..7c7f656 100644
--- a/src/vnet/ip/ip.api
+++ b/src/vnet/ip/ip.api
@@ -1,5 +1,6 @@
+/* Hey Emacs use -*- mode: C -*- */
 /*
- * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2018 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
@@ -70,6 +71,7 @@
   u8  address_length;
   u8  address[4];
   u32 count;
+  u32 stats_index;
   vl_api_fib_path_t path[count];
 };
 
@@ -97,6 +99,7 @@
   u8  address_length;
   u8  address[16];
   u32 count;
+  u32 stats_index;
   vl_api_fib_path_t path[count];
 };
 
@@ -389,7 +392,7 @@
     @param next_hop_out_label_stack - the next-hop output label stack, outer most first
     @param next_hop_via_label - The next-hop is a resolved via a local label
 */
-autoreply define ip_add_del_route
+define ip_add_del_route
 {
   u32 client_index;
   u32 context;
@@ -422,6 +425,13 @@
   vl_api_fib_mpls_label_t next_hop_out_label_stack[next_hop_n_out_labels];
 };
 
+define ip_add_del_route_reply
+{
+  u32 context;
+  i32 retval;
+  u32 stats_index;
+};
+
 /** \brief Add / del route request
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index 431a777..bed5889 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -212,6 +212,8 @@
 	  clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
   mp->address_length = pfx->fp_len;
   memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
+  mp->stats_index =
+    htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
 
   mp->count = htonl (path_count);
   fp = mp->path;
@@ -309,6 +311,8 @@
   memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
   memcpy (mp->table_name, table->ft_desc,
 	  clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
+  mp->stats_index =
+    htonl (fib_table_entry_get_stats_index (table->ft_index, pfx));
 
   mp->count = htonl (path_count);
   fp = mp->path;
@@ -962,7 +966,8 @@
 }
 
 static int
-ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
+ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
+			     u32 * stats_index)
 {
   u32 fib_index, next_hop_fib_index;
   fib_mpls_label_t *label_stack = NULL;
@@ -1006,32 +1011,37 @@
 	}
     }
 
-  return (add_del_route_t_handler (mp->is_multipath,
-				   mp->is_add,
-				   mp->is_drop,
-				   mp->is_unreach,
-				   mp->is_prohibit,
-				   mp->is_local, 0,
-				   mp->is_classify,
-				   mp->classify_table_index,
-				   mp->is_resolve_host,
-				   mp->is_resolve_attached, 0, 0,
-				   mp->is_dvr,
-				   mp->is_source_lookup,
-				   mp->is_udp_encap,
-				   fib_index, &pfx, DPO_PROTO_IP4,
-				   &nh,
-				   ntohl (mp->next_hop_id),
-				   ntohl (mp->next_hop_sw_if_index),
-				   next_hop_fib_index,
-				   mp->next_hop_weight,
-				   mp->next_hop_preference,
-				   ntohl (mp->next_hop_via_label),
-				   label_stack));
+  rv = add_del_route_t_handler (mp->is_multipath,
+				mp->is_add,
+				mp->is_drop,
+				mp->is_unreach,
+				mp->is_prohibit,
+				mp->is_local, 0,
+				mp->is_classify,
+				mp->classify_table_index,
+				mp->is_resolve_host,
+				mp->is_resolve_attached, 0, 0,
+				mp->is_dvr,
+				mp->is_source_lookup,
+				mp->is_udp_encap,
+				fib_index, &pfx, DPO_PROTO_IP4,
+				&nh,
+				ntohl (mp->next_hop_id),
+				ntohl (mp->next_hop_sw_if_index),
+				next_hop_fib_index,
+				mp->next_hop_weight,
+				mp->next_hop_preference,
+				ntohl (mp->next_hop_via_label), label_stack);
+
+  if (mp->is_add && 0 == rv)
+    *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
+
+  return (rv);
 }
 
 static int
-ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
+ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp,
+			     u32 * stats_index)
 {
   fib_mpls_label_t *label_stack = NULL;
   u32 fib_index, next_hop_fib_index;
@@ -1075,46 +1085,57 @@
 	}
     }
 
-  return (add_del_route_t_handler (mp->is_multipath,
-				   mp->is_add,
-				   mp->is_drop,
-				   mp->is_unreach,
-				   mp->is_prohibit,
-				   mp->is_local, 0,
-				   mp->is_classify,
-				   mp->classify_table_index,
-				   mp->is_resolve_host,
-				   mp->is_resolve_attached, 0, 0,
-				   mp->is_dvr,
-				   mp->is_source_lookup,
-				   mp->is_udp_encap,
-				   fib_index, &pfx, DPO_PROTO_IP6,
-				   &nh, ntohl (mp->next_hop_id),
-				   ntohl (mp->next_hop_sw_if_index),
-				   next_hop_fib_index,
-				   mp->next_hop_weight,
-				   mp->next_hop_preference,
-				   ntohl (mp->next_hop_via_label),
-				   label_stack));
+  rv = add_del_route_t_handler (mp->is_multipath,
+				mp->is_add,
+				mp->is_drop,
+				mp->is_unreach,
+				mp->is_prohibit,
+				mp->is_local, 0,
+				mp->is_classify,
+				mp->classify_table_index,
+				mp->is_resolve_host,
+				mp->is_resolve_attached, 0, 0,
+				mp->is_dvr,
+				mp->is_source_lookup,
+				mp->is_udp_encap,
+				fib_index, &pfx, DPO_PROTO_IP6,
+				&nh, ntohl (mp->next_hop_id),
+				ntohl (mp->next_hop_sw_if_index),
+				next_hop_fib_index,
+				mp->next_hop_weight,
+				mp->next_hop_preference,
+				ntohl (mp->next_hop_via_label), label_stack);
+
+  if (mp->is_add && 0 == rv)
+    *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
+
+  return (rv);
 }
 
 void
 vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
 {
   vl_api_ip_add_del_route_reply_t *rmp;
+  u32 stats_index;
   int rv;
   vnet_main_t *vnm = vnet_get_main ();
 
   vnm->api_errno = 0;
+  stats_index = ~0;
 
   if (mp->is_ipv6)
-    rv = ip6_add_del_route_t_handler (mp);
+    rv = ip6_add_del_route_t_handler (mp, &stats_index);
   else
-    rv = ip4_add_del_route_t_handler (mp);
+    rv = ip4_add_del_route_t_handler (mp, &stats_index);
 
   rv = (rv == 0) ? vnm->api_errno : rv;
 
-  REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
+  /* *INDENT-OFF* */
+  REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY,
+  ({
+    rmp->stats_index = htonl (stats_index);
+  }))
+  /* *INDENT-ON* */
 }
 
 void
@@ -1401,6 +1422,7 @@
       }));
       /* *INDENT-ON* */
     }
+
   BAD_SW_IF_INDEX_LABEL;
 }
 
diff --git a/src/vnet/mpls/mpls.api b/src/vnet/mpls/mpls.api
index 7ab0f37..7fa24f4 100644
--- a/src/vnet/mpls/mpls.api
+++ b/src/vnet/mpls/mpls.api
@@ -142,7 +142,7 @@
     @param mr_next_hop_out_label_stack - the next-hop output label stack, outer most first
     @param next_hop_via_label - The next-hop is a resolved via a local label
 */
-autoreply define mpls_route_add_del
+define mpls_route_add_del
 {
   u32 client_index;
   u32 context;
@@ -169,6 +169,13 @@
   vl_api_fib_mpls_label_t mr_next_hop_out_label_stack[mr_next_hop_n_out_labels];
 };
 
+define mpls_route_add_del_reply
+{
+  u32 context;
+  i32 retval;
+  u32 stats_index;
+};
+
 /** \brief Dump MPLS fib table
     @param client_index - opaque cookie to identify the sender
 */
diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c
index 8fec8e8..dbd1d8b 100644
--- a/src/vnet/mpls/mpls_api.c
+++ b/src/vnet/mpls/mpls_api.c
@@ -168,7 +168,8 @@
 
 static int
 mpls_route_add_del_t_handler (vnet_main_t * vnm,
-			      vl_api_mpls_route_add_del_t * mp)
+			      vl_api_mpls_route_add_del_t * mp,
+			      u32 * stats_index)
 {
   fib_mpls_label_t *label_stack = NULL;
   u32 fib_index, next_hop_fib_index;
@@ -227,31 +228,36 @@
     }
 
   /* *INDENT-OFF* */
-  return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add,
-                                   0,	// mp->is_drop,
-				   0,	// mp->is_unreach,
-				   0,	// mp->is_prohibit,
-				   0,	// mp->is_local,
-				   mp->mr_is_multicast,
-                                   mp->mr_is_classify,
-                                   mp->mr_classify_table_index,
-                                   mp->mr_is_resolve_host,
-                                   mp->mr_is_resolve_attached,
-                                   mp->mr_is_interface_rx,
-                                   mp->mr_is_rpf_id,
-                                   0,	// l2_bridged
-                                   0,   // is source_lookup
-                                   0,   // is_udp_encap
+  rv = add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add,
+                                0,	// mp->is_drop,
+                                0,	// mp->is_unreach,
+                                0,	// mp->is_prohibit,
+                                0,	// mp->is_local,
+                                mp->mr_is_multicast,
+                                mp->mr_is_classify,
+                                mp->mr_classify_table_index,
+                                mp->mr_is_resolve_host,
+                                mp->mr_is_resolve_attached,
+                                mp->mr_is_interface_rx,
+                                mp->mr_is_rpf_id,
+                                0,	// l2_bridged
+                                0,   // is source_lookup
+                                0,   // is_udp_encap
 				   fib_index, &pfx,
-				   mp->mr_next_hop_proto,
-				   &nh, ~0, // next_hop_id
-                                   ntohl (mp->mr_next_hop_sw_if_index),
-				   next_hop_fib_index,
-				   mp->mr_next_hop_weight,
-				   mp->mr_next_hop_preference,
-				   ntohl (mp->mr_next_hop_via_label),
-				   label_stack));
+                                mp->mr_next_hop_proto,
+                                &nh, ~0, // next_hop_id
+                                ntohl (mp->mr_next_hop_sw_if_index),
+                                next_hop_fib_index,
+                                mp->mr_next_hop_weight,
+                                mp->mr_next_hop_preference,
+                                ntohl (mp->mr_next_hop_via_label),
+                                label_stack);
   /* *INDENT-ON* */
+
+  if (mp->mr_is_add && 0 == rv)
+    *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx);
+
+  return (rv);
 }
 
 void
@@ -259,16 +265,20 @@
 {
   vl_api_mpls_route_add_del_reply_t *rmp;
   vnet_main_t *vnm;
+  u32 stats_index;
   int rv;
 
   vnm = vnet_get_main ();
-  vnm->api_errno = 0;
+  stats_index = ~0;
 
-  rv = mpls_route_add_del_t_handler (vnm, mp);
+  rv = mpls_route_add_del_t_handler (vnm, mp, &stats_index);
 
-  rv = (rv == 0) ? vnm->api_errno : rv;
-
-  REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
+  /* *INDENT-OFF* */
+  REPLY_MACRO2 (VL_API_MPLS_ROUTE_ADD_DEL_REPLY,
+  ({
+    rmp->stats_index = htonl (stats_index);
+  }));
+  /* *INDENT-ON* */
 }
 
 void