mactime: add a "top" command to watch device stats
[vpp.git] / src / plugins / mactime / mactime_test.c
index c13ae8c..f7f4600 100644 (file)
@@ -20,6 +20,8 @@
 #include <vppinfra/error.h>
 #include <vppinfra/time_range.h>
 #include <vnet/ethernet/ethernet.h>
+#include <mactime/mactime_device.h>
+#include <vpp-api/client/stat_client.h>
 
 /* Declare message IDs */
 #include <mactime/mactime.api_enum.h>
 
 typedef struct
 {
+  /* device table */
+  mactime_device_t *devices;
+  uword *device_by_device_name;
+  u32 vpp_table_epoch;
+
+  /* time range setup */
+  f64 sunday_midnight;
+  clib_timebase_t timebase;
+  f64 timezone_offset;
+
   /* API message ID base */
   u16 msg_id_base;
   vat_main_t *vat_main;
@@ -78,6 +90,206 @@ api_mactime_enable_disable (vat_main_t * vam)
   return ret;
 }
 
+#if VPP_API_TEST_BUILTIN
+extern u8 *format_bytes_with_width (u8 * s, va_list * va);
+#else
+u8 *
+format_bytes_with_width (u8 * s, va_list * va)
+{
+  uword nbytes = va_arg (*va, u64);
+  int width = va_arg (*va, int);
+  f64 nbytes_f64;
+  u8 *fmt;
+  char *suffix = "";
+
+  if (width > 0)
+    fmt = format (0, "%%%d.3f%%s%c", width, 0);
+  else
+    fmt = format (0, "%%.3f%%s%c", 0);
+
+  if (nbytes > (1024ULL * 1024ULL * 1024ULL))
+    {
+      nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0 * 1024.0);
+      suffix = "G";
+    }
+  else if (nbytes > (1024ULL * 1024ULL))
+    {
+      nbytes_f64 = ((f64) nbytes) / (1024.0 * 1024.0);
+      suffix = "M";
+    }
+  else if (nbytes > 1024ULL)
+    {
+      nbytes_f64 = ((f64) nbytes) / (1024.0);
+      suffix = "K";
+    }
+  else
+    {
+      nbytes_f64 = (f64) nbytes;
+      suffix = "B";
+    }
+
+  s = format (s, (char *) fmt, nbytes_f64, suffix);
+  vec_free (fmt);
+  return s;
+}
+#endif
+
+static u8 *
+format_device (u8 * s, va_list * args)
+{
+  mactime_device_t *dp = va_arg (*args, mactime_device_t *);
+  mactime_test_main_t *mm = &mactime_test_main;
+  int verbose = va_arg (*args, int);
+  int current_status = 99;
+  char *status_string;
+  u8 *macstring = 0;
+  f64 now;
+  int j;
+
+  if (dp == 0)
+    {
+      s = format (s, "%-15s %5s %18s %14s %10s %11s %13s",
+                 "Device Name", "Index", "Addresses", "Status",
+                 "AllowPkt", "AllowByte", "DropPkt");
+      vec_add1 (s, '\n');
+      return s;
+    }
+
+  now = clib_timebase_now (&mm->timebase);
+
+  /* Check dynamic ranges */
+  for (j = 0; j < vec_len (dp->ranges); j++)
+    {
+      clib_timebase_range_t *r = dp->ranges + j;
+      f64 start0, end0;
+
+      start0 = r->start + mm->sunday_midnight;
+      end0 = r->end + mm->sunday_midnight;
+      if (verbose)
+       s = format (s, "  Range %d: %U - %U\n", j,
+                   format_clib_timebase_time, start0,
+                   format_clib_timebase_time, end0);
+
+      if (now >= start0 && now <= end0)
+       {
+         if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
+           current_status = 3;
+         else if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
+           current_status = 5;
+         else
+           current_status = 2;
+         if (verbose)
+           {
+             s = format (s, "  Time in range %d:", j);
+             s = format (s, "     %U - %U\n",
+                         format_clib_timebase_time, start0,
+                         format_clib_timebase_time, end0);
+           }
+         goto print;
+       }
+    }
+  if (verbose && j)
+    s = format (s, "  No range match.\n");
+  if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_DROP)
+    current_status = 0;
+  if (dp->flags & MACTIME_DEVICE_FLAG_STATIC_ALLOW)
+    current_status = 1;
+  if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
+    current_status = 2;
+  if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_DROP)
+    current_status = 3;
+  if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
+    current_status = 4;
+
+print:
+  macstring = format (0, "%U", format_mac_address, dp->mac_address);
+  switch (current_status)
+    {
+    case 0:
+      status_string = "static drop";
+      break;
+    case 1:
+      status_string = "static allow";
+      break;
+    case 2:
+      status_string = "dynamic drop";
+      break;
+    case 3:
+      status_string = "dynamic allow";
+      break;
+    case 4:
+      status_string = "d-quota inact";
+      break;
+    case 5:
+      status_string = "d-quota activ";
+      break;
+    default:
+      status_string = "code bug!";
+      break;
+    }
+
+  s = format (s, "%-15s %5d %18s %14s\n",
+             dp->device_name, dp->pool_index, macstring, status_string);
+  vec_free (macstring);
+
+  if (dp->data_quota > 0)
+    {
+      s = format (s, "%-59s %s%U %s%U", " ", "Quota ",
+                 format_bytes_with_width, dp->data_quota, 10,
+                 "Use ", format_bytes_with_width, dp->data_used_in_range, 8);
+      vec_add1 (s, '\n');
+    }
+  return s;
+}
+
+static int
+api_mactime_dump (vat_main_t * vam)
+{
+  mactime_test_main_t *tm = &mactime_test_main;
+  unformat_input_t *i = vam->input;
+  vl_api_mactime_dump_t *mp;
+  int verbose = 0;
+  int ret;
+  f64 now;
+  mactime_device_t *dev;
+
+  now = clib_timebase_now (&tm->timebase);
+
+  if (PREDICT_FALSE ((now - tm->sunday_midnight) > 86400.0 * 7.0))
+    tm->sunday_midnight = clib_timebase_find_sunday_midnight (now);
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "force"))
+       tm->vpp_table_epoch = 0;
+      else if (unformat (i, "verbose"))
+       verbose = 1;
+      else
+       break;
+    }
+
+  /* Construct the API message */
+  M (MACTIME_DUMP, mp);
+  mp->my_table_epoch = clib_host_to_net_u32 (tm->vpp_table_epoch);
+
+  /* send it... */
+  S (mp);
+
+  /* Wait for a reply... */
+  W (ret);
+
+  fformat (vam->ofp, "%U", format_device, 0 /* header */ , 0 /* verbose */ );
+  /* *INDENT-OFF* */
+  pool_foreach (dev, tm->devices,
+  ({
+    fformat (vam->ofp, "%U", format_device, dev, verbose);
+  }));
+  /* *INDENT-ON* */
+
+  return ret;
+}
+
 /* These two ought to be in a library somewhere but they aren't */
 static uword
 my_unformat_mac_address (unformat_input_t * input, va_list * args)
@@ -212,6 +424,14 @@ api_mactime_add_del_range (vat_main_t * vam)
   return ret;
 }
 
+/* We shouldn't get these... */
+static void
+vl_api_mactime_details_t_handler (vl_api_mactime_details_t * mp)
+{
+  clib_warning ("WARNING: stub called...");
+}
+
+
 #include <mactime/mactime.api_test.c>
 
 /*