FD.io VPP  v17.07-30-g839fa73
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 <vppinfra/cpu.h>
42 #include <unistd.h>
43 #include <ctype.h>
44 
45 /* Root of all show commands. */
46 /* *INDENT-OFF* */
47 VLIB_CLI_COMMAND (vlib_cli_show_command, static) = {
48  .path = "show",
49  .short_help = "Show commands",
50 };
51 /* *INDENT-ON* */
52 
53 /* Root of all clear commands. */
54 /* *INDENT-OFF* */
55 VLIB_CLI_COMMAND (vlib_cli_clear_command, static) = {
56  .path = "clear",
57  .short_help = "Clear commands",
58 };
59 /* *INDENT-ON* */
60 
61 /* Root of all set commands. */
62 /* *INDENT-OFF* */
63 VLIB_CLI_COMMAND (vlib_cli_set_command, static) = {
64  .path = "set",
65  .short_help = "Set commands",
66 };
67 /* *INDENT-ON* */
68 
69 /* Root of all test commands. */
70 /* *INDENT-OFF* */
71 VLIB_CLI_COMMAND (vlib_cli_test_command, static) = {
72  .path = "test",
73  .short_help = "Test commands",
74 };
75 /* *INDENT-ON* */
76 
77 /* Returns bitmap of commands which match key. */
78 static uword *
80 {
81  int i, n;
82  uword *match = 0;
84 
86 
87  for (i = 0;; i++)
88  {
89  uword k;
90 
91  k = unformat_get_input (input);
92  switch (k)
93  {
94  case 'a' ... 'z':
95  case 'A' ... 'Z':
96  case '0' ... '9':
97  case '-':
98  case '_':
99  break;
100 
101  case ' ':
102  case '\t':
103  case '\r':
104  case '\n':
106  /* White space or end of input removes any non-white
107  matches that were before possible. */
108  if (i < vec_len (c->sub_command_positions)
109  && clib_bitmap_count_set_bits (match) > 1)
110  {
112  for (n = 0; n < vec_len (p->bitmaps); n++)
113  match = clib_bitmap_andnot (match, p->bitmaps[n]);
114  }
115  goto done;
116 
117  default:
118  unformat_put_input (input);
119  goto done;
120  }
121 
122  if (i >= vec_len (c->sub_command_positions))
123  {
124  no_match:
125  clib_bitmap_free (match);
126  return 0;
127  }
128 
130  if (vec_len (p->bitmaps) == 0)
131  goto no_match;
132 
133  n = k - p->min_char;
134  if (n < 0 || n >= vec_len (p->bitmaps))
135  goto no_match;
136 
137  if (i == 0)
138  match = clib_bitmap_dup (p->bitmaps[n]);
139  else
140  match = clib_bitmap_and (match, p->bitmaps[n]);
141 
142  if (clib_bitmap_is_zero (match))
143  goto no_match;
144  }
145 
146 done:
147  return match;
148 }
149 
150 /* Looks for string based sub-input formatted { SUB-INPUT }. */
151 uword
153 {
154  unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
155  u8 *s;
156  uword c;
157 
158  while (1)
159  {
160  c = unformat_get_input (i);
161  switch (c)
162  {
163  case ' ':
164  case '\t':
165  case '\n':
166  case '\r':
167  case '\f':
168  break;
169 
170  case '{':
171  default:
172  /* Put back paren. */
173  if (c != UNFORMAT_END_OF_INPUT)
174  unformat_put_input (i);
175 
176  if (c == '{' && unformat (i, "%v", &s))
177  {
178  unformat_init_vector (sub_input, s);
179  return 1;
180  }
181  return 0;
182  }
183  }
184  return 0;
185 }
186 
187 static vlib_cli_command_t *
189 {
191  return vec_elt_at_index (cm->commands, s->index);
192 }
193 
194 static uword
196 {
197  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
198  vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
199  vlib_cli_command_t **result = va_arg (*args, vlib_cli_command_t **);
200  vlib_cli_main_t *cm = &vm->cli_main;
201  uword *match_bitmap, is_unique, index;
202 
203  {
206  vec_foreach (sr, c->sub_rules)
207  {
208  void **d;
209  r = vec_elt_at_index (cm->parse_rules, sr->rule_index);
210  vec_add2 (cm->parse_rule_data, d, 1);
211  vec_reset_length (d[0]);
212  if (r->data_size)
213  d[0] = _vec_resize (d[0],
214  /* length increment */ 1,
215  r->data_size,
216  /* header_bytes */ 0,
217  /* data align */ sizeof (uword));
218  if (unformat_user (i, r->unformat_function, vm, d[0]))
219  {
220  *result = vec_elt_at_index (cm->commands, sr->command_index);
221  return 1;
222  }
223  }
224  }
225 
226  match_bitmap = vlib_cli_sub_command_match (c, i);
227  is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1;
228  index = ~0;
229  if (is_unique)
230  {
231  index = clib_bitmap_first_set (match_bitmap);
232  *result = get_sub_command (cm, c, index);
233  }
234  clib_bitmap_free (match_bitmap);
235 
236  return is_unique;
237 }
238 
239 static int
240 vlib_cli_cmp_strings (void *a1, void *a2)
241 {
242  u8 *c1 = *(u8 **) a1;
243  u8 *c2 = *(u8 **) a2;
244 
245  return vec_cmp (c1, c2);
246 }
247 
248 u8 **
250 {
253  vlib_main_t *vm = vlib_get_main ();
254  vlib_cli_main_t *vcm = &vm->cli_main;
255  uword *match_bitmap = 0;
256  uword index, is_unique, help_next_level;
257  u8 **result = 0;
258  unformat_input_t input;
259  unformat_init_vector (&input, vec_dup (str));
260  c = vec_elt_at_index (vcm->commands, 0);
261 
262  /* remove trailing whitespace, except for one of them */
263  while (vec_len (input.buffer) >= 2 &&
264  isspace (input.buffer[vec_len (input.buffer) - 1]) &&
265  isspace (input.buffer[vec_len (input.buffer) - 2]))
266  {
267  vec_del1 (input.buffer, vec_len (input.buffer) - 1);
268  }
269 
270  /* if input is empty, directly return list of root commands */
271  if (vec_len (input.buffer) == 0 ||
272  (vec_len (input.buffer) == 1 && isspace (input.buffer[0])))
273  {
274  vec_foreach (sc, c->sub_commands)
275  {
276  vec_add1 (result, (u8 *) sc->name);
277  }
278  goto done;
279  }
280 
281  /* add a trailing '?' so that vlib_cli_sub_command_match can find
282  * all commands starting with the input string */
283  vec_add1 (input.buffer, '?');
284 
285  while (1)
286  {
287  match_bitmap = vlib_cli_sub_command_match (c, &input);
288  /* no match: return no result */
289  if (match_bitmap == 0)
290  {
291  goto done;
292  }
293  is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1;
294  /* unique match: try to step one subcommand level further */
295  if (is_unique)
296  {
297  /* stop if no more input */
298  if (input.index >= vec_len (input.buffer) - 1)
299  {
300  break;
301  }
302 
303  index = clib_bitmap_first_set (match_bitmap);
304  c = get_sub_command (vcm, c, index);
305  clib_bitmap_free (match_bitmap);
306  continue;
307  }
308  /* multiple matches: stop here, return all matches */
309  break;
310  }
311 
312  /* remove trailing '?' */
313  vec_del1 (input.buffer, vec_len (input.buffer) - 1);
314 
315  /* if we have a space at the end of input, and a unique match,
316  * autocomplete the next level of subcommands */
317  help_next_level = (vec_len (str) == 0) || isspace (str[vec_len (str) - 1]);
318  /* *INDENT-OFF* */
319  clib_bitmap_foreach(index, match_bitmap, {
320  if (help_next_level && is_unique) {
321  c = get_sub_command (vcm, c, index);
322  vec_foreach (sc, c->sub_commands) {
323  vec_add1 (result, (u8*) sc->name);
324  }
325  goto done; /* break doesn't work in this macro-loop */
326  }
327  sc = &c->sub_commands[index];
328  vec_add1(result, (u8*) sc->name);
329  });
330  /* *INDENT-ON* */
331 
332 done:
333  clib_bitmap_free (match_bitmap);
334  unformat_free (&input);
335 
336  if (result)
338  return result;
339 }
340 
341 static u8 *
342 format_vlib_cli_command_help (u8 * s, va_list * args)
343 {
344  vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
345  int is_long = va_arg (*args, int);
346  if (is_long && c->long_help)
347  s = format (s, "%s", c->long_help);
348  else if (c->short_help)
349  s = format (s, "%s", c->short_help);
350  else
351  s = format (s, "%v commands", c->path);
352  return s;
353 }
354 
355 static u8 *
356 format_vlib_cli_parse_rule_name (u8 * s, va_list * args)
357 {
358  vlib_cli_parse_rule_t *r = va_arg (*args, vlib_cli_parse_rule_t *);
359  return format (s, "<%U>", format_c_identifier, r->name);
360 }
361 
362 static u8 *
363 format_vlib_cli_path (u8 * s, va_list * args)
364 {
365  u8 *path = va_arg (*args, u8 *);
366  int i, in_rule;
367  in_rule = 0;
368  for (i = 0; i < vec_len (path); i++)
369  {
370  switch (path[i])
371  {
372  case '%':
373  in_rule = 1;
374  vec_add1 (s, '<'); /* start of <RULE> */
375  break;
376 
377  case '_':
378  /* _ -> space in rules. */
379  vec_add1 (s, in_rule ? ' ' : '_');
380  break;
381 
382  case ' ':
383  if (in_rule)
384  {
385  vec_add1 (s, '>'); /* end of <RULE> */
386  in_rule = 0;
387  }
388  vec_add1 (s, ' ');
389  break;
390 
391  default:
392  vec_add1 (s, path[i]);
393  break;
394  }
395  }
396 
397  if (in_rule)
398  vec_add1 (s, '>'); /* terminate <RULE> */
399 
400  return s;
401 }
402 
403 static vlib_cli_command_t *
404 all_subs (vlib_cli_main_t * cm, vlib_cli_command_t * subs, u32 command_index)
405 {
406  vlib_cli_command_t *c = vec_elt_at_index (cm->commands, command_index);
409 
410  if (c->function)
411  vec_add1 (subs, c[0]);
412 
413  vec_foreach (sr, c->sub_rules)
414  subs = all_subs (cm, subs, sr->command_index);
415  vec_foreach (sc, c->sub_commands) subs = all_subs (cm, subs, sc->index);
416 
417  return subs;
418 }
419 
420 static int
421 vlib_cli_cmp_rule (void *a1, void *a2)
422 {
423  vlib_cli_sub_rule_t *r1 = a1;
424  vlib_cli_sub_rule_t *r2 = a2;
425 
426  return vec_cmp (r1->name, r2->name);
427 }
428 
429 static int
430 vlib_cli_cmp_command (void *a1, void *a2)
431 {
432  vlib_cli_command_t *c1 = a1;
433  vlib_cli_command_t *c2 = a2;
434 
435  return vec_cmp (c1->path, c2->path);
436 }
437 
438 static clib_error_t *
440  vlib_cli_main_t * cm,
441  unformat_input_t * input,
442  uword parent_command_index)
443 {
444  vlib_cli_command_t *parent, *c;
445  clib_error_t *error = 0;
446  unformat_input_t sub_input;
447  u8 *string;
448  uword is_main_dispatch = cm == &vm->cli_main;
449 
450  parent = vec_elt_at_index (cm->commands, parent_command_index);
451  if (is_main_dispatch && unformat (input, "help"))
452  {
453  uword help_at_end_of_line, i;
454 
455  help_at_end_of_line =
457  while (1)
458  {
459  c = parent;
460  if (unformat_user
461  (input, unformat_vlib_cli_sub_command, vm, c, &parent))
462  ;
463 
464  else if (!(unformat_check_input (input) == UNFORMAT_END_OF_INPUT))
465  goto unknown;
466 
467  else
468  break;
469  }
470 
471  /* help SUB-COMMAND => long format help.
472  "help" at end of line: show all commands. */
473  if (!help_at_end_of_line)
475  /* is_long */ 1);
476 
477  else if (vec_len (c->sub_commands) + vec_len (c->sub_rules) == 0)
478  vlib_cli_output (vm, "%v: no sub-commands", c->path);
479 
480  else
481  {
483  vlib_cli_sub_rule_t *sr, *subs;
484 
485  subs = vec_dup (c->sub_rules);
486 
487  /* Add in rules if any. */
488  vec_foreach (sc, c->sub_commands)
489  {
490  vec_add2 (subs, sr, 1);
491  sr->name = sc->name;
492  sr->command_index = sc->index;
493  sr->rule_index = ~0;
494  }
495 
497 
498  for (i = 0; i < vec_len (subs); i++)
499  {
502 
503  d = vec_elt_at_index (cm->commands, subs[i].command_index);
504  r =
505  subs[i].rule_index != ~0 ? vec_elt_at_index (cm->parse_rules,
506  subs
507  [i].rule_index) :
508  0;
509 
510  if (r)
512  (vm, " %-30U %U",
514  format_vlib_cli_command_help, d, /* is_long */ 0);
515  else
517  (vm, " %-30v %U",
518  subs[i].name,
519  format_vlib_cli_command_help, d, /* is_long */ 0);
520  }
521 
522  vec_free (subs);
523  }
524  }
525 
526  else if (is_main_dispatch
527  && (unformat (input, "choices") || unformat (input, "?")))
528  {
529  vlib_cli_command_t *sub, *subs;
530 
531  subs = all_subs (cm, 0, parent_command_index);
533  vec_foreach (sub, subs)
534  vlib_cli_output (vm, " %-40U %U",
536  format_vlib_cli_command_help, sub, /* is_long */ 0);
537  vec_free (subs);
538  }
539 
540  else if (unformat (input, "comment %v", &string))
541  {
542  vec_free (string);
543  }
544 
545  else if (unformat (input, "uncomment %U",
546  unformat_vlib_cli_sub_input, &sub_input))
547  {
548  error =
549  vlib_cli_dispatch_sub_commands (vm, cm, &sub_input,
550  parent_command_index);
551  unformat_free (&sub_input);
552  }
553 
554  else
555  if (unformat_user (input, unformat_vlib_cli_sub_command, vm, parent, &c))
556  {
557  unformat_input_t *si;
558  uword has_sub_commands =
559  vec_len (c->sub_commands) + vec_len (c->sub_rules) > 0;
560 
561  si = input;
562  if (unformat_user (input, unformat_vlib_cli_sub_input, &sub_input))
563  si = &sub_input;
564 
565  if (has_sub_commands)
566  error = vlib_cli_dispatch_sub_commands (vm, cm, si, c - cm->commands);
567 
568  if (has_sub_commands && !error)
569  /* Found valid sub-command. */ ;
570 
571  else if (c->function)
572  {
573  clib_error_t *c_error;
574 
575  /* Skip white space for benefit of called function. */
577 
578  if (unformat (si, "?"))
579  {
580  vlib_cli_output (vm, " %-40U %U", format_vlib_cli_path, c->path, format_vlib_cli_command_help, c, /* is_long */
581  0);
582  }
583  else
584  {
585  if (!c->is_mp_safe)
587 
588  c_error = c->function (vm, si, c);
589 
590  if (!c->is_mp_safe)
592 
593  if (c_error)
594  {
595  error =
596  clib_error_return (0, "%v: %v", c->path, c_error->what);
597  clib_error_free (c_error);
598  /* Free sub input. */
599  if (si != input)
600  unformat_free (si);
601 
602  return error;
603  }
604  }
605 
606  /* Free any previous error. */
607  clib_error_free (error);
608  }
609 
610  else if (!error)
611  error = clib_error_return (0, "%v: no sub-commands", c->path);
612 
613  /* Free sub input. */
614  if (si != input)
615  unformat_free (si);
616  }
617 
618  else
619  goto unknown;
620 
621  return error;
622 
623 unknown:
624  if (parent->path)
625  return clib_error_return (0, "%v: unknown input `%U'", parent->path,
626  format_unformat_error, input);
627  else
628  return clib_error_return (0, "unknown input `%U'", format_unformat_error,
629  input);
630 }
631 
632 
634  __attribute__ ((weak));
635 
636 void
638 {
639 }
640 
641 /* Process CLI input. */
642 void
644  unformat_input_t * input,
645  vlib_cli_output_function_t * function, uword function_arg)
646 {
648  vlib_cli_main_t *cm = &vm->cli_main;
649  clib_error_t *error;
650  vlib_cli_output_function_t *save_function;
651  uword save_function_arg;
652 
653  save_function = cp->output_function;
654  save_function_arg = cp->output_function_arg;
655 
656  cp->output_function = function;
657  cp->output_function_arg = function_arg;
658 
659  do
660  {
662  error = vlib_cli_dispatch_sub_commands (vm, &vm->cli_main, input, /* parent */
663  0);
664  }
665  while (!error && !unformat (input, "%U", unformat_eof));
666 
667  if (error)
668  {
669  vlib_cli_output (vm, "%v", error->what);
670  vlib_unix_error_report (vm, error);
671  clib_error_free (error);
672  }
673 
674  cp->output_function = save_function;
675  cp->output_function_arg = save_function_arg;
676 }
677 
678 /* Output to current CLI connection. */
679 void
680 vlib_cli_output (vlib_main_t * vm, char *fmt, ...)
681 {
683  va_list va;
684  u8 *s;
685 
686  va_start (va, fmt);
687  s = va_format (0, fmt, &va);
688  va_end (va);
689 
690  /* Terminate with \n if not present. */
691  if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n')
692  vec_add1 (s, '\n');
693 
694  if ((!cp) || (!cp->output_function))
695  fformat (stdout, "%v", s);
696  else
697  cp->output_function (cp->output_function_arg, s, vec_len (s));
698 
699  vec_free (s);
700 }
701 
702 static clib_error_t *
704  unformat_input_t * input, vlib_cli_command_t * cmd)
705 {
706  int verbose = 0;
707  clib_error_t *error;
708  u32 index = 0;
709 
711  {
712  if (unformat (input, "verbose"))
713  verbose = 1;
714  else
715  {
716  error = clib_error_return (0, "unknown input `%U'",
717  format_unformat_error, input);
718  return error;
719  }
720  }
721 
722  /* *INDENT-OFF* */
724  ({
725  vlib_cli_output (vm, "Thread %d %v\n", index, vlib_worker_threads[index].name);
726  vlib_cli_output (vm, "%U\n", format_mheap, clib_per_cpu_mheaps[index], verbose);
727  index++;
728  }));
729  /* *INDENT-ON* */
730  return 0;
731 }
732 
733 /* *INDENT-OFF* */
734 VLIB_CLI_COMMAND (show_memory_usage_command, static) = {
735  .path = "show memory",
736  .short_help = "Show current memory usage",
737  .function = show_memory_usage,
738 };
739 /* *INDENT-ON* */
740 
741 static clib_error_t *
743  vlib_cli_command_t * cmd)
744 {
745 #define _(a,b,c) vlib_cli_output (vm, "%-25s " b, a ":", c);
746  _("Model name", "%U", format_cpu_model_name);
747  _("Microarchitecture", "%U", format_cpu_uarch);
748  _("Flags", "%U", format_cpu_flags);
749  _("Base frequency", "%.2f GHz",
750  ((f64) vm->clib_time.clocks_per_second) * 1e-9);
751 #undef _
752  return 0;
753 }
754 
755 /*?
756  * Displays various information about the CPU.
757  *
758  * @cliexpar
759  * @cliexstart{show cpu}
760  * Model name: Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz
761  * Microarchitecture: Broadwell (Broadwell-EP/EX)
762  * Flags: sse3 ssse3 sse41 sse42 avx avx2 aes
763  * Base Frequency: 3.20 GHz
764  * @cliexend
765 ?*/
766 /* *INDENT-OFF* */
767 VLIB_CLI_COMMAND (show_cpu_command, static) = {
768  .path = "show cpu",
769  .short_help = "Show cpu information",
770  .function = show_cpu,
771 };
772 
773 /* *INDENT-ON* */
774 static clib_error_t *
776  unformat_input_t * input,
777  vlib_cli_command_t * cmd)
778 {
779  clib_error_t *error = 0;
780  int enable;
781 
782  if (!unformat_user (input, unformat_vlib_enable_disable, &enable))
783  {
784  error = clib_error_return (0, "expecting enable/on or disable/off");
785  goto done;
786  }
787 
788  clib_mem_trace (enable);
789 
790 done:
791  return error;
792 }
793 
794 /* *INDENT-OFF* */
795 VLIB_CLI_COMMAND (enable_disable_memory_trace_command, static) = {
796  .path = "memory-trace",
797  .short_help = "Enable/disable memory allocation trace",
798  .function = enable_disable_memory_trace,
799 };
800 /* *INDENT-ON* */
801 
802 
803 static clib_error_t *
805  vlib_cli_command_t * cmd)
806 {
807  clib_error_t *error = 0;
808  void *heap;
809  mheap_t *mheap;
810 
811  if (unformat (input, "on"))
812  {
813  /* *INDENT-OFF* */
815  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
816  mheap = mheap_header(heap);
817  mheap->flags |= MHEAP_FLAG_VALIDATE;
818  // Turn off small object cache because it delays detection of errors
820  });
821  /* *INDENT-ON* */
822 
823  }
824  else if (unformat (input, "off"))
825  {
826  /* *INDENT-OFF* */
828  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
829  mheap = mheap_header(heap);
830  mheap->flags &= ~MHEAP_FLAG_VALIDATE;
832  });
833  /* *INDENT-ON* */
834  }
835  else if (unformat (input, "now"))
836  {
837  /* *INDENT-OFF* */
839  heap = clib_per_cpu_mheaps[this_vlib_main->thread_index];
840  mheap = mheap_header(heap);
841  mheap_validate(heap);
842  });
843  /* *INDENT-ON* */
844  vlib_cli_output (vm, "heap validation complete");
845 
846  }
847  else
848  {
849  return clib_error_return (0, "unknown input `%U'",
850  format_unformat_error, input);
851  }
852 
853  return error;
854 }
855 
856 /* *INDENT-OFF* */
857 VLIB_CLI_COMMAND (cmd_test_heap_validate,static) = {
858  .path = "test heap-validate",
859  .short_help = "<on/off/now> validate heap on future allocs/frees or right now",
860  .function = test_heap_validate,
861 };
862 /* *INDENT-ON* */
863 
864 static clib_error_t *
866  vlib_cli_command_t * cmd)
867 {
868  char *newenviron[] = { NULL };
869 
870  execve (vm->name, (char **) vm->argv, newenviron);
871 
872  return 0;
873 }
874 
875 /* *INDENT-OFF* */
876 VLIB_CLI_COMMAND (restart_cmd,static) = {
877  .path = "restart",
878  .short_help = "restart process",
879  .function = restart_cmd_fn,
880 };
881 /* *INDENT-ON* */
882 
883 #ifdef TEST_CODE
884 /*
885  * A trivial test harness to verify the per-process output_function
886  * is working correcty.
887  */
888 
889 static clib_error_t *
890 sleep_ten_seconds (vlib_main_t * vm,
891  unformat_input_t * input, vlib_cli_command_t * cmd)
892 {
893  u16 i;
894  u16 my_id = rand ();
895 
896  vlib_cli_output (vm, "Starting 10 seconds sleep with id %u\n", my_id);
897 
898  for (i = 0; i < 10; i++)
899  {
901  vlib_cli_output (vm, "Iteration number %u, my id: %u\n", i, my_id);
902  }
903  vlib_cli_output (vm, "Done with sleep with id %u\n", my_id);
904  return 0;
905 }
906 
907 /* *INDENT-OFF* */
908 VLIB_CLI_COMMAND (ping_command, static) = {
909  .path = "test sleep",
910  .function = sleep_ten_seconds,
911  .short_help = "Sleep for 10 seconds",
912 };
913 /* *INDENT-ON* */
914 #endif /* ifdef TEST_CODE */
915 
916 static uword
917 vlib_cli_normalize_path (char *input, char **result)
918 {
919  char *i = input;
920  char *s = 0;
921  uword l = 0;
922  uword index_of_last_space = ~0;
923 
924  while (*i != 0)
925  {
926  u8 c = *i++;
927  /* Multiple white space -> single space. */
928  switch (c)
929  {
930  case ' ':
931  case '\t':
932  case '\n':
933  case '\r':
934  if (l > 0 && s[l - 1] != ' ')
935  {
936  vec_add1 (s, ' ');
937  l++;
938  }
939  break;
940 
941  default:
942  if (l > 0 && s[l - 1] == ' ')
943  index_of_last_space = vec_len (s);
944  vec_add1 (s, c);
945  l++;
946  break;
947  }
948  }
949 
950  /* Remove any extra space at end. */
951  if (l > 0 && s[l - 1] == ' ')
952  _vec_len (s) -= 1;
953 
954  *result = s;
955  return index_of_last_space;
956 }
957 
959 parent_path_len (char *path)
960 {
961  word i;
962  for (i = vec_len (path) - 1; i >= 0; i--)
963  {
964  if (path[i] == ' ')
965  return i;
966  }
967  return ~0;
968 }
969 
970 static void
971 add_sub_command (vlib_cli_main_t * cm, uword parent_index, uword child_index)
972 {
973  vlib_cli_command_t *p, *c;
974  vlib_cli_sub_command_t *sub_c;
975  u8 *sub_name;
976  word i, l;
977 
978  p = vec_elt_at_index (cm->commands, parent_index);
979  c = vec_elt_at_index (cm->commands, child_index);
980 
981  l = parent_path_len (c->path);
982  if (l == ~0)
983  sub_name = vec_dup ((u8 *) c->path);
984  else
985  {
986  ASSERT (l + 1 < vec_len (c->path));
987  sub_name = 0;
988  vec_add (sub_name, c->path + l + 1, vec_len (c->path) - (l + 1));
989  }
990 
991  if (sub_name[0] == '%')
992  {
993  uword *q;
995 
996  /* Remove %. */
997  vec_delete (sub_name, 1, 0);
998 
999  if (!p->sub_rule_index_by_name)
1000  p->sub_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
1001  sizeof (sub_name[0]),
1002  sizeof (uword));
1003  q = hash_get_mem (p->sub_rule_index_by_name, sub_name);
1004  if (q)
1005  {
1006  sr = vec_elt_at_index (p->sub_rules, q[0]);
1007  ASSERT (sr->command_index == child_index);
1008  return;
1009  }
1010 
1011  q = hash_get_mem (cm->parse_rule_index_by_name, sub_name);
1012  if (!q)
1013  {
1014  clib_error ("reference to unknown rule `%%%v' in path `%v'",
1015  sub_name, c->path);
1016  return;
1017  }
1018 
1019  hash_set_mem (p->sub_rule_index_by_name, sub_name,
1020  vec_len (p->sub_rules));
1021  vec_add2 (p->sub_rules, sr, 1);
1022  sr->name = sub_name;
1023  sr->rule_index = q[0];
1024  sr->command_index = child_index;
1025  return;
1026  }
1027 
1028  if (!p->sub_command_index_by_name)
1029  p->sub_command_index_by_name = hash_create_vec ( /* initial length */ 32,
1030  sizeof (c->path[0]),
1031  sizeof (uword));
1032 
1033  /* Check if sub-command has already been created. */
1034  if (hash_get_mem (p->sub_command_index_by_name, sub_name))
1035  {
1036  vec_free (sub_name);
1037  return;
1038  }
1039 
1040  vec_add2 (p->sub_commands, sub_c, 1);
1041  sub_c->index = child_index;
1042  sub_c->name = sub_name;
1044  sub_c - p->sub_commands);
1045 
1046  vec_validate (p->sub_command_positions, vec_len (sub_c->name) - 1);
1047  for (i = 0; i < vec_len (sub_c->name); i++)
1048  {
1049  int n;
1051 
1053 
1054  if (!pos->bitmaps)
1055  pos->min_char = sub_c->name[i];
1056 
1057  n = sub_c->name[i] - pos->min_char;
1058  if (n < 0)
1059  {
1060  pos->min_char = sub_c->name[i];
1061  vec_insert (pos->bitmaps, -n, 0);
1062  n = 0;
1063  }
1064 
1065  vec_validate (pos->bitmaps, n);
1066  pos->bitmaps[n] =
1067  clib_bitmap_ori (pos->bitmaps[n], sub_c - p->sub_commands);
1068  }
1069 }
1070 
1071 static void
1073 {
1074  uword p_len, pi, *p;
1075  char *p_path;
1076  vlib_cli_command_t *c, *parent;
1077 
1078  /* Root command (index 0) should have already been added. */
1079  ASSERT (vec_len (cm->commands) > 0);
1080 
1081  c = vec_elt_at_index (cm->commands, ci);
1082  p_len = parent_path_len (c->path);
1083 
1084  /* No space? Parent is root command. */
1085  if (p_len == ~0)
1086  {
1087  add_sub_command (cm, 0, ci);
1088  return;
1089  }
1090 
1091  p_path = 0;
1092  vec_add (p_path, c->path, p_len);
1093 
1094  p = hash_get_mem (cm->command_index_by_path, p_path);
1095 
1096  /* Parent exists? */
1097  if (!p)
1098  {
1099  /* Parent does not exist; create it. */
1100  vec_add2 (cm->commands, parent, 1);
1101  parent->path = p_path;
1102  hash_set_mem (cm->command_index_by_path, parent->path,
1103  parent - cm->commands);
1104  pi = parent - cm->commands;
1105  }
1106  else
1107  {
1108  pi = p[0];
1109  vec_free (p_path);
1110  }
1111 
1112  add_sub_command (cm, pi, ci);
1113 
1114  /* Create parent's parent. */
1115  if (!p)
1116  vlib_cli_make_parent (cm, pi);
1117 }
1118 
1121 {
1122  return (c->long_help == 0 && c->short_help == 0 && c->function == 0);
1123 }
1124 
1125 clib_error_t *
1127 {
1128  vlib_cli_main_t *cm = &vm->cli_main;
1129  clib_error_t *error = 0;
1130  uword ci, *p;
1131  char *normalized_path;
1132 
1133  if ((error = vlib_call_init_function (vm, vlib_cli_init)))
1134  return error;
1135 
1136  (void) vlib_cli_normalize_path (c->path, &normalized_path);
1137 
1138  if (!cm->command_index_by_path)
1139  cm->command_index_by_path = hash_create_vec ( /* initial length */ 32,
1140  sizeof (c->path[0]),
1141  sizeof (uword));
1142 
1143  /* See if command already exists with given path. */
1144  p = hash_get_mem (cm->command_index_by_path, normalized_path);
1145  if (p)
1146  {
1147  vlib_cli_command_t *d;
1148 
1149  ci = p[0];
1150  d = vec_elt_at_index (cm->commands, ci);
1151 
1152  /* If existing command was created via vlib_cli_make_parent
1153  replaced it with callers data. */
1154  if (vlib_cli_command_is_empty (d))
1155  {
1156  vlib_cli_command_t save = d[0];
1157 
1159 
1160  /* Copy callers fields. */
1161  d[0] = c[0];
1162 
1163  /* Save internal fields. */
1164  d->path = save.path;
1165  d->sub_commands = save.sub_commands;
1168  d->sub_rules = save.sub_rules;
1169  }
1170  else
1171  error =
1172  clib_error_return (0, "duplicate command name with path %v",
1173  normalized_path);
1174 
1175  vec_free (normalized_path);
1176  if (error)
1177  return error;
1178  }
1179  else
1180  {
1181  /* Command does not exist: create it. */
1182 
1183  /* Add root command (index 0). */
1184  if (vec_len (cm->commands) == 0)
1185  {
1186  /* Create command with index 0; path is empty string. */
1187  vec_resize (cm->commands, 1);
1188  }
1189 
1190  ci = vec_len (cm->commands);
1191  hash_set_mem (cm->command_index_by_path, normalized_path, ci);
1192  vec_add1 (cm->commands, c[0]);
1193 
1194  c = vec_elt_at_index (cm->commands, ci);
1195  c->path = normalized_path;
1196 
1197  /* Don't inherit from registration. */
1198  c->sub_commands = 0;
1200  c->sub_command_positions = 0;
1201  }
1202 
1203  vlib_cli_make_parent (cm, ci);
1204  return 0;
1205 }
1206 
1207 clib_error_t *
1209 {
1210  vlib_cli_main_t *cm = &vm->cli_main;
1212  clib_error_t *error = 0;
1213  u8 *r_name;
1214  uword *p;
1215 
1216  if (!cm->parse_rule_index_by_name)
1217  cm->parse_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
1218  sizeof (r->name[0]),
1219  sizeof (uword));
1220 
1221  /* Make vector copy of name. */
1222  r_name = format (0, "%s", r_reg->name);
1223 
1224  if ((p = hash_get_mem (cm->parse_rule_index_by_name, r_name)))
1225  {
1226  vec_free (r_name);
1227  return clib_error_return (0, "duplicate parse rule name `%s'",
1228  r_reg->name);
1229  }
1230 
1231  vec_add2 (cm->parse_rules, r, 1);
1232  r[0] = r_reg[0];
1233  r->name = (char *) r_name;
1235 
1236  return error;
1237 }
1238 
1239 #if 0
1240 /* $$$ turn back on again someday, maybe */
1241 static clib_error_t *vlib_cli_register_parse_rules (vlib_main_t * vm,
1243  lo,
1245  hi)
1246  __attribute__ ((unused))
1247 {
1248  clib_error_t *error = 0;
1250 
1251  for (r = lo; r < hi; r = clib_elf_section_data_next (r, 0))
1252  {
1253  if (!r->name || strlen (r->name) == 0)
1254  {
1255  error = clib_error_return (0, "parse rule with no name");
1256  goto done;
1257  }
1258 
1259  error = vlib_cli_register_parse_rule (vm, r);
1260  if (error)
1261  goto done;
1262  }
1263 
1264 done:
1265  return error;
1266 }
1267 #endif
1268 
1269 static int
1270 cli_path_compare (void *a1, void *a2)
1271 {
1272  u8 **s1 = a1;
1273  u8 **s2 = a2;
1274 
1275  if ((vec_len (*s1) < vec_len (*s2)) &&
1276  memcmp ((char *) *s1, (char *) *s2, vec_len (*s1)) == 0)
1277  return -1;
1278 
1279 
1280  if ((vec_len (*s1) > vec_len (*s2)) &&
1281  memcmp ((char *) *s1, (char *) *s2, vec_len (*s2)) == 0)
1282  return 1;
1283 
1284  return vec_cmp (*s1, *s2);
1285 }
1286 
1287 static clib_error_t *
1289  vlib_cli_command_t * cmd)
1290 {
1291  vlib_cli_main_t *cm = &vm->cli_main;
1292  vlib_cli_command_t *cli;
1293  u8 **paths = 0, **s;
1294 
1295  /* *INDENT-OFF* */
1296  vec_foreach (cli, cm->commands)
1297  if (vec_len (cli->path) > 0)
1298  vec_add1 (paths, (u8 *) cli->path);
1299 
1301 
1302  vec_foreach (s, paths)
1303  vlib_cli_output (vm, "%v", *s);
1304  /* *INDENT-ON* */
1305 
1306  vec_free (paths);
1307  return 0;
1308 }
1309 
1310 /* *INDENT-OFF* */
1311 VLIB_CLI_COMMAND (show_cli_command, static) = {
1312  .path = "show cli",
1313  .short_help = "Show cli commands",
1314  .function = show_cli_cmd_fn,
1315 };
1316 /* *INDENT-ON* */
1317 
1318 static clib_error_t *
1320 {
1321  vlib_cli_main_t *cm = &vm->cli_main;
1322  clib_error_t *error = 0;
1323  vlib_cli_command_t *cmd;
1324 
1325  cmd = cm->cli_command_registrations;
1326 
1327  while (cmd)
1328  {
1329  error = vlib_cli_register (vm, cmd);
1330  if (error)
1331  return error;
1332  cmd = cmd->next_cli_command;
1333  }
1334  return error;
1335 }
1336 
1338 
1339 /*
1340  * fd.io coding-style-patch-verification: ON
1341  *
1342  * Local Variables:
1343  * eval: (c-set-style "gnu")
1344  * End:
1345  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
uword output_function_arg
Definition: node.h:551
vmrglw vmrglh hi
unformat_function_t * unformat_function
Definition: cli.h:80
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
void * clib_per_cpu_mheaps[CLIB_MAX_MHEAPS]
Definition: mem_mheap.c:46
static clib_error_t * show_cpu(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:742
foreach_x86_64_flags format_function_t format_cpu_uarch
Definition: cpu.h:102
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:699
void vlib_cli_input(vlib_main_t *vm, unformat_input_t *input, vlib_cli_output_function_t *function, uword function_arg)
Definition: cli.c:643
uword data_size
Definition: cli.h:78
unformat_function_t unformat_eof
Definition: format.h:291
static u8 * format_vlib_cli_parse_rule_name(u8 *s, va_list *args)
Definition: cli.c:356
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:190
#define clib_error(format, args...)
Definition: error.h:62
vlib_cli_command_t * commands
Definition: cli.h:136
#define NULL
Definition: clib.h:55
f64 clocks_per_second
Definition: time.h:53
format_function_t format_cpu_flags
Definition: cpu.h:104
add_epi add_epi sub
Definition: vector_sse2.h:283
#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:561
static uword parent_path_len(char *path)
Definition: cli.c:959
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:274
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
clib_time_t clib_time
Definition: main.h:62
vlib_cli_main_t cli_main
Definition: main.h:118
static vlib_cli_command_t * all_subs(vlib_cli_main_t *cm, vlib_cli_command_t *subs, u32 command_index)
Definition: cli.c:404
u8 * format_mheap(u8 *s, va_list *va)
Definition: mheap.c:1162
#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.
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
static clib_error_t * test_heap_validate(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:804
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define always_inline
Definition: clib.h:84
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.
#define clib_error_return(e, args...)
Definition: error.h:99
uword * command_index_by_path
Definition: cli.h:139
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:241
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static void add_sub_command(vlib_cli_main_t *cm, uword parent_index, uword child_index)
Definition: cli.c:971
static uword unformat_vlib_cli_sub_command(unformat_input_t *i, va_list *args)
Definition: cli.c:195
static int vlib_cli_cmp_strings(void *a1, void *a2)
Definition: cli.c:240
static int vlib_cli_cmp_rule(void *a1, void *a2)
Definition: cli.c:421
u8 * format_c_identifier(u8 *s, va_list *va)
Definition: std-formats.c:258
char * name
Definition: main.h:98
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
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:775
#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:188
#define vec_insert(V, N, M)
Insert N vector elements starting at element M, initialize new elements to zero (no header...
Definition: vec.h:686
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
clib_error_t * vlib_cli_register_parse_rule(vlib_main_t *vm, vlib_cli_parse_rule_t *r_reg)
Definition: cli.c:1208
u8 ** vlib_cli_get_possible_completions(u8 *str)
Definition: cli.c:249
vlib_cli_sub_rule_t * sub_rules
Definition: cli.h:124
struct _unformat_input_t unformat_input_t
static int cli_path_compare(void *a1, void *a2)
Definition: cli.c:1270
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:805
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:203
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:439
#define foreach_vlib_main(body)
Definition: threads.h:208
word fformat(FILE *f, char *fmt,...)
Definition: format.c:453
void unformat_init_vector(unformat_input_t *input, u8 *vector_string)
Definition: unformat.c:1031
vlib_cli_sub_command_t * sub_commands
Definition: cli.h:111
u8 ** argv
Definition: main.h:176
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
svmdb_client_t * c
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:413
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
static uword * clib_bitmap_andnot(uword *ai, uword *bi)
Logical operator across two bitmaps.
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1166
uword ** bitmaps
Definition: cli.h:52
static u8 * format_vlib_cli_command_help(u8 *s, va_list *args)
Definition: cli.c:342
static uword * vlib_cli_sub_command_match(vlib_cli_command_t *c, unformat_input_t *input)
Definition: cli.c:79
static uword vlib_cli_command_is_empty(vlib_cli_command_t *c)
Definition: cli.c:1120
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static int vlib_cli_cmp_command(void *a1, void *a2)
Definition: cli.c:430
#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:1072
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static clib_error_t * vlib_cli_init(vlib_main_t *vm)
Definition: cli.c:1319
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
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
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
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:920
static clib_error_t * show_memory_usage(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:703
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
#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:441
struct vlib_cli_command_t * next_cli_command
Definition: cli.h:127
unsigned short u16
Definition: types.h:57
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:644
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
uword unformat_vlib_enable_disable(unformat_input_t *input, va_list *args)
Definition: format.c:116
unsigned char u8
Definition: types.h:56
uword unformat_vlib_cli_sub_input(unformat_input_t *i, va_list *args)
Definition: cli.c:152
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
void ** parse_rule_data
Definition: cli.h:148
#define clib_error_free(e)
Definition: error.h:86
#define hash_get_mem(h, key)
Definition: hash.h:268
clib_error_t * vlib_cli_register(vlib_main_t *vm, vlib_cli_command_t *c)
Definition: cli.c:1126
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:637
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1198
void mheap_validate(void *v)
Definition: mheap.c:1338
static clib_error_t * restart_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:865
#define vec_foreach(var, vec)
Vector iterator.
vlib_cli_parse_position_t * sub_command_positions
Definition: cli.h:118
static uword vlib_cli_normalize_path(char *input, char **result)
Definition: cli.c:917
vlib_cli_output_function_t * output_function
Definition: node.h:550
void clib_mem_trace(int enable)
Definition: mem_mheap.c:154
static clib_error_t * show_cli_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:1288
char * short_help
Definition: cli.h:98
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:815
format_function_t format_cpu_model_name
Definition: cpu.h:103
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:363
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:169