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