20 #include <sys/types.h> 39 if (total_counts == 0)
48 percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \ 49 / (f64) total_counts; \ 51 vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \ 52 vector_rate_histogram[SLEEP_##n##_US], \ 67 .path =
"show api histogram",
68 .short_help =
"show api histogram",
91 .path =
"clear api histogram",
92 .short_help =
"clear api histogram",
105 u32 *confused_indices = 0;
111 "Name",
"PID",
"Queue Length",
"Queue VA",
"Health");
120 if (regp->unanswered_pings > 0)
121 health =
"questionable";
125 q = regp->vl_input_queue;
127 vlib_cli_output (vm,
"%20s %8d %14d 0x%016llx %s\n",
128 regp->name, q->consumer_pid, q->cursize,
133 clib_warning (
"NULL client registration index %d",
134 regpp - am->vl_clients);
135 vec_add1 (confused_indices, regpp - am->vl_clients);
144 for (i = 0; i <
vec_len (confused_indices); i++)
151 if (am->missing_clients)
153 am->missing_clients);
198 .short_help =
"Show API information",
208 .path =
"show api clients",
209 .short_help =
"Client information",
220 .path =
"show api trace-status",
221 .short_help =
"Display API trace status",
271 .path =
"show api message-table",
272 .short_help =
"Message Table",
280 int len0, len1, clen;
284 clen = len0 < len1 ? len0 : len1;
285 return (strncmp ((
char *) a0->
name, (
char *) a1->
name, clen));
294 s =
format (s,
"%-50s%9s%9s",
"Name",
"First-ID",
"Last-ID");
324 for (i = 0; i <
vec_len (rp); i++)
338 .path =
"show api plugin",
339 .short_help =
"show api plugin",
364 trace_name =
"TX trace";
369 trace_name =
"RX trace";
378 s =
format (s,
"%s: not yet configured.\n", trace_name);
382 s =
format (s,
"%s: used %d of %d items, %s enabled, %s wrapped\n",
389 __attribute__ ((weak));
397 u32 first_index,
u32 last_index,
398 vl_api_replay_t which)
400 vl_api_trace_file_header_t *hp;
405 u8 endian_swap_needed = 0;
409 void **saved_print_handlers = 0;
411 fd = open ((
char *) filename, O_RDONLY);
419 if (fstat (fd, &statb) < 0)
426 if (!(statb.st_mode & S_IFREG) || (statb.st_size < sizeof (*hp)))
433 file_size = statb.st_size;
434 file_size = (file_size + 4095) & ~(4096);
436 hp = mmap (0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
438 if (hp == (vl_api_trace_file_header_t *) MAP_FAILED)
448 endian_swap_needed = 1;
450 if (endian_swap_needed)
451 nitems = ntohl (hp->nitems);
455 if (last_index == (
u32) ~ 0)
457 last_index = nitems - 1;
460 if (first_index >= nitems || last_index >= nitems)
463 first_index, last_index, nitems - 1);
464 munmap (hp, file_size);
469 "Note: wrapped/incomplete trace, results may vary\n");
478 msg = (
u8 *) (hp + 1);
480 for (i = 0; i < first_index; i++)
486 size = clib_host_to_net_u32 (*(
u32 *) msg);
490 msg_id = ntohs (*((
u16 *) msg));
492 msg_id = *((
u16 *) msg);
498 munmap (hp, file_size);
507 for (; i <= last_index; i++)
517 size = clib_host_to_net_u32 (*(
u32 *) msg);
521 msg_id = ntohs (*((
u16 *) msg));
523 msg_id = *((
u16 *) msg);
529 munmap (hp, file_size);
548 void (*endian_fp) (
void *);
553 munmap (hp, file_size);
559 (*endian_fp) (tmpbuf +
sizeof (
uword));
565 msg_idp = (
u16 *) (tmpbuf +
sizeof (
uword));
576 u8 *(*print_fp) (
void *,
void *);
579 (*print_fp) (tmpbuf +
sizeof (
uword), vm);
595 u8 *(*print_fp) (
void *,
void *);
601 (*print_fp) (tmpbuf +
sizeof (
uword), vm);
604 s =
format (0,
"static u8 * vl_api_%s_%d[%d] = {",
612 s =
format (s,
"0x%02x,", tmpbuf[
sizeof (
uword) + j]);
614 s =
format (s,
"\n};\n%c", 0);
630 (*handler) (tmpbuf +
sizeof (
uword), vm);
644 _vec_len (tmpbuf) = 0;
648 if (saved_print_handlers)
655 munmap (hp, file_size);
664 u32 nitems = 256 << 10;
677 if (
unformat (input,
"nitems %d", &nitems))
686 else if (
unformat (input,
"save %s", &filename))
689 if (strstr ((
char *) filename,
"..")
690 || index ((
char *) filename,
'/'))
697 chroot_filename =
format (0,
"/tmp/%s%c", filename, 0);
701 fp = fopen ((
char *) chroot_filename,
"w");
719 "Error while writing end of buffer trace to file\n");
722 "Error while writing start of buffer trace to file\n");
729 else if (
unformat (input,
"dump %s", &filename))
733 else if (
unformat (input,
"custom-dump %s", &filename))
737 else if (
unformat (input,
"replay %s", &filename))
741 else if (
unformat (input,
"initializers %s", &filename))
749 else if (
unformat (input,
"first %d", &first))
753 else if (
unformat (input,
"last %d", &last))
757 else if (
unformat (input,
"status"))
767 else if (
unformat (input,
"post-mortem-on"))
769 else if (
unformat (input,
"post-mortem-off"))
786 .short_help =
"api trace [on|off][first <n>][last <n>][status][free]" 787 "[post-mortem-on][dump|custom-dump|save|replay <file>]",
804 else if (
unformat (input,
"tx nitems %u", &nitems)
834 else if (
unformat (input,
"debug on"))
838 else if (
unformat (input,
"debug off"))
864 .path =
"set api-trace",
865 .short_help =
"API trace [on][on tx][on rx][off][free][debug on][debug off]",
873 u32 nitems = 256 << 10;
881 if (
unformat (input,
"nitems %d", &nitems))
887 else if (
unformat (input,
"save-api-table %s",
913 if (
unformat (input,
"length %d", &nitems) ||
914 (
unformat (input,
"len %d", &nitems)))
919 clib_warning (
"vlib input queue length %d too small, ignored",
954 for (i =
vec_len (rv) - 1; i >= 0; i--)
1004 int compare_current = 0;
1005 int numeric_sort = 0;
1008 u32 ndifferences = 0;
1012 if (
unformat (input,
"file %s", &filename))
1014 else if (
unformat (input,
"compare-current")
1016 compare_current = 1;
1017 else if (
unformat (input,
"numeric"))
1024 if (numeric_sort && compare_current)
1026 (0,
"Comparison and numeric sorting are incompatible");
1040 for (i = 0; i < nmsgs; i++)
1045 item->msg_index = msg_index;
1046 item->name_and_crc = name_and_crc;
1054 if (compare_current)
1062 for (i = 0; i < nmsgs; i++)
1068 item->msg_index = msg_index;
1069 item->name_and_crc = name_and_crc;
1083 if (compare_current)
1099 for (i = 0; i <
vec_len (table);)
1102 if (i == vec_len (table) - 1)
1110 ((
char *) table[i].name_and_crc,
1111 (
char *) table[i + 1].name_and_crc,
1112 vec_len (table[i].name_and_crc)))
1121 if (i + 1 == vec_len (table)
1122 || strcmp ((
char *) table[i].
name, (
char *) table[i + 1].name))
1126 table[i].name, table[i].which ?
1135 if (ndifferences == 0)
1144 vlib_cli_output (vm,
"%=60s %=8s %=10s",
"Message name",
"MsgID",
"CRC");
1146 for (i = 0; i <
vec_len (table); i++)
1150 item->msg_index, item->crc);
1154 for (i = 0; i <
vec_len (table); i++)
1201 .path =
"show api dump",
1202 .short_help =
"show api dump file <filename> [numeric | compare-current]",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Message range (belonging to a plugin)
static clib_error_t * vl_api_show_plugin_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
u64 vector_rate_histogram[]
u8 * name
name of the plugin
static u64 unserialize_likely_small_unsigned_integer(serialize_main_t *m)
u8 wrapped
trace has wrapped
int size
for sanity checking
u8 * message_bounce
Don't automatically free message buffer vetor.
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
void vl_sock_api_dump_clients(vlib_main_t *vm, api_main_t *am)
static heap_elt_t * last(heap_header_t *h)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
static u8 * extract_crc(u8 *s)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static vlib_cli_command_t cli_show_api_message_table_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_message_table_command)
static int range_compare(vl_api_msg_range_t *a0, vl_api_msg_range_t *a1)
trace_cfg_t * api_trace_cfg
Current trace configuration.
#define clib_memcpy(d, s, n)
static clib_error_t * api_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
vl_api_trace_t * rx_trace
Received message trace configuration.
void vl_msg_api_barrier_sync(void)
vl_api_registration_t ** vl_clients
vlib/vpp only: vector of client registrations
#define foreach_histogram_bucket
#define clib_arch_is_little_endian
int replay_in_progress
Replay in progress?
#define clib_error_return(e, args...)
static clib_error_t * vl_api_clear_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
static clib_error_t * vl_api_client_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
#define VL_API_BIG_ENDIAN
static heap_elt_t * first(heap_header_t *h)
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
u16 last_msg_id
last assigned message ID
static int table_id_cmp(void *a1, void *a2)
void(** msg_print_handlers)(void *, void *)
Message print function vector.
int replay_enable
This message can be replayed.
static vlib_cli_command_t cli_show_api_plugin_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_plugin_command)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
static void cleanup(void)
#define VLIB_CONFIG_FUNCTION(x, n,...)
static clib_error_t * api_trace_config_fn(vlib_main_t *vm, unformat_input_t *input)
void unserialize_cstring(serialize_main_t *m, char **s)
static vlib_cli_command_t cli_show_api_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_command)
API main structure, used by both vpp and binary API clients.
int vl_msg_api_trace_save(api_main_t *am, vl_api_trace_which_t which, FILE *fp)
u8 enabled
trace is enabled
An API client registration, only in vpp/vlib.
#define clib_arch_is_big_endian
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
static clib_error_t * vl_api_trace_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
void serialize_open_vector(serialize_main_t *m, u8 *vector)
#define vec_free(V)
Free vector's memory (no header).
vl_api_msg_range_t * msg_ranges
vector of message ranges
static u8 * extract_name(u8 *s)
clib_error_t * unserialize_open_clib_file(serialize_main_t *m, char *file)
static int table_name_and_crc_cmp(void *a1, void *a2)
#define clib_warning(format, args...)
static void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
u8 * vl_api_serialize_message_table(api_main_t *am, u8 *vector)
static void vl_msg_api_process_file(vlib_main_t *vm, u8 *filename, u32 first_index, u32 last_index, vl_api_replay_t which)
const char ** msg_names
Message name vector.
#define VLIB_CLI_COMMAND(x,...)
u8 * save_msg_table_filename
Dump (msg-name, crc) snapshot here at startup.
vl_api_trace_t * tx_trace
Sent message trace configuration.
#define pool_put_index(p, i)
Free pool element with given index.
static clib_error_t * vl_api_message_table_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
static clib_error_t * api_queue_config_fn(vlib_main_t *vm, unformat_input_t *input)
#define vec_delete(V, N, M)
Delete N elements starting at element M.
void serialize_close(serialize_main_t *m)
vl_api_trace_which_t
Trace RX / TX enum.
static clib_error_t * dump_api_table_file_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static vlib_cli_command_t cli_show_api_clients_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_clients_command)
static clib_error_t * vl_api_status_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
u16 first_msg_id
first assigned message ID
void(** msg_endian_handlers)(void *)
Message endian handler vector.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
static vlib_cli_command_t cli_show_api_status_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_status_command)
struct _svm_queue svm_queue_t
void(** msg_handlers)(void *)
Message handler vector.
u8 * is_mp_safe
Message is mp safe vector.
int msg_print_flag
Print every received message.
static vlib_cli_command_t api_trace_command
(constructor) VLIB_CLI_COMMAND (api_trace_command)
Trace configuration for a single message.
#define VL_API_LITTLE_ENDIAN
void vl_msg_api_custom_dump_configure(api_main_t *am)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
void vl_msg_api_barrier_release(void)
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
static clib_error_t * vl_api_show_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static vlib_cli_command_t dump_api_table_file
(constructor) VLIB_CLI_COMMAND (dump_api_table_file)
void vl_msg_api_post_mortem_dump_enable_disable(int enable)
static u8 * format_api_msg_range(u8 *s, va_list *args)
u32 nitems
Number of trace records.
u32 vlib_input_queue_length
vpp/vlib input queue length
u8 * format_vl_msg_api_trace_status(u8 *s, va_list *args)
static uword pool_elts(void *v)
Number of active elements in a pool.