X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fcli.c;h=a85fa93906c27a99ea357dae8fefd807bfcc6a50;hb=73710c7da2f8deaea83dbbbfce8737c9c6cd2949;hp=3cc95076914f1ab2e7e460db9d1e47d897e8a1af;hpb=586afd762bfa149f5ca167bd5fd5a0cd59ce94fe;p=vpp.git diff --git a/src/vlib/cli.c b/src/vlib/cli.c index 3cc95076914..a85fa93906c 100644 --- a/src/vlib/cli.c +++ b/src/vlib/cli.c @@ -40,6 +40,7 @@ #include #include #include +#include /* Root of all show commands. */ /* *INDENT-OFF* */ @@ -235,6 +236,108 @@ unformat_vlib_cli_sub_command (unformat_input_t * i, va_list * args) return is_unique; } +static int +vlib_cli_cmp_strings (void *a1, void *a2) +{ + u8 *c1 = *(u8 **) a1; + u8 *c2 = *(u8 **) a2; + + return vec_cmp (c1, c2); +} + +u8 ** +vlib_cli_get_possible_completions (u8 * str) +{ + vlib_cli_command_t *c; + vlib_cli_sub_command_t *sc; + vlib_main_t *vm = vlib_get_main (); + vlib_cli_main_t *vcm = &vm->cli_main; + uword *match_bitmap = 0; + uword index, is_unique, help_next_level; + u8 **result = 0; + unformat_input_t input; + unformat_init_vector (&input, vec_dup (str)); + c = vec_elt_at_index (vcm->commands, 0); + + /* remove trailing whitespace, except for one of them */ + while (vec_len (input.buffer) >= 2 && + isspace (input.buffer[vec_len (input.buffer) - 1]) && + isspace (input.buffer[vec_len (input.buffer) - 2])) + { + vec_del1 (input.buffer, vec_len (input.buffer) - 1); + } + + /* if input is empty, directly return list of root commands */ + if (vec_len (input.buffer) == 0 || + (vec_len (input.buffer) == 1 && isspace (input.buffer[0]))) + { + vec_foreach (sc, c->sub_commands) + { + vec_add1 (result, (u8 *) sc->name); + } + goto done; + } + + /* add a trailing '?' so that vlib_cli_sub_command_match can find + * all commands starting with the input string */ + vec_add1 (input.buffer, '?'); + + while (1) + { + match_bitmap = vlib_cli_sub_command_match (c, &input); + /* no match: return no result */ + if (match_bitmap == 0) + { + goto done; + } + is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1; + /* unique match: try to step one subcommand level further */ + if (is_unique) + { + /* stop if no more input */ + if (input.index >= vec_len (input.buffer) - 1) + { + break; + } + + index = clib_bitmap_first_set (match_bitmap); + c = get_sub_command (vcm, c, index); + clib_bitmap_free (match_bitmap); + continue; + } + /* multiple matches: stop here, return all matches */ + break; + } + + /* remove trailing '?' */ + vec_del1 (input.buffer, vec_len (input.buffer) - 1); + + /* if we have a space at the end of input, and a unique match, + * autocomplete the next level of subcommands */ + help_next_level = (vec_len (str) == 0) || isspace (str[vec_len (str) - 1]); + /* *INDENT-OFF* */ + clib_bitmap_foreach(index, match_bitmap, { + if (help_next_level && is_unique) { + c = get_sub_command (vcm, c, index); + vec_foreach (sc, c->sub_commands) { + vec_add1 (result, (u8*) sc->name); + } + goto done; /* break doesn't work in this macro-loop */ + } + sc = &c->sub_commands[index]; + vec_add1(result, (u8*) sc->name); + }); + /* *INDENT-ON* */ + +done: + clib_bitmap_free (match_bitmap); + unformat_free (&input); + + if (result) + vec_sort_with_function (result, vlib_cli_cmp_strings); + return result; +} + static u8 * format_vlib_cli_command_help (u8 * s, va_list * args) { @@ -596,11 +699,14 @@ vlib_cli_output (vlib_main_t * vm, char *fmt, ...) vec_free (s); } +void *vl_msg_push_heap (void) __attribute__ ((weak)); +void vl_msg_pop_heap (void *oldheap) __attribute__ ((weak)); + static clib_error_t * show_memory_usage (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - int verbose = 0; + int verbose = 0, api_segment = 0; clib_error_t *error; u32 index = 0; @@ -608,6 +714,8 @@ show_memory_usage (vlib_main_t * vm, { if (unformat (input, "verbose")) verbose = 1; + else if (unformat (input, "api-segment")) + api_segment = 1; else { error = clib_error_return (0, "unknown input `%U'", @@ -616,6 +724,23 @@ show_memory_usage (vlib_main_t * vm, } } + if (api_segment) + { + void *oldheap = vl_msg_push_heap (); + u8 *s_in_svm = + format (0, "%U\n", format_mheap, clib_mem_get_heap (), 1); + vl_msg_pop_heap (oldheap); + u8 *s = vec_dup (s_in_svm); + + oldheap = vl_msg_push_heap (); + vec_free (s_in_svm); + vl_msg_pop_heap (oldheap); + vlib_cli_output (vm, "API segment start:"); + vlib_cli_output (vm, "%v", s); + vlib_cli_output (vm, "API segment end:"); + vec_free (s); + } + /* *INDENT-OFF* */ foreach_vlib_main ( ({ @@ -630,7 +755,7 @@ show_memory_usage (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_memory_usage_command, static) = { .path = "show memory", - .short_help = "Show current memory usage", + .short_help = "[verbose | api-segment] Show current memory usage", .function = show_memory_usage, }; /* *INDENT-ON* */ @@ -668,30 +793,48 @@ VLIB_CLI_COMMAND (show_cpu_command, static) = { }; /* *INDENT-ON* */ + static clib_error_t * enable_disable_memory_trace (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - clib_error_t *error = 0; + unformat_input_t _line_input, *line_input = &_line_input; int enable; + int api_segment = 0; + void *oldheap; - if (!unformat_user (input, unformat_vlib_enable_disable, &enable)) + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - error = clib_error_return (0, "expecting enable/on or disable/off"); - goto done; + if (!unformat (line_input, "%U", unformat_vlib_enable_disable, &enable)) + ; + else if (unformat (line_input, "api-segment")) + api_segment = 1; + else + { + unformat_free (line_input); + return clib_error_return (0, "invalid input"); + } } + unformat_free (line_input); + if (api_segment) + oldheap = vl_msg_push_heap (); clib_mem_trace (enable); + if (api_segment) + vl_msg_pop_heap (oldheap); -done: - return error; + return 0; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (enable_disable_memory_trace_command, static) = { .path = "memory-trace", - .short_help = "Enable/disable memory allocation trace", + .short_help = "on|off [api-segment] Enable/disable memory allocation trace", .function = enable_disable_memory_trace, }; /* *INDENT-ON* */ @@ -1163,6 +1306,55 @@ done: } #endif +static int +cli_path_compare (void *a1, void *a2) +{ + u8 **s1 = a1; + u8 **s2 = a2; + + if ((vec_len (*s1) < vec_len (*s2)) && + memcmp ((char *) *s1, (char *) *s2, vec_len (*s1)) == 0) + return -1; + + + if ((vec_len (*s1) > vec_len (*s2)) && + memcmp ((char *) *s1, (char *) *s2, vec_len (*s2)) == 0) + return 1; + + return vec_cmp (*s1, *s2); +} + +static clib_error_t * +show_cli_cmd_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vlib_cli_main_t *cm = &vm->cli_main; + vlib_cli_command_t *cli; + u8 **paths = 0, **s; + + /* *INDENT-OFF* */ + vec_foreach (cli, cm->commands) + if (vec_len (cli->path) > 0) + vec_add1 (paths, (u8 *) cli->path); + + vec_sort_with_function (paths, cli_path_compare); + + vec_foreach (s, paths) + vlib_cli_output (vm, "%v", *s); + /* *INDENT-ON* */ + + vec_free (paths); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_cli_command, static) = { + .path = "show cli", + .short_help = "Show cli commands", + .function = show_cli_cmd_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * vlib_cli_init (vlib_main_t * vm) {