aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/perfmon/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/perfmon/cli.c')
-rw-r--r--src/plugins/perfmon/cli.c220
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,
};