From 7681b1c469eda79003eef550fda460f48e5a08d7 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Sat, 8 Jun 2019 12:33:13 -0400 Subject: [PATCH] mactime: add per-mac allow-with-quota feature 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 --- src/plugins/mactime/mactime.api | 3 ++- src/plugins/mactime/mactime.c | 34 ++++++++++++++++++++++++++++------ src/plugins/mactime/mactime.h | 4 +++- src/plugins/mactime/mactime_test.c | 10 ++++++++-- src/plugins/mactime/node.c | 37 ++++++++++++++++++++++++++++++++----- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/plugins/mactime/mactime.api b/src/plugins/mactime/mactime.api index d9049d8dbd1..3ba6464ec43 100644 --- a/src/plugins/mactime/mactime.api +++ b/src/plugins/mactime/mactime.api @@ -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 */ diff --git a/src/plugins/mactime/mactime.c b/src/plugins/mactime/mactime.c index d84151ed29e..57895404390 100644 --- a/src/plugins/mactime/mactime.c +++ b/src/plugins/mactime/mactime.c @@ -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++) { diff --git a/src/plugins/mactime/mactime.h b/src/plugins/mactime/mactime.h index 928d7e940b6..11e33c1122b 100644 --- a/src/plugins/mactime/mactime.h +++ b/src/plugins/mactime/mactime.h @@ -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 { diff --git a/src/plugins/mactime/mactime_test.c b/src/plugins/mactime/mactime_test.c index 36ee063135d..4557e57dbff 100644 --- a/src/plugins/mactime/mactime_test.c +++ b/src/plugins/mactime/mactime_test.c @@ -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)); diff --git a/src/plugins/mactime/node.c b/src/plugins/mactime/node.c index e4d12f80db4..608773d5ce4 100644 --- a/src/plugins/mactime/node.c +++ b/src/plugins/mactime/node.c @@ -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++; } -- 2.16.6