mactime: add per-mac allow-with-quota feature 43/20043/2
authorDave Barach <dave@barachs.net>
Sat, 8 Jun 2019 16:33:13 +0000 (12:33 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Sat, 8 Jun 2019 19:39:57 +0000 (19:39 +0000)
Specify a data limit during specified time ranges. Outside of the
specified time ranges, data will be allowed.

Clean up "show mactime" output.

Type: feature

Change-Id: Iddd6678e7ded1d0f9cb88d69c656de8d87d5694c
Signed-off-by: Dave Barach <dave@barachs.net>
src/plugins/mactime/mactime.api
src/plugins/mactime/mactime.c
src/plugins/mactime/mactime.h
src/plugins/mactime/mactime_test.c
src/plugins/mactime/node.c

index d9049d8..3ba6464 100644 (file)
@@ -16,7 +16,7 @@
 /** \file
     This file defines vpp mactime control-plane API messages
 */
-option version = "1.1.0";
+option version = "1.1.1";
 
 /** \brief api to enable or disable the time-based src mac filter on
     an interface
@@ -74,6 +74,7 @@ autoreply define mactime_add_del_range
   u8 is_add;                    /**< add=1, del=0  */
   u8 drop;                      /**< drop flag */
   u8 allow;                     /**< allow flag */
+  u8 allow_quota;               /**< allow subject to quota */
   u8 no_udp_10001;              /**< drop udp to port 10001 */
   u64 data_quota;              /**< max bytes this device */
   u8 mac_address[6];            /**< src mac address */
index d84151e..5789540 100644 (file)
@@ -266,6 +266,8 @@ static void vl_api_mactime_add_del_range_t_handler
                dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_DROP;
              if (mp->allow)
                dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW;
+             if (mp->allow_quota)
+               dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA;
            }
          else
            {
@@ -303,6 +305,8 @@ static void vl_api_mactime_add_del_range_t_handler
                dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_DROP;
              if (mp->allow)
                dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW;
+             if (mp->allow_quota)
+               dp->flags = MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA;
            }
          else
            {
@@ -462,7 +466,10 @@ format_bytes_with_width (u8 * s, va_list * va)
   u8 *fmt;
   char *suffix = "";
 
-  fmt = format (0, "%%%d.3f%%s%c", width, 0);
+  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))
     {
@@ -480,7 +487,10 @@ format_bytes_with_width (u8 * s, va_list * va)
       suffix = "K";
     }
   else
-    nbytes_f64 = (f64) nbytes;
+    {
+      nbytes_f64 = (f64) nbytes;
+      suffix = "B";
+    }
 
   s = format (s, (char *) fmt, nbytes_f64, suffix);
   vec_free (fmt);
@@ -534,7 +544,7 @@ show_mactime_command_fn (vlib_main_t * vm,
   }));
   /* *INDENT-ON* */
 
