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