diff options
author | 2018-06-13 09:26:05 -0400 | |
---|---|---|
committer | 2018-06-13 09:26:41 -0400 | |
commit | 1ddbc0138b64486b8e51e5e12fcad21fba8b8b68 (patch) | |
tree | af95c33e6e1681498a49b130119103b60f64db08 /src/vpp/app | |
parent | c7d50970d4ed8a4889b4374e6a1559aef7d3dcc0 (diff) |
Stat segment / client: show run" works now
Seems to have minimal-to-zero performance consequences. Data appears
accurate: result match the debug CLI output. Checked at low rates, 27
MPPS sprayed across two worker threads.
Change-Id: I09ede5150b88a91547feeee448a2854997613004
Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'src/vpp/app')
-rw-r--r-- | src/vpp/app/stat_client.c | 112 | ||||
-rw-r--r-- | src/vpp/app/stat_client.h | 3 |
2 files changed, 113 insertions, 2 deletions
diff --git a/src/vpp/app/stat_client.c b/src/vpp/app/stat_client.c index 610a6a5b98d..96c1bda2c8d 100644 --- a/src/vpp/app/stat_client.c +++ b/src/vpp/app/stat_client.c @@ -144,12 +144,17 @@ connect_to_vpp (stat_client_main_t * sm) #define foreach_cached_pointer \ _(vector_rate, SCALAR_POINTER, &stat_client_main.vector_rate_ptr) \ _(input_rate, SCALAR_POINTER, &stat_client_main.input_rate_ptr) \ +_(last_update, SCALAR_POINTER, &stat_client_main.last_runtime_ptr) \ +_(last_stats_clear, SCALAR_POINTER, \ + &stat_client_main.last_runtime_stats_clear_ptr) \ _(rx, COUNTER_VECTOR, &stat_client_main.intfc_rx_counters) \ _(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) + &stat_client_main.source_address_match_error_index) \ +_(serialized_nodes, SERIALIZED_NODES, \ + &stat_client_main.serialized_nodes) typedef struct { @@ -213,9 +218,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,6 +298,106 @@ 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"); + } + } } diff --git a/src/vpp/app/stat_client.h b/src/vpp/app/stat_client.h index 9cec1ee46f5..87e5409ed6f 100644 --- a/src/vpp/app/stat_client.h +++ b/src/vpp/app/stat_client.h @@ -31,6 +31,8 @@ typedef struct /* Cached pointers to scalar quantities, these wont change */ f64 *vector_rate_ptr; f64 *input_rate_ptr; + f64 *last_runtime_ptr; + f64 *last_runtime_stats_clear_ptr; volatile int segment_ready; @@ -40,6 +42,7 @@ typedef struct */ vlib_counter_t **intfc_rx_counters; vlib_counter_t **intfc_tx_counters; + u8 *serialized_nodes; u64 *thread_0_error_counts; u64 source_address_match_error_index; |