LCOV - code coverage report
Current view: top level - plugins/perfmon - cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 7 275 2.5 %
Date: 2023-10-26 01:39:38 Functions: 14 27 51.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2020 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/vnet.h>
      17             : #include <perfmon/perfmon.h>
      18             : #include <vppinfra/format_table.h>
      19             : 
      20             : uword
      21           0 : unformat_perfmon_bundle_name (unformat_input_t *input, va_list *args)
      22             : {
      23           0 :   perfmon_main_t *pm = &perfmon_main;
      24           0 :   perfmon_bundle_t **b = va_arg (*args, perfmon_bundle_t **);
      25             :   uword *p;
      26           0 :   u8 *str = 0;
      27             : 
      28           0 :   if (unformat (input, "%s", &str) == 0)
      29           0 :     return 0;
      30             : 
      31           0 :   p = hash_get_mem (pm->bundle_by_name, str);
      32             : 
      33           0 :   if (p)
      34           0 :     b[0] = (perfmon_bundle_t *) p[0];
      35             : 
      36           0 :   vec_free (str);
      37           0 :   return p ? 1 : 0;
      38             : }
      39             : 
      40             : uword
      41           0 : unformat_perfmon_active_type (unformat_input_t *input, va_list *args)
      42             : {
      43           0 :   perfmon_bundle_t *b = va_arg (*args, perfmon_bundle_t *);
      44           0 :   perfmon_bundle_type_t *bundle_type = va_arg (*args, perfmon_bundle_type_t *);
      45           0 :   char *str = 0;
      46             : 
      47             :   char *_str_types[PERFMON_BUNDLE_TYPE_MAX];
      48             : 
      49             : #define _(type, pstr) _str_types[type] = (char *) pstr;
      50             : 
      51           0 :   foreach_perfmon_bundle_type
      52             : #undef _
      53             : 
      54           0 :     if (!b) return 0;
      55             : 
      56           0 :   if (unformat (input, "%s", &str) == 0)
      57           0 :     return 0;
      58             : 
      59           0 :   for (int i = PERFMON_BUNDLE_TYPE_NODE; i < PERFMON_BUNDLE_TYPE_MAX; i++)
      60             :     {
      61             :       /* match the name and confirm it is available on this cpu */
      62           0 :       if (strncmp (str, _str_types[i], strlen (_str_types[i])) == 0 &&
      63           0 :           (b->type_flags & 1 << i))
      64             :         {
      65           0 :           *bundle_type = i;
      66           0 :           break;
      67             :         }
      68             :     }
      69             : 
      70           0 :   vec_free (str);
      71           0 :   return 1;
      72             : }
      73             : 
      74             : uword
      75           0 : unformat_perfmon_source_name (unformat_input_t *input, va_list *args)
      76             : {
      77           0 :   perfmon_main_t *pm = &perfmon_main;
      78           0 :   perfmon_source_t **b = va_arg (*args, perfmon_source_t **);
      79             :   uword *p;
      80           0 :   u8 *str = 0;
      81             : 
      82           0 :   if (unformat (input, "%s", &str) == 0)
      83           0 :     return 0;
      84             : 
      85           0 :   p = hash_get_mem (pm->source_by_name, str);
      86             : 
      87           0 :   if (p)
      88           0 :     b[0] = (perfmon_source_t *) p[0];
      89             : 
      90           0 :   vec_free (str);
      91           0 :   return p ? 1 : 0;
      92             : }
      93             : 
      94             : typedef enum
      95             : {
      96             :   FORMAT_PERFMON_BUNDLE_NONE = 0,
      97             :   FORMAT_PERFMON_BUNDLE_VERBOSE = 1,
      98             :   FORMAT_PERFMON_BUNDLE_SHOW_CONFIG = 2
      99             : } format_perfmon_bundle_args_t;
     100             : 
     101             : u8 *
     102           0 : format_perfmon_bundle (u8 *s, va_list *args)
     103             : {
     104           0 :   perfmon_bundle_t *b = va_arg (*args, perfmon_bundle_t *);
     105           0 :   format_perfmon_bundle_args_t cfg =
     106             :     va_arg (*args, format_perfmon_bundle_args_t);
     107             : 
     108           0 :   int vl = 0;
     109             : 
     110           0 :   u8 *_bundle_type = 0;
     111             :   const char *bundle_type[PERFMON_BUNDLE_TYPE_MAX];
     112             : #define _(type, pstr) bundle_type[type] = (const char *) pstr;
     113             : 
     114           0 :   foreach_perfmon_bundle_type
     115             : #undef _
     116             : 
     117           0 :     if (b == 0) return format (s, "%-20s%-20s%-20s%s", "Name", "Type(s)",
     118             :                                "Source", "Description");
     119             : 
     120           0 :   if (cfg != FORMAT_PERFMON_BUNDLE_NONE)
     121             :     {
     122           0 :       s = format (s, "name: %s\n", b->name);
     123           0 :       s = format (s, "description: %s\n", b->description);
     124           0 :       s = format (s, "source: %s\n", b->src->name);
     125           0 :       for (int i = 0; i < b->n_events; i++)
     126             :         {
     127           0 :           perfmon_event_t *e = b->src->events + b->events[i];
     128           0 :           s = format (s, "event %u: %s", i, e->name);
     129             : 
     130           0 :           format_function_t *format_config = b->src->format_config;
     131             : 
     132           0 :           if (format_config && cfg == FORMAT_PERFMON_BUNDLE_SHOW_CONFIG)
     133           0 :             s = format (s, " (%U)", format_config, e->config);
     134             : 
     135           0 :           s = format (s, "\n");
     136             :         }
     137             :     }
     138             :   else
     139             :     {
     140           0 :       s = format (s, "%-20s", b->name);
     141           0 :       for (int i = PERFMON_BUNDLE_TYPE_NODE; i < PERFMON_BUNDLE_TYPE_MAX; i++)
     142             :         {
     143             :           /* check the type is available on this uarch*/
     144           0 :           if (b->type_flags & 1 << i)
     145           0 :             _bundle_type = format (_bundle_type, "%s,", bundle_type[i]);
     146             :         }
     147             :       /* remove any stray commas */
     148           0 :       if ((vl = vec_len (_bundle_type)))
     149           0 :         _bundle_type[vl - 1] = 0;
     150             : 
     151             :       s =
     152           0 :         format (s, "%-20s%-20s%s", _bundle_type, b->src->name, b->description);
     153             :     }
     154             : 
     155           0 :   vec_free (_bundle_type);
     156             : 
     157           0 :   return s;
     158             : }
     159             : 
     160             : static int
     161           0 : bundle_name_sort_cmp (void *a1, void *a2)
     162             : {
     163           0 :   perfmon_bundle_t **n1 = a1;
     164           0 :   perfmon_bundle_t **n2 = a2;
     165             : 
     166           0 :   return clib_strcmp ((char *) (*n1)->name, (char *) (*n2)->name);
     167             : }
     168             : 
     169             : static clib_error_t *
     170           0 : show_perfmon_bundle_command_fn (vlib_main_t *vm, unformat_input_t *input,
     171             :                                 vlib_cli_command_t *cmd)
     172             : {
     173           0 :   perfmon_main_t *pm = &perfmon_main;
     174           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     175           0 :   perfmon_bundle_t *b = 0, **vb = 0;
     176           0 :   int verbose = 0;
     177           0 :   format_perfmon_bundle_args_t cfg = FORMAT_PERFMON_BUNDLE_NONE;
     178             : 
     179           0 :   if (unformat_user (input, unformat_line_input, line_input))
     180             :     {
     181           0 :       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     182             :         {
     183           0 :           if (unformat (line_input, "verbose"))
     184           0 :             verbose = 1;
     185           0 :           else if (unformat (line_input, "%U", unformat_perfmon_bundle_name,
     186             :                              &b))
     187           0 :             vec_add (vb, &b, 1);
     188             :           else
     189           0 :             return clib_error_return (0, "unknown input `%U'",
     190             :                                       format_unformat_error, line_input);
     191             :         }
     192           0 :       unformat_free (line_input);
     193             :     }
     194             : 
     195           0 :   if (verbose) /* if verbose is specified */
     196           0 :     cfg = FORMAT_PERFMON_BUNDLE_VERBOSE;
     197             : 
     198           0 :   if (vb)
     199             :     {
     200           0 :       if (verbose) /* if verbose is specified with a bundle */
     201           0 :         cfg = FORMAT_PERFMON_BUNDLE_SHOW_CONFIG;
     202             :       else
     203           0 :         cfg = FORMAT_PERFMON_BUNDLE_VERBOSE;
     204             :     }
     205             :   else
     206             :     {
     207             :       char *key;
     208           0 :       hash_foreach_mem (key, b, pm->bundle_by_name, vec_add (vb, &b, 1););
     209             :     }
     210             : 
     211           0 :   if (cfg == FORMAT_PERFMON_BUNDLE_NONE)
     212           0 :     vlib_cli_output (vm, "%U\n", format_perfmon_bundle, 0, cfg);
     213             : 
     214           0 :   vec_sort_with_function (vb, bundle_name_sort_cmp);
     215             : 
     216           0 :   for (int i = 0; i < vec_len (vb); i++)
     217             :     /* bundle type will be unknown if no cpu_supports matched */
     218           0 :     if (vb[i]->type_flags)
     219           0 :       vlib_cli_output (vm, "%U\n", format_perfmon_bundle, vb[i], cfg);
     220             : 
     221           0 :   vec_free (vb);
     222           0 :   return 0;
     223             : }
     224             : 
     225       52565 : VLIB_CLI_COMMAND (show_perfmon_bundle_command, static) = {
     226             :   .path = "show perfmon bundle",
     227             :   .short_help = "show perfmon bundle [<bundle-name>] [verbose]",
     228             :   .function = show_perfmon_bundle_command_fn,
     229             :   .is_mp_safe = 1,
     230             : };
     231             : 
     232             : u8 *
     233           0 : format_perfmon_source (u8 *s, va_list *args)
     234             : {
     235           0 :   perfmon_source_t *src = va_arg (*args, perfmon_source_t *);
     236           0 :   int verbose = va_arg (*args, int);
     237             : 
     238           0 :   if (src == 0)
     239           0 :     return format (s, "%-20s%-9s %s", "Name", "NumEvents", "Description");
     240             : 
     241           0 :   if (verbose)
     242             :     {
     243           0 :       s = format (s, "name:        %s\n", src->name);
     244           0 :       s = format (s, "description: %s\n", src->description);
     245           0 :       s = format (s, "Events:\n");
     246           0 :       for (int i = 0; i < src->n_events; i++)
     247             :         {
     248           0 :           perfmon_event_t *e = src->events + i;
     249           0 :           s = format (s, "  %s", e->name);
     250           0 :           if (src->format_config)
     251           0 :             s = format (s, " (%U)\n", src->format_config, e->config);
     252             :           else
     253           0 :             s = format (s, " (0x%x)\n", e->config);
     254           0 :           if (e->description)
     255           0 :             s = format (s, "    %s\n", e->description);
     256             :         }
     257             : 
     258           0 :       if (src->instances_by_type)
     259             :         {
     260           0 :           s = format (s, "Instances:\n");
     261           0 :           for (int i = 0; i < vec_len (src->instances_by_type); i++)
     262             :             {
     263             :               perfmon_instance_type_t *it;
     264           0 :               it = vec_elt_at_index (src->instances_by_type, i);
     265           0 :               if (vec_len (it->instances) == 0)
     266           0 :                 continue;
     267           0 :               s = format (s, "  %s:\n   ", it->name);
     268           0 :               for (int j = 0; j < vec_len (it->instances); j++)
     269             :                 {
     270           0 :                   perfmon_instance_t *in = vec_elt_at_index (it->instances, j);
     271           0 :                   s = format (s, " %s", in->name);
     272             :                 }
     273           0 :               s = format (s, "\n");
     274             :             }
     275             :         }
     276             :     }
     277             :   else
     278           0 :     s = format (s, "%-20s%9u %s", src->name, src->n_events, src->description);
     279             : 
     280           0 :   return s;
     281             : }
     282             : 
     283             : static clib_error_t *
     284           0 : show_perfmon_source_command_fn (vlib_main_t *vm, unformat_input_t *input,
     285             :                                 vlib_cli_command_t *cmd)
     286             : {
     287           0 :   perfmon_main_t *pm = &perfmon_main;
     288           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     289           0 :   perfmon_source_t *s = 0, **vs = 0;
     290           0 :   int verbose = 0;
     291             : 
     292           0 :   if (unformat_user (input, unformat_line_input, line_input))
     293             :     {
     294           0 :       while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     295             :         {
     296           0 :           if (unformat (line_input, "verbose"))
     297           0 :             verbose = 1;
     298           0 :           else if (unformat (line_input, "%U", unformat_perfmon_source_name,
     299             :                              &s))
     300           0 :             vec_add (vs, &s, 1);
     301             :           else
     302           0 :             return clib_error_return (0, "unknown input `%U'",
     303             :                                       format_unformat_error, line_input);
     304             :         }
     305           0 :       unformat_free (line_input);
     306             :     }
     307             : 
     308           0 :   if (vs == 0)
     309             :     {
     310             :       char *key;
     311           0 :       hash_foreach_mem (key, s, pm->source_by_name, vec_add (vs, &s, 1););
     312             :     }
     313             :   else
     314           0 :     verbose = 1;
     315             : 
     316           0 :   if (verbose == 0)
     317           0 :     vlib_cli_output (vm, "%U\n", format_perfmon_source, 0, 0);
     318             : 
     319           0 :   for (int i = 0; i < vec_len (vs); i++)
     320           0 :     vlib_cli_output (vm, "%U\n", format_perfmon_source, vs[i], verbose);
     321             : 
     322           0 :   vec_free (vs);
     323           0 :   return 0;
     324             : }
     325             : 
     326       52565 : VLIB_CLI_COMMAND (show_perfmon_source_command, static) = {
     327             :   .path = "show perfmon source",
     328             :   .short_help = "show perfmon source [<source-name>] [verbose]",
     329             :   .function = show_perfmon_source_command_fn,
     330             :   .is_mp_safe = 1,
     331             : };
     332             : 
     333             : static clib_error_t *
     334           0 : show_perfmon_active_bundle_command_fn (vlib_main_t *vm,
     335             :                                        unformat_input_t *input,
     336             :                                        vlib_cli_command_t *cmd)
     337             : {
     338           0 :   perfmon_main_t *pm = &perfmon_main;
     339             : 
     340           0 :   vlib_cli_output (vm, "%U\n", format_perfmon_bundle, pm->active_bundle, 1);
     341           0 :   return 0;
     342             : }
     343             : 
     344       52565 : VLIB_CLI_COMMAND (show_perfmon_active_bundle_command, static) = {
     345             :   .path = "show perfmon active-bundle",
     346             :   .short_help = "show perfmon active-bundle",
     347             :   .function = show_perfmon_active_bundle_command_fn,
     348             :   .is_mp_safe = 1,
     349             : };
     350             : 
     351             : static clib_error_t *
     352           0 : show_perfmon_stats_command_fn (vlib_main_t *vm, unformat_input_t *input,
     353             :                                vlib_cli_command_t *cmd)
     354             : {
     355           0 :   perfmon_main_t *pm = &perfmon_main;
     356           0 :   perfmon_bundle_t *b = pm->active_bundle;
     357           0 :   clib_error_t *err = 0;
     358           0 :   table_t table = {}, *t = &table;
     359             :   u32 n_instances;
     360           0 :   perfmon_reading_t *r, *readings = 0;
     361           0 :   perfmon_instance_type_t *it = pm->active_instance_type;
     362             :   perfmon_instance_t *in;
     363           0 :   u8 *s = 0;
     364           0 :   int n_row = 0;
     365             : 
     366           0 :   if (b == 0)
     367           0 :     return clib_error_return (0, "no bundle selected");
     368             : 
     369           0 :   n_instances = vec_len (it->instances);
     370           0 :   vec_validate (readings, n_instances - 1);
     371             : 
     372             :   /*Only perform read() for THREAD or SYSTEM bundles*/
     373           0 :   for (int i = 0;
     374           0 :        i < n_instances && b->active_type != PERFMON_BUNDLE_TYPE_NODE; i++)
     375             :     {
     376           0 :       in = vec_elt_at_index (it->instances, i);
     377           0 :       r = vec_elt_at_index (readings, i);
     378             : 
     379           0 :       if (read (pm->group_fds[i], r, (b->n_events + 3) * sizeof (u64)) == -1)
     380             :         {
     381           0 :           err = clib_error_return_unix (0, "read");
     382           0 :           goto done;
     383             :         }
     384             :     }
     385             : 
     386           0 :   table_format_title (t, "%s", b->description);
     387             : 
     388           0 :   table_add_header_col (t, 0);
     389           0 :   table_add_header_row (t, 0);
     390             : 
     391           0 :   if (b->column_headers)
     392             :     {
     393           0 :       char **hdr = b->column_headers;
     394           0 :       while (hdr[0])
     395           0 :         table_format_cell (t, -1, n_row++, "%s", hdr++[0]);
     396             :     }
     397             : 
     398           0 :   int col = 0;
     399           0 :   for (int i = 0; i < n_instances; i++)
     400             :     {
     401           0 :       in = vec_elt_at_index (it->instances, i);
     402           0 :       r = vec_elt_at_index (readings, i);
     403           0 :       table_format_cell (t, col, -1, "%s", in->name, b->active_type);
     404           0 :       if (b->active_type == PERFMON_BUNDLE_TYPE_NODE)
     405             :         {
     406             :           perfmon_thread_runtime_t *tr;
     407           0 :           tr = vec_elt_at_index (pm->thread_runtimes, i);
     408           0 :           for (int j = 0; j < tr->n_nodes; j++)
     409           0 :             if (tr->node_stats[j].n_calls)
     410             :               {
     411             :                 perfmon_node_stats_t ns;
     412           0 :                 table_format_cell (t, ++col, -1, "%U", format_vlib_node_name,
     413           0 :                                    vm, j, b->active_type);
     414           0 :                 table_set_cell_align (t, col, -1, TTAA_RIGHT);
     415           0 :                 table_set_cell_fg_color (t, col, -1, TTAC_CYAN);
     416             : 
     417           0 :                 if (PREDICT_TRUE (clib_bitmap_is_zero (b->event_disabled)))
     418           0 :                   clib_memcpy_fast (&ns, tr->node_stats + j, sizeof (ns));
     419             :                 /* if some events are not implemented, we need to realign these
     420             :                    to display under the correct column headers */
     421             :                 else
     422             :                   {
     423           0 :                     perfmon_node_stats_t *tr_ns = tr->node_stats + j;
     424           0 :                     ns.n_calls = tr_ns->n_calls;
     425           0 :                     ns.n_packets = tr_ns->n_packets;
     426             :                     /* loop through all events in bundle + manually copy into
     427             :                        the correct place, until we've read all values that are
     428             :                        implemented */
     429           0 :                     int num_enabled_events =
     430           0 :                       b->n_events -
     431           0 :                       clib_bitmap_count_set_bits (b->event_disabled);
     432           0 :                     for (int i = 0, k = 0; k < num_enabled_events; i++)
     433             :                       {
     434           0 :                         if (!clib_bitmap_get (b->event_disabled, i))
     435             :                           {
     436           0 :                             ns.value[i] = tr_ns->value[k];
     437           0 :                             k++;
     438             :                           }
     439             :                       }
     440             :                   }
     441             : 
     442           0 :                 for (int j = 0; j < n_row; j++)
     443             :                   {
     444           0 :                     if (clib_bitmap_get (b->column_disabled, j))
     445           0 :                       table_format_cell (t, col, j, "-");
     446             :                     else
     447           0 :                       table_format_cell (t, col, j, "%U", b->format_fn, &ns, j,
     448           0 :                                          b->active_type);
     449             :                   }
     450             :               }
     451             :         }
     452             :       else /* b->type != PERFMON_BUNDLE_TYPE_NODE */
     453             :         {
     454           0 :           if (PREDICT_TRUE (clib_bitmap_is_zero (b->event_disabled)))
     455             :             {
     456           0 :               for (int j = 0; j < n_row; j++)
     457           0 :                 table_format_cell (t, i, j, "%U", b->format_fn, r, j,
     458           0 :                                    b->active_type);
     459             :             }
     460             :           /* similarly for THREAD/SYSTEM bundles, if some events are not
     461             :              implemented, we need to realign readings under column headings */
     462             :           else
     463           0 :             {
     464           0 :               perfmon_reading_t aligned_r[b->n_events];
     465           0 :               aligned_r->nr = r->nr;
     466           0 :               aligned_r->time_enabled = r->time_enabled;
     467           0 :               aligned_r->time_running = r->time_running;
     468           0 :               int num_enabled_events =
     469           0 :                 b->n_events - clib_bitmap_count_set_bits (b->event_disabled);
     470           0 :               for (int i = 0, k = 0; k < num_enabled_events; i++)
     471             :                 {
     472           0 :                   if (!clib_bitmap_get (b->event_disabled, i))
     473             :                     {
     474           0 :                       aligned_r->value[i] = r->value[k];
     475           0 :                       k++;
     476             :                     }
     477             :                 }
     478           0 :               for (int j = 0; j < n_row; j++)
     479             :                 {
     480           0 :                   if (clib_bitmap_get (b->column_disabled, j))
     481           0 :                     table_format_cell (t, col, j, "-");
     482             :                   else
     483           0 :                     table_format_cell (t, i, j, "%U", b->format_fn, aligned_r,
     484           0 :                                        j, b->active_type);
     485             :                 }
     486             :             }
     487             :         }
     488           0 :       col++;
     489             :     }
     490             : 
     491           0 :   vlib_cli_output (vm, "%U\n", format_table, t);
     492           0 :   table_free (t);
     493             : 
     494           0 :   if (b->footer)
     495           0 :     vlib_cli_output (vm, "\n%s\n", b->footer);
     496             : 
     497           0 : done:
     498           0 :   vec_free (readings);
     499           0 :   vec_free (s);
     500           0 :   return err;
     501             : }
     502             : 
     503       52565 : VLIB_CLI_COMMAND (show_perfmon_stats_command, static) = {
     504             :   .path = "show perfmon statistics",
     505             :   .short_help = "show perfmon statistics [raw]",
     506             :   .function = show_perfmon_stats_command_fn,
     507             :   .is_mp_safe = 1,
     508             : };
     509             : 
     510             : static clib_error_t *
     511           0 : perfmon_reset_command_fn (vlib_main_t *vm, unformat_input_t *input,
     512             :                           vlib_cli_command_t *cmd)
     513             : {
     514           0 :   perfmon_reset (vm);
     515           0 :   return 0;
     516             : }
     517             : 
     518       52565 : VLIB_CLI_COMMAND (perfmon_reset_command, static) = {
     519             :   .path = "perfmon reset",
     520             :   .short_help = "perfmon reset",
     521             :   .function = perfmon_reset_command_fn,
     522             :   .is_mp_safe = 1,
     523             : };
     524             : 
     525             : static clib_error_t *
     526           0 : perfmon_start_command_fn (vlib_main_t *vm, unformat_input_t *input,
     527             :                           vlib_cli_command_t *cmd)
     528             : {
     529           0 :   perfmon_main_t *pm = &perfmon_main;
     530           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     531           0 :   perfmon_bundle_t *b = 0;
     532           0 :   perfmon_bundle_type_t bundle_type = PERFMON_BUNDLE_TYPE_UNKNOWN;
     533             : 
     534           0 :   if (pm->is_running)
     535           0 :     return clib_error_return (0, "please stop first");
     536             : 
     537           0 :   if (unformat_user (input, unformat_line_input, line_input) == 0)
     538           0 :     return clib_error_return (0, "please specify bundle name");
     539             : 
     540           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     541             :     {
     542           0 :       if (unformat (line_input, "bundle %U", unformat_perfmon_bundle_name, &b))
     543             :         ;
     544           0 :       else if (unformat (line_input, "type %U", unformat_perfmon_active_type,
     545             :                          b, &bundle_type))
     546             :         ;
     547             :       else
     548           0 :         return clib_error_return (0, "unknown input '%U'",
     549             :                                   format_unformat_error, line_input);
     550             :     }
     551           0 :   unformat_free (line_input);
     552             : 
     553           0 :   if (b == 0)
     554           0 :     return clib_error_return (0, "please specify bundle name");
     555             : 
     556             :   /* if there is more than one valid mode */
     557           0 :   if (count_set_bits (b->type_flags) > 1)
     558             :     {
     559             :       /* what did the user indicate */
     560           0 :       if (!bundle_type)
     561           0 :         return clib_error_return (0, "please specify a valid type");
     562             :     }
     563             :   /* otherwise just use the default  */
     564           0 :   else if (!bundle_type)
     565             :     {
     566           0 :       bundle_type =
     567           0 :         (perfmon_bundle_type_t) count_trailing_zeros (b->type_flags);
     568             :     }
     569             : 
     570           0 :   b->active_type = bundle_type;
     571             : 
     572           0 :   return perfmon_start (vm, b);
     573             : }
     574             : 
     575       52565 : VLIB_CLI_COMMAND (perfmon_start_command, static) = {
     576             :   .path = "perfmon start",
     577             :   .short_help = "perfmon start bundle [<bundle-name>] type [<node|thread>]",
     578             :   .function = perfmon_start_command_fn,
     579             :   .is_mp_safe = 1,
     580             : };
     581             : 
     582             : static clib_error_t *
     583           0 : perfmon_stop_command_fn (vlib_main_t *vm, unformat_input_t *input,
     584             :                          vlib_cli_command_t *cmd)
     585             : {
     586           0 :   return perfmon_stop (vm);
     587             : }
     588             : 
     589       52565 : VLIB_CLI_COMMAND (perfmon_stop_command, static) = {
     590             :   .path = "perfmon stop",
     591             :   .short_help = "perfmon stop",
     592             :   .function = perfmon_stop_command_fn,
     593             :   .is_mp_safe = 1,
     594             : };

Generated by: LCOV version 1.14