From fe0ffd52cc9322512ad4d8e8f4d7527882450fa4 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Wed, 28 Aug 2024 11:23:09 +0200 Subject: [PATCH 1/6] cleanup(libscap): detach per-CPU counters from global kernel counters Signed-off-by: Andrea Terzolo --- userspace/libpman/src/stats.c | 74 +++++++++++++++---- userspace/libscap/engine/bpf/scap_bpf.c | 64 ++++++++++++---- userspace/libscap/engine/kmod/scap_kmod.c | 62 ++++++++++++---- .../libscap/examples/01-open/scap_open.c | 2 +- userspace/libscap/metrics_v2.h | 1 + 5 files changed, 157 insertions(+), 46 deletions(-) diff --git a/userspace/libpman/src/stats.c b/userspace/libpman/src/stats.c index 43766cc15f..05ecac3bc7 100644 --- a/userspace/libpman/src/stats.c +++ b/userspace/libpman/src/stats.c @@ -140,10 +140,10 @@ int pman_get_scap_stats(struct scap_stats *stats) return errno; } -static void set_u64_monotonic_kernel_counter(uint32_t pos, uint64_t val) +static void set_u64_monotonic_kernel_counter(uint32_t pos, uint64_t val, uint32_t metric_type) { g_state.stats[pos].type = METRIC_VALUE_TYPE_U64; - g_state.stats[pos].flags = METRICS_V2_KERNEL_COUNTERS; + g_state.stats[pos].flags = metric_type; g_state.stats[pos].unit = METRIC_VALUE_UNIT_COUNT; g_state.stats[pos].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; g_state.stats[pos].value.u64 = val; @@ -166,11 +166,15 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t } } - // At the moment for each available CPU we want: - // - the number of events. - // - the number of drops. - uint32_t per_cpu_stats = g_state.n_possible_cpus* 2; - + uint32_t per_cpu_stats = 0; + if(flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) + { + // At the moment for each available CPU we want: + // - the number of events. + // - the number of drops. + per_cpu_stats = g_state.n_possible_cpus* 2; + } + g_state.nstats = MODERN_BPF_MAX_KERNEL_COUNTERS_STATS + per_cpu_stats + (nprogs_attached * MODERN_BPF_MAX_LIBBPF_STATS); g_state.stats = (metrics_v2 *)calloc(g_state.nstats, sizeof(metrics_v2)); if(!g_state.stats) @@ -197,7 +201,7 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t for(uint32_t stat = 0; stat < MODERN_BPF_MAX_KERNEL_COUNTERS_STATS; stat++) { - set_u64_monotonic_kernel_counter(stat, 0); + set_u64_monotonic_kernel_counter(stat, 0, METRICS_V2_KERNEL_COUNTERS); strlcpy(g_state.stats[stat].name, (char*)modern_bpf_kernel_counters_stats_names[stat], METRIC_NAME_MAX); } @@ -234,17 +238,57 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t g_state.stats[MODERN_BPF_N_DROPS_SCRATCH_MAP].value.u64 += cnt_map.n_drops_max_event_size; g_state.stats[MODERN_BPF_N_DROPS].value.u64 += (cnt_map.n_drops_buffer + cnt_map.n_drops_max_event_size); + if((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU)) + { + // We set the num events for that CPU. + set_u64_monotonic_kernel_counter(pos, cnt_map.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(g_state.stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", index); + pos++; + + // We set the drops for that CPU. + set_u64_monotonic_kernel_counter(pos, cnt_map.n_drops_buffer + cnt_map.n_drops_max_event_size, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(g_state.stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", index); + pos++; + } + } + offset = pos; + } + + /* KERNEL COUNTERS PER CPU STATS + * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. + * It is an unsual case but at the moment we support it. + */ + if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) + { + char error_message[MAX_ERROR_MESSAGE_LEN]; + int counter_maps_fd = bpf_map__fd(g_state.skel->maps.counter_maps); + if(counter_maps_fd <= 0) + { + pman_print_error("unable to get 'counter_maps' fd during kernel stats processing"); + return NULL; + } + + struct counter_map cnt_map = {}; + for(uint32_t index = 0; index < g_state.n_possible_cpus; index++) + { + if(bpf_map_lookup_elem(counter_maps_fd, &index, &cnt_map) < 0) + { + snprintf(error_message, MAX_ERROR_MESSAGE_LEN, "unable to get the counter map for CPU %d", index); + pman_print_error((const char *)error_message); + close(counter_maps_fd); + return NULL; + } + // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(pos, cnt_map.n_evts); - snprintf(g_state.stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", index); - pos++; + set_u64_monotonic_kernel_counter(offset, cnt_map.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(g_state.stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", index); + offset++; // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(pos, cnt_map.n_drops_buffer + cnt_map.n_drops_max_event_size); - snprintf(g_state.stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", index); - pos++; + set_u64_monotonic_kernel_counter(offset, cnt_map.n_drops_buffer + cnt_map.n_drops_max_event_size, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(g_state.stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", index); + offset++; } - offset = pos; } /* LIBBPF STATS */ diff --git a/userspace/libscap/engine/bpf/scap_bpf.c b/userspace/libscap/engine/bpf/scap_bpf.c index 7728408c49..ee5af30918 100644 --- a/userspace/libscap/engine/bpf/scap_bpf.c +++ b/userspace/libscap/engine/bpf/scap_bpf.c @@ -1688,10 +1688,10 @@ int32_t scap_bpf_get_stats(struct scap_engine_handle engine, scap_stats* stats) return SCAP_SUCCESS; } -static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val) +static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_type) { m->type = METRIC_VALUE_TYPE_U64; - m->flags = METRICS_V2_KERNEL_COUNTERS; + m->flags = metric_type; m->unit = METRIC_VALUE_UNIT_COUNT; m->metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; m->value.u64 = val; @@ -1722,11 +1722,15 @@ const struct metrics_v2* scap_bpf_get_stats_v2(struct scap_engine_handle engine, } } - // At the moment for each available CPU we want: - // - the number of events. - // - the number of drops. - uint32_t per_cpu_stats = handle->m_ncpus* 2; - + uint32_t per_cpu_stats = 0; + if(flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) + { + // At the moment for each available CPU we want: + // - the number of events. + // - the number of drops. + per_cpu_stats = handle->m_ncpus* 2; + } + handle->m_nstats = BPF_MAX_KERNEL_COUNTERS_STATS + per_cpu_stats + (nprogs_attached * BPF_MAX_LIBBPF_STATS); handle->m_stats = (metrics_v2*)calloc(handle->m_nstats, sizeof(metrics_v2)); if(!handle->m_stats) @@ -1746,7 +1750,7 @@ const struct metrics_v2* scap_bpf_get_stats_v2(struct scap_engine_handle engine, { for(uint32_t stat = 0; stat < BPF_MAX_KERNEL_COUNTERS_STATS; stat++) { - set_u64_monotonic_kernel_counter(&(stats[stat]), 0); + set_u64_monotonic_kernel_counter(&(stats[stat]), 0, METRICS_V2_KERNEL_COUNTERS); strlcpy(stats[stat].name, (char*)bpf_kernel_counters_stats_names[stat], METRIC_NAME_MAX); } @@ -1783,17 +1787,47 @@ const struct metrics_v2* scap_bpf_get_stats_v2(struct scap_engine_handle engine, v.n_drops_pf + \ v.n_drops_bug; + if((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU)) + { + // We set the num events for that CPU. + set_u64_monotonic_kernel_counter(&(stats[pos]), v.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", cpu); + pos++; + + // We set the drops for that CPU. + set_u64_monotonic_kernel_counter(&(stats[pos]), v.n_drops_buffer + v.n_drops_scratch_map + v.n_drops_pf + v.n_drops_bug, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", cpu); + pos++; + } + } + offset = pos; + } + + /* KERNEL COUNTERS PER CPU STATS + * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. + * It is an unsual case but at the moment we support it. + */ + if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) + { + struct scap_bpf_per_cpu_state v = {}; + for(int cpu = 0; cpu < handle->m_ncpus; cpu++) + { + if(bpf_map_lookup_elem(handle->m_bpf_map_fds[SCAP_LOCAL_STATE_MAP], &cpu, &v) < 0) + { + *rc = scap_errprintf(handle->m_lasterr, errno, "Error looking up local state %d", cpu); + return NULL; + } + // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(&(stats[pos]), v.n_evts); - snprintf(stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", cpu); - pos++; + set_u64_monotonic_kernel_counter(&(stats[offset]), v.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", cpu); + offset++; // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(&(stats[pos]), v.n_drops_buffer + v.n_drops_scratch_map + v.n_drops_pf + v.n_drops_bug); - snprintf(stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", cpu); - pos++; + set_u64_monotonic_kernel_counter(&(stats[offset]), v.n_drops_buffer + v.n_drops_scratch_map + v.n_drops_pf + v.n_drops_bug, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", cpu); + offset++; } - offset = pos; } /* LIBBPF STATS */ diff --git a/userspace/libscap/engine/kmod/scap_kmod.c b/userspace/libscap/engine/kmod/scap_kmod.c index 80d3dc6859..3024ac50b7 100644 --- a/userspace/libscap/engine/kmod/scap_kmod.c +++ b/userspace/libscap/engine/kmod/scap_kmod.c @@ -586,10 +586,10 @@ int32_t scap_kmod_get_stats(struct scap_engine_handle engine, scap_stats* stats) return SCAP_SUCCESS; } -static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val) +static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_type) { m->type = METRIC_VALUE_TYPE_U64; - m->flags = METRICS_V2_KERNEL_COUNTERS; + m->flags = metric_type; m->unit = METRIC_VALUE_UNIT_COUNT; m->metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; m->value.u64 = val; @@ -606,11 +606,17 @@ const struct metrics_v2* scap_kmod_get_stats_v2(struct scap_engine_handle engine // If it is the first time we call this function, we allocate the stats if(handle->m_stats == NULL) { - // The difference with other drivers is that here we consider only ONLINE CPUs and not the AVILABLE ones. - // At the moment for each ONLINE CPU we want: - // - the number of events. - // - the number of drops. - uint32_t per_dev_stats = devset->m_ndevs* 2; + // We don't allocate space for per-cpu stats, if we don't enable them at init time. + // At the moment we don't support dynamic metrics selection at runtime. + uint32_t per_dev_stats = 0; + if(flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) + { + // The difference with other drivers is that here we consider only ONLINE CPUs and not the AVILABLE ones. + // At the moment for each ONLINE CPU we want: + // - the number of events. + // - the number of drops. + per_dev_stats = devset->m_ndevs* 2; + } handle->m_nstats = KMOD_MAX_KERNEL_COUNTERS_STATS + per_dev_stats; handle->m_stats = (metrics_v2*)calloc(handle->m_nstats, sizeof(metrics_v2)); @@ -631,7 +637,7 @@ const struct metrics_v2* scap_kmod_get_stats_v2(struct scap_engine_handle engine { for(uint32_t stat = 0; stat < KMOD_MAX_KERNEL_COUNTERS_STATS; stat++) { - set_u64_monotonic_kernel_counter(&(stats[stat]), 0); + set_u64_monotonic_kernel_counter(&(stats[stat]), 0, METRICS_V2_KERNEL_COUNTERS); strlcpy(stats[stat].name, (char*)kmod_kernel_counters_stats_names[stat], METRIC_NAME_MAX); } @@ -660,17 +666,43 @@ const struct metrics_v2* scap_kmod_get_stats_v2(struct scap_engine_handle engine dev->m_bufinfo->n_drops_pf; stats[KMOD_N_PREEMPTIONS].value.u64 += dev->m_bufinfo->n_preemptions; + // This is just a way to avoid the double loop on the number of devices. + if((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU)) + { + // We set the num events for that CPU. + set_u64_monotonic_kernel_counter(&(stats[pos]), dev->m_bufinfo->n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_DEVICE_PREFIX"%d", j); + pos++; + + // We set the drops for that CPU. + set_u64_monotonic_kernel_counter(&(stats[pos]), dev->m_bufinfo->n_drops_buffer + dev->m_bufinfo->n_drops_pf, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_DEVICE_PREFIX"%d", j); + pos++; + } + } + offset = pos; + } + + /* KERNEL COUNTERS PER CPU STATS + * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. + * It is an unsual case but at the moment we support it. + */ + if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) + { + for(uint32_t j = 0; j < devset->m_ndevs; j++) + { + struct scap_device *dev = &devset->m_devs[j]; + // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(&(stats[pos]), dev->m_bufinfo->n_evts); - snprintf(stats[pos].name, METRIC_NAME_MAX, N_EVENTS_PER_DEVICE_PREFIX"%d", j); - pos++; + set_u64_monotonic_kernel_counter(&(stats[offset]), dev->m_bufinfo->n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_DEVICE_PREFIX"%d", j); + offset++; // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(&(stats[pos]), dev->m_bufinfo->n_drops_buffer + dev->m_bufinfo->n_drops_pf); - snprintf(stats[pos].name, METRIC_NAME_MAX, N_DROPS_PER_DEVICE_PREFIX"%d", j); - pos++; + set_u64_monotonic_kernel_counter(&(stats[offset]), dev->m_bufinfo->n_drops_buffer + dev->m_bufinfo->n_drops_pf, METRICS_V2_KERNEL_COUNTERS_PER_CPU); + snprintf(stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_DEVICE_PREFIX"%d", j); + offset++; } - offset = pos; } *nstats = offset; diff --git a/userspace/libscap/examples/01-open/scap_open.c b/userspace/libscap/examples/01-open/scap_open.c index 43dc6ddedf..c38f228420 100644 --- a/userspace/libscap/examples/01-open/scap_open.c +++ b/userspace/libscap/examples/01-open/scap_open.c @@ -866,7 +866,7 @@ void print_stats() { gettimeofday(&tval_end, NULL); timersub(&tval_end, &tval_start, &tval_result); - uint32_t flags = METRICS_V2_KERNEL_COUNTERS | METRICS_V2_LIBBPF_STATS; + uint32_t flags = METRICS_V2_KERNEL_COUNTERS | METRICS_V2_LIBBPF_STATS | METRICS_V2_KERNEL_COUNTERS_PER_CPU; uint32_t nstats; int32_t rc; const metrics_v2* stats_v2; diff --git a/userspace/libscap/metrics_v2.h b/userspace/libscap/metrics_v2.h index 31d611c621..3f952155fa 100644 --- a/userspace/libscap/metrics_v2.h +++ b/userspace/libscap/metrics_v2.h @@ -52,6 +52,7 @@ extern "C" { #define METRICS_V2_RULE_COUNTERS (1 << 4) #define METRICS_V2_MISC (1 << 5) #define METRICS_V2_PLUGINS (1 << 6) +#define METRICS_V2_KERNEL_COUNTERS_PER_CPU (1 << 7) typedef union metrics_v2_value { uint32_t u32; From 6224bcdcbbcdd7718c8dbceb4552b52b42bc037e Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Wed, 28 Aug 2024 18:13:50 +0200 Subject: [PATCH 2/6] fix(pman): remove a wrong flag Signed-off-by: Andrea Terzolo --- userspace/libpman/src/stats.c | 1 - 1 file changed, 1 deletion(-) diff --git a/userspace/libpman/src/stats.c b/userspace/libpman/src/stats.c index 05ecac3bc7..bed4a48da8 100644 --- a/userspace/libpman/src/stats.c +++ b/userspace/libpman/src/stats.c @@ -333,7 +333,6 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t { case RUN_CNT: strlcat(g_state.stats[offset].name, modern_bpf_libbpf_stats_names[RUN_CNT], sizeof(g_state.stats[offset].name)); - g_state.stats[stat].flags = METRICS_V2_KERNEL_COUNTERS; g_state.stats[stat].unit = METRIC_VALUE_UNIT_COUNT; g_state.stats[stat].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; g_state.stats[offset].value.u64 = info.run_cnt; From c43131409b2d8f7c76e5326c61514c8eb520d0dd Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Wed, 28 Aug 2024 18:37:26 +0200 Subject: [PATCH 3/6] cleanup(libscap): always enable global counters when per-cpu ones are enabled Signed-off-by: Andrea Terzolo --- test/libscap/test_suites/engines/bpf/bpf.cpp | 25 +++++++++++- .../libscap/test_suites/engines/kmod/kmod.cpp | 25 +++++++++++- .../engines/modern_bpf/modern_bpf.cpp | 25 +++++++++++- userspace/libpman/src/stats.c | 39 +------------------ userspace/libscap/engine/bpf/scap_bpf.c | 29 +------------- userspace/libscap/engine/kmod/scap_kmod.c | 25 +----------- userspace/libscap/metrics_v2.h | 5 +++ userspace/libscap/scap.c | 6 +++ userspace/libsinsp/metrics_collector.cpp | 2 +- userspace/libsinsp/metrics_collector.h | 2 +- 10 files changed, 85 insertions(+), 98 deletions(-) diff --git a/test/libscap/test_suites/engines/bpf/bpf.cpp b/test/libscap/test_suites/engines/bpf/bpf.cpp index e68befc6b9..6c450e0e2b 100644 --- a/test/libscap/test_suites/engines/bpf/bpf.cpp +++ b/test/libscap/test_suites/engines/bpf/bpf.cpp @@ -138,8 +138,8 @@ TEST(bpf, metrics_v2_check_per_CPU_stats) ssize_t num_possible_CPUs = num_possible_cpus(); - // We want to check our CPUs counters - uint32_t flags = METRICS_V2_KERNEL_COUNTERS; + // Enabling `METRICS_V2_KERNEL_COUNTERS_PER_CPU` we also enable `METRICS_V2_KERNEL_COUNTERS` + uint32_t flags = METRICS_V2_KERNEL_COUNTERS_PER_CPU; uint32_t nstats = 0; int32_t rc = 0; const metrics_v2* stats_v2 = scap_get_stats_v2(h, flags, &nstats, &rc); @@ -151,9 +151,18 @@ TEST(bpf, metrics_v2_check_per_CPU_stats) ssize_t found = 0; char expected_name[METRIC_NAME_MAX] = ""; snprintf(expected_name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%ld", found); + bool check_general_kernel_counters_presence = false; while(i < nstats) { + // We check if `METRICS_V2_KERNEL_COUNTERS` are enabled as well + if(strncmp(stats_v2[i].name, N_EVENTS_PREFIX, sizeof(N_EVENTS_PREFIX)) == 0) + { + check_general_kernel_counters_presence = true; + i++; + continue; + } + // `sizeof(N_EVENTS_PER_CPU_PREFIX)-1` because we need to exclude the `\0` if(strncmp(stats_v2[i].name, N_EVENTS_PER_CPU_PREFIX, sizeof(N_EVENTS_PER_CPU_PREFIX)-1) == 0) { @@ -176,6 +185,8 @@ TEST(bpf, metrics_v2_check_per_CPU_stats) } } + ASSERT_TRUE(check_general_kernel_counters_presence) << "per-CPU counter are enabled but general kernel counters are not"; + // This test could fail in case of rare race conditions in which the number of available CPUs changes // between the scap_open and the `num_possible_cpus` function. In CI we shouldn't have hot plugs so probably we // can live with this. @@ -220,6 +231,16 @@ TEST(bpf, metrics_v2_check_results) FAIL() << "unable to find stat '" << stat_name << "' into the array"; } } + + // Check per-CPU stats are not enabled since we didn't provide the flag. + for(i = 0; i < nstats; i++) + { + if(strncmp(stats_v2[i].name, N_EVENTS_PER_CPU_PREFIX, sizeof(N_EVENTS_PER_CPU_PREFIX)-1) == 0) + { + FAIL() << "per-CPU counters are enabled but we didn't provide the flag!"; + } + } + scap_close(h); } diff --git a/test/libscap/test_suites/engines/kmod/kmod.cpp b/test/libscap/test_suites/engines/kmod/kmod.cpp index e7e1933371..6a1cc4b420 100644 --- a/test/libscap/test_suites/engines/kmod/kmod.cpp +++ b/test/libscap/test_suites/engines/kmod/kmod.cpp @@ -193,8 +193,8 @@ TEST(kmod, metrics_v2_check_per_CPU_stats) ssize_t num_online_CPUs = sysconf(_SC_NPROCESSORS_ONLN); - // We want to check our CPUs counters - uint32_t flags = METRICS_V2_KERNEL_COUNTERS; + // Enabling `METRICS_V2_KERNEL_COUNTERS_PER_CPU` we also enable `METRICS_V2_KERNEL_COUNTERS` + uint32_t flags = METRICS_V2_KERNEL_COUNTERS_PER_CPU; uint32_t nstats = 0; int32_t rc = 0; const metrics_v2* stats_v2 = scap_get_stats_v2(h, flags, &nstats, &rc); @@ -206,9 +206,18 @@ TEST(kmod, metrics_v2_check_per_CPU_stats) ssize_t found = 0; char expected_name[METRIC_NAME_MAX] = ""; snprintf(expected_name, METRIC_NAME_MAX, N_EVENTS_PER_DEVICE_PREFIX"%ld", found); + bool check_general_kernel_counters_presence = false; while(i < nstats) { + // We check if `METRICS_V2_KERNEL_COUNTERS` are enabled as well + if(strncmp(stats_v2[i].name, N_EVENTS_PREFIX, sizeof(N_EVENTS_PREFIX)) == 0) + { + check_general_kernel_counters_presence = true; + i++; + continue; + } + // `sizeof(N_EVENTS_PER_DEVICE_PREFIX)-1` because we need to exclude the `\0` if(strncmp(stats_v2[i].name, N_EVENTS_PER_DEVICE_PREFIX, sizeof(N_EVENTS_PER_DEVICE_PREFIX)-1) == 0) { @@ -231,6 +240,8 @@ TEST(kmod, metrics_v2_check_per_CPU_stats) } } + ASSERT_TRUE(check_general_kernel_counters_presence) << "per-CPU counter are enabled but general kernel counters are not"; + // This test could fail in case of rare race conditions in which the number of online CPUs changes // between the scap_open and the `sysconf(_SC_NPROCESSORS_ONLN)` function. In CI we shouldn't have hot plugs so probably we // can live with this. @@ -271,6 +282,16 @@ TEST(kmod, metrics_v2_check_results) FAIL() << "unable to find stat '" << stat_name << "' into the array"; } } + + // Check per-CPU stats are not enabled since we didn't provide the flag. + for(i = 0; i < nstats; i++) + { + if(strncmp(stats_v2[i].name, N_EVENTS_PER_DEVICE_PREFIX, sizeof(N_EVENTS_PER_DEVICE_PREFIX)-1) == 0) + { + FAIL() << "per-CPU counters are enabled but we didn't provide the flag!"; + } + } + scap_close(h); } diff --git a/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp b/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp index 267f0b7a0f..3863b17a15 100644 --- a/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp +++ b/test/libscap/test_suites/engines/modern_bpf/modern_bpf.cpp @@ -257,8 +257,8 @@ TEST(modern_bpf, metrics_v2_check_per_CPU_stats) ssize_t num_possible_CPUs = num_possible_cpus(); - // We want to check our CPUs counters - uint32_t flags = METRICS_V2_KERNEL_COUNTERS; + // Enabling `METRICS_V2_KERNEL_COUNTERS_PER_CPU` we also enable `METRICS_V2_KERNEL_COUNTERS` + uint32_t flags = METRICS_V2_KERNEL_COUNTERS_PER_CPU; uint32_t nstats = 0; int32_t rc = 0; const metrics_v2* stats_v2 = scap_get_stats_v2(h, flags, &nstats, &rc); @@ -270,9 +270,18 @@ TEST(modern_bpf, metrics_v2_check_per_CPU_stats) ssize_t found = 0; char expected_name[METRIC_NAME_MAX] = ""; snprintf(expected_name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%ld", found); + bool check_general_kernel_counters_presence = false; while(i < nstats) { + // We check if `METRICS_V2_KERNEL_COUNTERS` are enabled as well + if(strncmp(stats_v2[i].name, N_EVENTS_PREFIX, sizeof(N_EVENTS_PREFIX)) == 0) + { + check_general_kernel_counters_presence = true; + i++; + continue; + } + // `sizeof(N_EVENTS_PER_CPU_PREFIX)-1` because we need to exclude the `\0` if(strncmp(stats_v2[i].name, N_EVENTS_PER_CPU_PREFIX, sizeof(N_EVENTS_PER_CPU_PREFIX)-1) == 0) { @@ -295,6 +304,8 @@ TEST(modern_bpf, metrics_v2_check_per_CPU_stats) } } + ASSERT_TRUE(check_general_kernel_counters_presence) << "per-CPU counter are enabled but general kernel counters are not"; + // This test could fail in case of rare race conditions in which the number of available CPUs changes // between the scap_open and the `num_possible_cpus` function. In CI we shouldn't have hot plugs so probably we // can live with this. @@ -340,6 +351,16 @@ TEST(modern_bpf, metrics_v2_check_results) FAIL() << "unable to find stat '" << stat_name << "' into the array"; } } + + // Check per-CPU stats are not enabled since we didn't provide the flag. + for(i = 0; i < nstats; i++) + { + if(strncmp(stats_v2[i].name, N_EVENTS_PER_CPU_PREFIX, sizeof(N_EVENTS_PER_CPU_PREFIX)-1) == 0) + { + FAIL() << "per-CPU counters are enabled but we didn't provide the flag!"; + } + } + scap_close(h); } diff --git a/userspace/libpman/src/stats.c b/userspace/libpman/src/stats.c index bed4a48da8..8c2dc66d3e 100644 --- a/userspace/libpman/src/stats.c +++ b/userspace/libpman/src/stats.c @@ -53,7 +53,7 @@ typedef enum modern_bpf_libbpf_stats } modern_bpf_libbpf_stats; const char *const modern_bpf_kernel_counters_stats_names[] = { - [MODERN_BPF_N_EVTS] = "n_evts", + [MODERN_BPF_N_EVTS] = N_EVENTS_PREFIX, [MODERN_BPF_N_DROPS_BUFFER_TOTAL] = "n_drops_buffer_total", [MODERN_BPF_N_DROPS_BUFFER_CLONE_FORK_ENTER] = "n_drops_buffer_clone_fork_enter", [MODERN_BPF_N_DROPS_BUFFER_CLONE_FORK_EXIT] = "n_drops_buffer_clone_fork_exit", @@ -254,43 +254,6 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t offset = pos; } - /* KERNEL COUNTERS PER CPU STATS - * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. - * It is an unsual case but at the moment we support it. - */ - if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) - { - char error_message[MAX_ERROR_MESSAGE_LEN]; - int counter_maps_fd = bpf_map__fd(g_state.skel->maps.counter_maps); - if(counter_maps_fd <= 0) - { - pman_print_error("unable to get 'counter_maps' fd during kernel stats processing"); - return NULL; - } - - struct counter_map cnt_map = {}; - for(uint32_t index = 0; index < g_state.n_possible_cpus; index++) - { - if(bpf_map_lookup_elem(counter_maps_fd, &index, &cnt_map) < 0) - { - snprintf(error_message, MAX_ERROR_MESSAGE_LEN, "unable to get the counter map for CPU %d", index); - pman_print_error((const char *)error_message); - close(counter_maps_fd); - return NULL; - } - - // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(offset, cnt_map.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(g_state.stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", index); - offset++; - - // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(offset, cnt_map.n_drops_buffer + cnt_map.n_drops_max_event_size, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(g_state.stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", index); - offset++; - } - } - /* LIBBPF STATS */ /* At the time of writing (Apr 2, 2023) libbpf stats are only available on a per program granularity. diff --git a/userspace/libscap/engine/bpf/scap_bpf.c b/userspace/libscap/engine/bpf/scap_bpf.c index ee5af30918..7cb0a5a107 100644 --- a/userspace/libscap/engine/bpf/scap_bpf.c +++ b/userspace/libscap/engine/bpf/scap_bpf.c @@ -50,7 +50,7 @@ limitations under the License. #include static const char * const bpf_kernel_counters_stats_names[] = { - [BPF_N_EVTS] = "n_evts", + [BPF_N_EVTS] = N_EVENTS_PREFIX, [BPF_N_DROPS_BUFFER_TOTAL] = "n_drops_buffer_total", [BPF_N_DROPS_BUFFER_CLONE_FORK_ENTER] = "n_drops_buffer_clone_fork_enter", [BPF_N_DROPS_BUFFER_CLONE_FORK_EXIT] = "n_drops_buffer_clone_fork_exit", @@ -1803,33 +1803,6 @@ const struct metrics_v2* scap_bpf_get_stats_v2(struct scap_engine_handle engine, offset = pos; } - /* KERNEL COUNTERS PER CPU STATS - * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. - * It is an unsual case but at the moment we support it. - */ - if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) - { - struct scap_bpf_per_cpu_state v = {}; - for(int cpu = 0; cpu < handle->m_ncpus; cpu++) - { - if(bpf_map_lookup_elem(handle->m_bpf_map_fds[SCAP_LOCAL_STATE_MAP], &cpu, &v) < 0) - { - *rc = scap_errprintf(handle->m_lasterr, errno, "Error looking up local state %d", cpu); - return NULL; - } - - // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(&(stats[offset]), v.n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_CPU_PREFIX"%d", cpu); - offset++; - - // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(&(stats[offset]), v.n_drops_buffer + v.n_drops_scratch_map + v.n_drops_pf + v.n_drops_bug, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_CPU_PREFIX"%d", cpu); - offset++; - } - } - /* LIBBPF STATS */ /* At the time of writing (Apr 2, 2023) libbpf stats are only available on a per program granularity. diff --git a/userspace/libscap/engine/kmod/scap_kmod.c b/userspace/libscap/engine/kmod/scap_kmod.c index 3024ac50b7..45a27fb95d 100644 --- a/userspace/libscap/engine/kmod/scap_kmod.c +++ b/userspace/libscap/engine/kmod/scap_kmod.c @@ -40,7 +40,7 @@ limitations under the License. #include static const char * const kmod_kernel_counters_stats_names[] = { - [KMOD_N_EVTS] = "n_evts", + [KMOD_N_EVTS] = N_EVENTS_PREFIX, [KMOD_N_DROPS_BUFFER_TOTAL] = "n_drops_buffer_total", [KMOD_N_DROPS_BUFFER_CLONE_FORK_ENTER] = "n_drops_buffer_clone_fork_enter", [KMOD_N_DROPS_BUFFER_CLONE_FORK_EXIT] = "n_drops_buffer_clone_fork_exit", @@ -666,7 +666,6 @@ const struct metrics_v2* scap_kmod_get_stats_v2(struct scap_engine_handle engine dev->m_bufinfo->n_drops_pf; stats[KMOD_N_PREEMPTIONS].value.u64 += dev->m_bufinfo->n_preemptions; - // This is just a way to avoid the double loop on the number of devices. if((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU)) { // We set the num events for that CPU. @@ -683,28 +682,6 @@ const struct metrics_v2* scap_kmod_get_stats_v2(struct scap_engine_handle engine offset = pos; } - /* KERNEL COUNTERS PER CPU STATS - * The following `if` handle the case in which we want to get the metrics per CPU but not the global ones. - * It is an unsual case but at the moment we support it. - */ - if ((flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) && !(flags & METRICS_V2_KERNEL_COUNTERS)) - { - for(uint32_t j = 0; j < devset->m_ndevs; j++) - { - struct scap_device *dev = &devset->m_devs[j]; - - // We set the num events for that CPU. - set_u64_monotonic_kernel_counter(&(stats[offset]), dev->m_bufinfo->n_evts, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(stats[offset].name, METRIC_NAME_MAX, N_EVENTS_PER_DEVICE_PREFIX"%d", j); - offset++; - - // We set the drops for that CPU. - set_u64_monotonic_kernel_counter(&(stats[offset]), dev->m_bufinfo->n_drops_buffer + dev->m_bufinfo->n_drops_pf, METRICS_V2_KERNEL_COUNTERS_PER_CPU); - snprintf(stats[offset].name, METRIC_NAME_MAX, N_DROPS_PER_DEVICE_PREFIX"%d", j); - offset++; - } - } - *nstats = offset; *rc = SCAP_SUCCESS; return stats; diff --git a/userspace/libscap/metrics_v2.h b/userspace/libscap/metrics_v2.h index 3f952155fa..15ca28df31 100644 --- a/userspace/libscap/metrics_v2.h +++ b/userspace/libscap/metrics_v2.h @@ -30,6 +30,11 @@ extern "C" { // #define METRIC_NAME_MAX 512 +// +// Prefix name for n_evts metric (Used by all drivers) +// +#define N_EVENTS_PREFIX "n_evts" + // // Prefix names for per-CPU metrics (Used by legacy ebpf and modern ebpf) // diff --git a/userspace/libscap/scap.c b/userspace/libscap/scap.c index 6a143dd8d1..fb5e05500d 100644 --- a/userspace/libscap/scap.c +++ b/userspace/libscap/scap.c @@ -302,6 +302,12 @@ int32_t scap_get_stats(scap_t* handle, scap_stats* stats) // const struct metrics_v2* scap_get_stats_v2(scap_t* handle, uint32_t flags, uint32_t* nstats, int32_t* rc) { + // If we enable per-cpu counters, we also enable kernel global counters by default. + if(flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU) + { + flags |= METRICS_V2_KERNEL_COUNTERS; + } + if(handle && handle->m_vtable) { return handle->m_vtable->get_stats_v2(handle->m_engine, flags, nstats, rc); diff --git a/userspace/libsinsp/metrics_collector.cpp b/userspace/libsinsp/metrics_collector.cpp index 164dbc5011..1ff68279d6 100644 --- a/userspace/libsinsp/metrics_collector.cpp +++ b/userspace/libsinsp/metrics_collector.cpp @@ -696,7 +696,7 @@ void libs_metrics_collector::snapshot() * libscap metrics */ - if((m_metrics_flags & METRICS_V2_KERNEL_COUNTERS) || (m_metrics_flags & METRICS_V2_LIBBPF_STATS)) + if((m_metrics_flags & METRICS_V2_KERNEL_COUNTERS) || (m_metrics_flags & METRICS_V2_LIBBPF_STATS) || (m_metrics_flags & METRICS_V2_KERNEL_COUNTERS_PER_CPU)) { uint32_t nstats = 0; int32_t rc = 0; diff --git a/userspace/libsinsp/metrics_collector.h b/userspace/libsinsp/metrics_collector.h index 4852cad40c..654081336b 100644 --- a/userspace/libsinsp/metrics_collector.h +++ b/userspace/libsinsp/metrics_collector.h @@ -339,7 +339,7 @@ class libs_metrics_collector private: sinsp* m_inspector; std::shared_ptr m_sinsp_stats_v2; - uint32_t m_metrics_flags = METRICS_V2_KERNEL_COUNTERS | METRICS_V2_LIBBPF_STATS | METRICS_V2_RESOURCE_UTILIZATION | METRICS_V2_STATE_COUNTERS | METRICS_V2_PLUGINS; + uint32_t m_metrics_flags = METRICS_V2_KERNEL_COUNTERS | METRICS_V2_LIBBPF_STATS | METRICS_V2_RESOURCE_UTILIZATION | METRICS_V2_STATE_COUNTERS | METRICS_V2_PLUGINS | METRICS_V2_KERNEL_COUNTERS_PER_CPU; std::vector m_metrics; }; From 2300299c0927a924338f9cb2f13b5bf8e4fbdf13 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Thu, 29 Aug 2024 10:49:22 +0200 Subject: [PATCH 4/6] docs(libscap): add a comment Signed-off-by: Andrea Terzolo Co-authored-by: Federico Di Pierro --- userspace/libscap/metrics_v2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userspace/libscap/metrics_v2.h b/userspace/libscap/metrics_v2.h index 15ca28df31..896ed16709 100644 --- a/userspace/libscap/metrics_v2.h +++ b/userspace/libscap/metrics_v2.h @@ -57,7 +57,7 @@ extern "C" { #define METRICS_V2_RULE_COUNTERS (1 << 4) #define METRICS_V2_MISC (1 << 5) #define METRICS_V2_PLUGINS (1 << 6) -#define METRICS_V2_KERNEL_COUNTERS_PER_CPU (1 << 7) +#define METRICS_V2_KERNEL_COUNTERS_PER_CPU (1 << 7) // Requesting this does also silently enable METRICS_V2_KERNEL_COUNTERS typedef union metrics_v2_value { uint32_t u32; From c27ef9cc245e6f0ac17501be903ef6197adc57eb Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 3 Sep 2024 08:59:14 +0200 Subject: [PATCH 5/6] cleanup: rename a parameter Signed-off-by: Andrea Terzolo Co-authored-by: Melissa Kilby --- userspace/libpman/src/stats.c | 4 ++-- userspace/libscap/engine/bpf/scap_bpf.c | 4 ++-- userspace/libscap/engine/kmod/scap_kmod.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/userspace/libpman/src/stats.c b/userspace/libpman/src/stats.c index 8c2dc66d3e..9fe241aea7 100644 --- a/userspace/libpman/src/stats.c +++ b/userspace/libpman/src/stats.c @@ -140,10 +140,10 @@ int pman_get_scap_stats(struct scap_stats *stats) return errno; } -static void set_u64_monotonic_kernel_counter(uint32_t pos, uint64_t val, uint32_t metric_type) +static void set_u64_monotonic_kernel_counter(uint32_t pos, uint64_t val, uint32_t metric_flag) { g_state.stats[pos].type = METRIC_VALUE_TYPE_U64; - g_state.stats[pos].flags = metric_type; + g_state.stats[pos].flags = metric_flag; g_state.stats[pos].unit = METRIC_VALUE_UNIT_COUNT; g_state.stats[pos].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; g_state.stats[pos].value.u64 = val; diff --git a/userspace/libscap/engine/bpf/scap_bpf.c b/userspace/libscap/engine/bpf/scap_bpf.c index 7cb0a5a107..f3c389426f 100644 --- a/userspace/libscap/engine/bpf/scap_bpf.c +++ b/userspace/libscap/engine/bpf/scap_bpf.c @@ -1688,10 +1688,10 @@ int32_t scap_bpf_get_stats(struct scap_engine_handle engine, scap_stats* stats) return SCAP_SUCCESS; } -static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_type) +static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_flag) { m->type = METRIC_VALUE_TYPE_U64; - m->flags = metric_type; + m->flags = metric_flag; m->unit = METRIC_VALUE_UNIT_COUNT; m->metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; m->value.u64 = val; diff --git a/userspace/libscap/engine/kmod/scap_kmod.c b/userspace/libscap/engine/kmod/scap_kmod.c index 45a27fb95d..3622781987 100644 --- a/userspace/libscap/engine/kmod/scap_kmod.c +++ b/userspace/libscap/engine/kmod/scap_kmod.c @@ -586,10 +586,10 @@ int32_t scap_kmod_get_stats(struct scap_engine_handle engine, scap_stats* stats) return SCAP_SUCCESS; } -static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_type) +static void set_u64_monotonic_kernel_counter(struct metrics_v2* m, uint64_t val, uint32_t metric_flag) { m->type = METRIC_VALUE_TYPE_U64; - m->flags = metric_type; + m->flags = metric_flag; m->unit = METRIC_VALUE_UNIT_COUNT; m->metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; m->value.u64 = val; From 6aaec6c729e29f434b2caf00da27a9f73b4215a3 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 3 Sep 2024 10:36:50 +0200 Subject: [PATCH 6/6] fix: use correct index for libbpf stats Signed-off-by: Andrea Terzolo Co-authored-by: Melissa Kilby --- userspace/libpman/src/stats.c | 16 +++++++--------- userspace/libscap/engine/bpf/scap_bpf.c | 4 +--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/userspace/libpman/src/stats.c b/userspace/libpman/src/stats.c index 9fe241aea7..9d4bd16001 100644 --- a/userspace/libpman/src/stats.c +++ b/userspace/libpman/src/stats.c @@ -292,24 +292,22 @@ struct metrics_v2 *pman_get_metrics_v2(uint32_t flags, uint32_t *nstats, int32_t g_state.stats[offset].type = METRIC_VALUE_TYPE_U64; g_state.stats[offset].flags = METRICS_V2_LIBBPF_STATS; strlcpy(g_state.stats[offset].name, info.name, METRIC_NAME_MAX); + strlcat(g_state.stats[offset].name, modern_bpf_libbpf_stats_names[stat], sizeof(g_state.stats[offset].name)); switch(stat) { case RUN_CNT: - strlcat(g_state.stats[offset].name, modern_bpf_libbpf_stats_names[RUN_CNT], sizeof(g_state.stats[offset].name)); - g_state.stats[stat].unit = METRIC_VALUE_UNIT_COUNT; - g_state.stats[stat].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; + g_state.stats[offset].unit = METRIC_VALUE_UNIT_COUNT; + g_state.stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; g_state.stats[offset].value.u64 = info.run_cnt; break; case RUN_TIME_NS: - strlcat(g_state.stats[offset].name, modern_bpf_libbpf_stats_names[RUN_TIME_NS], sizeof(g_state.stats[offset].name)); - g_state.stats[stat].unit = METRIC_VALUE_UNIT_TIME_NS_COUNT; - g_state.stats[stat].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; + g_state.stats[offset].unit = METRIC_VALUE_UNIT_TIME_NS_COUNT; + g_state.stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; g_state.stats[offset].value.u64 = info.run_time_ns; break; case AVG_TIME_NS: - strlcat(g_state.stats[offset].name, modern_bpf_libbpf_stats_names[AVG_TIME_NS], sizeof(g_state.stats[offset].name)); - g_state.stats[stat].unit = METRIC_VALUE_UNIT_TIME_NS; - g_state.stats[stat].metric_type = METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT; + g_state.stats[offset].unit = METRIC_VALUE_UNIT_TIME_NS; + g_state.stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT; g_state.stats[offset].value.u64 = 0; if(info.run_cnt > 0) { diff --git a/userspace/libscap/engine/bpf/scap_bpf.c b/userspace/libscap/engine/bpf/scap_bpf.c index f3c389426f..f814072f57 100644 --- a/userspace/libscap/engine/bpf/scap_bpf.c +++ b/userspace/libscap/engine/bpf/scap_bpf.c @@ -1856,22 +1856,20 @@ const struct metrics_v2* scap_bpf_get_stats_v2(struct scap_engine_handle engine, { strlcpy(stats[offset].name, info.name, METRIC_NAME_MAX); } + strlcat(stats[offset].name, bpf_libbpf_stats_names[stat], sizeof(stats[offset].name)); switch(stat) { case RUN_CNT: - strlcat(stats[offset].name, bpf_libbpf_stats_names[RUN_CNT], sizeof(stats[offset].name)); stats[offset].value.u64 = info.run_cnt; stats[offset].unit = METRIC_VALUE_UNIT_COUNT; stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; break; case RUN_TIME_NS: - strlcat(stats[offset].name, bpf_libbpf_stats_names[RUN_TIME_NS], sizeof(stats[offset].name)); stats[offset].value.u64 = info.run_time_ns; stats[offset].unit = METRIC_VALUE_UNIT_TIME_NS_COUNT; stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_MONOTONIC; break; case AVG_TIME_NS: - strlcat(stats[offset].name, bpf_libbpf_stats_names[AVG_TIME_NS], sizeof(stats[offset].name)); stats[offset].value.u64 = 0; stats[offset].unit = METRIC_VALUE_UNIT_TIME_NS; stats[offset].metric_type = METRIC_VALUE_METRIC_TYPE_NON_MONOTONIC_CURRENT;