FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
cli.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * cli.c: command line interface
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vlib/unix/unix.h>
42 #include <vppinfra/cpu.h>
43 #include <vppinfra/elog.h>
44 #include <unistd.h>
45 #include <ctype.h>
46 
47 int vl_api_set_elog_trace_api_messages (int enable);
49 
50 static void *current_traced_heap;
51 
52 /* Root of all show commands. */
53 /* *INDENT-OFF* */
54 VLIB_CLI_COMMAND (vlib_cli_show_command, static) = {
55  .path = "show",
56  .short_help = "Show commands",
57 };
58 /* *INDENT-ON* */
59 
60 /* Root of all clear commands. */
61 /* *INDENT-OFF* */
62 VLIB_CLI_COMMAND (vlib_cli_clear_command, static) = {
63  .path = "clear",
64  .short_help = "Clear commands",
65 };
66 /* *INDENT-ON* */
67 
68 /* Root of all set commands. */
69 /* *INDENT-OFF* */
70 VLIB_CLI_COMMAND (vlib_cli_set_command, static) = {
71  .path = "set",
72  .short_help = "Set commands",
73 };
74 /* *INDENT-ON* */
75 
76 /* Root of all test commands. */
77 /* *INDENT-OFF* */
78 VLIB_CLI_COMMAND (vlib_cli_test_command, static) = {
79  .path = "test",
80  .short_help = "Test commands",
81 };
82 /* *INDENT-ON* */
83 
84 /* Returns bitmap of commands which match key. */
85 static uword *
87 {
88  int i, n;
89  uword *match = 0;
91 
93 
94  for (i = 0;; i++)
95  {
96  uword k;
97 
98  k = unformat_get_input (input);
99  switch (k)
100  {
101  case 'a' ... 'z':
102  case 'A' ... 'Z':
103  case '0' ... '9':
104  case '-':
105  case '_':
106  break;
107 
108  case ' ':
109  case '\t':
110  case '\r':
111  case '\n':
113  /* White space or end of input removes any non-white
114  matches that were before possible. */
115  if (i < vec_len (c->sub_command_positions)
116  && clib_bitmap_count_set_bits (match) > 1)
117  {
119  for (n = 0; n < vec_len (p->bitmaps); n++)
120  match = clib_bitmap_andnot (match, p->bitmaps[n]);
121  }
122  goto done;
123 
124  default:
125  unformat_put_input (input);
126  goto done;
127  }
128 
129  if (i >= vec_len (c->sub_command_positions))
130  {
131  no_match:
132  clib_bitmap_free (match);
133  return 0;
134  }
135 
137  if (vec_len (p->bitmaps) == 0)
138  goto no_match;
139 
140  n = k - p->min_char;
141  if (n < 0 || n >= vec_len (p->bitmaps))
142  goto no_match;
143 
144  if (i == 0)
145  match = clib_bitmap_dup (p->bitmaps[n]);
146  else
147  match = clib_bitmap_and (match, p->bitmaps[n]);
148 
149  if (clib_bitmap_is_zero (match))
150  goto no_match;
151  }
152 
153 done:
154  return match;
155 }
156 
157 /* Looks for string based sub-input formatted { SUB-INPUT }. */
158 uword
160 {
161  unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
162  u8 *s;
163  uword c;
164 
165  while (1)
166  {
167  c = unformat_get_input (i);
168  switch (c)
169  {
170  case ' ':
171  case '\t':
172  case '\n':
173  case '\r':
174  case '\f':
175  break;
176 
177  case '{':
178  default:
179  /* Put back paren. */
180  if (c != UNFORMAT_END_OF_INPUT)
181  unformat_put_input (i);
182 
183  if (c == '{' && unformat (i, "%v", &s))
184  {
185  unformat_init_vector (sub_input, s);
186  return 1;
187  }
188  return 0;
189  }
190  }
191  return 0;
192 }
193 
194 static vlib_cli_command_t *
196 {
198  return vec_elt_at_index (cm->commands, s->index);
199 }
200 
201 static uword
203 {
204  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
205  vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
206  vlib_cli_command_t **result = va_arg (*args, vlib_cli_command_t **);
207  vlib_cli_main_t *cm = &vm->cli_main;
208  uword *match_bitmap, is_unique, index;
209 
210  {
213  vec_foreach (sr, c->sub_rules)
214  {
215  void **d;
216  r = vec_elt_at_index (cm->parse_rules, sr->rule_index);
217  vec_add2 (cm->parse_rule_data, d, 1);
218  vec_reset_length (d[0]);
219  if (r->data_size)
220  d[0] = _vec_resize (d[0],
221  /* length increment */ 1,
222  r->data_size,
223  /* header_bytes */ 0,
224  /* data align */ sizeof (uword));
225  if (unformat_user (i, r->unformat_function, vm, d[0]))
226  {
227  *result = vec_elt_at_index (cm->commands, sr->command_index);
228  return 1;
229  }
230  }
231  }
232 
233  match_bitmap = vlib_cli_sub_command_match (c, i);
234  is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1;
235  index = ~0;
236  if (is_unique)
237  {
238  index = clib_bitmap_first_set (match_bitmap);
239  *result = get_sub_command (cm, c, index);
240  }
241  clib_bitmap_free (match_bitmap);
242 
243  return is_unique;
244 }
245 
246 static int
247 vlib_cli_cmp_strings (void *a1, void *a2)
248 {
249  u8 *c1 = *(u8 **) a1;
250  u8 *c2 = *(u8 **) a2;
251 
252  return vec_cmp (c1, c2);
253 }
254 
255 u8 **
257 {
260  vlib_main_t *vm = vlib_get_main ();
261  vlib_cli_main_t *vcm = &vm->cli_main;
262  uword *match_bitmap = 0;
263  uword index, is_unique, help_next_level;
264  u8 **result = 0;
265  unformat_input_t input;
266  unformat_init_vector (&input, vec_dup (str));
267  c = vec_elt_at_index (vcm->commands, 0);
268 
269  /* remove trailing whitespace, except for one of them */
270  while (vec_len (input.buffer) >= 2 &&
271  isspace (input.buffer[vec_len (input.buffer) - 1]) &&
272  isspace (input.buffer[vec_len (input.buffer) - 2]))
273  {
274  vec_del1 (input.buffer, vec_len (input.buffer) - 1);
275  }
276 
277  /* if input is empty, directly return list of root commands */
278  if (vec_len (input.buffer) == 0 ||
279  (vec_len (input.buffer) == 1 && isspace (input.buffer[0])))
280  {
281  vec_foreach (sc, c->sub_commands)
282  {
283  vec_add1 (result, (u8 *) sc->name);
284  }
285  goto done;
286  }
287 
288  /* add a trailing '?' so that vlib_cli_sub_command_match can find
289  * all commands starting with the input string */
290  vec_add1 (input.buffer, '?');
291 
292  while (1)
293  {
294  match_bitmap = vlib_cli_sub_command_match (c, &input);
295  /* no match: return no result */
296  if (match_bitmap == 0)
297  {
298  goto done;
299  }
300  is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1;
301  /* unique match: try to step one subcommand level further */
302  if (is_unique)
303  {
304  /* stop if no more input */
305  if (input.index >= vec_len (input.buffer) - 1)
306  {
307  break;
308  }
309 
310  index = clib_bitmap_first_set (match_bitmap);
311  c = get_sub_command (vcm, c, index);
312  clib_bitmap_free (match_bitmap);
313  continue;
314  }
315  /* multiple matches: stop here, return all matches */
316  break;
317  }
318 
319  /* remove trailing '?' */
320  vec_del1 (input.buffer, vec_len (input.buffer) - 1);
321 
322  /* if we have a space at the end of input, and a unique match,
323  * autocomplete the next level of subcommands */
324  help_next_level = (vec_len (str) == 0) || isspace (str[vec_len (str) - 1]);
325  /* *INDENT-OFF* */
326  clib_bitmap_foreach(index, match_bitmap, {
327  if (help_next_level && is_unique) {
328  c = get_sub_command (vcm, c, index);
329  vec_foreach (sc, c->sub_commands) {
330  vec_add1 (result, (u8*) sc->name);
331  }
332  goto done; /* break doesn't work in this macro-loop */
333  }
334  sc = &c->sub_commands[index];
335  vec_add1(result, (u8*) sc->name);
336  });
337  /* *INDENT-ON* */
338 
339 done:
340  clib_bitmap_free (match_bitmap);
341  unformat_free (&input);
342 
343  if (result)
345  return result;
346 }
347 
348 static u8 *
349 format_vlib_cli_command_help (u8 * s, va_list * args)
350 {
351  vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
352  int is_long = va_arg (*args, int);
353  if (is_long && c->long_help)
354  s = format (s, "%s", c->long_help);
355  else if (c->short_help)
356  s = format (s, "%s", c->short_help);
357  else
358  s = format (s, "%v commands", c->path);
359  return s;
360 }
361 
362 static u8 *
363 format_vlib_cli_parse_rule_name (u8 * s, va_list * args)
364 {
365  vlib_cli_parse_rule_t *r = va_arg (*args, vlib_cli_parse_rule_t *);
366  return format (s, "<%U>", format_c_identifier, r->name);
367 }
368 
369 static u8 *
370 format_vlib_cli_path (u8 * s, va_list * args)
371 {
372  u8 *path = va_arg (*args, u8 *);
373  int i, in_rule;
374  in_rule = 0;
375  for (i = 0; i < vec_len (path); i++)
376  {
377  switch (path[i])
378  {
379  case '%':
380  in_rule = 1;
381  vec_add1 (s, '<'); /* start of <RULE> */
382  break;
383 
384  case '_':
385  /* _ -> space in rules. */
386  vec_add1 (s, in_rule ? ' ' : '_');
387  break;
388 
389  case ' ':
390  if (in_rule)
391  {
392  vec_add1 (s, '>'); /* end of <RULE> */
393  in_rule = 0;
394  }
395  vec_add1 (s, ' ');
396  break;
397 
398  default:
399  vec_add1 (s, path[i]);
400  break;
401  }
402  }
403 
404  if (in_rule)
405  vec_add1 (s, '>'); /* terminate <RULE> */
406 
407  return s;
408 }
409 
410 static vlib_cli_command_t *
412 {
413  vlib_cli_command_t *c = vec_elt_at_index (cm->commands, command_index);
416 
417  if (c->function)
418  vec_add1 (subs, c[0]);
419 
420  vec_foreach (sr, c->sub_rules)
421  subs = all_subs (cm, subs, sr->command_index);
422  vec_foreach (sc, c->sub_commands) subs = all_subs (cm, subs, sc->index);
423 
424  return subs;
425 }
426 
427 static int
428 vlib_cli_cmp_rule (void *a1, void *a2)
429 {
430  vlib_cli_sub_rule_t *r1 = a1;
431  vlib_cli_sub_rule_t *r2 = a2;
432 
433  return vec_cmp (r1->name, r2->name);
434 }
435 
436 static int
437 vlib_cli_cmp_command (void *a1, void *a2)
438 {
439  vlib_cli_command_t *c1 = a1;
440  vlib_cli_command_t *c2 = a2;
441 
442  return vec_cmp (c1->path, c2->path);
443 }
444 
445 static clib_error_t *
448  unformat_input_t * input,
449  uword parent_command_index)
450 {
451  vlib_cli_command_t *parent, *c;
452  clib_error_t *error = 0;
453  unformat_input_t sub_input;
454  u8 *string;
455  uword is_main_dispatch = cm == &vm->cli_main;
456 
457  parent = vec_elt_at_index (cm->commands, parent_command_index);
458  if (is_main_dispatch && unformat (input, "help"))
459  {
460  uword help_at_end_of_line, i;
461 
462  help_at_end_of_line =
464  while (1)
465  {
466  c = parent;
467  if (unformat_user
468  (input, unformat_vlib_cli_sub_command, vm, c, &parent))
469  ;
470 
471  else if (!(unformat_check_input (input) == UNFORMAT_END_OF_INPUT))
472  goto unknown;
473 
474  else
475  break;
476  }
477 
478  /* help SUB-COMMAND => long format help.
479  "help" at end of line: show all commands. */
480  if (!help_at_end_of_line)
482  /* is_long */ 1);
483 
484  else if (vec_len (c->sub_commands) + vec_len (c->sub_rules) == 0)
485  vlib_cli_output (vm, "%v: no sub-commands", c->path);
486 
487  else
488  {
490  vlib_cli_sub_rule_t *sr, *subs;
491 
492  subs = vec_dup (c->sub_rules);
493 
494  /* Add in rules if any. */
495  vec_foreach (sc, c->sub_commands)
496  {
497  vec_add2 (subs, sr, 1);
498  sr->name = sc->name;
499  sr->command_index = sc->index;
500  sr->rule_index = ~0;
501  }
502 
504 
505  for (i = 0; i < vec_len (subs); i++)
506  {
509 
510  d = vec_elt_at_index (cm->commands, subs[i].command_index);
511  r =
512  subs[i].rule_index != ~0 ? vec_elt_at_index (cm->parse_rules,
513  subs
514  [i].rule_index) :
515  0;
516 
517  if (r)
519  (vm, " %-30U %U",
521  format_vlib_cli_command_help, d, /* is_long */ 0);
522  else
524  (vm, " %-30v %U",
525  subs[i].name,
526  format_vlib_cli_command_help, d, /* is_long */ 0);
527  }
528 
529  vec_free (subs);
530  }
531  }
532 
533  else if (is_main_dispatch
534  && (unformat (input, "choices") || unformat (input, "?")))
535  {
536  vlib_cli_command_t *sub, *subs;
537 
538  subs = all_subs (cm, 0, parent_command_index);
540  vec_foreach (sub, subs)
541  vlib_cli_output (vm, " %-40U %U",
543  format_vlib_cli_command_help, sub, /* is_long */ 0);
544  vec_free (subs);
545  }
546 
547  else if (unformat (input, "comment %v", &string))
548  {
549  vec_free (string);
550  }
551 
552  else if (unformat (input, "uncomment %U",
553  unformat_vlib_cli_sub_input, &sub_input))
554  {
555  error =
556  vlib_cli_dispatch_sub_commands (vm, cm, &sub_input,
557  parent_command_index);
558  unformat_free (&sub_input);
559  }
560  else if (unformat (input, "leak-check %U",
561  unformat_vlib_cli_sub_input, &sub_input))
562  {
563  u8 *leak_report;
565  {
566  void *oldheap;
568  clib_mem_trace (0);
569  clib_mem_set_heap (oldheap);
571  }
572  clib_mem_trace (1);
573  error =
574  vlib_cli_dispatch_sub_commands (vm, cm, &sub_input,
575  parent_command_index);
576  unformat_free (&sub_input);
577 
578  /* Otherwise, the clib_error_t shows up as a leak... */
579  if (error)
580  {
581  vlib_cli_output (vm, "%v", error->what);
582  clib_error_free (error);
583  error = 0;
584  }
585 
587  leak_report = format (0, "%U", format_mheap, clib_mem_get_heap (),
588  1 /* verbose, i.e. print leaks */ );
589  clib_mem_trace (0);
590  vlib_cli_output (vm, "%v", leak_report);
591  vec_free (leak_report);
592  }
593 
594  else
595  if (unformat_user (input, unformat_vlib_cli_sub_command, vm, parent, &c))
596  {
597  unformat_input_t *si;
598  uword has_sub_commands =
599  vec_len (c->sub_commands) + vec_len (c->sub_rules) > 0;
600 
601  si = input;
602  if (unformat_user (input, unformat_vlib_cli_sub_input, &sub_input))
603  si = &sub_input;
604 
605  if (has_sub_commands)
606  error = vlib_cli_dispatch_sub_commands (vm, cm, si, c - cm->commands);
607 
608  if (has_sub_commands && !error)
609  /* Found valid sub-command. */ ;
610 
611  else if (c->function)
612  {
613  clib_error_t *c_error;
614 
615  /* Skip white space for benefit of called function. */
617 
618  if (unformat (si, "?"))
619  {
620  vlib_cli_output (vm, " %-40U %U", format_vlib_cli_path, c->path, format_vlib_cli_command_help, c, /* is_long */
621  0);
622  }
623  else
624  {
626  {
627  /* *INDENT-OFF* */
628  ELOG_TYPE_DECLARE (e) =
629  {
630  .format = "cli-cmd: %s",
631  .format_args = "T4",
632  };
633  /* *INDENT-ON* */
634  struct
635  {
636  u32 c;
637  } *ed;
638  ed = ELOG_DATA (&vm->elog_main, e);
639  ed->c = elog_string (&vm->elog_main, c->path);
640  }
641 
642  if (!c->is_mp_safe)
644 
645  c_error = c->function (vm, si, c);
646 
647  if (!c->is_mp_safe)
649 
651  {
652  /* *INDENT-OFF* */
653  ELOG_TYPE_DECLARE (e) =
654  {
655  .format = "cli-cmd: %s %s",
656  .format_args = "T4T4",
657  };
658  /* *INDENT-ON* */
659  struct
660  {
661  u32 c, err;
662  } *ed;
663  ed = ELOG_DATA (&vm->elog_main, e);
664  ed->c = elog_string (&vm->elog_main, c->path);
665  if (c_error)
666  {
667  vec_add1 (c_error->what, 0);
668  ed->err = elog_string (&vm->elog_main,
669  (char *) c_error->what);
670  _vec_len (c_error->what) -= 1;
671  }
672  else
673  ed->err = elog_string (&vm->elog_main, "OK");
674  }
675 
676  if (c_error)
677  {
678  error =
679  clib_error_return (0, "%v: %v", c->path, c_error->what);
680  clib_error_free (c_error);
681  /* Free sub input. */
682  if (si != input)
683  unformat_free (si);
684 
685  return error;
686  }
687  }
688 
689  /* Free any previous error. */
690  clib_error_free (error);
691  }
692 
693  else if (!error)
694  error = clib_error_return (0, "%v: no sub-commands", c->path);
695 
696  /* Free sub input. */
697  if (si != input)
698  unformat_free (si);
699  }
700 
701  else
702  goto unknown;
703 
704  return error;
705 
706 unknown:
707  if (parent->path)
708  return clib_error_return (0, "%v: unknown input `%U'", parent->path,
709  format_unformat_error, input);
710  else
711  return clib_error_return (0, "unknown input `%U'", format_unformat_error,
712  input);
713 }
714 
715 
717  __attribute__ ((weak));
718 
719 void
721 {
722 }
723 
724 /* Process CLI input. */
725 int
727  unformat_input_t * input,
728  vlib_cli_output_function_t * function, uword function_arg)
729 {
731  vlib_cli_main_t *cm = &vm->cli_main;
732  clib_error_t *error;
733  vlib_cli_output_function_t *save_function;
734  uword save_function_arg;
735  int rv = 0;
736 
737  save_function = cp->output_function;
738  save_function_arg = cp->output_function_arg;
739 
740  cp->output_function = function;
741  cp->output_function_arg = function_arg;
742 
743  do
744  {
746  error = vlib_cli_dispatch_sub_commands (vm, &vm->cli_main, input, /* parent */
747  0);
748  }
749  while (!error && !unformat (input, "%U", unformat_eof));
750 
751  if (error)
752  {
753  vlib_cli_output (vm, "%v", error->what);
754  vlib_unix_error_report (vm, error);
755  /* clib_error_return is unfortunately often called with a '0'
756  return code */
757  rv = error->code != 0 ? error->code : -1;
758  clib_error_free (error);
759  }
760 
761  cp->output_function = save_function;
762  cp->output_function_arg = save_function_arg;
763  return rv;
764 }
765 
766 /* Output to current CLI connection. */
767 void
768 vlib_cli_output (vlib_main_t * vm, char *fmt, ...)
769 {
771  va_list va;
772  u8 *s;
773 
774  va_start (va, fmt);
775  s = va_format (0, fmt, &va);
776  va_end (va);
777 
778  /* Terminate with \n if not present. */
779  if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n')
780  vec_add1 (s, '\n');
781 
782  if ((!cp) || (!cp->output_function))
783  fformat (stdout, "%v", s);
784  else
785  cp->output_function (cp->output_function_arg, s, vec_len (s));
786 
787  vec_free (s);
788 }
789 
790 void *vl_msg_push_heap (void) __attribute__ ((weak));
791 void *
793 {
794  return 0;
795 }
796 
797 void vl_msg_pop_heap (void *oldheap) __attribute__ ((weak));
798 void
799 vl_msg_pop_heap (void *oldheap)
800 {
801 }
802 
803 void *vlib_stats_push_heap (void *) __attribute__ ((weak));
804 void *
805 vlib_stats_push_heap (void *notused)
806 {
807  return 0;
808 }
809 
810 static clib_error_t *
812  unformat_input_t * input, vlib_cli_command_t * cmd)
813 {
814  int verbose __attribute__ ((unused)) = 0;
815  int api_segment = 0, stats_segment = 0, main_heap = 0;
816  clib_error_t *error;
817  u32 index = 0;
819  uword was_enabled;
820 
821 
823  {
824  if (unformat (input, "verbose"))
825  verbose = 1;
826  else if (unformat (input, "api-segment"))
827  api_segment = 1;
828  else if (unformat (input, "stats-segment"))
829  stats_segment = 1;
830  else if (unformat (input, "main-heap"))
831  main_heap = 1;
832  else
833  {
834  error = clib_error_return (0, "unknown input `%U'",
835  format_unformat_error, input);
836  return error;
837  }
838  }
839 
840  if ((api_segment + stats_segment + main_heap) == 0)
841  return clib_error_return
842  (0, "Please supply one of api-segment, stats-segment or main-heap");
843 
844  if (api_segment)
845  {
846  void *oldheap = vl_msg_push_heap ();
847  was_enabled = clib_mem_trace_enable_disable (0);
848  u8 *s_in_svm =
849  format (0, "%U\n", format_mheap, clib_mem_get_heap (), 1);
850  vl_msg_pop_heap (oldheap);
851  u8 *s = vec_dup (s_in_svm);
852 
853  oldheap = vl_msg_push_heap ();
854  vec_free (s_in_svm);
855  clib_mem_trace_enable_disable (was_enabled);
856  vl_msg_pop_heap (oldheap);
857  vlib_cli_output (vm, "API segment");
858  vlib_cli_output (vm, "%v", s);
859  vec_free (s);
860  }
861  if (stats_segment)
862  {
863  void *oldheap = vlib_stats_push_heap (0);
864  was_enabled = clib_mem_trace_enable_disable (0);
865  u8 *s_in_svm =
866  format (0, "%U\n", format_mheap, clib_mem_get_heap (), 1);
867  if (oldheap)
868  clib_mem_set_heap (oldheap);
869  u8 *s = vec_dup (s_in_svm);
870 
871  oldheap = vlib_stats_push_heap (0);
872  vec_free (s_in_svm);
873  if (oldheap)
874  {
875  clib_mem_trace_enable_disable (was_enabled);
876  clib_mem_set_heap (oldheap);
877  }
878  vlib_cli_output (vm, "Stats segment");
879  vlib_cli_output (vm, "%v", s);
880  vec_free (s);
881  }
882 
883 #if USE_DLMALLOC == 0
884  /* *INDENT-OFF* */
886  ({
888  vlib_cli_output (vm, "%sThread %d %s\n", index ? "\n":"", index,
889  vlib_worker_threads[index].name);
892  h->vm_alloc_size);
893  vlib_cli_output (vm, " %U\n", format_mheap, clib_per_cpu_mheaps[index],
894  verbose);
895  index++;
896  }));
897  /* *INDENT-ON* */
898 #else
899  {
900  if (main_heap)
901  {
902  /*
903  * Note: the foreach_vlib_main causes allocator traffic,
904  * so shut off tracing before we go there...
905  */
906  was_enabled = clib_mem_trace_enable_disable (0);
907 
908  /* *INDENT-OFF* */
910  ({
911  struct dlmallinfo mi;
912  void *mspace;
913  mspace = clib_per_cpu_mheaps[index];
914 
915  mi = mspace_mallinfo (mspace);
916  vlib_cli_output (vm, "%sThread %d %s\n", index ? "\n":"", index,
917  vlib_worker_threads[index].name);
918  vlib_cli_output (vm, " %U\n", format_page_map,
920  mi.arena);
921  vlib_cli_output (vm, " %U\n", format_mheap,
922  clib_per_cpu_mheaps[index],
923  verbose);
924  index++;
925  }));
926  /* *INDENT-ON* */
927 
928  /* Restore the trace flag */
929  clib_mem_trace_enable_disable (was_enabled);
930  }
931  }
932 #endif /* USE_DLMALLOC */
933  return 0;
934 }
935 
936 /* *INDENT-OFF* */
937 VLIB_CLI_COMMAND (show_memory_usage_command, static) = {
938  .path = "show memory",
939  .short_help = "show memory [api-segment][stats-segment][verbose]",
940  .function = show_memory_usage,
941 };
942 /* *INDENT-ON* */
943 
944 static clib_error_t *
946  vlib_cli_command_t * cmd)
947 {
948 #define _(a,b,c) vlib_cli_output (vm, "%-25s " b, a ":", c);
949  _("Model name", "%U", format_cpu_model_name);
950  _("Microarch model (family)", "%U", format_cpu_uarch);
951  _("Flags", "%U", format_cpu_flags);
952  _("Base frequency", "%.2f GHz",
953  ((f64) vm->clib_time.clocks_per_second) * 1e-9);
954 #undef _
955  return 0;
956 }
957 
958 /*?
959  * Displays various information about the CPU.
960  *
961  * @cliexpar
962  * @cliexstart{show cpu}
963  * Model name: Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz
964  * Microarchitecture: Broadwell (Broadwell-EP/EX)
965  * Flags: sse3 ssse3 sse41 sse42 avx avx2 aes
966  * Base Frequency: 3.20 GHz
967  * @cliexend
968 ?*/
969 /* *INDENT-OFF* */
970 VLIB_CLI_COMMAND (show_cpu_command, static) = {
971  .path = "show cpu",
972  .short_help = "Show cpu information",
973  .function = show_cpu,
974 };
975 /* *INDENT-ON* */
976 
977 static clib_error_t *
979  unformat_input_t * input,
980  vlib_cli_command_t * cmd)
981 {
982  unformat_input_t _line_input, *line_input = &_line_input;
983  int enable = 1;
984  int api_segment = 0;
985  int stats_segment = 0;
986  int main_heap = 0;
987  void *oldheap;
988 
989  if (!unformat_user (input, unformat_line_input, line_input))
990  return 0;
991 
992  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
993  {
994  if (unformat (line_input, "%U", unformat_vlib_enable_disable, &enable))
995  ;
996  else if (unformat (line_input, "api-segment"))
997  api_segment = 1;
998  else if (unformat (line_input, "stats-segment"))
999  stats_segment = 1;
1000  else if (unformat (line_input, "main-heap"))
1001  main_heap = 1;
1002  else
1003  {
1004  unformat_free (line_input);
1005  return clib_error_return (0, "invalid input");
1006  }
1007  }
1008  unformat_free (line_input);
1009 
1010  if ((api_segment + stats_segment + main_heap + (enable == 0)) == 0)
1011  {
1012  return clib_error_return
1013  (0, "Need one of main-heap, stats-segment or api-segment");
1014  }
1015 
1016  /* Turn off current trace, if any */
1017  if (current_traced_heap)
1018  {
1019  void *oldheap;
1021  clib_mem_trace (0);
1022  clib_mem_set_heap (oldheap);
1023  current_traced_heap = 0;
1024  }
1025 
1026  if (enable == 0)
1027  return 0;
1028 
1029  /* API segment */
1030  if (api_segment)
1031  {
1032  oldheap = vl_msg_push_heap ();
1034  clib_mem_trace (1);
1035  vl_msg_pop_heap (oldheap);
1036 
1037  }
1038 
1039  /* Stats segment */
1040  if (stats_segment)
1041  {
1042  oldheap = vlib_stats_push_heap (0);
1044  clib_mem_trace (stats_segment);
1045  /* We don't want to call vlib_stats_pop_heap... */
1046  if (oldheap)
1047  clib_mem_set_heap (oldheap);
1048  }
1049 
1050  /* main_heap */
1051  if (main_heap)
1052  {
1054  clib_mem_trace (main_heap);
1055  }
1056 
1057  return 0;
1058 }
1059 
1060 /* *INDENT-OFF* */
1061 VLIB_CLI_COMMAND (enable_disable_memory_trace_command, static) = {
1062  .path = "memory-trace",
1063  .short_help = "memory-trace on|off [api-segment][stats-segment][main-heap]\n",
1064  .function = enable_disable_memory_trace,
1065 };
1066 /* *INDENT-ON* */
1067 
1068 
1069 static clib_error_t *
1071  vlib_cli_command_t * cmd)
1072 {
1073 #if USE_DLMALLOC == 0
1074  clib_error_t *error = 0;
1075  void *heap;
1076  mheap_t *mheap;
1077 
1078  if (unformat (input, "on"))
1079  {
1080  /* *INDENT-OFF* */
1082  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
1083  mheap = mheap_header(heap);
1084  mheap->flags |= MHEAP_FLAG_VALIDATE;
1085  // Turn off small object cache because it delays detection of errors
1087  });
1088  /* *INDENT-ON* */
1089 
1090  }
1091  else if (unformat (input, "off"))
1092  {
1093  /* *INDENT-OFF* */
1095  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
1096  mheap = mheap_header(heap);
1097  mheap->flags &= ~MHEAP_FLAG_VALIDATE;
1099  });
1100  /* *INDENT-ON* */
1101  }
1102  else if (unformat (input, "now"))
1103  {
1104  /* *INDENT-OFF* */
1106  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
1107  mheap = mheap_header(heap);
1108  mheap_validate(heap);
1109  });
1110  /* *INDENT-ON* */
1111  vlib_cli_output (vm, "heap validation complete");
1112 
1113  }
1114  else
1115  {
1116  return clib_error_return (0, "unknown input `%U'",
1117  format_unformat_error, input);
1118  }
1119 
1120  return error;
1121 #else
1122  return clib_error_return (0, "unimplemented...");
1123 #endif /* USE_DLMALLOC */
1124 }
1125 
1126 /* *INDENT-OFF* */
1127 VLIB_CLI_COMMAND (cmd_test_heap_validate,static) = {
1128  .path = "test heap-validate",
1129  .short_help = "<on/off/now> validate heap on future allocs/frees or right now",
1130  .function = test_heap_validate,
1131 };
1132 /* *INDENT-ON* */
1133 
1134 static clib_error_t *
1136  vlib_cli_command_t * cmd)
1137 {
1139  clib_file_t *f;
1140 
1141  /* environ(7) does not indicate a header for this */
1142  extern char **environ;
1143 
1144  /* Close all known open files */
1145  /* *INDENT-OFF* */
1146  pool_foreach(f, fm->file_pool,
1147  ({
1148  if (f->file_descriptor > 2)
1149  close(f->file_descriptor);
1150  }));
1151  /* *INDENT-ON* */
1152 
1153  /* Exec ourself */
1154  execve (vm->name, (char **) vm->argv, environ);
1155 
1156  return 0;
1157 }
1158 
1159 /* *INDENT-OFF* */
1160 VLIB_CLI_COMMAND (restart_cmd,static) = {
1161  .path = "restart",
1162  .short_help = "restart process",
1163  .function = restart_cmd_fn,
1164 };
1165 /* *INDENT-ON* */
1166 
1167 #ifdef TEST_CODE
1168 /*
1169  * A trivial test harness to verify the per-process output_function
1170  * is working correcty.
1171  */
1172 
1173 static clib_error_t *
1174 sleep_ten_seconds (vlib_main_t * vm,
1175  unformat_input_t * input, vlib_cli_command_t * cmd)
1176 {
1177  u16 i;
1178  u16 my_id = rand ();
1179 
1180  vlib_cli_output (vm, "Starting 10 seconds sleep with id %u\n", my_id);
1181 
1182  for (i = 0; i < 10; i++)
1183  {
1185  vlib_cli_output (vm, "Iteration number %u, my id: %u\n", i, my_id);
1186  }
1187  vlib_cli_output (vm, "Done with sleep with id %u\n", my_id);
1188  return 0;
1189 }
1190 
1191 /* *INDENT-OFF* */
1192 VLIB_CLI_COMMAND (ping_command, static) = {
1193  .path = "test sleep",
1194  .function = sleep_ten_seconds,
1195  .short_help = "Sleep for 10 seconds",
1196 };
1197 /* *INDENT-ON* */
1198 #endif /* ifdef TEST_CODE */
1199 
1200 static uword
1201 vlib_cli_normalize_path (char *input, char **result)
1202 {
1203  char *i = input;
1204  char *s = 0;
1205  uword l = 0;
1206  uword index_of_last_space = ~0;
1207 
1208  while (*i != 0)
1209  {
1210  u8 c = *i++;
1211  /* Multiple white space -> single space. */
1212  switch (c)
1213  {
1214  case ' ':
1215  case '\t':
1216  case '\n':
1217  case '\r':
1218  if (l > 0 && s[l - 1] != ' ')
1219  {
1220  vec_add1 (s, ' ');
1221  l++;
1222  }
1223  break;
1224 
1225  default:
1226  if (l > 0 && s[l - 1] == ' ')
1227  index_of_last_space = vec_len (s);
1228  vec_add1 (s, c);
1229  l++;
1230  break;
1231  }
1232  }
1233 
1234  /* Remove any extra space at end. */
1235  if (l > 0 && s[l - 1] == ' ')
1236  _vec_len (s) -= 1;
1237 
1238  *result = s;
1239  return index_of_last_space;
1240 }
1241 
1243 parent_path_len (char *path)
1244 {
1245  word i;
1246  for (i = vec_len (path) - 1; i >= 0; i--)
1247  {
1248  if (path[i] == ' ')
1249  return i;
1250  }
1251  return ~0;
1252 }
1253 
1254 static void
1255 add_sub_command (vlib_cli_main_t * cm, uword parent_index, uword child_index)
1256 {
1257  vlib_cli_command_t *p, *c;
1258  vlib_cli_sub_command_t *sub_c;
1259  u8 *sub_name;
1260  word i, l;
1261 
1262  p = vec_elt_at_index (cm->commands, parent_index);
1263  c = vec_elt_at_index (cm->commands, child_index);
1264 
1265  l = parent_path_len (c->path);
1266  if (l == ~0)
1267  sub_name = vec_dup ((u8 *) c->path);
1268  else
1269  {
1270  ASSERT (l + 1 < vec_len (c->path));
1271  sub_name = 0;
1272  vec_add (sub_name, c->path + l + 1, vec_len (c->path) - (l + 1));
1273  }
1274 
1275  if (sub_name[0] == '%')
1276  {
1277  uword *q;
1278  vlib_cli_sub_rule_t *sr;
1279 
1280  /* Remove %. */
1281  vec_delete (sub_name, 1, 0);
1282 
1283  if (!p->sub_rule_index_by_name)
1284  p->sub_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
1285  sizeof (sub_name[0]),
1286  sizeof (uword));
1287  q = hash_get_mem (p->sub_rule_index_by_name, sub_name);
1288  if (q)
1289  {
1290  sr = vec_elt_at_index (p->sub_rules, q[0]);
1291  ASSERT (sr->command_index == child_index);
1292  return;
1293  }
1294 
1295  q = hash_get_mem (cm->parse_rule_index_by_name, sub_name);
1296  if (!q)
1297  {
1298  clib_error ("reference to unknown rule `%%%v' in path `%v'",
1299  sub_name, c->path);
1300  return;
1301  }
1302 
1303  hash_set_mem (p->sub_rule_index_by_name, sub_name,
1304  vec_len (p->sub_rules));
1305  vec_add2 (p->sub_rules, sr, 1);
1306  sr->name = sub_name;
1307  sr->rule_index = q[0];
1308  sr->command_index = child_index;
1309  return;
1310  }
1311 
1312  if (!p->sub_command_index_by_name)
1313  p->sub_command_index_by_name = hash_create_vec ( /* initial length */ 32,
1314  sizeof (c->path[0]),
1315  sizeof (uword));
1316 
1317  /* Check if sub-command has already been created. */
1318  if (hash_get_mem (p->sub_command_index_by_name, sub_name))
1319  {
1320  vec_free (sub_name);
1321  return;
1322  }
1323 
1324  vec_add2 (p->sub_commands, sub_c, 1);
1325  sub_c->index = child_index;
1326  sub_c->name = sub_name;
1328  sub_c - p->sub_commands);
1329 
1330  vec_validate (p->sub_command_positions, vec_len (sub_c->name) - 1);
1331  for (i = 0; i < vec_len (sub_c->name); i++)
1332  {
1333  int n;
1335 
1337 
1338  if (!pos->bitmaps)
1339  pos->min_char = sub_c->name[i];
1340 
1341  n = sub_c->name[i] - pos->min_char;
1342  if (n < 0)
1343  {
1344  pos->min_char = sub_c->name[i];
1345  vec_insert (pos->bitmaps, -n, 0);
1346  n = 0;
1347  }
1348 
1349  vec_validate (pos->bitmaps, n);
1350  pos->bitmaps[n] =
1351  clib_bitmap_ori (pos->bitmaps[n], sub_c - p->sub_commands);
1352  }
1353 }
1354 
1355 static void
1357 {
1358  uword p_len, pi, *p;
1359  char *p_path;
1360  vlib_cli_command_t *c, *parent;
1361 
1362  /* Root command (index 0) should have already been added. */
1363  ASSERT (vec_len (cm->commands) > 0);
1364 
1365  c = vec_elt_at_index (cm->commands, ci);
1366  p_len = parent_path_len (c->path);
1367 
1368  /* No space? Parent is root command. */
1369  if (p_len == ~0)
1370  {
1371  add_sub_command (cm, 0, ci);
1372  return;
1373  }
1374 
1375  p_path = 0;
1376  vec_add (p_path, c->path, p_len);
1377 
1378  p = hash_get_mem (cm->command_index_by_path, p_path);
1379 
1380  /* Parent exists? */
1381  if (!p)
1382  {
1383  /* Parent does not exist; create it. */
1384  vec_add2 (cm->commands, parent, 1);
1385  parent->path = p_path;
1386  hash_set_mem (cm->command_index_by_path, parent->path,
1387  parent - cm->commands);
1388  pi = parent - cm->commands;
1389  }
1390  else
1391  {
1392  pi = p[0];
1393  vec_free (p_path);
1394  }
1395 
1396  add_sub_command (cm, pi, ci);
1397 
1398  /* Create parent's parent. */
1399  if (!p)
1400  vlib_cli_make_parent (cm, pi);
1401 }
1402 
1405 {
1406  return (c->long_help == 0 && c->short_help == 0 && c->function == 0);
1407 }
1408 
1409 clib_error_t *
1411 {
1412  vlib_cli_main_t *cm = &vm->cli_main;
1413  clib_error_t *error = 0;
1414  uword ci, *p;
1415  char *normalized_path;
1416 
1417  if ((error = vlib_call_init_function (vm, vlib_cli_init)))
1418  return error;
1419 
1420  (void) vlib_cli_normalize_path (c->path, &normalized_path);
1421 
1422  if (!cm->command_index_by_path)
1423  cm->command_index_by_path = hash_create_vec ( /* initial length */ 32,
1424  sizeof (c->path[0]),
1425  sizeof (uword));
1426 
1427  /* See if command already exists with given path. */
1428  p = hash_get_mem (cm->command_index_by_path, normalized_path);
1429  if (p)
1430  {
1431  vlib_cli_command_t *d;
1432 
1433  ci = p[0];
1434  d = vec_elt_at_index (cm->commands, ci);
1435 
1436  /* If existing command was created via vlib_cli_make_parent
1437  replaced it with callers data. */
1438  if (vlib_cli_command_is_empty (d))
1439  {
1440  vlib_cli_command_t save = d[0];
1441 
1443 
1444  /* Copy callers fields. */
1445  d[0] = c[0];
1446 
1447  /* Save internal fields. */
1448  d->path = save.path;
1449  d->sub_commands = save.sub_commands;
1452  d->sub_rules = save.sub_rules;
1453  }
1454  else
1455  error =
1456  clib_error_return (0, "duplicate command name with path %v",
1457  normalized_path);
1458 
1459  vec_free (normalized_path);
1460  if (error)
1461  return error;
1462  }
1463  else
1464  {
1465  /* Command does not exist: create it. */
1466 
1467  /* Add root command (index 0). */
1468  if (vec_len (cm->commands) == 0)
1469  {
1470  /* Create command with index 0; path is empty string. */
1471  vec_resize (cm->commands, 1);
1472  }
1473 
1474  ci = vec_len (cm->commands);
1475  hash_set_mem (cm->command_index_by_path, normalized_path, ci);
1476  vec_add1 (cm->commands, c[0]);
1477 
1478  c = vec_elt_at_index (cm->commands, ci);
1479  c->path = normalized_path;
1480 
1481  /* Don't inherit from registration. */
1482  c->sub_commands = 0;
1484  c->sub_command_positions = 0;
1485  }
1486 
1487  vlib_cli_make_parent (cm, ci);
1488  return 0;
1489 }
1490 
1491 clib_error_t *
1493 {
1494  vlib_cli_main_t *cm = &vm->cli_main;
1496  clib_error_t *error = 0;
1497  u8 *r_name;
1498  uword *p;
1499 
1500  if (!cm->parse_rule_index_by_name)
1501  cm->parse_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
1502  sizeof (r->name[0]),
1503  sizeof (uword));
1504 
1505  /* Make vector copy of name. */
1506  r_name = format (0, "%s", r_reg->name);
1507 
1508  if ((p = hash_get_mem (cm->parse_rule_index_by_name, r_name)))
1509  {
1510  vec_free (r_name);
1511  return clib_error_return (0, "duplicate parse rule name `%s'",
1512  r_reg->name);
1513  }
1514 
1515  vec_add2 (cm->parse_rules, r, 1);
1516  r[0] = r_reg[0];
1517  r->name = (char *) r_name;
1519 
1520  return error;
1521 }
1522 
1523 #if 0
1524 /* $$$ turn back on again someday, maybe */
1525 static clib_error_t *vlib_cli_register_parse_rules (vlib_main_t * vm,
1527  lo,
1529  hi)
1530  __attribute__ ((unused))
1531 {
1532  clib_error_t *error = 0;
1534 
1535  for (r = lo; r < hi; r = clib_elf_section_data_next (r, 0))
1536  {
1537  if (!r->name || strlen (r->name) == 0)
1538  {
1539  error = clib_error_return (0, "parse rule with no name");
1540  goto done;
1541  }
1542 
1543  error = vlib_cli_register_parse_rule (vm, r);
1544  if (error)
1545  goto done;
1546  }
1547 
1548 done:
1549  return error;
1550 }
1551 #endif
1552 
1553 static int
1554 cli_path_compare (void *a1, void *a2)
1555 {
1556  u8 **s1 = a1;
1557  u8 **s2 = a2;
1558 
1559  if ((vec_len (*s1) < vec_len (*s2)) &&
1560  memcmp ((char *) *s1, (char *) *s2, vec_len (*s1)) == 0)
1561  return -1;
1562 
1563 
1564  if ((vec_len (*s1) > vec_len (*s2)) &&
1565  memcmp ((char *) *s1, (char *) *s2, vec_len (*s2)) == 0)
1566  return 1;
1567 
1568  return vec_cmp (*s1, *s2);
1569 }
1570 
1571 static clib_error_t *
1573  vlib_cli_command_t * cmd)
1574 {
1575  vlib_cli_main_t *cm = &vm->cli_main;
1576  vlib_cli_command_t *cli;
1577  u8 **paths = 0, **s;
1578 
1579  /* *INDENT-OFF* */
1580  vec_foreach (cli, cm->commands)
1581  if (vec_len (cli->path) > 0)
1582  vec_add1 (paths, (u8 *) cli->path);
1583 
1585 
1586  vec_foreach (s, paths)
1587  vlib_cli_output (vm, "%v", *s);
1588  /* *INDENT-ON* */
1589 
1590  vec_free (paths);
1591  return 0;
1592 }
1593 
1594 /* *INDENT-OFF* */
1595 VLIB_CLI_COMMAND (show_cli_command, static) = {
1596  .path = "show cli",
1597  .short_help = "Show cli commands",
1598  .function = show_cli_cmd_fn,
1599 };
1600 /* *INDENT-ON* */
1601 
1602 static clib_error_t *
1604  unformat_input_t * input, vlib_cli_command_t * cmd)
1605 {
1606  unformat_input_t _line_input, *line_input = &_line_input;
1607  int enable = 1;
1608  int api = 0, cli = 0, barrier = 0, dispatch = 0, circuit = 0;
1609  u32 circuit_node_index;
1610 
1611  if (!unformat_user (input, unformat_line_input, line_input))
1612  goto print_status;
1613 
1614  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1615  {
1616  if (unformat (line_input, "api"))
1617  api = 1;
1618  else if (unformat (line_input, "dispatch"))
1619  dispatch = 1;
1620  else if (unformat (line_input, "circuit-node %U",
1621  unformat_vlib_node, vm, &circuit_node_index))
1622  circuit = 1;
1623  else if (unformat (line_input, "cli"))
1624  cli = 1;
1625  else if (unformat (line_input, "barrier"))
1626  barrier = 1;
1627  else if (unformat (line_input, "disable"))
1628  enable = 0;
1629  else if (unformat (line_input, "enable"))
1630  enable = 1;
1631  else
1632  break;
1633  }
1634  unformat_free (line_input);
1635 
1637  (api ? enable : vl_api_get_elog_trace_api_messages ());
1638  vm->elog_trace_cli_commands = cli ? enable : vm->elog_trace_cli_commands;
1639  vm->elog_trace_graph_dispatch = dispatch ?
1640  enable : vm->elog_trace_graph_dispatch;
1641  vm->elog_trace_graph_circuit = circuit ?
1642  enable : vm->elog_trace_graph_circuit;
1644  barrier ? enable : vlib_worker_threads->barrier_elog_enabled;
1645  vm->elog_trace_graph_circuit_node_index = circuit_node_index;
1646 
1647  /*
1648  * Set up start-of-buffer logic-analyzer trigger
1649  * for main loop event logs, which are fairly heavyweight.
1650  * See src/vlib/main/vlib_elog_main_loop_event(...), which
1651  * will fully disable the scheme when the elog buffer fills.
1652  */
1653  if (dispatch || circuit)
1654  {
1655  elog_main_t *em = &vm->elog_main;
1656 
1658  em->n_total_events + vec_len (em->event_ring);
1659  }
1660 
1661 
1662 print_status:
1663  vlib_cli_output (vm, "Current status:");
1664 
1666  (vm, " Event log API message trace: %s\n CLI command trace: %s",
1667  vl_api_get_elog_trace_api_messages ()? "on" : "off",
1668  vm->elog_trace_cli_commands ? "on" : "off");
1670  (vm, " Barrier sync trace: %s",
1671  vlib_worker_threads->barrier_elog_enabled ? "on" : "off");
1673  (vm, " Graph Dispatch: %s",
1674  vm->elog_trace_graph_dispatch ? "on" : "off");
1676  (vm, " Graph Circuit: %s",
1677  vm->elog_trace_graph_circuit ? "on" : "off");
1678  if (vm->elog_trace_graph_circuit)
1680  (vm, " node %U",
1682 
1683  return 0;
1684 }
1685 
1686 /*?
1687  * Control event logging of api, cli, and thread barrier events
1688  * With no arguments, displays the current trace status.
1689  * Name the event groups you wish to trace or stop tracing.
1690  *
1691  * @cliexpar
1692  * @clistart
1693  * elog trace api cli barrier
1694  * elog trace api cli barrier disable
1695  * elog trace dispatch
1696  * elog trace circuit-node ethernet-input
1697  * elog trace
1698  * @cliend
1699  * @cliexcmd{elog trace [api][cli][barrier][disable]}
1700 ?*/
1701 /* *INDENT-OFF* */
1702 VLIB_CLI_COMMAND (elog_trace_command, static) =
1703 {
1704  .path = "elog trace",
1705  .short_help = "elog trace [api][cli][barrier][dispatch]\n"
1706  "[circuit-node <name> e.g. ethernet-input][disable]",
1707  .function = elog_trace_command_fn,
1708 };
1709 /* *INDENT-ON* */
1710 
1711 static clib_error_t *
1713  unformat_input_t * input, vlib_cli_command_t * cmd)
1714 {
1715  vlib_process_suspend (vm, 30e-3);
1716  return 0;
1717 }
1718 
1719 /* *INDENT-OFF* */
1720 VLIB_CLI_COMMAND (suspend_command, static) =
1721 {
1722  .path = "suspend",
1723  .short_help = "suspend debug CLI for 30ms",
1724  .function = suspend_command_fn,
1725 };
1726 /* *INDENT-ON* */
1727 
1728 static clib_error_t *
1730 {
1731  vlib_cli_main_t *cm = &vm->cli_main;
1732  clib_error_t *error = 0;
1733  vlib_cli_command_t *cmd;
1734 
1735  cmd = cm->cli_command_registrations;
1736 
1737  while (cmd)
1738  {
1739  error = vlib_cli_register (vm, cmd);
1740  if (error)
1741  return error;
1742  cmd = cmd->next_cli_command;
1743  }
1744  return error;
1745 }
1746 
1748 
1749 /*
1750  * fd.io coding-style-patch-verification: ON
1751  *
1752  * Local Variables:
1753  * eval: (c-set-style "gnu")
1754  * End:
1755  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
uword output_function_arg
Definition: node.h:610
void * vlib_stats_push_heap(void *)
Definition: cli.c:805
vmrglw vmrglh hi
unformat_function_t * unformat_function
Definition: cli.h:80
void * clib_per_cpu_mheaps[CLIB_MAX_MHEAPS]
Definition: mem_dlmalloc.c:23
static clib_error_t * show_cpu(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:945
void * mspace
Definition: dlmalloc.h:1306
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:673
format_function_t format_vlib_node_name
Definition: node_funcs.h:1141
uword data_size
Definition: cli.h:78
uword vm_alloc_offset_from_header
unformat_function_t unformat_eof
Definition: format.h:293
static u8 * format_vlib_cli_parse_rule_name(u8 *s, va_list *args)
Definition: cli.c:363
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:192
int elog_trace_cli_commands
Definition: main.h:176
#define clib_error(format, args...)
Definition: error.h:62
vlib_cli_command_t * commands
Definition: cli.h:136
f64 clocks_per_second
Definition: time.h:53
format_function_t format_cpu_flags
Definition: cpu.h:391
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:560
int i
static uword parent_path_len(char *path)
Definition: cli.c:1243
static mheap_t * mheap_header(u8 *v)
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
uword * sub_rule_index_by_name
Definition: cli.h:121
#define hash_set_mem(h, key, value)
Definition: hash.h:275
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
clib_time_t clib_time
Definition: main.h:72
DLMALLOC_EXPORT struct dlmallinfo mspace_mallinfo(mspace msp)
vlib_cli_main_t cli_main
Definition: main.h:143
static vlib_cli_command_t * all_subs(vlib_cli_main_t *cm, vlib_cli_command_t *subs, u32 command_index)
Definition: cli.c:411
unsigned char u8
Definition: types.h:56
#define clib_bitmap_dup(v)
Duplicate a bitmap.
Definition: bitmap.h:87
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:204
#define fm
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:598
clib_file_t * file_pool
Definition: file.h:88
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:422
static clib_error_t * test_heap_validate(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1070
i64 word
Definition: types.h:111
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
MALLINFO_FIELD_TYPE arena
Definition: dlmalloc.h:800
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
#define always_inline
Definition: clib.h:98
static uword clib_bitmap_is_zero(uword *ai)
predicate function; is an entire bitmap empty?
Definition: bitmap.h:57
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
u8 * format_page_map(u8 *s, va_list *args)
Definition: unix-formats.c:969
#define clib_error_return(e, args...)
Definition: error.h:99
uword * command_index_by_path
Definition: cli.h:139
clib_file_main_t file_main
Definition: main.c:63
u32 command_index
Definition: cli.h:68
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:242
unsigned int u32
Definition: types.h:88
#define vlib_call_init_function(vm, x)
Definition: init.h:270
static void add_sub_command(vlib_cli_main_t *cm, uword parent_index, uword child_index)
Definition: cli.c:1255
static uword unformat_vlib_cli_sub_command(unformat_input_t *i, va_list *args)
Definition: cli.c:202
static int vlib_cli_cmp_strings(void *a1, void *a2)
Definition: cli.c:247
uword clib_mem_trace_enable_disable(uword enable)
Definition: mem_dlmalloc.c:441
static int vlib_cli_cmp_rule(void *a1, void *a2)
Definition: cli.c:428
unformat_function_t unformat_line_input
Definition: format.h:283
u8 * format_c_identifier(u8 *s, va_list *va)
Definition: std-formats.c:274
u8 * format_mheap(u8 *s, va_list *va)
Definition: mem_dlmalloc.c:354
char * name
Definition: main.h:122
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:37
vlib_cli_parse_rule_t * parse_rules
Definition: cli.h:142
static clib_error_t * enable_disable_memory_trace(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:978
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
static vlib_cli_command_t * get_sub_command(vlib_cli_main_t *cm, vlib_cli_command_t *parent, u32 si)
Definition: cli.c:195
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header...
Definition: vec.h:685
vlib_cli_command_function_t * function
Definition: cli.h:102
static uword clib_bitmap_first_set(uword *ai)
Return the lowest numbered set bit in a bitmap.
Definition: bitmap.h:385
static clib_error_t * elog_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1603
clib_error_t * vlib_cli_register_parse_rule(vlib_main_t *vm, vlib_cli_parse_rule_t *r_reg)
Definition: cli.c:1492
u8 ** vlib_cli_get_possible_completions(u8 *str)
Definition: cli.c:256
vlib_cli_sub_rule_t * sub_rules
Definition: cli.h:124
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
static int cli_path_compare(void *a1, void *a2)
Definition: cli.c:1554
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:375
#define ELOG_DATA(em, f)
Definition: elog.h:484
elog_event_t * event_ring
Vector of events (circular buffer).
Definition: elog.h:149
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:804
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:205
void vl_msg_pop_heap(void *oldheap)
Definition: cli.c:799
static clib_error_t * vlib_cli_dispatch_sub_commands(vlib_main_t *vm, vlib_cli_main_t *cm, unformat_input_t *input, uword parent_command_index)
Definition: cli.c:446
#define foreach_vlib_main(body)
Definition: threads.h:236
u8 name[64]
Definition: memclnt.api:152
word fformat(FILE *f, char *fmt,...)
Definition: format.c:462
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1037
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
vlib_cli_sub_command_t * sub_commands
Definition: cli.h:111
u8 ** argv
Definition: main.h:213
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
svmdb_client_t * c
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:391
int elog_trace_graph_dispatch
Definition: main.h:177
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
void * vl_msg_push_heap(void)
Definition: cli.c:792
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:282
static uword * clib_bitmap_andnot(uword *ai, uword *bi)
Logical operator across two bitmaps.
int vl_api_get_elog_trace_api_messages(void)
Definition: main.c:2003
elog_main_t elog_main
Definition: main.h:172
uword ** bitmaps
Definition: cli.h:52
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
static u8 * format_vlib_cli_command_help(u8 *s, va_list *args)
Definition: cli.c:349
u32 n_total_events_disable_limit
When count reaches limit logging is disabled.
Definition: elog.h:139
static uword * vlib_cli_sub_command_match(vlib_cli_command_t *c, unformat_input_t *input)
Definition: cli.c:86
static uword vlib_cli_command_is_empty(vlib_cli_command_t *c)
Definition: cli.c:1404
static void * clib_mem_get_heap(void)
Definition: mem.h:276
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
static int vlib_cli_cmp_command(void *a1, void *a2)
Definition: cli.c:437
#define clib_elf_section_data_next(a, extra)
Definition: elf_clib.h:57
static void vlib_cli_make_parent(vlib_cli_main_t *cm, uword ci)
Definition: cli.c:1356
#define ASSERT(truth)
static clib_error_t * vlib_cli_init(vlib_main_t *vm)
Definition: cli.c:1729
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:784
uword * parse_rule_index_by_name
Definition: cli.h:145
void( vlib_cli_output_function_t)(uword arg, u8 *buffer, uword buffer_bytes)
Definition: cli.h:131
uword vm_alloc_size
char * long_help
Definition: cli.h:99
uword is_mp_safe
Definition: cli.h:108
#define MHEAP_FLAG_VALIDATE
char * path
Definition: cli.h:95
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
int vl_api_set_elog_trace_api_messages(int enable)
Definition: main.c:1995
uword * sub_command_index_by_name
Definition: cli.h:114
u32 elog_trace_graph_circuit_node_index
Definition: main.h:179
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:919
int vlib_cli_input(vlib_main_t *vm, unformat_input_t *input, vlib_cli_output_function_t *function, uword function_arg)
Definition: cli.c:726
static uword pointer_to_uword(const void *p)
Definition: types.h:131
static clib_error_t * show_memory_usage(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:811
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_mfib_path_t paths[n_paths]
Definition: ip.api:458
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:462
struct vlib_cli_command_t * next_cli_command
Definition: cli.h:127
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:668
static void * current_traced_heap
Definition: cli.c:50
u32 elog_string(elog_main_t *em, char *fmt,...)
add a string to the event-log string table
Definition: elog.c:562
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
uword unformat_vlib_enable_disable(unformat_input_t *input, va_list *args)
Definition: format.c:116
uword unformat_vlib_cli_sub_input(unformat_input_t *i, va_list *args)
Definition: cli.c:159
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:980
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
void ** parse_rule_data
Definition: cli.h:148
format_function_t format_cpu_uarch
Definition: cpu.h:389
#define clib_error_free(e)
Definition: error.h:86
static clib_error_t * suspend_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1712
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1147
#define hash_get_mem(h, key)
Definition: hash.h:269
clib_error_t * vlib_cli_register(vlib_main_t *vm, vlib_cli_command_t *c)
Definition: cli.c:1410
vlib_cli_command_t * cli_command_registrations
Definition: cli.h:151
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
import vnet fib fib_types api
Definition: bier.api:23
void vlib_unix_error_report(vlib_main_t *, clib_error_t *)
Definition: cli.c:720
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1487
void mheap_validate(void *v)
Definition: mheap.c:1378
static clib_error_t * restart_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1135
#define vec_foreach(var, vec)
Vector iterator.
Definition: file.h:51
vlib_cli_parse_position_t * sub_command_positions
Definition: cli.h:118
u32 n_total_events
Total number of events in buffer.
Definition: elog.h:135
static uword vlib_cli_normalize_path(char *input, char **result)
Definition: cli.c:1201
vlib_cli_output_function_t * output_function
Definition: node.h:609
void clib_mem_trace(int enable)
Definition: mem_dlmalloc.c:420
static clib_error_t * show_cli_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1572
char * short_help
Definition: cli.h:98
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:768
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:821
format_function_t format_cpu_model_name
Definition: cpu.h:390
DLMALLOC_EXPORT void * mspace_least_addr(mspace msp)
int elog_trace_graph_circuit
Definition: main.h:178
static uword * clib_bitmap_and(uword *ai, uword *bi)
Logical operator across two bitmaps.
static u8 * format_vlib_cli_path(u8 *s, va_list *args)
Definition: cli.c:370
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
u32 rule_index
Definition: cli.h:66
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171