stats: refactor
Type: refactor Change-Id: Ifd533a095d979dc55bfbe5fac7e0b7510a4d900c Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
committed by
Damjan Marion
parent
317cace618
commit
8973b07eec
@@ -16,7 +16,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <vnet/bonding/node.h>
|
||||
#include <lacp/node.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
static int
|
||||
lacp_packet_scan (vlib_main_t * vm, member_if_t * mif)
|
||||
@@ -213,12 +213,12 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
|
||||
/* Actually scan the packet */
|
||||
e = lacp_packet_scan (vm, mif);
|
||||
bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
mif->last_packet_signature_valid = 1;
|
||||
mif->last_packet_signature = last_packet_signature;
|
||||
}
|
||||
|
||||
+13
-13
@@ -21,7 +21,7 @@
|
||||
#include <vppinfra/hash.h>
|
||||
#include <vnet/bonding/node.h>
|
||||
#include <lacp/node.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
lacp_main_t lacp_main;
|
||||
|
||||
@@ -173,16 +173,16 @@ lacp_periodic (vlib_main_t * vm)
|
||||
if (actor_state != mif->actor.state)
|
||||
{
|
||||
bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
}
|
||||
if (partner_state != mif->partner.state)
|
||||
{
|
||||
bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
}
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
@@ -380,12 +380,12 @@ lacp_init_state_machines (vlib_main_t * vm, member_if_t * mif)
|
||||
lacp_init_mux_machine (vm, mif);
|
||||
lacp_init_ptx_machine (vm, mif);
|
||||
lacp_init_rx_machine (vm, mif);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
stat_segment_set_state_counter (bm->stats[bif->sw_if_index]
|
||||
[mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state,
|
||||
mif->actor.state);
|
||||
vlib_stats_set_gauge (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state,
|
||||
mif->partner.state);
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (lacp_periodic_init);
|
||||
|
||||
@@ -187,7 +187,7 @@ scrape_stats_segment (mt_main_t * mm)
|
||||
mactime_device_t *dev;
|
||||
stat_segment_access_t sa;
|
||||
stat_client_main_t *sm = mm->stat_client_main;
|
||||
stat_segment_directory_entry_t *ep;
|
||||
vlib_stats_entry_t *ep;
|
||||
int need_update2 = 0;
|
||||
static u32 *pool_indices;
|
||||
int i, j;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <nat/nat44-ed/nat44_ed_affinity.h>
|
||||
#include <nat/nat44-ed/nat44_ed_inlines.h>
|
||||
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
snat_main_t snat_main;
|
||||
|
||||
@@ -2290,8 +2290,8 @@ nat_init (vlib_main_t * vm)
|
||||
|
||||
nat_init_simple_counter (sm->total_sessions, "total-sessions",
|
||||
"/nat44-ed/total-sessions");
|
||||
sm->max_cfg_sessions_gauge = stat_segment_new_entry (
|
||||
(u8 *) "/nat44-ed/max-cfg-sessions", STAT_DIR_TYPE_SCALAR_INDEX);
|
||||
sm->max_cfg_sessions_gauge =
|
||||
vlib_stats_add_gauge ("/nat44-ed/max-cfg-sessions");
|
||||
|
||||
#define _(x) \
|
||||
nat_init_simple_counter (sm->counters.fastpath.in2out.x, #x, \
|
||||
@@ -2373,8 +2373,8 @@ nat44_plugin_enable (nat44_config_t c)
|
||||
c.sessions = 63 * 1024;
|
||||
|
||||
sm->max_translations_per_thread = c.sessions;
|
||||
stat_segment_set_state_counter (sm->max_cfg_sessions_gauge,
|
||||
sm->max_translations_per_thread);
|
||||
vlib_stats_set_gauge (sm->max_cfg_sessions_gauge,
|
||||
sm->max_translations_per_thread);
|
||||
sm->translation_buckets = nat_calc_bihash_buckets (c.sessions);
|
||||
|
||||
vec_add1 (sm->max_translations_per_fib, sm->max_translations_per_thread);
|
||||
@@ -3145,8 +3145,8 @@ nat44_update_session_limit (u32 session_limit, u32 vrf_id)
|
||||
return 1;
|
||||
sm->max_translations_per_thread = nat44_get_max_session_limit ();
|
||||
|
||||
stat_segment_set_state_counter (sm->max_cfg_sessions_gauge,
|
||||
sm->max_translations_per_thread);
|
||||
vlib_stats_set_gauge (sm->max_cfg_sessions_gauge,
|
||||
sm->max_translations_per_thread);
|
||||
|
||||
sm->translation_buckets =
|
||||
nat_calc_bihash_buckets (sm->max_translations_per_thread);
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
void os_panic(void) {}
|
||||
void os_exit(int code) {}
|
||||
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index) { return 0; }
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
clib_error_t *stat_segment_register_gauge(u8 *names,
|
||||
stat_segment_update_fn update_fn,
|
||||
u32 index) {
|
||||
return 0;
|
||||
};
|
||||
#include <vnet/feature/feature.h>
|
||||
vnet_feature_main_t feature_main;
|
||||
void classify_get_trace_chain(void){};
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <prom/prom.h>
|
||||
#include <vpp-api/client/stat_client.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static prom_main_t prom_main;
|
||||
@@ -388,7 +388,7 @@ static void
|
||||
prom_stat_segment_client_init (void)
|
||||
{
|
||||
stat_client_main_t *scm = &stat_client_main;
|
||||
stat_segment_main_t *sm = &stat_segment_main;
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
uword size;
|
||||
|
||||
size = sm->memory_size ? sm->memory_size : STAT_SEGMENT_DEFAULT_SIZE;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <vppinfra/error.h>
|
||||
|
||||
#include <vlib/counter.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -38,7 +38,7 @@ enum
|
||||
static uint64_t
|
||||
get_stats_epoch ()
|
||||
{
|
||||
stat_segment_main_t *sm = &stat_segment_main;
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
return sm->shared_header->epoch;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ get_stats_epoch ()
|
||||
static int
|
||||
get_vec_mem_size (void *v, uword data_size)
|
||||
{
|
||||
stat_segment_main_t *sm = &stat_segment_main;
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
|
||||
if (v == 0)
|
||||
return 0;
|
||||
|
||||
@@ -88,6 +88,12 @@ add_vpp_library(vlib
|
||||
physmem.c
|
||||
punt.c
|
||||
punt_node.c
|
||||
stats/cli.c
|
||||
stats/collector.c
|
||||
stats/format.c
|
||||
stats/init.c
|
||||
stats/provider_mem.c
|
||||
stats/stats.c
|
||||
threads.c
|
||||
threads_cli.c
|
||||
time.c
|
||||
@@ -130,6 +136,8 @@ add_vpp_library(vlib
|
||||
physmem_funcs.h
|
||||
physmem.h
|
||||
punt.h
|
||||
stats/shared.h
|
||||
stats/stats.h
|
||||
threads.h
|
||||
time.h
|
||||
trace_funcs.h
|
||||
|
||||
+25
-34
@@ -46,7 +46,7 @@
|
||||
#include <vppinfra/linux/sysfs.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
#define VLIB_BUFFER_DEFAULT_BUFFERS_PER_NUMA 16384
|
||||
#define VLIB_BUFFER_DEFAULT_BUFFERS_PER_NUMA_UNPRIV 8192
|
||||
@@ -63,17 +63,6 @@ STATIC_ASSERT_OFFSET_OF (vlib_buffer_t, template_end, 64);
|
||||
|
||||
u16 __vlib_buffer_external_hdr_size = 0;
|
||||
|
||||
static void
|
||||
buffer_gauges_update_cached_fn (stat_segment_directory_entry_t * e,
|
||||
u32 index);
|
||||
|
||||
static void
|
||||
buffer_gauges_update_available_fn (stat_segment_directory_entry_t * e,
|
||||
u32 index);
|
||||
|
||||
static void
|
||||
buffer_gauges_update_used_fn (stat_segment_directory_entry_t * e, u32 index);
|
||||
|
||||
uword
|
||||
vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
|
||||
vlib_buffer_t * b_first)
|
||||
@@ -798,37 +787,39 @@ buffer_get_by_index (vlib_buffer_main_t * bm, u32 index)
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_gauges_update_used_fn (stat_segment_directory_entry_t * e, u32 index)
|
||||
buffer_gauges_collect_used_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vlib_buffer_pool_t *bp = buffer_get_by_index (vm->buffer_main, index);
|
||||
vlib_buffer_pool_t *bp =
|
||||
buffer_get_by_index (vm->buffer_main, d->private_data);
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
e->value = bp->n_buffers - bp->n_avail - buffer_get_cached (bp);
|
||||
d->entry->value = bp->n_buffers - bp->n_avail - buffer_get_cached (bp);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_gauges_update_available_fn (stat_segment_directory_entry_t * e,
|
||||
u32 index)
|
||||
buffer_gauges_collect_available_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vlib_buffer_pool_t *bp = buffer_get_by_index (vm->buffer_main, index);
|
||||
vlib_buffer_pool_t *bp =
|
||||
buffer_get_by_index (vm->buffer_main, d->private_data);
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
e->value = bp->n_avail;
|
||||
d->entry->value = bp->n_avail;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_gauges_update_cached_fn (stat_segment_directory_entry_t * e, u32 index)
|
||||
buffer_gauges_collect_cached_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vlib_buffer_pool_t *bp = buffer_get_by_index (vm->buffer_main, index);
|
||||
vlib_buffer_pool_t *bp =
|
||||
buffer_get_by_index (vm->buffer_main, d->private_data);
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
e->value = buffer_get_cached (bp);
|
||||
d->entry->value = buffer_get_cached (bp);
|
||||
}
|
||||
|
||||
clib_error_t *
|
||||
@@ -902,23 +893,23 @@ vlib_buffer_main_init (struct vlib_main_t * vm)
|
||||
|
||||
vec_foreach (bp, bm->buffer_pools)
|
||||
{
|
||||
vlib_stats_collector_reg_t reg = { .private_data = bp - bm->buffer_pools };
|
||||
if (bp->n_buffers == 0)
|
||||
continue;
|
||||
|
||||
vec_reset_length (name);
|
||||
name = format (name, "/buffer-pools/%s/cached%c", bp->name, 0);
|
||||
stat_segment_register_gauge (name, buffer_gauges_update_cached_fn,
|
||||
bp - bm->buffer_pools);
|
||||
reg.entry_index =
|
||||
vlib_stats_add_gauge ("/buffer-pools/%s/cached", bp->name);
|
||||
reg.collect_fn = buffer_gauges_collect_cached_fn;
|
||||
vlib_stats_register_collector_fn (®);
|
||||
|
||||
vec_reset_length (name);
|
||||
name = format (name, "/buffer-pools/%s/used%c", bp->name, 0);
|
||||
stat_segment_register_gauge (name, buffer_gauges_update_used_fn,
|
||||
bp - bm->buffer_pools);
|
||||
reg.entry_index = vlib_stats_add_gauge ("/buffer-pools/%s/used", bp->name);
|
||||
reg.collect_fn = buffer_gauges_collect_used_fn;
|
||||
vlib_stats_register_collector_fn (®);
|
||||
|
||||
vec_reset_length (name);
|
||||
name = format (name, "/buffer-pools/%s/available%c", bp->name, 0);
|
||||
stat_segment_register_gauge (name, buffer_gauges_update_available_fn,
|
||||
bp - bm->buffer_pools);
|
||||
reg.entry_index =
|
||||
vlib_stats_add_gauge ("/buffer-pools/%s/available", bp->name);
|
||||
reg.collect_fn = buffer_gauges_collect_available_fn;
|
||||
vlib_stats_register_collector_fn (®);
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
+4
-10
@@ -38,6 +38,7 @@
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vppinfra/callback.h>
|
||||
#include <vppinfra/cpu.h>
|
||||
@@ -753,13 +754,6 @@ vl_msg_pop_heap (void *oldheap)
|
||||
{
|
||||
}
|
||||
|
||||
void *vlib_stats_push_heap (void *) __attribute__ ((weak));
|
||||
void *
|
||||
vlib_stats_push_heap (void *notused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
show_memory_usage (vlib_main_t * vm,
|
||||
unformat_input_t * input, vlib_cli_command_t * cmd)
|
||||
@@ -820,14 +814,14 @@ show_memory_usage (vlib_main_t * vm,
|
||||
}
|
||||
if (stats_segment)
|
||||
{
|
||||
void *oldheap = vlib_stats_push_heap (0);
|
||||
void *oldheap = vlib_stats_set_heap (0);
|
||||
was_enabled = clib_mem_trace_enable_disable (0);
|
||||
u8 *s_in_svm = format (0, "%U\n", format_clib_mem_heap, 0, 1);
|
||||
if (oldheap)
|
||||
clib_mem_set_heap (oldheap);
|
||||
u8 *s = vec_dup (s_in_svm);
|
||||
|
||||
oldheap = vlib_stats_push_heap (0);
|
||||
oldheap = vlib_stats_set_heap (0);
|
||||
vec_free (s_in_svm);
|
||||
if (oldheap)
|
||||
{
|
||||
@@ -1038,7 +1032,7 @@ enable_disable_memory_trace (vlib_main_t * vm,
|
||||
/* Stats segment */
|
||||
if (stats_segment)
|
||||
{
|
||||
oldheap = vlib_stats_push_heap (0);
|
||||
oldheap = vlib_stats_set_heap ();
|
||||
current_traced_heap = clib_mem_get_heap ();
|
||||
clib_mem_trace (stats_segment);
|
||||
/* We don't want to call vlib_stats_pop_heap... */
|
||||
|
||||
+11
-14
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/stat_weak_inlines.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
void
|
||||
vlib_clear_simple_counters (vlib_simple_counter_main_t * cm)
|
||||
@@ -80,7 +80,7 @@ vlib_validate_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
|
||||
{
|
||||
vlib_thread_main_t *tm = vlib_get_thread_main ();
|
||||
int i, resized = 0;
|
||||
void *oldheap = vlib_stats_push_heap (cm->counters);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
|
||||
vec_validate (cm->counters, tm->n_vlib_mains - 1);
|
||||
for (i = 0; i < tm->n_vlib_mains; i++)
|
||||
@@ -93,12 +93,10 @@ vlib_validate_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
|
||||
vec_validate_aligned (cm->counters[i], index, CLIB_CACHE_LINE_BYTES);
|
||||
}
|
||||
|
||||
clib_mem_set_heap (oldheap);
|
||||
/* Avoid the epoch increase when there was no counter vector resize. */
|
||||
if (resized)
|
||||
vlib_stats_pop_heap (cm, oldheap, index,
|
||||
2 /* STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE */);
|
||||
else
|
||||
clib_mem_set_heap (oldheap);
|
||||
vlib_stats_update_counter (cm, index, STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -108,7 +106,7 @@ vlib_free_simple_counter (vlib_simple_counter_main_t * cm)
|
||||
|
||||
vlib_stats_delete_cm (cm);
|
||||
|
||||
void *oldheap = vlib_stats_push_heap (cm->counters);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
for (i = 0; i < vec_len (cm->counters); i++)
|
||||
vec_free (cm->counters[i]);
|
||||
vec_free (cm->counters);
|
||||
@@ -120,7 +118,7 @@ vlib_validate_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
|
||||
{
|
||||
vlib_thread_main_t *tm = vlib_get_thread_main ();
|
||||
int i, resized = 0;
|
||||
void *oldheap = vlib_stats_push_heap (cm->counters);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
|
||||
vec_validate (cm->counters, tm->n_vlib_mains - 1);
|
||||
for (i = 0; i < tm->n_vlib_mains; i++)
|
||||
@@ -133,12 +131,11 @@ vlib_validate_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
|
||||
vec_validate_aligned (cm->counters[i], index, CLIB_CACHE_LINE_BYTES);
|
||||
}
|
||||
|
||||
clib_mem_set_heap (oldheap);
|
||||
/* Avoid the epoch increase when there was no counter vector resize. */
|
||||
if (resized)
|
||||
vlib_stats_pop_heap (cm, oldheap, index,
|
||||
3 /*STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED */);
|
||||
else
|
||||
clib_mem_set_heap (oldheap);
|
||||
vlib_stats_update_counter (cm, index,
|
||||
STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -147,7 +144,7 @@ int
|
||||
{
|
||||
vlib_thread_main_t *tm = vlib_get_thread_main ();
|
||||
int i;
|
||||
void *oldheap = vlib_stats_push_heap (cm->counters);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
|
||||
/* Possibly once in recorded history */
|
||||
if (PREDICT_FALSE (vec_len (cm->counters) == 0))
|
||||
@@ -180,7 +177,7 @@ vlib_free_combined_counter (vlib_combined_counter_main_t * cm)
|
||||
|
||||
vlib_stats_delete_cm (cm);
|
||||
|
||||
void *oldheap = vlib_stats_push_heap (cm->counters);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
for (i = 0; i < vec_len (cm->counters); i++)
|
||||
vec_free (cm->counters[i]);
|
||||
vec_free (cm->counters);
|
||||
|
||||
+8
-10
@@ -39,7 +39,7 @@
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vppinfra/heap.h>
|
||||
#include <vlib/stat_weak_inlines.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
uword
|
||||
vlib_error_drop_buffers (vlib_main_t * vm,
|
||||
@@ -158,7 +158,7 @@ vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors,
|
||||
vec_validate (vm->error_elog_event_types, l - 1);
|
||||
|
||||
/* Switch to the stats segment ... */
|
||||
oldheap = vlib_stats_push_heap (0);
|
||||
oldheap = vlib_stats_set_heap ();
|
||||
|
||||
/* Allocate a counter/elog type for each error. */
|
||||
vec_validate (em->counters, l - 1);
|
||||
@@ -172,25 +172,23 @@ vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors,
|
||||
clib_memset (em->counters + n->error_heap_index,
|
||||
0, n_errors * sizeof (em->counters[0]));
|
||||
|
||||
oldheap = clib_mem_set_heap (oldheap);
|
||||
|
||||
/* Register counter indices in the stat segment directory */
|
||||
{
|
||||
int i;
|
||||
u8 *error_name = 0;
|
||||
|
||||
for (i = 0; i < n_errors; i++)
|
||||
{
|
||||
vec_reset_length (error_name);
|
||||
error_name =
|
||||
format (error_name, "/err/%v/%s%c", n->name, counters[i].name, 0);
|
||||
vlib_stats_register_error_index (oldheap, error_name, em->counters,
|
||||
n->error_heap_index + i);
|
||||
vlib_stats_register_error_index (em->counters, n->error_heap_index + i,
|
||||
"/err/%v/%s", n->name,
|
||||
counters[i].name);
|
||||
}
|
||||
|
||||
vec_free (error_name);
|
||||
}
|
||||
|
||||
/* (re)register the em->counters base address, switch back to main heap */
|
||||
vlib_stats_pop_heap2 (em->counters, vm->thread_index, oldheap, 1);
|
||||
vlib_stats_update_error_vector (em->counters, vm->thread_index, 1);
|
||||
|
||||
{
|
||||
elog_event_type_t t;
|
||||
|
||||
+2
-2
@@ -41,6 +41,7 @@
|
||||
#include <vppinfra/format.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/threads.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
|
||||
|
||||
#include <vlib/unix/unix.h>
|
||||
@@ -1826,7 +1827,6 @@ placeholder_queue_signal_callback (vlib_main_t * vm)
|
||||
}
|
||||
|
||||
#define foreach_weak_reference_stub \
|
||||
_(vlib_map_stat_segment_init) \
|
||||
_(vpe_api_init) \
|
||||
_(vlibmemory_init) \
|
||||
_(map_api_segment_init)
|
||||
@@ -1887,7 +1887,7 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((error = vlib_map_stat_segment_init (vm)))
|
||||
if ((error = vlib_stats_init (vm)))
|
||||
{
|
||||
clib_error_report (error);
|
||||
goto done;
|
||||
|
||||
+11
-17
@@ -42,6 +42,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/threads.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <math.h>
|
||||
|
||||
static int
|
||||
@@ -465,13 +466,6 @@ format_vlib_node_stats (u8 * s, va_list * va)
|
||||
return s;
|
||||
}
|
||||
|
||||
f64 vlib_get_stat_segment_update_rate (void) __attribute__ ((weak));
|
||||
f64
|
||||
vlib_get_stat_segment_update_rate (void)
|
||||
{
|
||||
return 1e70;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
show_node_runtime (vlib_main_t * vm,
|
||||
unformat_input_t * input, vlib_cli_command_t * cmd)
|
||||
@@ -598,16 +592,14 @@ show_node_runtime (vlib_main_t * vm,
|
||||
}
|
||||
|
||||
dt = time_now - nm->time_last_runtime_stats_clear;
|
||||
vlib_cli_output
|
||||
(vm,
|
||||
"Time %.1f, %f sec internal node vector rate %.2f loops/sec %.2f\n"
|
||||
" vector rates in %.4e, out %.4e, drop %.4e, punt %.4e",
|
||||
dt,
|
||||
vlib_get_stat_segment_update_rate (),
|
||||
internal_node_vector_rates[j],
|
||||
stat_vm->loops_per_second,
|
||||
(f64) n_input / dt,
|
||||
(f64) n_output / dt, (f64) n_drop / dt, (f64) n_punt / dt);
|
||||
vlib_cli_output (
|
||||
vm,
|
||||
"Time %.1f, %f sec internal node vector rate %.2f loops/sec %.2f\n"
|
||||
" vector rates in %.4e, out %.4e, drop %.4e, punt %.4e",
|
||||
dt, vlib_stats_get_segment_update_rate (),
|
||||
internal_node_vector_rates[j], stat_vm->loops_per_second,
|
||||
(f64) n_input / dt, (f64) n_output / dt, (f64) n_drop / dt,
|
||||
(f64) n_punt / dt);
|
||||
|
||||
if (summary == 0)
|
||||
{
|
||||
@@ -684,6 +676,8 @@ clear_node_runtime (vlib_main_t * vm,
|
||||
nm->time_last_runtime_stats_clear = vlib_time_now (vm);
|
||||
}
|
||||
|
||||
vlib_stats_set_timestamp (STAT_COUNTER_LAST_STATS_CLEAR,
|
||||
vm->node_main.time_last_runtime_stats_clear);
|
||||
vlib_worker_thread_barrier_release (vm);
|
||||
|
||||
vec_free (stat_vms);
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: Only include this file from external components that require
|
||||
* a loose coupling to the stats component.
|
||||
*/
|
||||
|
||||
#ifndef included_stat_weak_inlines_h
|
||||
#define included_stat_weak_inlines_h
|
||||
void *vlib_stats_push_heap (void *) __attribute__ ((weak));
|
||||
void *
|
||||
vlib_stats_push_heap (void *unused)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
void vlib_stats_pop_heap (void *, void *, u32, int) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stats_pop_heap (void *notused, void *notused2, u32 i, int type)
|
||||
{
|
||||
};
|
||||
void vlib_stats_register_error_index (void *, u8 *, u64 *, u64)
|
||||
__attribute__ ((weak));
|
||||
void
|
||||
vlib_stats_register_error_index (void * notused, u8 * notused2, u64 * notused3, u64 notused4)
|
||||
{
|
||||
};
|
||||
|
||||
void vlib_stats_pop_heap2 (void *, u32, void *, int) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stats_pop_heap2 (void *notused, u32 notused2, void *notused3,
|
||||
int notused4)
|
||||
{
|
||||
};
|
||||
|
||||
void vlib_stat_segment_lock (void) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stat_segment_lock (void)
|
||||
{
|
||||
}
|
||||
|
||||
void vlib_stat_segment_unlock (void) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stat_segment_unlock (void)
|
||||
{
|
||||
}
|
||||
void vlib_stats_delete_cm (void *) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stats_delete_cm (void *notused)
|
||||
{
|
||||
}
|
||||
|
||||
void vlib_stats_register_mem_heap (void *) __attribute__ ((weak));
|
||||
void
|
||||
vlib_stats_register_mem_heap (void *notused)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
static int
|
||||
name_sort_cmp (void *a1, void *a2)
|
||||
{
|
||||
vlib_stats_entry_t *n1 = a1;
|
||||
vlib_stats_entry_t *n2 = a2;
|
||||
|
||||
return strcmp ((char *) n1->name, (char *) n2->name);
|
||||
}
|
||||
|
||||
static u8 *
|
||||
format_stat_dir_entry (u8 *s, va_list *args)
|
||||
{
|
||||
vlib_stats_entry_t *ep = va_arg (*args, vlib_stats_entry_t *);
|
||||
char *type_name;
|
||||
char *format_string;
|
||||
|
||||
format_string = "%-74s %-10s %10lld";
|
||||
|
||||
switch (ep->type)
|
||||
{
|
||||
case STAT_DIR_TYPE_SCALAR_INDEX:
|
||||
type_name = "ScalarPtr";
|
||||
break;
|
||||
|
||||
case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
|
||||
case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
|
||||
type_name = "CMainPtr";
|
||||
break;
|
||||
|
||||
case STAT_DIR_TYPE_ERROR_INDEX:
|
||||
type_name = "ErrIndex";
|
||||
break;
|
||||
|
||||
case STAT_DIR_TYPE_NAME_VECTOR:
|
||||
type_name = "NameVector";
|
||||
break;
|
||||
|
||||
case STAT_DIR_TYPE_EMPTY:
|
||||
type_name = "empty";
|
||||
break;
|
||||
|
||||
case STAT_DIR_TYPE_SYMLINK:
|
||||
type_name = "Symlink";
|
||||
break;
|
||||
|
||||
default:
|
||||
type_name = "illegal!";
|
||||
break;
|
||||
}
|
||||
|
||||
return format (s, format_string, ep->name, type_name, 0);
|
||||
}
|
||||
static clib_error_t *
|
||||
show_stat_segment_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
vlib_cli_command_t *cmd)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
vlib_stats_entry_t *show_data;
|
||||
int i;
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
if (unformat (input, "verbose"))
|
||||
verbose = 1;
|
||||
|
||||
/* Lock even as reader, as this command doesn't handle epoch changes */
|
||||
vlib_stats_segment_lock ();
|
||||
show_data = vec_dup (sm->directory_vector);
|
||||
vlib_stats_segment_unlock ();
|
||||
|
||||
vec_sort_with_function (show_data, name_sort_cmp);
|
||||
|
||||
vlib_cli_output (vm, "%-74s %10s %10s", "Name", "Type", "Value");
|
||||
|
||||
for (i = 0; i < vec_len (show_data); i++)
|
||||
{
|
||||
vlib_stats_entry_t *ep = vec_elt_at_index (show_data, i);
|
||||
|
||||
if (ep->type == STAT_DIR_TYPE_EMPTY)
|
||||
continue;
|
||||
|
||||
vlib_cli_output (vm, "%-100U", format_stat_dir_entry,
|
||||
vec_elt_at_index (show_data, i));
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
ASSERT (sm->heap);
|
||||
vlib_cli_output (vm, "%U", format_clib_mem_heap, sm->heap,
|
||||
0 /* verbose */);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
show_stat_segment_hash_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
vlib_cli_command_t *cmd)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
char *name;
|
||||
u32 i;
|
||||
hash_foreach_mem (name, i, sm->directory_vector_by_name,
|
||||
({ vlib_cli_output (vm, "%d: %s\n", i, name); }));
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_CLI_COMMAND (show_stat_segment_hash_command, static) = {
|
||||
.path = "show statistics hash",
|
||||
.short_help = "show statistics hash",
|
||||
.function = show_stat_segment_hash_command_fn,
|
||||
};
|
||||
|
||||
VLIB_CLI_COMMAND (show_stat_segment_command, static) = {
|
||||
.path = "show statistics segment",
|
||||
.short_help = "show statistics segment [verbose]",
|
||||
.function = show_stat_segment_command_fn,
|
||||
};
|
||||
@@ -0,0 +1,192 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
static void
|
||||
stat_validate_counter_vector2 (vlib_stats_entry_t *ep, u32 max1, u32 max2)
|
||||
{
|
||||
counter_t **counters = ep->data;
|
||||
int i;
|
||||
vec_validate_aligned (counters, max1, CLIB_CACHE_LINE_BYTES);
|
||||
for (i = 0; i <= max1; i++)
|
||||
vec_validate_aligned (counters[i], max2, CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
ep->data = counters;
|
||||
}
|
||||
|
||||
static void
|
||||
stat_validate_counter_vector (vlib_stats_entry_t *ep, u32 max)
|
||||
{
|
||||
vlib_thread_main_t *tm = vlib_get_thread_main ();
|
||||
ASSERT (tm->n_vlib_mains > 0);
|
||||
stat_validate_counter_vector2 (ep, tm->n_vlib_mains, max);
|
||||
}
|
||||
|
||||
static inline void
|
||||
update_node_counters (vlib_stats_segment_t *sm)
|
||||
{
|
||||
vlib_main_t **stat_vms = 0;
|
||||
vlib_node_t ***node_dups = 0;
|
||||
int i, j;
|
||||
static u32 no_max_nodes = 0;
|
||||
|
||||
vlib_node_get_nodes (0 /* vm, for barrier sync */,
|
||||
(u32) ~0 /* all threads */, 1 /* include stats */,
|
||||
0 /* barrier sync */, &node_dups, &stat_vms);
|
||||
|
||||
u32 l = vec_len (node_dups[0]);
|
||||
u8 *symlink_name = 0;
|
||||
|
||||
/*
|
||||
* Extend performance nodes if necessary
|
||||
*/
|
||||
if (l > no_max_nodes)
|
||||
{
|
||||
void *oldheap = clib_mem_set_heap (sm->heap);
|
||||
vlib_stats_segment_lock ();
|
||||
|
||||
stat_validate_counter_vector (
|
||||
&sm->directory_vector[STAT_COUNTER_NODE_CLOCKS], l - 1);
|
||||
stat_validate_counter_vector (
|
||||
&sm->directory_vector[STAT_COUNTER_NODE_VECTORS], l - 1);
|
||||
stat_validate_counter_vector (
|
||||
&sm->directory_vector[STAT_COUNTER_NODE_CALLS], l - 1);
|
||||
stat_validate_counter_vector (
|
||||
&sm->directory_vector[STAT_COUNTER_NODE_SUSPENDS], l - 1);
|
||||
|
||||
vec_validate (sm->nodes, l - 1);
|
||||
vlib_stats_entry_t *ep;
|
||||
ep = &sm->directory_vector[STAT_COUNTER_NODE_NAMES];
|
||||
ep->data = sm->nodes;
|
||||
|
||||
/* Update names dictionary */
|
||||
vlib_node_t **nodes = node_dups[0];
|
||||
int i;
|
||||
for (i = 0; i < vec_len (nodes); i++)
|
||||
{
|
||||
vlib_node_t *n = nodes[i];
|
||||
u8 *s = format (0, "%v%c", n->name, 0);
|
||||
if (sm->nodes[n->index])
|
||||
vec_free (sm->nodes[n->index]);
|
||||
sm->nodes[n->index] = s;
|
||||
|
||||
oldheap = clib_mem_set_heap (oldheap);
|
||||
#define _(E, t, name, p) \
|
||||
vlib_stats_add_symlink (STAT_COUNTER_##E, n->index, "/nodes/%U/" #name, \
|
||||
format_vlib_stats_symlink, s);
|
||||
foreach_stat_segment_node_counter_name
|
||||
#undef _
|
||||
oldheap = clib_mem_set_heap (oldheap);
|
||||
}
|
||||
|
||||
vlib_stats_segment_unlock ();
|
||||
clib_mem_set_heap (oldheap);
|
||||
no_max_nodes = l;
|
||||
}
|
||||
|
||||
for (j = 0; j < vec_len (node_dups); j++)
|
||||
{
|
||||
vlib_node_t **nodes = node_dups[j];
|
||||
|
||||
for (i = 0; i < vec_len (nodes); i++)
|
||||
{
|
||||
counter_t **counters;
|
||||
counter_t *c;
|
||||
vlib_node_t *n = nodes[i];
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
if (strncmp ((char *) sm->nodes[n->index], (char *) n->name,
|
||||
strlen ((char *) sm->nodes[n->index])))
|
||||
{
|
||||
u32 vector_index;
|
||||
void *oldheap = clib_mem_set_heap (sm->heap);
|
||||
vlib_stats_segment_lock ();
|
||||
u8 *s = format (0, "%v%c", n->name, 0);
|
||||
clib_mem_set_heap (oldheap);
|
||||
#define _(E, t, name, p) \
|
||||
vec_reset_length (symlink_name); \
|
||||
symlink_name = format (symlink_name, "/nodes/%U/" #name, \
|
||||
format_vlib_stats_symlink, sm->nodes[n->index]); \
|
||||
vector_index = vlib_stats_find_entry_index ("%v", symlink_name); \
|
||||
ASSERT (vector_index != -1); \
|
||||
vlib_stats_rename_symlink (vector_index, "/nodes/%U/" #name, \
|
||||
format_vlib_stats_symlink, s);
|
||||
foreach_stat_segment_node_counter_name
|
||||
#undef _
|
||||
vec_free (symlink_name);
|
||||
clib_mem_set_heap (sm->heap);
|
||||
vec_free (sm->nodes[n->index]);
|
||||
sm->nodes[n->index] = s;
|
||||
vlib_stats_segment_unlock ();
|
||||
clib_mem_set_heap (oldheap);
|
||||
}
|
||||
}
|
||||
|
||||
counters = sm->directory_vector[STAT_COUNTER_NODE_CLOCKS].data;
|
||||
c = counters[j];
|
||||
c[n->index] = n->stats_total.clocks - n->stats_last_clear.clocks;
|
||||
|
||||
counters = sm->directory_vector[STAT_COUNTER_NODE_VECTORS].data;
|
||||
c = counters[j];
|
||||
c[n->index] = n->stats_total.vectors - n->stats_last_clear.vectors;
|
||||
|
||||
counters = sm->directory_vector[STAT_COUNTER_NODE_CALLS].data;
|
||||
c = counters[j];
|
||||
c[n->index] = n->stats_total.calls - n->stats_last_clear.calls;
|
||||
|
||||
counters = sm->directory_vector[STAT_COUNTER_NODE_SUSPENDS].data;
|
||||
c = counters[j];
|
||||
c[n->index] = n->stats_total.suspends - n->stats_last_clear.suspends;
|
||||
}
|
||||
vec_free (node_dups[j]);
|
||||
}
|
||||
vec_free (node_dups);
|
||||
vec_free (stat_vms);
|
||||
}
|
||||
|
||||
static void
|
||||
do_stat_segment_updates (vlib_main_t *vm, vlib_stats_segment_t *sm)
|
||||
{
|
||||
if (sm->node_counters_enabled)
|
||||
update_node_counters (sm);
|
||||
|
||||
vlib_stats_collector_t *c;
|
||||
pool_foreach (c, sm->collectors)
|
||||
{
|
||||
vlib_stats_collector_data_t data = {
|
||||
.entry_index = c->entry_index,
|
||||
.vector_index = c->vector_index,
|
||||
.private_data = c->private_data,
|
||||
.entry = sm->directory_vector + c->entry_index,
|
||||
};
|
||||
c->fn (&data);
|
||||
}
|
||||
|
||||
/* Heartbeat, so clients detect we're still here */
|
||||
sm->directory_vector[STAT_COUNTER_HEARTBEAT].value++;
|
||||
}
|
||||
|
||||
static uword
|
||||
stat_segment_collector_process (vlib_main_t *vm, vlib_node_runtime_t *rt,
|
||||
vlib_frame_t *f)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
do_stat_segment_updates (vm, sm);
|
||||
vlib_process_suspend (vm, sm->update_interval);
|
||||
}
|
||||
return 0; /* or not */
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (stat_segment_collector, static) = {
|
||||
.function = stat_segment_collector_process,
|
||||
.name = "statseg-collector-process",
|
||||
.type = VLIB_NODE_TYPE_PROCESS,
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
u8 *
|
||||
format_vlib_stats_symlink (u8 *s, va_list *args)
|
||||
{
|
||||
char *input = va_arg (*args, char *);
|
||||
char *modified_input = vec_dup (input);
|
||||
int i;
|
||||
u8 *result;
|
||||
|
||||
for (i = 0; i < strlen (modified_input); i++)
|
||||
if (modified_input[i] == '/')
|
||||
modified_input[i] = '_';
|
||||
|
||||
result = format (s, "%s", modified_input);
|
||||
vec_free (modified_input);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
#define STAT_SEGMENT_SOCKET_FILENAME "stats.sock"
|
||||
|
||||
static void
|
||||
vector_rate_collector_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
vlib_main_t *this_vlib_main;
|
||||
counter_t **counters = d->entry->data;
|
||||
counter_t *cb = counters[0];
|
||||
f64 vector_rate = 0.0;
|
||||
u32 i, n_threads = vlib_get_n_threads ();
|
||||
|
||||
vlib_stats_validate_counter_vector (d->entry_index, n_threads - 1);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
{
|
||||
f64 this_vector_rate;
|
||||
this_vlib_main = vlib_get_main_by_index (i);
|
||||
|
||||
this_vector_rate = vlib_internal_node_vector_rate (this_vlib_main);
|
||||
vlib_clear_internal_node_vector_rate (this_vlib_main);
|
||||
|
||||
cb[i] = this_vector_rate;
|
||||
vector_rate += this_vector_rate;
|
||||
}
|
||||
|
||||
/* And set the system average rate */
|
||||
vector_rate /= (f64) (i > 1 ? i - 1 : 1);
|
||||
vlib_stats_set_gauge (d->private_data, vector_rate);
|
||||
}
|
||||
|
||||
clib_error_t *
|
||||
vlib_stats_init (vlib_main_t *vm)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
vlib_stats_shared_header_t *shared_header;
|
||||
vlib_stats_collector_reg_t reg = {};
|
||||
|
||||
void *oldheap;
|
||||
uword memory_size, sys_page_sz;
|
||||
int mfd;
|
||||
char *mem_name = "stat segment";
|
||||
void *heap, *memaddr;
|
||||
|
||||
memory_size = sm->memory_size;
|
||||
if (memory_size == 0)
|
||||
memory_size = STAT_SEGMENT_DEFAULT_SIZE;
|
||||
|
||||
if (sm->log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN)
|
||||
sm->log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT;
|
||||
|
||||
mfd = clib_mem_vm_create_fd (sm->log2_page_sz, mem_name);
|
||||
|
||||
if (mfd == -1)
|
||||
return clib_error_return (0, "stat segment memory fd failure: %U",
|
||||
format_clib_error, clib_mem_get_last_error ());
|
||||
/* Set size */
|
||||
if ((ftruncate (mfd, memory_size)) == -1)
|
||||
{
|
||||
close (mfd);
|
||||
return clib_error_return (0, "stat segment ftruncate failure");
|
||||
}
|
||||
|
||||
memaddr = clib_mem_vm_map_shared (0, memory_size, mfd, 0, mem_name);
|
||||
|
||||
if (memaddr == CLIB_MEM_VM_MAP_FAILED)
|
||||
return clib_error_return (0, "stat segment mmap failure");
|
||||
|
||||
sys_page_sz = clib_mem_get_page_size ();
|
||||
|
||||
heap =
|
||||
clib_mem_create_heap (((u8 *) memaddr) + sys_page_sz,
|
||||
memory_size - sys_page_sz, 1 /* locked */, mem_name);
|
||||
sm->heap = heap;
|
||||
sm->memfd = mfd;
|
||||
|
||||
sm->directory_vector_by_name = hash_create_string (0, sizeof (uword));
|
||||
sm->shared_header = shared_header = memaddr;
|
||||
|
||||
shared_header->version = STAT_SEGMENT_VERSION;
|
||||
shared_header->base = memaddr;
|
||||
|
||||
sm->stat_segment_lockp = clib_mem_alloc (sizeof (clib_spinlock_t));
|
||||
clib_spinlock_init (sm->stat_segment_lockp);
|
||||
|
||||
oldheap = clib_mem_set_heap (sm->heap);
|
||||
|
||||
/* Set up the name to counter-vector hash table */
|
||||
sm->directory_vector = 0;
|
||||
|
||||
shared_header->epoch = 1;
|
||||
|
||||
/* Scalar stats and node counters */
|
||||
vec_validate (sm->directory_vector, STAT_COUNTERS - 1);
|
||||
#define _(E, t, n, p) \
|
||||
strcpy (sm->directory_vector[STAT_COUNTER_##E].name, p "/" #n); \
|
||||
sm->directory_vector[STAT_COUNTER_##E].type = STAT_DIR_TYPE_##t;
|
||||
foreach_stat_segment_counter_name
|
||||
#undef _
|
||||
/* Save the vector in the shared segment, for clients */
|
||||
shared_header->directory_vector = sm->directory_vector;
|
||||
|
||||
clib_mem_set_heap (oldheap);
|
||||
|
||||
vlib_stats_register_mem_heap (heap);
|
||||
|
||||
reg.collect_fn = vector_rate_collector_fn;
|
||||
reg.private_data = vlib_stats_add_gauge ("/sys/vector_rate");
|
||||
reg.entry_index =
|
||||
vlib_stats_add_counter_vector ("/sys/vector_rate_per_worker");
|
||||
vlib_stats_register_collector_fn (®);
|
||||
vlib_stats_validate_counter_vector (reg.entry_index, vlib_get_n_threads ());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
statseg_config (vlib_main_t *vm, unformat_input_t *input)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
sm->update_interval = 10.0;
|
||||
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "socket-name %s", &sm->socket_name))
|
||||
;
|
||||
/* DEPRECATE: default (does nothing) */
|
||||
else if (unformat (input, "default"))
|
||||
;
|
||||
else if (unformat (input, "size %U", unformat_memory_size,
|
||||
&sm->memory_size))
|
||||
;
|
||||
else if (unformat (input, "page-size %U", unformat_log2_page_size,
|
||||
&sm->log2_page_sz))
|
||||
;
|
||||
else if (unformat (input, "per-node-counters on"))
|
||||
sm->node_counters_enabled = 1;
|
||||
else if (unformat (input, "per-node-counters off"))
|
||||
sm->node_counters_enabled = 0;
|
||||
else if (unformat (input, "update-interval %f", &sm->update_interval))
|
||||
;
|
||||
else
|
||||
return clib_error_return (0, "unknown input `%U'",
|
||||
format_unformat_error, input);
|
||||
}
|
||||
|
||||
/*
|
||||
* NULL-terminate socket name string
|
||||
* clib_socket_init()->socket_config() use C str*
|
||||
*/
|
||||
if (vec_len (sm->socket_name))
|
||||
vec_terminate_c_string (sm->socket_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_EARLY_CONFIG_FUNCTION (statseg_config, "statseg");
|
||||
|
||||
/*
|
||||
* Accept connection on the socket and exchange the fd for the shared
|
||||
* memory segment.
|
||||
*/
|
||||
static clib_error_t *
|
||||
stats_socket_accept_ready (clib_file_t *uf)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
clib_error_t *err;
|
||||
clib_socket_t client = { 0 };
|
||||
|
||||
err = clib_socket_accept (sm->socket, &client);
|
||||
if (err)
|
||||
{
|
||||
clib_error_report (err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Send the fd across and close */
|
||||
err = clib_socket_sendmsg (&client, 0, 0, &sm->memfd, 1);
|
||||
if (err)
|
||||
clib_error_report (err);
|
||||
clib_socket_close (&client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
stats_segment_socket_init (void)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
clib_error_t *error;
|
||||
clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t));
|
||||
|
||||
memset (s, 0, sizeof (clib_socket_t));
|
||||
s->config = (char *) sm->socket_name;
|
||||
s->flags = CLIB_SOCKET_F_IS_SERVER | CLIB_SOCKET_F_SEQPACKET |
|
||||
CLIB_SOCKET_F_ALLOW_GROUP_WRITE | CLIB_SOCKET_F_PASSCRED;
|
||||
|
||||
if ((error = clib_socket_init (s)))
|
||||
return error;
|
||||
|
||||
clib_file_t template = { 0 };
|
||||
template.read_function = stats_socket_accept_ready;
|
||||
template.file_descriptor = s->fd;
|
||||
template.description = format (0, "stats segment listener %s", s->config);
|
||||
clib_file_add (&file_main, &template);
|
||||
|
||||
sm->socket = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
stats_segment_socket_exit (vlib_main_t *vm)
|
||||
{
|
||||
/*
|
||||
* cleanup the listener socket on exit.
|
||||
*/
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
unlink ((char *) sm->socket_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_MAIN_LOOP_EXIT_FUNCTION (stats_segment_socket_exit);
|
||||
|
||||
static clib_error_t *
|
||||
statseg_init (vlib_main_t *vm)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
|
||||
/* set default socket file name when statseg config stanza is empty. */
|
||||
if (!vec_len (sm->socket_name))
|
||||
sm->socket_name = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
|
||||
STAT_SEGMENT_SOCKET_FILENAME, 0);
|
||||
return stats_segment_socket_init ();
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (statseg_init) = {
|
||||
.runs_after = VLIB_INITS ("unix_input_init", "linux_epoll_input_init"),
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
static clib_mem_heap_t **memory_heaps_vec;
|
||||
|
||||
enum
|
||||
{
|
||||
STAT_MEM_TOTAL = 0,
|
||||
STAT_MEM_USED,
|
||||
STAT_MEM_FREE,
|
||||
STAT_MEM_USED_MMAP,
|
||||
STAT_MEM_TOTAL_ALLOC,
|
||||
STAT_MEM_FREE_CHUNKS,
|
||||
STAT_MEM_RELEASABLE,
|
||||
} stat_mem_usage_e;
|
||||
|
||||
/*
|
||||
* Called from the stats periodic process to update memory counters.
|
||||
*/
|
||||
static void
|
||||
stat_provider_mem_usage_update_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
clib_mem_usage_t usage;
|
||||
clib_mem_heap_t *heap;
|
||||
counter_t **counters = d->entry->data;
|
||||
counter_t *cb;
|
||||
|
||||
heap = vec_elt (memory_heaps_vec, d->private_data);
|
||||
clib_mem_get_heap_usage (heap, &usage);
|
||||
cb = counters[0];
|
||||
cb[STAT_MEM_TOTAL] = usage.bytes_total;
|
||||
cb[STAT_MEM_USED] = usage.bytes_used;
|
||||
cb[STAT_MEM_FREE] = usage.bytes_free;
|
||||
cb[STAT_MEM_USED_MMAP] = usage.bytes_used_mmap;
|
||||
cb[STAT_MEM_TOTAL_ALLOC] = usage.bytes_max;
|
||||
cb[STAT_MEM_FREE_CHUNKS] = usage.bytes_free_reclaimed;
|
||||
cb[STAT_MEM_RELEASABLE] = usage.bytes_overhead;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide memory heap counters.
|
||||
* Two dimensional array of heap index and per-heap gauges.
|
||||
*/
|
||||
void
|
||||
vlib_stats_register_mem_heap (clib_mem_heap_t *heap)
|
||||
{
|
||||
vlib_stats_collector_reg_t r = {};
|
||||
u32 idx;
|
||||
|
||||
vec_add1 (memory_heaps_vec, heap);
|
||||
|
||||
r.entry_index = idx = vlib_stats_add_counter_vector ("/mem/%s", heap->name);
|
||||
vlib_stats_validate_counter_vector (idx, STAT_MEM_RELEASABLE);
|
||||
|
||||
/* Create symlink */
|
||||
vlib_stats_add_symlink (idx, STAT_MEM_TOTAL, "/mem/%s/used", heap->name);
|
||||
vlib_stats_add_symlink (idx, STAT_MEM_USED, "/mem/%s/total", heap->name);
|
||||
vlib_stats_add_symlink (idx, STAT_MEM_FREE, "/mem/%s/free", heap->name);
|
||||
|
||||
r.private_data = vec_len (memory_heaps_vec) - 1;
|
||||
r.collect_fn = stat_provider_mem_usage_update_fn;
|
||||
vlib_stats_register_collector_fn (&r);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#ifndef included_stat_segment_shared_h
|
||||
#define included_stat_segment_shared_h
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STAT_DIR_TYPE_ILLEGAL = 0,
|
||||
STAT_DIR_TYPE_SCALAR_INDEX,
|
||||
STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE,
|
||||
STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED,
|
||||
STAT_DIR_TYPE_ERROR_INDEX,
|
||||
STAT_DIR_TYPE_NAME_VECTOR,
|
||||
STAT_DIR_TYPE_EMPTY,
|
||||
STAT_DIR_TYPE_SYMLINK,
|
||||
} stat_directory_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
stat_directory_type_t type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t index1;
|
||||
uint32_t index2;
|
||||
};
|
||||
uint64_t index;
|
||||
uint64_t value;
|
||||
void *data;
|
||||
uint8_t **string_vector;
|
||||
};
|
||||
#define VLIB_STATS_MAX_NAME_SZ 128
|
||||
char name[VLIB_STATS_MAX_NAME_SZ];
|
||||
} vlib_stats_entry_t;
|
||||
|
||||
/*
|
||||
* Shared header first in the shared memory segment.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint64_t version;
|
||||
void *base;
|
||||
volatile uint64_t epoch;
|
||||
volatile uint64_t in_progress;
|
||||
volatile vlib_stats_entry_t *directory_vector;
|
||||
volatile uint64_t **error_vector;
|
||||
} vlib_stats_shared_header_t;
|
||||
|
||||
#endif /* included_stat_segment_shared_h */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#ifndef included_stats_stats_h
|
||||
#define included_stats_stats_h
|
||||
|
||||
#include <vppinfra/socket.h>
|
||||
#include <vppinfra/lock.h>
|
||||
#include <vlib/stats/shared.h>
|
||||
|
||||
/* Default stat segment 32m */
|
||||
#define STAT_SEGMENT_DEFAULT_SIZE (32 << 20)
|
||||
|
||||
/* Shared segment memory layout version */
|
||||
#define STAT_SEGMENT_VERSION 2
|
||||
|
||||
#define STAT_SEGMENT_INDEX_INVALID UINT32_MAX
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STAT_COUNTER_HEARTBEAT = 0,
|
||||
STAT_COUNTER_LAST_STATS_CLEAR,
|
||||
STAT_COUNTER_NODE_CLOCKS,
|
||||
STAT_COUNTER_NODE_VECTORS,
|
||||
STAT_COUNTER_NODE_CALLS,
|
||||
STAT_COUNTER_NODE_SUSPENDS,
|
||||
STAT_COUNTER_NODE_NAMES,
|
||||
STAT_COUNTERS
|
||||
} stat_segment_counter_t;
|
||||
|
||||
#define foreach_stat_segment_node_counter_name \
|
||||
_ (NODE_CLOCKS, COUNTER_VECTOR_SIMPLE, clocks, "/sys/node") \
|
||||
_ (NODE_VECTORS, COUNTER_VECTOR_SIMPLE, vectors, "/sys/node") \
|
||||
_ (NODE_CALLS, COUNTER_VECTOR_SIMPLE, calls, "/sys/node") \
|
||||
_ (NODE_SUSPENDS, COUNTER_VECTOR_SIMPLE, suspends, "/sys/node")
|
||||
|
||||
#define foreach_stat_segment_counter_name \
|
||||
_ (LAST_STATS_CLEAR, SCALAR_INDEX, last_stats_clear, "/sys") \
|
||||
_ (HEARTBEAT, SCALAR_INDEX, heartbeat, "/sys") \
|
||||
_ (NODE_NAMES, NAME_VECTOR, names, "/sys/node") \
|
||||
foreach_stat_segment_node_counter_name
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 entry_index;
|
||||
u32 vector_index;
|
||||
u64 private_data;
|
||||
vlib_stats_entry_t *entry;
|
||||
} vlib_stats_collector_data_t;
|
||||
|
||||
typedef void (*vlib_stats_collector_fn_t) (vlib_stats_collector_data_t *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vlib_stats_collector_fn_t collect_fn;
|
||||
u32 entry_index;
|
||||
u32 vector_index;
|
||||
u64 private_data;
|
||||
} vlib_stats_collector_reg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vlib_stats_collector_fn_t fn;
|
||||
u32 entry_index;
|
||||
u32 vector_index;
|
||||
u64 private_data;
|
||||
} vlib_stats_collector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* internal, does not point to shared memory */
|
||||
vlib_stats_collector_t *collectors;
|
||||
|
||||
/* statistics segment */
|
||||
uword *directory_vector_by_name;
|
||||
vlib_stats_entry_t *directory_vector;
|
||||
volatile u64 **error_vector;
|
||||
u8 **nodes;
|
||||
|
||||
/* Update interval */
|
||||
f64 update_interval;
|
||||
|
||||
clib_spinlock_t *stat_segment_lockp;
|
||||
clib_socket_t *socket;
|
||||
u8 *socket_name;
|
||||
ssize_t memory_size;
|
||||
clib_mem_page_sz_t log2_page_sz;
|
||||
u8 node_counters_enabled;
|
||||
void *heap;
|
||||
vlib_stats_shared_header_t
|
||||
*shared_header; /* pointer to shared memory segment */
|
||||
int memfd;
|
||||
|
||||
} vlib_stats_segment_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vlib_stats_segment_t segment;
|
||||
} vlib_stats_main_t;
|
||||
|
||||
extern vlib_stats_main_t vlib_stats_main;
|
||||
|
||||
static_always_inline vlib_stats_segment_t *
|
||||
vlib_stats_get_segment ()
|
||||
{
|
||||
return &vlib_stats_main.segment;
|
||||
}
|
||||
|
||||
static_always_inline vlib_stats_entry_t *
|
||||
vlib_stats_get_entry (vlib_stats_segment_t *sm, u32 entry_index)
|
||||
{
|
||||
vlib_stats_entry_t *e;
|
||||
ASSERT (entry_index < vec_len (sm->directory_vector));
|
||||
e = sm->directory_vector + entry_index;
|
||||
ASSERT (e->type != STAT_DIR_TYPE_EMPTY && e->type != STAT_DIR_TYPE_ILLEGAL);
|
||||
return e;
|
||||
}
|
||||
|
||||
clib_error_t *vlib_stats_init (vlib_main_t *vm);
|
||||
void *vlib_stats_set_heap ();
|
||||
void vlib_stats_update_counter (void *, u32, stat_directory_type_t);
|
||||
void vlib_stats_register_error_index (u64 *em_vec, u64 index, char *fmt, ...);
|
||||
void vlib_stats_update_error_vector (u64 *error_vector, u32 thread_index,
|
||||
int lock);
|
||||
void vlib_stats_segment_lock (void);
|
||||
void vlib_stats_segment_unlock (void);
|
||||
void vlib_stats_delete_cm (void *);
|
||||
void vlib_stats_register_mem_heap (clib_mem_heap_t *);
|
||||
f64 vlib_stats_get_segment_update_rate (void);
|
||||
|
||||
/* gauge */
|
||||
u32 vlib_stats_add_gauge (char *fmt, ...);
|
||||
void vlib_stats_set_gauge (u32 entry_index, u64 value);
|
||||
|
||||
/* timestamp */
|
||||
u32 vlib_stats_add_timestamp (char *fmt, ...);
|
||||
void vlib_stats_set_timestamp (u32 entry_index, f64 value);
|
||||
|
||||
/* vector */
|
||||
u32 vlib_stats_add_counter_vector (char *fmt, ...);
|
||||
void vlib_stats_validate_counter_vector (u32 entry_index, u32 vector_index);
|
||||
|
||||
/* string vector */
|
||||
u32 vlib_stats_add_string_vector (char *fmt, ...);
|
||||
void vlib_stats_set_string_vector (u32 entry_index, u32 vector_index,
|
||||
char *fmt, ...);
|
||||
|
||||
/* symlink */
|
||||
u32 vlib_stats_add_symlink (u32 entry_index, u32 vector_index, char *fmt, ...);
|
||||
void vlib_stats_rename_symlink (u64 entry_index, char *fmt, ...);
|
||||
|
||||
/* common to all types */
|
||||
void vlib_stats_remove_entry (u32 entry_index);
|
||||
u32 vlib_stats_find_entry_index (char *fmt, ...);
|
||||
void vlib_stats_register_collector_fn (vlib_stats_collector_reg_t *r);
|
||||
|
||||
format_function_t format_vlib_stats_symlink;
|
||||
|
||||
#endif
|
||||
+17
-9
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <vlib/threads.h>
|
||||
|
||||
#include <vlib/stat_weak_inlines.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
u32
|
||||
vl (void *p)
|
||||
@@ -180,6 +180,11 @@ vlib_thread_init (vlib_main_t * vm)
|
||||
u32 first_index = 1;
|
||||
u32 i;
|
||||
uword *avail_cpu;
|
||||
u32 stats_num_worker_threads_dir_index;
|
||||
|
||||
stats_num_worker_threads_dir_index =
|
||||
vlib_stats_add_gauge ("/sys/num_worker_threads");
|
||||
ASSERT (stats_num_worker_threads_dir_index != ~0);
|
||||
|
||||
/* get bitmaps of active cpu cores and sockets */
|
||||
tm->cpu_core_bitmap =
|
||||
@@ -319,6 +324,7 @@ vlib_thread_init (vlib_main_t * vm)
|
||||
clib_bitmap_free (avail_cpu);
|
||||
|
||||
tm->n_vlib_mains = n_vlib_mains;
|
||||
vlib_stats_set_gauge (stats_num_worker_threads_dir_index, n_vlib_mains - 1);
|
||||
|
||||
/*
|
||||
* Allocate the remaining worker threads, and thread stack vector slots
|
||||
@@ -729,12 +735,13 @@ start_workers (vlib_main_t * vm)
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
/* Switch to the stats segment ... */
|
||||
void *oldheap = vlib_stats_push_heap (0);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
vm_clone->error_main.counters =
|
||||
vec_dup_aligned (vlib_get_first_main ()->error_main.counters,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
vlib_stats_pop_heap2 (vm_clone->error_main.counters,
|
||||
worker_thread_index, oldheap, 1);
|
||||
clib_mem_set_heap (oldheap);
|
||||
vlib_stats_update_error_vector (vm_clone->error_main.counters,
|
||||
worker_thread_index, 1);
|
||||
|
||||
vm_clone->error_main.counters_last_clear = vec_dup_aligned (
|
||||
vlib_get_first_main ()->error_main.counters_last_clear,
|
||||
@@ -892,11 +899,12 @@ vlib_worker_thread_node_refork (void)
|
||||
j = vec_len (vm->error_main.counters) - 1;
|
||||
|
||||
/* Switch to the stats segment ... */
|
||||
void *oldheap = vlib_stats_push_heap (0);
|
||||
void *oldheap = vlib_stats_set_heap ();
|
||||
vec_validate_aligned (old_counters, j, CLIB_CACHE_LINE_BYTES);
|
||||
clib_mem_set_heap (oldheap);
|
||||
vm_clone->error_main.counters = old_counters;
|
||||
vlib_stats_pop_heap2 (vm_clone->error_main.counters, vm_clone->thread_index,
|
||||
oldheap, 0);
|
||||
vlib_stats_update_error_vector (vm_clone->error_main.counters,
|
||||
vm_clone->thread_index, 0);
|
||||
|
||||
vec_validate_aligned (old_counters_all_clear, j, CLIB_CACHE_LINE_BYTES);
|
||||
vm_clone->error_main.counters_last_clear = old_counters_all_clear;
|
||||
@@ -1392,7 +1400,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm)
|
||||
* rebuilding the stat segment node clones from the
|
||||
* stat thread...
|
||||
*/
|
||||
vlib_stat_segment_lock ();
|
||||
vlib_stats_segment_lock ();
|
||||
|
||||
/* Do stats elements on main thread */
|
||||
worker_thread_node_runtime_update_internal ();
|
||||
@@ -1443,7 +1451,7 @@ vlib_worker_thread_barrier_release (vlib_main_t * vm)
|
||||
os_panic ();
|
||||
}
|
||||
}
|
||||
vlib_stat_segment_unlock ();
|
||||
vlib_stats_segment_unlock ();
|
||||
}
|
||||
|
||||
t_closed_total = now - vm->barrier_epoch;
|
||||
|
||||
@@ -41,6 +41,7 @@ list(APPEND VNET_SOURCES
|
||||
interface/tx_queue.c
|
||||
interface/runtime.c
|
||||
interface/monitor.c
|
||||
interface/stats.c
|
||||
interface_stats.c
|
||||
misc.c
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <vnet/dpo/receive_dpo.h>
|
||||
#include <vnet/fib/fib_entry.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <vnet/bfd/bfd_debug.h>
|
||||
#include <vnet/bfd/bfd_udp.h>
|
||||
#include <vnet/bfd/bfd_main.h>
|
||||
@@ -85,9 +85,9 @@ bfd_udp_main_t bfd_udp_main;
|
||||
void
|
||||
bfd_udp_update_stat_segment_entry (u32 entry, u64 value)
|
||||
{
|
||||
vlib_stat_segment_lock ();
|
||||
stat_segment_set_state_counter (entry, value);
|
||||
vlib_stat_segment_unlock ();
|
||||
vlib_stats_segment_lock ();
|
||||
vlib_stats_set_gauge (entry, value);
|
||||
vlib_stats_segment_unlock ();
|
||||
}
|
||||
|
||||
vnet_api_error_t
|
||||
@@ -1694,19 +1694,18 @@ clib_error_t *
|
||||
bfd_udp_stats_init (bfd_udp_main_t *bum)
|
||||
{
|
||||
const char *name4 = "/bfd/udp4/sessions";
|
||||
bum->udp4_sessions_count_stat_seg_entry =
|
||||
stat_segment_new_entry ((u8 *) name4, STAT_DIR_TYPE_SCALAR_INDEX);
|
||||
bum->udp4_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name4);
|
||||
|
||||
stat_segment_set_state_counter (bum->udp4_sessions_count_stat_seg_entry, 0);
|
||||
vlib_stats_set_gauge (bum->udp4_sessions_count_stat_seg_entry, 0);
|
||||
if (~0 == bum->udp4_sessions_count_stat_seg_entry)
|
||||
{
|
||||
return clib_error_return (
|
||||
0, "Could not create stat segment entry for %s", name4);
|
||||
}
|
||||
const char *name6 = "/bfd/udp6/sessions";
|
||||
bum->udp6_sessions_count_stat_seg_entry =
|
||||
stat_segment_new_entry ((u8 *) name6, STAT_DIR_TYPE_SCALAR_INDEX);
|
||||
bum->udp6_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name6);
|
||||
|
||||
vlib_stats_set_gauge (bum->udp6_sessions_count_stat_seg_entry, 0);
|
||||
if (~0 == bum->udp6_sessions_count_stat_seg_entry)
|
||||
{
|
||||
return clib_error_return (
|
||||
|
||||
+25
-28
@@ -20,7 +20,7 @@
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vnet/bonding/node.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
void
|
||||
bond_disable_collecting_distributing (vlib_main_t * vm, member_if_t * mif)
|
||||
@@ -323,10 +323,10 @@ bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, member_if_t * mif)
|
||||
|
||||
if (bif->mode == BOND_MODE_LACP)
|
||||
{
|
||||
stat_segment_deregister_state_counter
|
||||
(bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state);
|
||||
stat_segment_deregister_state_counter
|
||||
(bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state);
|
||||
vlib_stats_remove_entry (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].actor_state);
|
||||
vlib_stats_remove_entry (
|
||||
bm->stats[bif->sw_if_index][mif->sw_if_index].partner_state);
|
||||
}
|
||||
|
||||
pool_put (bm->neighbors, mif);
|
||||
@@ -650,32 +650,29 @@ bond_add_member (vlib_main_t * vm, bond_add_member_args_t * args)
|
||||
}
|
||||
if (bif->mode == BOND_MODE_LACP)
|
||||
{
|
||||
u8 *name = format (0, "/if/lacp/%u/%u/state%c", bif->sw_if_index,
|
||||
args->member, 0);
|
||||
u32 actor_idx, partner_idx;
|
||||
|
||||
actor_idx = vlib_stats_add_gauge ("/if/lacp/%u/%u/state",
|
||||
bif->sw_if_index, args->member);
|
||||
if (actor_idx == ~0)
|
||||
{
|
||||
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
|
||||
return;
|
||||
}
|
||||
|
||||
partner_idx = vlib_stats_add_gauge ("/if/lacp/%u/%u/partner-state",
|
||||
bif->sw_if_index, args->member);
|
||||
if (partner_idx == ~0)
|
||||
{
|
||||
vlib_stats_remove_entry (actor_idx);
|
||||
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
|
||||
return;
|
||||
}
|
||||
|
||||
vec_validate (bm->stats, bif->sw_if_index);
|
||||
vec_validate (bm->stats[bif->sw_if_index], args->member);
|
||||
|
||||
args->error = stat_segment_register_state_counter
|
||||
(name, &bm->stats[bif->sw_if_index][args->member].actor_state);
|
||||
if (args->error != 0)
|
||||
{
|
||||
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
|
||||
vec_free (name);
|
||||
return;
|
||||
}
|
||||
|
||||
vec_reset_length (name);
|
||||
name = format (0, "/if/lacp/%u/%u/partner-state%c", bif->sw_if_index,
|
||||
args->member, 0);
|
||||
args->error = stat_segment_register_state_counter
|
||||
(name, &bm->stats[bif->sw_if_index][args->member].partner_state);
|
||||
vec_free (name);
|
||||
if (args->error != 0)
|
||||
{
|
||||
args->rv = VNET_API_ERROR_INVALID_INTERFACE;
|
||||
return;
|
||||
}
|
||||
bm->stats[bif->sw_if_index][args->member].actor_state = actor_idx;
|
||||
bm->stats[bif->sw_if_index][args->member].partner_state = partner_idx;
|
||||
}
|
||||
|
||||
pool_get (bm->neighbors, mif);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <vnet/feature/feature.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
|
||||
vnet_device_main_t vnet_device_main;
|
||||
|
||||
@@ -101,12 +102,30 @@ VNET_FEATURE_INIT (ethernet_input, static) = {
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
input_rate_collector_fn (vlib_stats_collector_data_t *d)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
vlib_stats_entry_t *e2 = sm->directory_vector + d->private_data;
|
||||
static u64 last_input_packets = 0;
|
||||
f64 dt, now;
|
||||
|
||||
now = vlib_time_now (vlib_get_main ());
|
||||
u64 input_packets = vnet_get_aggregate_rx_packets ();
|
||||
|
||||
dt = now - e2->value;
|
||||
d->entry->value = (f64) (input_packets - last_input_packets) / dt;
|
||||
last_input_packets = input_packets;
|
||||
e2->value = now;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
vnet_device_init (vlib_main_t * vm)
|
||||
{
|
||||
vnet_device_main_t *vdm = &vnet_device_main;
|
||||
vlib_thread_main_t *tm = vlib_get_thread_main ();
|
||||
vlib_thread_registration_t *tr;
|
||||
vlib_stats_collector_reg_t reg = {};
|
||||
uword *p;
|
||||
|
||||
vec_validate_aligned (vdm->workers, tm->n_vlib_mains - 1,
|
||||
@@ -120,6 +139,12 @@ vnet_device_init (vlib_main_t * vm)
|
||||
vdm->next_worker_thread_index = tr->first_index;
|
||||
vdm->last_worker_thread_index = tr->first_index + tr->count - 1;
|
||||
}
|
||||
|
||||
reg.private_data = vlib_stats_add_timestamp ("/sys/last_update");
|
||||
reg.entry_index = vlib_stats_add_gauge ("/sys/input_rate");
|
||||
reg.collect_fn = input_rate_collector_fn;
|
||||
vlib_stats_register_collector_fn (®);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2022 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/devices/devices.h> /* vnet_get_aggregate_rx_packets */
|
||||
#include <vnet/interface.h>
|
||||
|
||||
static u32 if_names_stats_entry_index = ~0;
|
||||
static u32 **dir_entry_indices = 0;
|
||||
|
||||
static struct
|
||||
{
|
||||
char *prefix, *name;
|
||||
u32 index;
|
||||
} if_counters[] = {
|
||||
#define _(e, n, p) { .prefix = #p, .name = #n },
|
||||
foreach_simple_interface_counter_name foreach_combined_interface_counter_name
|
||||
#undef _
|
||||
};
|
||||
|
||||
static clib_error_t *
|
||||
statseg_sw_interface_add_del (vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
|
||||
{
|
||||
vlib_stats_segment_t *sm = vlib_stats_get_segment ();
|
||||
vlib_stats_entry_t *e;
|
||||
void *oldheap;
|
||||
|
||||
if (if_names_stats_entry_index == ~0)
|
||||
{
|
||||
if_names_stats_entry_index = vlib_stats_add_string_vector ("/if/names");
|
||||
|
||||
for (int i = 0; i < ARRAY_LEN (if_counters); i++)
|
||||
if_counters[i].index = vlib_stats_find_entry_index (
|
||||
"/%s/%s", if_counters[i].prefix, if_counters[i].name);
|
||||
}
|
||||
|
||||
e = sm->directory_vector + if_names_stats_entry_index;
|
||||
|
||||
vec_validate (dir_entry_indices, sw_if_index);
|
||||
|
||||
vlib_stats_segment_lock ();
|
||||
|
||||
if (is_add)
|
||||
{
|
||||
vnet_sw_interface_t *si, *si_sup;
|
||||
vnet_hw_interface_t *hi_sup;
|
||||
u8 *s;
|
||||
|
||||
si = vnet_get_sw_interface (vnm, sw_if_index);
|
||||
si_sup = vnet_get_sup_sw_interface (vnm, si->sw_if_index);
|
||||
ASSERT (si_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE);
|
||||
hi_sup = vnet_get_hw_interface (vnm, si_sup->hw_if_index);
|
||||
|
||||
oldheap = clib_mem_set_heap (sm->heap);
|
||||
s = format (0, "%v", hi_sup->name);
|
||||
if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
|
||||
s = format (s, ".%d", si->sub.id);
|
||||
s = format (s, "%c", 0);
|
||||
|
||||
vec_validate (e->string_vector, sw_if_index);
|
||||
|
||||
ASSERT (e->string_vector[sw_if_index] == 0);
|
||||
e->string_vector[sw_if_index] = s;
|
||||
clib_mem_set_heap (oldheap);
|
||||
|
||||
s = format (0, "/interfaces/%U", format_vlib_stats_symlink, s);
|
||||
for (u32 index, i = 0; i < ARRAY_LEN (if_counters); i++)
|
||||
{
|
||||
index = vlib_stats_add_symlink (if_counters[i].index, sw_if_index,
|
||||
"%v/%s", s, if_counters[i].name);
|
||||
ASSERT (index != ~0);
|
||||
vec_add1 (dir_entry_indices[sw_if_index], index);
|
||||
}
|
||||
vec_free (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldheap = clib_mem_set_heap (sm->heap);
|
||||
vec_free (e->string_vector[sw_if_index]);
|
||||
clib_mem_set_heap (oldheap);
|
||||
for (u32 i = 0; i < vec_len (dir_entry_indices[sw_if_index]); i++)
|
||||
vlib_stats_remove_entry (dir_entry_indices[sw_if_index][i]);
|
||||
vec_free (dir_entry_indices[sw_if_index]);
|
||||
}
|
||||
|
||||
vlib_stats_segment_unlock ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (statseg_sw_interface_add_del);
|
||||
@@ -29,7 +29,8 @@
|
||||
#include <vppinfra/vec.h>
|
||||
#include <vppinfra/lock.h>
|
||||
#include <stdatomic.h>
|
||||
#include <vpp/stats/stat_segment.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vlib/stats/stats.h>
|
||||
#include <vpp-api/client/stat_client.h>
|
||||
|
||||
stat_client_main_t stat_client_main;
|
||||
@@ -81,8 +82,8 @@ recv_fd (int sock)
|
||||
return fd;
|
||||
}
|
||||
|
||||
static stat_segment_directory_entry_t *
|
||||
get_stat_vector_r (stat_client_main_t * sm)
|
||||
static vlib_stats_entry_t *
|
||||
get_stat_vector_r (stat_client_main_t *sm)
|
||||
{
|
||||
ASSERT (sm->shared_header);
|
||||
return stat_segment_adjust (sm,
|
||||
@@ -172,7 +173,7 @@ double
|
||||
stat_segment_heartbeat_r (stat_client_main_t * sm)
|
||||
{
|
||||
stat_segment_access_t sa;
|
||||
stat_segment_directory_entry_t *ep;
|
||||
vlib_stats_entry_t *ep;
|
||||
|
||||
/* Has directory been updated? */
|
||||
if (sm->shared_header->epoch != sm->current_epoch)
|
||||
@@ -223,7 +224,7 @@ stat_vec_combined_init (vlib_counter_t c)
|
||||
* threads), otherwise copy out all values.
|
||||
*/
|
||||
static stat_segment_data_t
|
||||
copy_data (stat_segment_directory_entry_t *ep, u32 index2, char *name,
|
||||
copy_data (vlib_stats_entry_t *ep, u32 index2, char *name,
|
||||
stat_client_main_t *sm)
|
||||
{
|
||||
stat_segment_data_t result = { 0 };
|
||||
@@ -297,7 +298,7 @@ copy_data (stat_segment_directory_entry_t *ep, u32 index2, char *name,
|
||||
case STAT_DIR_TYPE_SYMLINK:
|
||||
/* Gather info from all threads into a vector */
|
||||
{
|
||||
stat_segment_directory_entry_t *ep2;
|
||||
vlib_stats_entry_t *ep2;
|
||||
ep2 = vec_elt_at_index (sm->directory_vector, ep->index1);
|
||||
return copy_data (ep2, ep->index2, ep->name, sm);
|
||||
}
|
||||
@@ -370,7 +371,7 @@ stat_segment_ls_r (uint8_t ** patterns, stat_client_main_t * sm)
|
||||
if (stat_segment_access_start (&sa, sm))
|
||||
return 0;
|
||||
|
||||
stat_segment_directory_entry_t *counter_vec = get_stat_vector_r (sm);
|
||||
vlib_stats_entry_t *counter_vec = get_stat_vector_r (sm);
|
||||
for (j = 0; j < vec_len (counter_vec); j++)
|
||||
{
|
||||
for (i = 0; i < vec_len (patterns); i++)
|
||||
@@ -413,7 +414,7 @@ stat_segment_data_t *
|
||||
stat_segment_dump_r (uint32_t * stats, stat_client_main_t * sm)
|
||||
{
|
||||
int i;
|
||||
stat_segment_directory_entry_t *ep;
|
||||
vlib_stats_entry_t *ep;
|
||||
stat_segment_data_t *res = 0;
|
||||
stat_segment_access_t sa;
|
||||
|
||||
@@ -474,7 +475,7 @@ stat_segment_string_vector (uint8_t ** string_vector, const char *string)
|
||||
stat_segment_data_t *
|
||||
stat_segment_dump_entry_r (uint32_t index, stat_client_main_t * sm)
|
||||
{
|
||||
stat_segment_directory_entry_t *ep;
|
||||
vlib_stats_entry_t *ep;
|
||||
stat_segment_data_t *res = 0;
|
||||
stat_segment_access_t sa;
|
||||
|
||||
@@ -504,9 +505,9 @@ stat_segment_dump_entry (uint32_t index)
|
||||
char *
|
||||
stat_segment_index_to_name_r (uint32_t index, stat_client_main_t * sm)
|
||||
{
|
||||
stat_segment_directory_entry_t *ep;
|
||||
vlib_stats_entry_t *ep;
|
||||
stat_segment_access_t sa;
|
||||
stat_segment_directory_entry_t *vec;
|
||||
vlib_stats_entry_t *vec;
|
||||
|
||||
/* Has directory been update? */
|
||||
if (sm->shared_header->epoch != sm->current_epoch)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user