X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fmactime%2Fmactime.c;h=502ac98b7233d433ca4526a4dc88836c89ea4dd8;hb=2c41a61d5fc87737b9b46b88cb9271d0f987721e;hp=80d1b1b3e268c28fa83903fa8d4fc834dc98cae9;hpb=a6726b59f1488f1510b143e7533f0062e19786f6;p=vpp.git diff --git a/src/plugins/mactime/mactime.c b/src/plugins/mactime/mactime.c index 80d1b1b3e26..502ac98b723 100644 --- a/src/plugins/mactime/mactime.c +++ b/src/plugins/mactime/mactime.c @@ -24,28 +24,10 @@ #include /* define message IDs */ -#include +#include +#include -/* define message structures */ -#define vl_typedefs -#include -#undef vl_typedefs - -/* define generated endian-swappers */ -#define vl_endianfun -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - -/* Get the API version number */ -#define vl_api_version(n,v) static u32 api_version=(v); -#include -#undef vl_api_version #define REPLY_MSG_ID_BASE mm->msg_id_base #include @@ -55,12 +37,6 @@ mactime_main_t mactime_main; /** \file time-base src-mac filter device-input feature arc implementation */ -/* List of message types that this plugin understands */ - -#define foreach_mactime_plugin_api_msg \ -_(MACTIME_ENABLE_DISABLE, mactime_enable_disable) \ -_(MACTIME_ADD_DEL_RANGE, mactime_add_del_range) - static void feature_init (mactime_main_t * mm) { @@ -103,6 +79,8 @@ mactime_enable_disable (mactime_main_t * mm, u32 sw_if_index, vnet_feature_enable_disable ("device-input", "mactime", sw_if_index, enable_disable, 0, 0); + vnet_feature_enable_disable ("interface-output", "mactime-tx", + sw_if_index, enable_disable, 0, 0); return rv; } @@ -124,6 +102,8 @@ mactime_enable_disable_command_fn (vlib_main_t * vm, else if (unformat (input, "%U", unformat_vnet_sw_interface, mm->vnet_main, &sw_if_index)) ; + else if (unformat (input, "sw_if_index %d", &sw_if_index)) + ; else break; } @@ -143,11 +123,6 @@ mactime_enable_disable_command_fn (vlib_main_t * vm, (0, "Invalid interface, only works on physical ports"); break; - case VNET_API_ERROR_UNIMPLEMENTED: - return clib_error_return (0, - "Device driver doesn't support redirection"); - break; - default: return clib_error_return (0, "mactime_enable_disable returned %d", rv); } @@ -175,12 +150,111 @@ static void vl_api_mactime_enable_disable_t_handler mactime_main_t *mm = &mactime_main; int rv; + VALIDATE_SW_IF_INDEX (mp); + rv = mactime_enable_disable (mm, ntohl (mp->sw_if_index), (int) (mp->enable_disable)); - + BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_MACTIME_ENABLE_DISABLE_REPLY); } +static void +vl_api_mactime_dump_t_handler (vl_api_mactime_dump_t * mp) +{ + vl_api_mactime_details_t *ep; + vl_api_mactime_dump_reply_t *rmp; + mactime_device_t *dev; + mactime_main_t *mm = &mactime_main; + vl_api_registration_t *rp; + int rv = 0, i; + u32 his_table_epoch = clib_net_to_host_u32 (mp->my_table_epoch); + u32 message_size; + u32 name_len; + u32 nranges; + + rp = vl_api_client_index_to_registration (mp->client_index); + if (rp == 0) + return; + + if (his_table_epoch == mm->device_table_epoch) + { + rv = VNET_API_ERROR_NO_CHANGE; + goto send_reply; + } + + /* *INDENT-OFF* */ + pool_foreach (dev, mm->devices, + ({ + message_size = sizeof(*ep) + vec_len(dev->device_name) + + vec_len(dev->ranges) * sizeof(ep->ranges[0]); + + ep = vl_msg_api_alloc (message_size); + memset (ep, 0, message_size); + ep->_vl_msg_id = clib_host_to_net_u16 (VL_API_MACTIME_DETAILS + + mm->msg_id_base); + /* Index is the key for the stats segment combined counters */ + ep->pool_index = clib_host_to_net_u32 (dev - mm->devices); + + clib_memcpy_fast (ep->mac_address, dev->mac_address, + sizeof (ep->mac_address)); + ep->data_quota = clib_host_to_net_u64 (dev->data_quota); + ep->data_used_in_range = clib_host_to_net_u64 (dev->data_used_in_range); + ep->flags = clib_host_to_net_u32 (dev->flags); + nranges = vec_len (dev->ranges); + ep->nranges = clib_host_to_net_u32 (nranges); + + for (i = 0; i < vec_len (dev->ranges); i++) + { + ep->ranges[i].start = dev->ranges[i].start; + ep->ranges[i].end = dev->ranges[i].end; + } + + name_len = vec_len (dev->device_name); + name_len = (name_len < ARRAY_LEN(ep->device_name)) ? + name_len : ARRAY_LEN(ep->device_name) - 1; + + clib_memcpy_fast (ep->device_name, dev->device_name, + name_len); + ep->device_name [ARRAY_LEN(ep->device_name) -1] = 0; + vl_api_send_msg (rp, (u8 *)ep); + })); + /* *INDENT-OFF* */ + + send_reply: + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_MACTIME_DUMP_REPLY, + ({ + rmp->table_epoch = clib_host_to_net_u32 (mm->device_table_epoch); + })); + /* *INDENT-ON* */ +} + +/** Create a lookup table entry for the indicated mac address + */ +void +mactime_send_create_entry_message (u8 * mac_address) +{ + mactime_main_t *mm = &mactime_main; + api_main_t *am; + vl_shmem_hdr_t *shmem_hdr; + u8 *name; + vl_api_mactime_add_del_range_t *mp; + + am = &api_main; + shmem_hdr = am->shmem_hdr; + mp = vl_msg_api_alloc_as_if_client (sizeof (*mp)); + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_MACTIME_ADD_DEL_RANGE + mm->msg_id_base); + name = format (0, "mac-%U", format_mac_address, mac_address); + + memcpy (mp->device_name, name, vec_len (name)); + memcpy (mp->mac_address, mac_address, sizeof (mp->mac_address)); + /* $$$ config: create allow / drop / range */ + mp->allow = 1; + mp->is_add = 1; + vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp); +} + /** Add or delete static / dynamic accept/drop configuration for a src mac */ @@ -193,11 +267,22 @@ static void vl_api_mactime_add_del_range_t_handler clib_bihash_kv_8_8_t kv; int found = 1; clib_bihash_8_8_t *lut = &mm->lookup_table; + u64 data_quota; int i, rv = 0; feature_init (mm); - memset (&kv, 0, sizeof (kv)); + /* + * Change the table epoch. Skip 0 so clients can code my_table_epoch = 0 + * to receive a full dump. + */ + mm->device_table_epoch++; + if (PREDICT_FALSE (mm->device_table_epoch == 0)) + mm->device_table_epoch++; + + data_quota = clib_net_to_host_u64 (mp->data_quota); + + clib_memset (&kv, 0, sizeof (kv)); memcpy (&kv.key, mp->mac_address, sizeof (mp->mac_address)); /* See if we have a lookup table entry for this src mac address */ @@ -211,14 +296,15 @@ static void vl_api_mactime_add_del_range_t_handler if (found == 0) { pool_get (mm->devices, dp); - memset (dp, 0, sizeof (*dp)); - vlib_validate_simple_counter (&mm->allow_counters, - dp - mm->devices); - vlib_zero_simple_counter (&mm->allow_counters, dp - mm->devices); - vlib_validate_simple_counter (&mm->drop_counters, dp - mm->devices); - vlib_zero_simple_counter (&mm->drop_counters, dp - mm->devices); + clib_memset (dp, 0, sizeof (*dp)); + vlib_validate_combined_counter (&mm->allow_counters, + dp - mm->devices); + vlib_zero_combined_counter (&mm->allow_counters, dp - mm->devices); + vlib_validate_combined_counter (&mm->drop_counters, + dp - mm->devices); + vlib_zero_combined_counter (&mm->drop_counters, dp - mm->devices); mp->device_name[ARRAY_LEN (mp->device_name) - 1] = 0; - dp->device_name = format (0, "%s", mp->device_name); + dp->device_name = format (0, "%s%c", mp->device_name, 0); memcpy (dp->mac_address, mp->mac_address, sizeof (mp->mac_address)); for (i = 0; i < clib_net_to_host_u32 (mp->count); i++) { @@ -235,6 +321,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 { @@ -244,14 +332,19 @@ static void vl_api_mactime_add_del_range_t_handler if (mp->allow) dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW; } + if (mp->no_udp_10001) + dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001; + + dp->data_quota = data_quota; /* Add the hash table entry */ kv.value = dp - mm->devices; clib_bihash_add_del_8_8 (lut, &kv, 1 /* is_add */ ); } - else /* add more ranges */ + else /* add more ranges, flags, etc. */ { dp = pool_elt_at_index (mm->devices, kv.value); + for (i = 0; i < clib_net_to_host_u32 (mp->count); i++) { clib_timebase_range_t _r, *r = &_r; @@ -259,6 +352,29 @@ static void vl_api_mactime_add_del_range_t_handler r->end = mp->ranges[i].end; vec_add1 (dp->ranges, r[0]); } + + if (vec_len (dp->ranges)) + { + /* Set allow/drop based on msg flags */ + if (mp->drop) + 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 + { + /* no ranges, it's a static allow/drop */ + if (mp->drop) + dp->flags = MACTIME_DEVICE_FLAG_STATIC_DROP; + if (mp->allow) + dp->flags = MACTIME_DEVICE_FLAG_STATIC_ALLOW; + } + if (mp->no_udp_10001) + dp->flags |= MACTIME_DEVICE_FLAG_DROP_UDP_10001; + + dp->data_quota = data_quota; } } else /* delete case */ @@ -282,64 +398,22 @@ reply: REPLY_MACRO (VL_API_MACTIME_ADD_DEL_RANGE_REPLY); } -/* Set up the API message handling tables */ -static clib_error_t * -mactime_plugin_api_hookup (vlib_main_t * vm) -{ - mactime_main_t *mm = &mactime_main; -#define _(N,n) \ - vl_msg_api_set_handlers((VL_API_##N + mm->msg_id_base), \ - #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_mactime_plugin_api_msg; -#undef _ - - return 0; -} - -#define vl_msg_name_crc_list -#include -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (mactime_main_t * mm, api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n #crc, id + mm->msg_id_base); - foreach_vl_msg_name_crc_mactime; -#undef _ -} - +#include static clib_error_t * mactime_init (vlib_main_t * vm) { mactime_main_t *mm = &mactime_main; - clib_error_t *error = 0; - u8 *name; mm->vlib_main = vm; mm->vnet_main = vnet_get_main (); - name = format (0, "mactime_%08x%c", api_version, 0); - /* Ask for a correctly-sized block of API message decode slots */ - mm->msg_id_base = vl_msg_api_get_msg_ids - ((char *) name, VL_MSG_FIRST_AVAILABLE); - - error = mactime_plugin_api_hookup (vm); - - /* Add our API messages to the global name_crc hash table */ - setup_message_id_table (mm, &api_main); - - vec_free (name); + mm->msg_id_base = setup_message_id_table (); mm->lookup_table_num_buckets = MACTIME_NUM_BUCKETS; mm->lookup_table_memory_size = MACTIME_MEMORY_SIZE; mm->timezone_offset = -5; /* US EST / EDT */ - return error; + return 0; } VLIB_INIT_FUNCTION (mactime_init); @@ -379,20 +453,61 @@ VNET_FEATURE_INIT (mactime, static) = }; /* *INDENT-ON */ +/* *INDENT-OFF* */ +VNET_FEATURE_INIT (mactime_tx, static) = +{ + .arc_name = "interface-output", + .node_name = "mactime-tx", + .runs_before = VNET_FEATURES ("interface-tx"), +}; +/* *INDENT-ON */ + /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, - .description = "Time-based MAC source-address filter", + .description = "Time-based MAC Source Address Filter", }; /* *INDENT-ON* */ -static u8 * -format_mac_address (u8 * s, va_list * args) +u8 * +format_bytes_with_width (u8 * s, va_list * va) { - u8 *a = va_arg (*args, u8 *); - return format (s, "%02x:%02x:%02x:%02x:%02x:%02x", - a[0], a[1], a[2], a[3], a[4], a[5]); + 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; } static clib_error_t * @@ -408,7 +523,18 @@ show_mactime_command_fn (vlib_main_t * vm, int current_status = 99; int i, j; f64 now; - u64 allow, drop; + vlib_counter_t allow, drop; + ethernet_arp_ip4_entry_t *n, *pool; + + vec_reset_length (mm->arp_cache_copy); + pool = ip4_neighbors_pool (); + + /* *INDENT-OFF* */ + pool_foreach (n, pool, + ({ + vec_add1 (mm->arp_cache_copy, n[0]); + })); + /* *INDENT-ON* */ now = clib_timebase_now (&mm->timebase); @@ -431,9 +557,9 @@ show_mactime_command_fn (vlib_main_t * vm, })); /* *INDENT-ON* */ - vlib_cli_output (vm, "%-15s %20s %16s %10s %10s", - "Device Name", "MAC address", "Current Status", "Allow", - "Drop"); + vlib_cli_output (vm, "%-15s %18s %14s %10s %11s %13s", + "Device Name", "Addresses", "Status", + "AllowPkt", "AllowByte", "DropPkt"); for (i = 0; i < vec_len (pool_indices); i++) { @@ -456,6 +582,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) @@ -478,6 +606,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); @@ -496,17 +626,39 @@ 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; } - allow = vlib_get_simple_counter (&mm->allow_counters, dp - mm->devices); - drop = vlib_get_simple_counter (&mm->drop_counters, dp - mm->devices); - vlib_cli_output (vm, "%-15s %20s %16s %10lld %10lld", + 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 %13lld", dp->device_name, macstring, status_string, - allow, drop); + allow.packets, format_bytes_with_width, allow.bytes, + 10, drop.packets); + if (dp->data_quota > 0) + 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++) + { + n = mm->arp_cache_copy + j; + if (!memcmp (dp->mac_address, n->mac.bytes, sizeof (n->mac))) + { + vlib_cli_output (vm, "%17s%U", " ", format_ip4_address, + &n->ip4_address); + } + } } - vec_free (macstring); vec_free (pool_indices); @@ -522,6 +674,30 @@ VLIB_CLI_COMMAND (show_mactime_command, static) = }; /* *INDENT-ON* */ +static clib_error_t * +clear_mactime_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + mactime_main_t *mm = &mactime_main; + + if (mm->feature_initialized == 0) + return clib_error_return (0, "feature not enabled"); + + vlib_clear_combined_counters (&mm->allow_counters); + vlib_clear_combined_counters (&mm->drop_counters); + vlib_cli_output (vm, "Mactime counters cleared..."); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (clear_mactime_command, static) = +{ + .path = "clear mactime", + .short_help = "clear mactime counters", + .function = clear_mactime_command_fn, +}; +/* *INDENT-ON* */ + /*