+ for (i = 0; i < lmin; i++)
+ {
+ if (c1->path[i] < c2->path[i])
+ return -1;
+ else if (c1->path[i] > c2->path[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+typedef struct
+{
+ vlib_cli_main_t *cm;
+ u32 parent_command_index;
+ int show_mp_safe;
+ int show_not_mp_safe;
+ int show_hit;
+ int clear_hit;
+} vlib_cli_walk_args_t;
+
+static void
+cli_recursive_walk (vlib_cli_walk_args_t * aa)
+{
+ vlib_cli_command_t *parent;
+ vlib_cli_sub_command_t *sub;
+ vlib_cli_walk_args_t _a, *a = &_a;
+ vlib_cli_main_t *cm;
+ int i;
+
+ /* Copy args into this stack frame */
+ *a = *aa;
+ cm = a->cm;
+
+ parent = vec_elt_at_index (cm->commands, a->parent_command_index);
+
+ if (parent->function)
+ {
+ if (((a->show_mp_safe && parent->is_mp_safe)
+ || (a->show_not_mp_safe && !parent->is_mp_safe))
+ && (a->show_hit == 0 || parent->hit_counter))
+ {
+ vec_add1 (cm->sort_vector, a->parent_command_index);
+ }
+
+ if (a->clear_hit)
+ parent->hit_counter = 0;
+ }
+
+ for (i = 0; i < vec_len (parent->sub_commands); i++)
+ {
+ sub = vec_elt_at_index (parent->sub_commands, i);
+ a->parent_command_index = sub->index;
+ cli_recursive_walk (a);
+ }
+}
+
+static u8 *
+format_mp_safe (u8 * s, va_list * args)
+{
+ vlib_cli_main_t *cm = va_arg (*args, vlib_cli_main_t *);
+ int show_mp_safe = va_arg (*args, int);
+ int show_not_mp_safe = va_arg (*args, int);
+ int show_hit = va_arg (*args, int);
+ int clear_hit = va_arg (*args, int);
+ vlib_cli_command_t *c;
+ vlib_cli_walk_args_t _a, *a = &_a;
+ int i;
+ char *format_string = "\n%v";
+
+ if (show_hit)
+ format_string = "\n%v: %u";
+
+ vec_reset_length (cm->sort_vector);
+
+ a->cm = cm;
+ a->parent_command_index = 0;
+ a->show_mp_safe = show_mp_safe;
+ a->show_not_mp_safe = show_not_mp_safe;
+ a->show_hit = show_hit;
+ a->clear_hit = clear_hit;
+
+ cli_recursive_walk (a);
+
+ vec_sort_with_function (cm->sort_vector, sort_cmds_by_path);
+
+ for (i = 0; i < vec_len (cm->sort_vector); i++)
+ {
+ c = vec_elt_at_index (cm->commands, cm->sort_vector[i]);
+ s = format (s, format_string, c->path, c->hit_counter);
+ }
+
+ return s;
+}
+
+
+static clib_error_t *
+show_cli_command_fn (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ int show_mp_safe = 0;
+ int show_not_mp_safe = 0;
+ int show_hit = 0;
+ int clear_hit = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "mp-safe"))
+ show_mp_safe = 1;
+ if (unformat (input, "not-mp-safe"))
+ show_not_mp_safe = 1;
+ else if (unformat (input, "hit"))
+ show_hit = 1;
+ else if (unformat (input, "clear-hit"))
+ clear_hit = 1;
+ else
+ break;
+ }
+
+ /* default set: all cli commands */
+ if (clear_hit == 0 && (show_mp_safe + show_not_mp_safe) == 0)
+ show_mp_safe = show_not_mp_safe = 1;
+
+ vlib_cli_output (vm, "%U", format_mp_safe, &vm->cli_main,
+ show_mp_safe, show_not_mp_safe, show_hit, clear_hit);
+ if (clear_hit)
+ vlib_cli_output (vm, "hit counters cleared...");