-  vlib_cli_output (vm, "%-15s %18s %14s %10s %11s %10s",
+  vlib_cli_output (vm, "%-15s %18s %14s %10s %11s %13s",
                   "Device Name", "Addresses", "Status",
                   "AllowPkt", "AllowByte", "DropPkt");
 
@@ -559,6 +569,8 @@ show_mactime_command_fn (vlib_main_t * vm,
            {
              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)
@@ -581,6 +593,8 @@ show_mactime_command_fn (vlib_main_t * vm,
        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:
       vec_reset_length (macstring);
@@ -599,6 +613,12 @@ show_mactime_command_fn (vlib_main_t * vm,
        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;
@@ -606,13 +626,15 @@ show_mactime_command_fn (vlib_main_t * vm,
       vlib_get_combined_counter (&mm->allow_counters, dp - mm->devices,
                                 &allow);
       vlib_get_combined_counter (&mm->drop_counters, dp - mm->devices, &drop);
-      vlib_cli_output (vm, "%-15s %18s %14s %10lld %U %10lld",
+      vlib_cli_output (vm, "%-15s %18s %14s %10lld %U %13lld",
                       dp->device_name, macstring, status_string,
                       allow.packets, format_bytes_with_width, allow.bytes,
                       10, drop.packets);
       if (dp->data_quota > 0)
-       vlib_cli_output (vm, "%-54s %s%U", " ", "Quota ",
-                        format_bytes_with_width, dp->data_quota, 10);
+       vlib_cli_output (vm, "%-54s %s%U %s%U", " ", "Quota ",
+                        format_bytes_with_width, dp->data_quota, 10,
+                        "Use ", format_bytes_with_width,
+                        dp->data_used_in_range, 8);
       /* This is really only good for small N... */
       for (j = 0; j < vec_len (mm->arp_cache_copy); j++)
        {
index 928d7e9..11e33c1 100644 (file)
@@ -37,6 +37,7 @@ typedef struct
   u8 *device_name;
   u8 mac_address[6];
   u64 data_quota;
+  u64 data_used_in_range;
   u32 flags;
   clib_timebase_range_t *ranges;
 } mactime_device_t;
@@ -46,7 +47,8 @@ typedef struct
 #define MACTIME_DEVICE_FLAG_STATIC_ALLOW       (1<<1)
 #define MACTIME_DEVICE_FLAG_DYNAMIC_DROP       (1<<2)
 #define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW      (1<<3)
-#define MACTIME_DEVICE_FLAG_DROP_UDP_10001      (1<<4)
+#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA        (1<<4)
+#define MACTIME_DEVICE_FLAG_DROP_UDP_10001      (1<<5)
 
 typedef struct
 {
index 36ee063..4557e57 100644 (file)
@@ -158,6 +158,7 @@ api_mactime_add_del_range (vat_main_t * vam)
   int mac_set = 0;
   u8 is_add = 1;
   u8 allow = 0;
+  u8 allow_quota = 0;
   u8 drop = 0;
   u8 no_udp_10001 = 0;
   u64 data_quota = 0;
@@ -175,6 +176,9 @@ api_mactime_add_del_range (vat_main_t * vam)
       else if (unformat (i, "allow-range %U",
                         unformat_clib_timebase_range_vector, &rp))
        allow = 1;
+      else if (unformat (i, "allow-quota-range %U",
+                        unformat_clib_timebase_range_vector, &rp))
+       allow_quota = 1;
       else if (unformat (i, "drop-range %U",
                         unformat_clib_timebase_range_vector, &rp))
        drop = 1;
@@ -206,11 +210,12 @@ api_mactime_add_del_range (vat_main_t * vam)
     }
 
   /* allow-range / drop-range parse errors cause this condition */
-  if (is_add && allow == 0 && drop == 0)
+  if (is_add && allow == 0 && drop == 0 && allow_quota == 0)
     {
       vec_free (rp);
       vec_free (device_name);
-      errmsg ("neither allow nor drop set, parse error...\n");
+      errmsg ("parse error...\n");
+      return -99;
     }
 
   /* Unlikely, but check anyhow */
@@ -234,6 +239,7 @@ api_mactime_add_del_range (vat_main_t * vam)
   mp->is_add = is_add;
   mp->drop = drop;
   mp->allow = allow;
+  mp->allow_quota = allow_quota;
   mp->no_udp_10001 = no_udp_10001;
   mp->data_quota = clib_host_to_net_u64 (data_quota);
   memcpy (mp->mac_address, mac_address, sizeof (mp->mac_address));
index e4d12f8..608773d 100644 (file)
@@ -120,6 +120,7 @@ mactime_node_inline (vlib_main_t * vm,
          u32 device_index0;
          u32 len0;
          ethernet_header_t *en0;
+         int has_dynamic_range_allow = 0;
          int i;
 
          /* speculatively enqueue b0 to the current next frame */
@@ -168,8 +169,9 @@ mactime_node_inline (vlib_main_t * vm,
 
          dp = pool_elt_at_index (mm->devices, device_index0);
 
-         /* Known device, check for a traffic quota */
-         if (PREDICT_FALSE (dp->data_quota))
+         /* Known device, check for an always-on traffic quota */
+         if ((dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW)
+             && PREDICT_FALSE (dp->data_quota))
            {
              vlib_counter_t device_current_count;
              vlib_get_combined_counter (&mm->allow_counters,
@@ -242,6 +244,9 @@ mactime_node_inline (vlib_main_t * vm,
 
              start0 = r->start + mm->sunday_midnight;
              end0 = r->end + mm->sunday_midnight;
+             if (dp->flags & MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA)
+               has_dynamic_range_allow = 1;
+
              /* Packet within time range */
              if (now >= start0 && now <= end0)
                {
@@ -253,15 +258,35 @@ mactime_node_inline (vlib_main_t * vm,
                         dp - mm->devices, 1, len0);
                      next0 = MACTIME_NEXT_DROP;
                      b0->error = node->errors[MACTIME_ERROR_RANGE_DROP];
+                     goto trace0;
                    }
-                 else          /* it's an allow range, allow it */
+                 /* Quota-check allow range? */
+                 else if (has_dynamic_range_allow)
                    {
+                     if (dp->data_used_in_range + len0 >= dp->data_quota)
+                       {
+                         next0 = MACTIME_NEXT_DROP;
+                         b0->error = node->errors[MACTIME_ERROR_QUOTA_DROP];
+                         vlib_increment_combined_counter
+                           (&mm->drop_counters, thread_index,
+                            dp - mm->devices, 1, len0);
+                         goto trace0;
+                       }
+                     else
+                       {
+                         dp->data_used_in_range += len0;
+                         goto allow0;
+                       }
+                   }
+                 else
+                   {           /* it's an allow range, allow it */
+                   allow0:
                      vlib_increment_combined_counter
                        (&mm->allow_counters, thread_index,
                         dp - mm->devices, 1, len0);
                      packets_ok++;
+                     goto trace0;
                    }
-                 goto trace0;
                }
            }
          /*
@@ -275,11 +300,13 @@ mactime_node_inline (vlib_main_t * vm,
              vlib_increment_combined_counter
                (&mm->drop_counters, thread_index, dp - mm->devices, 1, len0);
            }
-         else
+         else                  /* DYNAMIC_DROP, DYNAMIC_RANGE_ALLOW_QUOTA */
            {
              vlib_increment_combined_counter
                (&mm->allow_counters, thread_index, dp - mm->devices, 1,
                 len0);
+             /* Clear the data quota accumulater */
+             dp->data_used_in_range = 0;
              packets_ok++;
            }