diff options
Diffstat (limited to 'src/plugins/perfmon/cli.c')
-rw-r--r-- | src/plugins/perfmon/cli.c | 220 |
1 files changed, 188 insertions, 32 deletions
diff --git a/src/plugins/perfmon/cli.c b/src/plugins/perfmon/cli.c index ce191eac35b..2c59ddd478a 100644 --- a/src/plugins/perfmon/cli.c +++ b/src/plugins/perfmon/cli.c @@ -15,7 +15,7 @@ #include <vnet/vnet.h> #include <perfmon/perfmon.h> -#include <perfmon/table.h> +#include <vppinfra/format_table.h> uword unformat_perfmon_bundle_name (unformat_input_t *input, va_list *args) @@ -38,6 +38,40 @@ unformat_perfmon_bundle_name (unformat_input_t *input, va_list *args) } uword +unformat_perfmon_active_type (unformat_input_t *input, va_list *args) +{ + perfmon_bundle_t *b = va_arg (*args, perfmon_bundle_t *); + perfmon_bundle_type_t *bundle_type = va_arg (*args, perfmon_bundle_type_t *); + char *str = 0; + + char *_str_types[PERFMON_BUNDLE_TYPE_MAX]; + +#define _(type, pstr) _str_types[type] = (char *) pstr; + + foreach_perfmon_bundle_type +#undef _ + + if (!b) return 0; + + if (unformat (input, "%s", &str) == 0) + return 0; + + for (int i = PERFMON_BUNDLE_TYPE_NODE; i < PERFMON_BUNDLE_TYPE_MAX; i++) + { + /* match the name and confirm it is available on this cpu */ + if (strncmp (str, _str_types[i], strlen (_str_types[i])) == 0 && + (b->type_flags & 1 << i)) + { + *bundle_type = i; + break; + } + } + + vec_free (str); + return 1; +} + +uword unformat_perfmon_source_name (unformat_input_t *input, va_list *args) { perfmon_main_t *pm = &perfmon_main; @@ -57,23 +91,33 @@ unformat_perfmon_source_name (unformat_input_t *input, va_list *args) return p ? 1 : 0; } +typedef enum +{ + FORMAT_PERFMON_BUNDLE_NONE = 0, + FORMAT_PERFMON_BUNDLE_VERBOSE = 1, + FORMAT_PERFMON_BUNDLE_SHOW_CONFIG = 2 +} format_perfmon_bundle_args_t; + u8 * format_perfmon_bundle (u8 *s, va_list *args) { perfmon_bundle_t *b = va_arg (*args, perfmon_bundle_t *); - int verbose = va_arg (*args, int); + format_perfmon_bundle_args_t cfg = + va_arg (*args, format_perfmon_bundle_args_t); - const char *bundle_type[] = { - [PERFMON_BUNDLE_TYPE_NODE] = "node", - [PERFMON_BUNDLE_TYPE_THREAD] = "thread", - [PERFMON_BUNDLE_TYPE_SYSTEM] = "system", - }; + int vl = 0; - if (b == 0) - return format (s, "%-20s%-10s%-20s%s", "Name", "Type", "Source", - "Description"); + u8 *_bundle_type = 0; + const char *bundle_type[PERFMON_BUNDLE_TYPE_MAX]; +#define _(type, pstr) bundle_type[type] = (const char *) pstr; - if (verbose) + foreach_perfmon_bundle_type +#undef _ + + if (b == 0) return format (s, "%-20s%-20s%-20s%s", "Name", "Type(s)", + "Source", "Description"); + + if (cfg != FORMAT_PERFMON_BUNDLE_NONE) { s = format (s, "name: %s\n", b->name); s = format (s, "description: %s\n", b->description); @@ -81,12 +125,34 @@ format_perfmon_bundle (u8 *s, va_list *args) for (int i = 0; i < b->n_events; i++) { perfmon_event_t *e = b->src->events + b->events[i]; - s = format (s, "event %u: %s\n", i, e->name); + s = format (s, "event %u: %s", i, e->name); + + format_function_t *format_config = b->src->format_config; + + if (format_config && cfg == FORMAT_PERFMON_BUNDLE_SHOW_CONFIG) + s = format (s, " (%U)", format_config, e->config); + + s = format (s, "\n"); } } else - s = format (s, "%-20s%-10s%-20s%s", b->name, bundle_type[b->type], - b->src->name, b->description); + { + s = format (s, "%-20s", b->name); + for (int i = PERFMON_BUNDLE_TYPE_NODE; i < PERFMON_BUNDLE_TYPE_MAX; i++) + { + /* check the type is available on this uarch*/ + if (b->type_flags & 1 << i) + _bundle_type = format (_bundle_type, "%s,", bundle_type[i]); + } + /* remove any stray commas */ + if ((vl = vec_len (_bundle_type))) + _bundle_type[vl - 1] = 0; + + s = + format (s, "%-20s%-20s%s", _bundle_type, b->src->name, b->description); + } + + vec_free (_bundle_type); return s; } @@ -108,6 +174,7 @@ show_perfmon_bundle_command_fn (vlib_main_t *vm, unformat_input_t *input, unformat_input_t _line_input, *line_input = &_line_input; perfmon_bundle_t *b = 0, **vb = 0; int verbose = 0; + format_perfmon_bundle_args_t cfg = FORMAT_PERFMON_BUNDLE_NONE; if (unformat_user (input, unformat_line_input, line_input)) { @@ -125,23 +192,31 @@ show_perfmon_bundle_command_fn (vlib_main_t *vm, unformat_input_t *input, unformat_free (line_input); } - if (vb == 0) + if (verbose) /* if verbose is specified */ + cfg = FORMAT_PERFMON_BUNDLE_VERBOSE; + + if (vb) + { + if (verbose) /* if verbose is specified with a bundle */ + cfg = FORMAT_PERFMON_BUNDLE_SHOW_CONFIG; + else + cfg = FORMAT_PERFMON_BUNDLE_VERBOSE; + } + else { char *key; hash_foreach_mem (key, b, pm->bundle_by_name, vec_add (vb, &b, 1);); } - else - verbose = 1; - if (verbose == 0) - vlib_cli_output (vm, "%U\n", format_perfmon_bundle, 0, 0); + if (cfg == FORMAT_PERFMON_BUNDLE_NONE) + vlib_cli_output (vm, "%U\n", format_perfmon_bundle, 0, cfg); vec_sort_with_function (vb, bundle_name_sort_cmp); for (int i = 0; i < vec_len (vb); i++) /* bundle type will be unknown if no cpu_supports matched */ - if (vb[i]->type != PERFMON_BUNDLE_TYPE_UNKNOWN) - vlib_cli_output (vm, "%U\n", format_perfmon_bundle, vb[i], verbose); + if (vb[i]->type_flags) + vlib_cli_output (vm, "%U\n", format_perfmon_bundle, vb[i], cfg); vec_free (vb); return 0; @@ -295,7 +370,8 @@ show_perfmon_stats_command_fn (vlib_main_t *vm, unformat_input_t *input, vec_validate (readings, n_instances - 1); /*Only perform read() for THREAD or SYSTEM bundles*/ - for (int i = 0; i < n_instances && b->type != PERFMON_BUNDLE_TYPE_NODE; i++) + for (int i = 0; + i < n_instances && b->active_type != PERFMON_BUNDLE_TYPE_NODE; i++) { in = vec_elt_at_index (it->instances, i); r = vec_elt_at_index (readings, i); @@ -324,8 +400,8 @@ show_perfmon_stats_command_fn (vlib_main_t *vm, unformat_input_t *input, { in = vec_elt_at_index (it->instances, i); r = vec_elt_at_index (readings, i); - table_format_cell (t, col, -1, "%s", in->name, b->type); - if (b->type == PERFMON_BUNDLE_TYPE_NODE) + table_format_cell (t, col, -1, "%s", in->name, b->active_type); + if (b->active_type == PERFMON_BUNDLE_TYPE_NODE) { perfmon_thread_runtime_t *tr; tr = vec_elt_at_index (pm->thread_runtimes, i); @@ -334,20 +410,80 @@ show_perfmon_stats_command_fn (vlib_main_t *vm, unformat_input_t *input, { perfmon_node_stats_t ns; table_format_cell (t, ++col, -1, "%U", format_vlib_node_name, - vm, j, b->type); + vm, j, b->active_type); table_set_cell_align (t, col, -1, TTAA_RIGHT); table_set_cell_fg_color (t, col, -1, TTAC_CYAN); - clib_memcpy_fast (&ns, tr->node_stats + j, sizeof (ns)); + + if (PREDICT_TRUE (clib_bitmap_is_zero (b->event_disabled))) + clib_memcpy_fast (&ns, tr->node_stats + j, sizeof (ns)); + /* if some events are not implemented, we need to realign these + to display under the correct column headers */ + else + { + perfmon_node_stats_t *tr_ns = tr->node_stats + j; + ns.n_calls = tr_ns->n_calls; + ns.n_packets = tr_ns->n_packets; + /* loop through all events in bundle + manually copy into + the correct place, until we've read all values that are + implemented */ + int num_enabled_events = + b->n_events - + clib_bitmap_count_set_bits (b->event_disabled); + for (int i = 0, k = 0; k < num_enabled_events; i++) + { + if (!clib_bitmap_get (b->event_disabled, i)) + { + ns.value[i] = tr_ns->value[k]; + k++; + } + } + } for (int j = 0; j < n_row; j++) - table_format_cell (t, col, j, "%U", b->format_fn, &ns, j, - b->type); + { + if (clib_bitmap_get (b->column_disabled, j)) + table_format_cell (t, col, j, "-"); + else + table_format_cell (t, col, j, "%U", b->format_fn, &ns, j, + b->active_type); + } } } - else + else /* b->type != PERFMON_BUNDLE_TYPE_NODE */ { - for (int j = 0; j < n_row; j++) - table_format_cell (t, i, j, "%U", b->format_fn, r, j, b->type); + if (PREDICT_TRUE (clib_bitmap_is_zero (b->event_disabled))) + { + for (int j = 0; j < n_row; j++) + table_format_cell (t, i, j, "%U", b->format_fn, r, j, + b->active_type); + } + /* similarly for THREAD/SYSTEM bundles, if some events are not + implemented, we need to realign readings under column headings */ + else + { + perfmon_reading_t aligned_r[b->n_events]; + aligned_r->nr = r->nr; + aligned_r->time_enabled = r->time_enabled; + aligned_r->time_running = r->time_running; + int num_enabled_events = + b->n_events - clib_bitmap_count_set_bits (b->event_disabled); + for (int i = 0, k = 0; k < num_enabled_events; i++) + { + if (!clib_bitmap_get (b->event_disabled, i)) + { + aligned_r->value[i] = r->value[k]; + k++; + } + } + for (int j = 0; j < n_row; j++) + { + if (clib_bitmap_get (b->column_disabled, j)) + table_format_cell (t, col, j, "-"); + else + table_format_cell (t, i, j, "%U", b->format_fn, aligned_r, + j, b->active_type); + } + } } col++; } @@ -393,6 +529,7 @@ perfmon_start_command_fn (vlib_main_t *vm, unformat_input_t *input, perfmon_main_t *pm = &perfmon_main; unformat_input_t _line_input, *line_input = &_line_input; perfmon_bundle_t *b = 0; + perfmon_bundle_type_t bundle_type = PERFMON_BUNDLE_TYPE_UNKNOWN; if (pm->is_running) return clib_error_return (0, "please stop first"); @@ -404,6 +541,9 @@ perfmon_start_command_fn (vlib_main_t *vm, unformat_input_t *input, { if (unformat (line_input, "bundle %U", unformat_perfmon_bundle_name, &b)) ; + else if (unformat (line_input, "type %U", unformat_perfmon_active_type, + b, &bundle_type)) + ; else return clib_error_return (0, "unknown input '%U'", format_unformat_error, line_input); @@ -413,12 +553,28 @@ perfmon_start_command_fn (vlib_main_t *vm, unformat_input_t *input, if (b == 0) return clib_error_return (0, "please specify bundle name"); + /* if there is more than one valid mode */ + if (count_set_bits (b->type_flags) > 1) + { + /* what did the user indicate */ + if (!bundle_type) + return clib_error_return (0, "please specify a valid type"); + } + /* otherwise just use the default */ + else if (!bundle_type) + { + bundle_type = + (perfmon_bundle_type_t) count_trailing_zeros (b->type_flags); + } + + b->active_type = bundle_type; + return perfmon_start (vm, b); } VLIB_CLI_COMMAND (perfmon_start_command, static) = { .path = "perfmon start", - .short_help = "perfmon start bundle [<bundle-name>]", + .short_help = "perfmon start bundle [<bundle-name>] type [<node|thread>]", .function = perfmon_start_command_fn, .is_mp_safe = 1, }; |