session: add session lookup cli for stats

Type: improvement

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I96bff47206ef64ea7369ae92e1b9ff1f74dfd71b
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c
index a884599..335905d 100644
--- a/src/vnet/session/session_lookup.c
+++ b/src/vnet/session/session_lookup.c
@@ -1710,6 +1710,85 @@
 };
 /* *INDENT-ON* */
 
+u8 *
+format_session_lookup_tables (u8 *s, va_list *args)
+{
+  u32 fib_proto = va_arg (*args, u32);
+  u32 *fibs, num_fibs = 0, fib_index, indent;
+  session_table_t *st;
+  u64 total_mem = 0;
+
+  fibs = fib_index_to_table_index[fib_proto];
+
+  for (fib_index = 0; fib_index < vec_len (fibs); fib_index++)
+    {
+      if (fibs[fib_index] == ~0)
+	continue;
+
+      num_fibs += 1;
+      st = session_table_get (fibs[fib_index]);
+      total_mem += session_table_memory_size (st);
+    }
+
+  indent = format_get_indent (s);
+  s = format (s, "active fibs:\t%u\n", num_fibs);
+  s = format (s, "%Umax fib-index:\t%u\n", format_white_space, indent,
+	      vec_len (fibs) - 1);
+  s = format (s, "%Utable memory:\t%U\n", format_white_space, indent,
+	      format_memory_size, total_mem);
+  s = format (s, "%Uvec memory:\t%U\n", format_white_space, indent,
+	      format_memory_size, vec_mem_size (fibs));
+
+  return s;
+}
+
+static clib_error_t *
+show_session_lookup_command_fn (vlib_main_t *vm, unformat_input_t *input,
+				vlib_cli_command_t *cmd)
+{
+  session_table_t *st;
+  u32 fib_index = ~0;
+
+  session_cli_return_if_not_enabled ();
+  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (input, "table %u", &fib_index))
+	;
+      else
+	return clib_error_return (0, "unknown input `%U'",
+				  format_unformat_error, input);
+    }
+
+  if (fib_index != ~0)
+    {
+      st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
+      if (st)
+	vlib_cli_output (vm, "%U", format_session_table, st);
+      else
+	vlib_cli_output (vm, "no ip4 table for fib-index %u", fib_index);
+      st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
+      if (st)
+	vlib_cli_output (vm, "%U", format_session_table, st);
+      else
+	vlib_cli_output (vm, "no ip6 table for fib-index %u", fib_index);
+      goto done;
+    }
+
+  vlib_cli_output (vm, "ip4 fib lookup tables:\n %U",
+		   format_session_lookup_tables, FIB_PROTOCOL_IP4);
+  vlib_cli_output (vm, "ip6 fib lookup tables:\n %U",
+		   format_session_lookup_tables, FIB_PROTOCOL_IP6);
+
+done:
+  return 0;
+}
+
+VLIB_CLI_COMMAND (show_session_lookup_command, static) = {
+  .path = "show session lookup",
+  .short_help = "show session lookup [table <fib-index>]",
+  .function = show_session_lookup_command_fn,
+};
+
 void
 session_lookup_init (void)
 {
diff --git a/src/vnet/session/session_table.c b/src/vnet/session/session_table.c
index 9af8ae6..cbb284d 100644
--- a/src/vnet/session/session_table.c
+++ b/src/vnet/session/session_table.c
@@ -185,6 +185,66 @@
 					   &ctx);
 }
 
+u32
+session_table_memory_size (session_table_t *st)
+{
+  u64 total_size = 0;
+
+  if (clib_bihash_is_initialised_16_8 (&st->v4_session_hash))
+    {
+      clib_bihash_alloc_chunk_16_8_t *c = st->v4_session_hash.chunks;
+      while (c)
+	{
+	  total_size += c->size;
+	  c = c->next;
+	}
+      c = st->v4_half_open_hash.chunks;
+      while (c)
+	{
+	  total_size += c->size;
+	  c = c->next;
+	}
+    }
+
+  if (clib_bihash_is_initialised_48_8 (&st->v6_session_hash))
+    {
+      clib_bihash_alloc_chunk_48_8_t *c = st->v6_session_hash.chunks;
+      while (c)
+	{
+	  total_size += c->size;
+	  c = c->next;
+	}
+      c = st->v6_half_open_hash.chunks;
+      while (c)
+	{
+	  total_size += c->size;
+	  c = c->next;
+	}
+    }
+
+  return total_size;
+}
+
+u8 *
+format_session_table (u8 *s, va_list *args)
+{
+  session_table_t *st = va_arg (*args, session_table_t *);
+
+  if (clib_bihash_is_initialised_16_8 (&st->v4_session_hash))
+    {
+      s = format (s, "%U", format_bihash_16_8, &st->v4_session_hash, 0);
+      s = format (s, "%U", format_bihash_16_8, &st->v4_half_open_hash, 0);
+    }
+
+  if (clib_bihash_is_initialised_48_8 (&st->v6_session_hash))
+    {
+      s = format (s, "%U", format_bihash_48_8, &st->v6_session_hash, 0);
+      s = format (s, "%U", format_bihash_48_8, &st->v6_half_open_hash, 0);
+    }
+
+  return s;
+}
+
 /* *INDENT-ON* */
 /*
  * fd.io coding-style-patch-verification: ON
diff --git a/src/vnet/session/session_table.h b/src/vnet/session/session_table.h
index 2127ea4..8e10b2f 100644
--- a/src/vnet/session/session_table.h
+++ b/src/vnet/session/session_table.h
@@ -69,6 +69,9 @@
 void session_table_init (session_table_t * slt, u8 fib_proto);
 void session_table_free (session_table_t *slt, u8 fib_proto);
 
+u32 session_table_memory_size (session_table_t *st);
+u8 *format_session_table (u8 *s, va_list *args);
+
 /* Internal, try not to use it! */
 session_table_t *_get_session_tables ();