Added show command to display only the routes in the RIB that does not count ECMPs

Signed-off-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Reviewed-by: JR Rivers <jrrivers@cumulusnetworks.com>
Reviewed-by: Paul Jakma <paul@opensourcerouting.org>
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 1d12ac5..9d6c1dd 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1074,6 +1074,84 @@
 	   fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE);  
 }
 
+/*
+ * Implementation of the ip route summary prefix command.
+ *
+ * This command prints the primary prefixes that have been installed by various
+ * protocols on the box.
+ *
+ */
+static void
+vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table)
+{
+  struct route_node *rn;
+  struct rib *rib;
+  struct nexthop *nexthop;
+#define ZEBRA_ROUTE_IBGP  ZEBRA_ROUTE_MAX
+#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
+  u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+  u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+  u_int32_t i;
+  int       cnt;
+
+  memset (&rib_cnt, 0, sizeof(rib_cnt));
+  memset (&fib_cnt, 0, sizeof(fib_cnt));
+  for (rn = route_top (table); rn; rn = route_next (rn))
+    RNODE_FOREACH_RIB (rn, rib)
+      {
+
+       /*
+        * In case of ECMP, count only once.
+        */
+       cnt = 0;
+       for (nexthop = rib->nexthop; (!cnt && nexthop); nexthop = nexthop->next)
+         {
+          cnt++;
+          rib_cnt[ZEBRA_ROUTE_TOTAL]++;
+          rib_cnt[rib->type]++;
+          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+	        {
+	         fib_cnt[ZEBRA_ROUTE_TOTAL]++;
+             fib_cnt[rib->type]++;
+            }
+	      if (rib->type == ZEBRA_ROUTE_BGP &&
+	          CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
+            {
+	         rib_cnt[ZEBRA_ROUTE_IBGP]++;
+		     if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+		        fib_cnt[ZEBRA_ROUTE_IBGP]++;
+            }
+	     }
+      }
+
+  vty_out (vty, "%-20s %-20s %-20s %s",
+	   "Route Source", "Prefix Routes", "FIB", VTY_NEWLINE);
+
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+    {
+      if (rib_cnt[i] > 0)
+	{
+	  if (i == ZEBRA_ROUTE_BGP)
+	    {
+	      vty_out (vty, "%-20s %-20d %-20d %s", "ebgp",
+		       rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP],
+		       fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP],
+		       VTY_NEWLINE);
+	      vty_out (vty, "%-20s %-20d %-20d %s", "ibgp",
+		       rib_cnt[ZEBRA_ROUTE_IBGP], fib_cnt[ZEBRA_ROUTE_IBGP],
+		       VTY_NEWLINE);
+	    }
+	  else
+	    vty_out (vty, "%-20s %-20d %-20d %s", zebra_route_string(i),
+		     rib_cnt[i], fib_cnt[i], VTY_NEWLINE);
+	}
+    }
+
+  vty_out (vty, "------%s", VTY_NEWLINE);
+  vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL],
+	   fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE);
+}
+
 /* Show route summary.  */
 DEFUN (show_ip_route_summary,
        show_ip_route_summary_cmd,
@@ -1094,6 +1172,27 @@
   return CMD_SUCCESS;
 }
 
+/* Show route summary prefix.  */
+DEFUN (show_ip_route_summary_prefix,
+       show_ip_route_summary_prefix_cmd,
+       "show ip route summary prefix",
+       SHOW_STR
+       IP_STR
+       "IP routing table\n"
+       "Summary of all routes\n"
+       "Prefix routes\n")
+{
+  struct route_table *table;
+
+  table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
+
+  vty_show_ip_route_summary_prefix (vty, table);
+
+  return CMD_SUCCESS;
+}
+
 /* Write IPv4 static route configuration. */
 static int
 static_config_ipv4 (struct vty *vty)
@@ -1931,6 +2030,27 @@
   return CMD_SUCCESS;
 }
 
+/* Show ipv6 route summary prefix.  */
+DEFUN (show_ipv6_route_summary_prefix,
+       show_ipv6_route_summary_prefix_cmd,
+       "show ipv6 route summary prefix",
+       SHOW_STR
+       IP_STR
+       "IPv6 routing table\n"
+       "Summary of all IPv6 routes\n"
+       "Prefix routes\n")
+{
+  struct route_table *table;
+
+  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
+  if (! table)
+    return CMD_SUCCESS;
+
+  vty_show_ip_route_summary_prefix (vty, table);
+
+  return CMD_SUCCESS;
+}
+
 /*
  * Show IPv6 mroute command.Used to dump
  * the Multicast routing table.
@@ -2100,6 +2220,7 @@
   install_element (VIEW_NODE, &show_ip_route_protocol_cmd);
   install_element (VIEW_NODE, &show_ip_route_supernets_cmd);
   install_element (VIEW_NODE, &show_ip_route_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_route_summary_prefix_cmd);
   install_element (ENABLE_NODE, &show_ip_route_cmd);
   install_element (ENABLE_NODE, &show_ip_route_addr_cmd);
   install_element (ENABLE_NODE, &show_ip_route_prefix_cmd);
@@ -2107,6 +2228,7 @@
   install_element (ENABLE_NODE, &show_ip_route_protocol_cmd);
   install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
   install_element (ENABLE_NODE, &show_ip_route_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_route_summary_prefix_cmd);
 
   install_element (VIEW_NODE, &show_ip_mroute_cmd);
   install_element (ENABLE_NODE, &show_ip_mroute_cmd);
@@ -2131,6 +2253,7 @@
   install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_summary_cmd);
+  install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_addr_cmd);
   install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd);
@@ -2141,6 +2264,7 @@
   install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
   install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
   install_element (ENABLE_NODE, &show_ipv6_route_summary_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_route_summary_prefix_cmd);
 
   install_element (VIEW_NODE, &show_ipv6_mroute_cmd);
   install_element (ENABLE_NODE, &show_ipv6_mroute_cmd);