X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvpp%2Fapp%2Fstat_client.c;h=0ee78d200af3e6ca11367dd265f3dd11214587be;hb=e906aacc1089ce86158486ec52d37a8470359ec2;hp=610a6a5b98d3c1e25be4b8296d1960744a44b051;hpb=048a4e5a000017d0d632ebf02dcc23d9bf9ccf72;p=vpp.git diff --git a/src/vpp/app/stat_client.c b/src/vpp/app/stat_client.c index 610a6a5b98d..0ee78d200af 100644 --- a/src/vpp/app/stat_client.c +++ b/src/vpp/app/stat_client.c @@ -1,6 +1,6 @@ /* *------------------------------------------------------------------ - * api_format.c + * stat_client.c * * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,60 +19,42 @@ #include -#include - -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs - -#define vl_endianfun /* define endian fcns */ -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) fformat (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - stat_client_main_t stat_client_main; -static void vl_api_map_stats_segment_reply_t_handler - (vl_api_map_stats_segment_reply_t * mp) +static int +stat_segment_connect (stat_client_main_t * sm) { - stat_client_main_t *sm = &stat_client_main; ssvm_private_t *ssvmp = &sm->stat_segment; ssvm_shared_header_t *shared_header; - socket_client_main_t *scm = sm->socket_client_main; - int rv = ntohl (mp->retval); - int my_fd, retval; - clib_error_t *error; - - if (rv != 0) + clib_socket_t s = { 0 }; + clib_error_t *err; + int fd = -1, retval; + + s.config = (char *) sm->socket_name; + s.flags = CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET; + err = clib_socket_init (&s); + if (err) { - fformat (stderr, "ERROR mapping stats segment: %d", rv); + clib_error_report (err); exit (1); } - - /* - * Check the socket for the magic fd - */ - error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 5); - if (error) + err = clib_socket_recvmsg (&s, 0, 0, &fd, 1); + if (err) { - clib_error_report (error); - exit (1); + clib_error_report (err); + return -1; } + clib_socket_close (&s); memset (ssvmp, 0, sizeof (*ssvmp)); - ssvmp->fd = my_fd; + ssvmp->fd = fd; /* Note: this closes memfd.fd */ retval = ssvm_slave_init_memfd (ssvmp); if (retval) { clib_warning ("WARNING: segment map returned %d", retval); - exit (1); + return -1; } fformat (stdout, "Stat segment mapped OK...\n"); @@ -84,72 +66,21 @@ static void vl_api_map_stats_segment_reply_t_handler sm->stat_segment_lockp = (clib_spinlock_t *) (shared_header->opaque[0]); sm->segment_ready = 1; - /* No need to keep the socket API connection open */ - close (sm->socket_client_main->socket_fd); -} - -#define foreach_api_reply_msg \ -_(MAP_STATS_SEGMENT_REPLY, map_stats_segment_reply) - -static void -vpp_api_hookup (void) -{ -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_api_reply_msg; -#undef _ -} - -static int -connect_to_vpp (stat_client_main_t * sm) -{ - int rv; - vl_api_map_stats_segment_t *mp; - api_main_t *am = &api_main; - - sm->socket_client_main = &socket_client_main; - - rv = vl_socket_client_connect ((char *) sm->socket_name, - "stat_client", - 0 /* default socket rx, tx buffer */ ); - if (rv) - { - fformat (stderr, "Error connecting to vpp...\n"); - exit (1); - } - - /* Hook up reply handler */ - vpp_api_hookup (); - - /* Map the stats segment */ - mp = vl_socket_client_msg_alloc (sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_MAP_STATS_SEGMENT); - mp->client_index = am->my_client_index; - mp->context = 0xdeaddabe; - - /* Send the message */ - vl_socket_client_write (); - - /* Wait for a reply, process it.. */ - vl_socket_client_read (5 /* timeout in seconds */ ); - return 0; } #define foreach_cached_pointer \ -_(vector_rate, SCALAR_POINTER, &stat_client_main.vector_rate_ptr) \ -_(input_rate, SCALAR_POINTER, &stat_client_main.input_rate_ptr) \ -_(rx, COUNTER_VECTOR, &stat_client_main.intfc_rx_counters) \ -_(tx, COUNTER_VECTOR, &stat_client_main.intfc_tx_counters) \ +_(/sys/vector_rate, SCALAR_POINTER, &stat_client_main.vector_rate_ptr) \ +_(/sys/input_rate, SCALAR_POINTER, &stat_client_main.input_rate_ptr) \ +_(/sys/last_update, SCALAR_POINTER, &stat_client_main.last_runtime_ptr) \ +_(/sys/last_stats_clear, SCALAR_POINTER, \ + &stat_client_main.last_runtime_stats_clear_ptr) \ +_(/if/rx, COUNTER_VECTOR, &stat_client_main.intfc_rx_counters) \ +_(/if/tx, COUNTER_VECTOR, &stat_client_main.intfc_tx_counters) \ _(/err/0/counter_vector, VECTOR_POINTER, \ &stat_client_main.thread_0_error_counts) \ -_(/err/IP4 source address matches local interface, ERROR_INDEX, \ - &stat_client_main.source_address_match_error_index) +_(serialized_nodes, SERIALIZED_NODES, \ + &stat_client_main.serialized_nodes) typedef struct { @@ -213,9 +144,12 @@ stat_poll_loop (stat_client_main_t * sm) ssvm_private_t *ssvmp = &sm->stat_segment; ssvm_shared_header_t *shared_header; vlib_counter_t *thread0_rx_counters = 0, *thread0_tx_counters = 0; + vlib_node_t ***nodes_by_thread; + vlib_node_t **nodes; + vlib_node_t *n; f64 vector_rate, input_rate; u32 len; - int i; + int i, j; u32 source_address_match_errors; /* Wait until the stats segment is mapped */ @@ -290,27 +224,126 @@ stat_poll_loop (stat_client_main_t * sm) fformat (stdout, "%lld source address match errors\n", source_address_match_errors); + + if (sm->serialized_nodes) + { + nodes_by_thread = vlib_node_unserialize (sm->serialized_nodes); + + /* Across all threads... */ + for (i = 0; i < vec_len (nodes_by_thread); i++) + { + u64 n_input, n_output, n_drop, n_punt; + u64 n_internal_vectors, n_internal_calls; + u64 n_clocks, l, v, c; + f64 dt; + + nodes = nodes_by_thread[i]; + + fformat (stdout, "Thread %d -------------------------\n", i); + + n_input = n_output = n_drop = n_punt = n_clocks = 0; + n_internal_vectors = n_internal_calls = 0; + + /* Across all nodes */ + for (j = 0; j < vec_len (nodes); j++) + { + n = nodes[j]; + + /* Exactly stolen from node_cli.c... */ + l = n->stats_total.clocks - n->stats_last_clear.clocks; + n_clocks += l; + + v = n->stats_total.vectors - n->stats_last_clear.vectors; + c = n->stats_total.calls - n->stats_last_clear.calls; + + switch (n->type) + { + default: + continue; + + case VLIB_NODE_TYPE_INTERNAL: + n_output += + (n->flags & VLIB_NODE_FLAG_IS_OUTPUT) ? v : 0; + n_drop += (n->flags & VLIB_NODE_FLAG_IS_DROP) ? v : 0; + n_punt += (n->flags & VLIB_NODE_FLAG_IS_PUNT) ? v : 0; + if (!(n->flags & VLIB_NODE_FLAG_IS_OUTPUT)) + { + n_internal_vectors += v; + n_internal_calls += c; + } + if (n->flags & VLIB_NODE_FLAG_IS_HANDOFF) + n_input += v; + break; + + case VLIB_NODE_TYPE_INPUT: + n_input += v; + break; + } + + if (n->stats_total.calls) + { + fformat (stdout, + "%s (%s): clocks %lld calls %lld vectors %lld ", + n->name, + n->state_string, + n->stats_total.clocks, + n->stats_total.calls, n->stats_total.vectors); + if (n->stats_total.vectors) + fformat (stdout, "clocks/pkt %.2f\n", + (f64) n->stats_total.clocks / + (f64) n->stats_total.vectors); + else + fformat (stdout, "\n"); + } + vec_free (n->name); + vec_free (n->next_nodes); + vec_free (n); + } + + fformat (stdout, "average vectors/node %.2f\n", + (n_internal_calls > 0 + ? (f64) n_internal_vectors / (f64) n_internal_calls + : 0)); + + + dt = *sm->last_runtime_ptr - *sm->last_runtime_stats_clear_ptr; + + fformat (stdout, + " vectors rates in %.4e, out %.4e, drop %.4e, " + "punt %.4e\n", + (f64) n_input / dt, + (f64) n_output / dt, (f64) n_drop / dt, + (f64) n_punt / dt); + + vec_free (nodes); + } + vec_free (nodes_by_thread); + } + else + { + fformat (stdout, "serialized nodes NULL?\n"); + } + } } - int main (int argc, char **argv) { unformat_input_t _argv, *a = &_argv; stat_client_main_t *sm = &stat_client_main; - u8 *socket_name; + u8 *stat_segment_name; int rv; clib_mem_init (0, 128 << 20); unformat_init_command_line (a, argv); - socket_name = (u8 *) API_SOCKET_FILE; + stat_segment_name = (u8 *) STAT_SEGMENT_SOCKET_FILE; while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT) { - if (unformat (a, "socket-name %s", &socket_name)) + if (unformat (a, "socket-name %s", &stat_segment_name)) ; else { @@ -319,14 +352,13 @@ main (int argc, char **argv) } } - sm->socket_name = socket_name; - - rv = connect_to_vpp (sm); + sm->socket_name = stat_segment_name; + rv = stat_segment_connect (sm); if (rv) { fformat (stderr, "Couldn't connect to vpp, does %s exist?\n", - socket_name); + stat_segment_name); exit (1); }