aboutsummaryrefslogtreecommitdiffstats
path: root/src/vpp/stats
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2018-06-13 09:26:05 -0400
committerDave Barach <dave@barachs.net>2018-06-13 09:26:41 -0400
commit1ddbc0138b64486b8e51e5e12fcad21fba8b8b68 (patch)
treeaf95c33e6e1681498a49b130119103b60f64db08 /src/vpp/stats
parentc7d50970d4ed8a4889b4374e6a1559aef7d3dcc0 (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/stats')
-rw-r--r--src/vpp/stats/stat_segment.c185
-rw-r--r--src/vpp/stats/stats.c8
-rw-r--r--src/vpp/stats/stats.h19
3 files changed, 161 insertions, 51 deletions
diff --git a/src/vpp/stats/stat_segment.c b/src/vpp/stats/stat_segment.c
index f1db684fecd..6fb9c83a369 100644
--- a/src/vpp/stats/stat_segment.c
+++ b/src/vpp/stats/stat_segment.c
@@ -14,6 +14,20 @@
*/
#include <vpp/stats/stats.h>
+void
+vlib_stat_segment_lock (void)
+{
+ stats_main_t *sm = &stats_main;
+ clib_spinlock_lock (sm->stat_segment_lockp);
+}
+
+void
+vlib_stat_segment_unlock (void)
+{
+ stats_main_t *sm = &stats_main;
+ clib_spinlock_unlock (sm->stat_segment_lockp);
+}
+
void *
vlib_stats_push_heap (void)
{
@@ -215,6 +229,8 @@ map_stat_segment_init (vlib_main_t * vm)
CLIB_CACHE_LINE_BYTES);
sm->vector_rate_ptr = (scalar_data + 0);
sm->input_rate_ptr = (scalar_data + 1);
+ sm->last_runtime_ptr = (scalar_data + 2);
+ sm->last_runtime_stats_clear_ptr = (scalar_data + 3);
name = format (0, "vector_rate%c", 0);
ep = clib_mem_alloc (sizeof (*ep));
@@ -230,6 +246,21 @@ map_stat_segment_init (vlib_main_t * vm)
hash_set_mem (sm->counter_vector_by_name, name, ep);
+ name = format (0, "last_update%c", 0);
+ ep = clib_mem_alloc (sizeof (*ep));
+ ep->type = STAT_DIR_TYPE_SCALAR_POINTER;
+ ep->value = sm->last_runtime_ptr;
+
+ hash_set_mem (sm->counter_vector_by_name, name, ep);
+
+ name = format (0, "last_stats_clear%c", 0);
+ ep = clib_mem_alloc (sizeof (*ep));
+ ep->type = STAT_DIR_TYPE_SCALAR_POINTER;
+ ep->value = sm->last_runtime_stats_clear_ptr;
+
+ hash_set_mem (sm->counter_vector_by_name, name, ep);
+
+
/* Publish the hash table */
shared_header->opaque[STAT_SEGMENT_OPAQUE_DIR] = sm->counter_vector_by_name;
@@ -279,6 +310,10 @@ format_stat_dir_entry (u8 * s, va_list * args)
type_name = "CMainPtr";
break;
+ case STAT_DIR_TYPE_SERIALIZED_NODES:
+ type_name = "SerNodesPtr";
+ break;
+
case STAT_DIR_TYPE_ERROR_INDEX:
type_name = "ErrIndex";
format_string = "%-10s %20lld";
@@ -292,8 +327,6 @@ format_stat_dir_entry (u8 * s, va_list * args)
return format (s, format_string, type_name, ep->value);
}
-
-
static clib_error_t *
show_stat_segment_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -362,62 +395,120 @@ VLIB_CLI_COMMAND (show_stat_segment_command, static) =
};
/* *INDENT-ON* */
-static uword
-stat_segment_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
- vlib_frame_t * f)
+static inline void
+update_serialized_nodes (stats_main_t * sm)
{
- f64 vector_rate;
- u64 input_packets, last_input_packets;
- f64 last_runtime, dt, now;
- vlib_main_t *this_vlib_main;
- stats_main_t *sm = &stats_main;
int i;
+ vlib_main_t *vm = vlib_mains[0];
+ ssvm_private_t *ssvmp = &sm->stat_segment;
+ ssvm_shared_header_t *shared_header;
+ void *oldheap;
+ stat_segment_directory_entry_t *ep;
+ hash_pair_t *hp;
+ u8 *name_copy;
- last_runtime = 0.0;
- last_input_packets = 0;
+ ASSERT (ssvmp && ssvmp->sh);
- last_runtime = 0.0;
- last_input_packets = 0;
+ vec_reset_length (sm->serialized_nodes);
- while (1)
+ shared_header = ssvmp->sh;
+
+ oldheap = ssvm_push_heap (shared_header);
+
+ clib_spinlock_lock (sm->stat_segment_lockp);
+
+ vlib_node_get_nodes (0 /* vm, for barrier sync */ ,
+ (u32) ~ 0 /* all threads */ ,
+ 1 /* include stats */ ,
+ 0 /* barrier sync */ ,
+ &sm->node_dups, &sm->stat_vms);
+
+ sm->serialized_nodes = vlib_node_serialize (vm, sm->node_dups,
+ sm->serialized_nodes,
+ 0 /* include nexts */ ,
+ 1 /* include stats */ );
+
+ hp = hash_get_pair (sm->counter_vector_by_name, "serialized_nodes");
+ if (hp)
+ {
+ name_copy = (u8 *) hp->key;
+ ep = (stat_segment_directory_entry_t *) (hp->value[0]);
+
+ if (ep->value != sm->serialized_nodes)
+ {
+ ep->value = sm->serialized_nodes;
+ /* Warn clients to refresh any pointers they might be holding */
+ shared_header->opaque[STAT_SEGMENT_OPAQUE_EPOCH] = (void *)
+ ((u64) shared_header->opaque[STAT_SEGMENT_OPAQUE_EPOCH] + 1);
+ }
+ }
+ else
{
- vlib_process_suspend (vm, 5.0);
-
- /*
- * Compute the average vector rate across all workers
- */
- vector_rate = 0.0;
-
- /* *INDENT-OFF* */
- for (i = 0; i < vec_len (vlib_mains); i++)
- {
- this_vlib_main = vlib_mains[i];
- vector_rate += vlib_last_vector_length_per_node (vm);
- }
- vector_rate /= (f64) i;
-
- /* *INDENT-ON* */
-
- *sm->vector_rate_ptr = vector_rate / ((f64) vec_len (vlib_mains));
- now = vlib_time_now (vm);
- dt = now - last_runtime;
- input_packets = vnet_get_aggregate_rx_packets ();
- *sm->input_rate_ptr = (f64) (input_packets - last_input_packets) / dt;
- last_runtime = now;
- last_input_packets = input_packets;
+ name_copy = format (0, "%s%c", "serialized_nodes", 0);
+ ep = clib_mem_alloc (sizeof (*ep));
+ ep->type = STAT_DIR_TYPE_SERIALIZED_NODES;
+ ep->value = sm->serialized_nodes;
+ hash_set_mem (sm->counter_vector_by_name, name_copy, ep);
+
+ /* Reset the client hash table pointer */
+ shared_header->opaque[STAT_SEGMENT_OPAQUE_DIR]
+ = sm->counter_vector_by_name;
+
+ /* Warn clients to refresh any pointers they might be holding */
+ shared_header->opaque[STAT_SEGMENT_OPAQUE_EPOCH] = (void *)
+ ((u64) shared_header->opaque[STAT_SEGMENT_OPAQUE_EPOCH] + 1);
}
- return 0; /* not so much */
+ clib_spinlock_unlock (sm->stat_segment_lockp);
+ ssvm_pop_heap (oldheap);
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (stat_segment_node,static) =
+/*
+ * Called by stats_thread_fn, in stats.c, which runs in a
+ * separate pthread, which won't halt the parade
+ * in single-forwarding-core cases.
+ */
+
+void
+do_stat_segment_updates (stats_main_t * sm)
{
- .function = stat_segment_process,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name = "stat-segment-process",
-};
-/* *INDENT-ON* */
+ vlib_main_t *vm = vlib_mains[0];
+ f64 vector_rate;
+ u64 input_packets, last_input_packets;
+ f64 dt, now;
+ vlib_main_t *this_vlib_main;
+ int i, start;
+
+ /*
+ * Compute the average vector rate across all workers
+ */
+ vector_rate = 0.0;
+
+ start = vec_len (vlib_mains) > 1 ? 1 : 0;
+
+ for (i = start; i < vec_len (vlib_mains); i++)
+ {
+ this_vlib_main = vlib_mains[i];
+ vector_rate += vlib_last_vector_length_per_node (this_vlib_main);
+ }
+ vector_rate /= (f64) (i - start);
+
+ *sm->vector_rate_ptr = vector_rate / ((f64) (vec_len (vlib_mains) - start));
+
+ /*
+ * Compute the aggregate input rate
+ */
+ now = vlib_time_now (vm);
+ dt = now - sm->last_runtime_ptr[0];
+ input_packets = vnet_get_aggregate_rx_packets ();
+ *sm->input_rate_ptr = (f64) (input_packets - sm->last_input_packets) / dt;
+ sm->last_runtime_ptr[0] = now;
+ sm->last_input_packets = input_packets;
+ sm->last_runtime_stats_clear_ptr[0] =
+ vm->node_main.time_last_runtime_stats_clear;
+
+ update_serialized_nodes (sm);
+}
/*
diff --git a/src/vpp/stats/stats.c b/src/vpp/stats/stats.c
index f1c40e630d2..31cfc336aca 100644
--- a/src/vpp/stats/stats.c
+++ b/src/vpp/stats/stats.c
@@ -2340,10 +2340,12 @@ stats_thread_fn (void *arg)
ip46_fib_stats_delay (sm, sm->stats_poll_interval_in_seconds,
0 /* nsec */ );
+ /* Always update stats segment data */
+ do_stat_segment_updates (sm);
+
if (!(sm->enable_poller))
- {
- continue;
- }
+ continue;
+
if (pool_elts
(sm->stats_registrations[IDX_PER_INTERFACE_COMBINED_COUNTERS]))
do_combined_per_interface_counters (sm);
diff --git a/src/vpp/stats/stats.h b/src/vpp/stats/stats.h
index fd1ab271f78..262304e81ed 100644
--- a/src/vpp/stats/stats.h
+++ b/src/vpp/stats/stats.h
@@ -163,9 +163,23 @@ typedef struct
uword *counter_vector_by_name;
clib_spinlock_t *stat_segment_lockp;
- /* Pointers to scalar stats maintained by the stat segment process */
+ /* Pointers to scalar stats maintained by the stat thread */
f64 *input_rate_ptr;
+ f64 *last_runtime_ptr;
+ f64 *last_runtime_stats_clear_ptr;
f64 *vector_rate_ptr;
+ u64 last_input_packets;
+
+ /* Pointers to vector stats maintained by the stat thread */
+ u8 *serialized_nodes;
+ vlib_main_t **stat_vms;
+ vlib_node_t ***node_dups;
+
+ f64 *vectors_per_node;
+ f64 *vector_rate_in;
+ f64 *vector_rate_out;
+ f64 *vector_rate_drop;
+ f64 *vector_rate_punt;
/* convenience */
vlib_main_t *vlib_main;
@@ -187,6 +201,7 @@ typedef enum
STAT_DIR_TYPE_VECTOR_POINTER,
STAT_DIR_TYPE_COUNTER_VECTOR,
STAT_DIR_TYPE_ERROR_INDEX,
+ STAT_DIR_TYPE_SERIALIZED_NODES,
} stat_directory_type_t;
typedef struct
@@ -195,6 +210,8 @@ typedef struct
void *value;
} stat_segment_directory_entry_t;
+void do_stat_segment_updates (stats_main_t * sm);
+
#endif /* __included_stats_h__ */
/*