summaryrefslogtreecommitdiffstats
path: root/libnetdata/ebpf
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/ebpf')
-rw-r--r--libnetdata/ebpf/ebpf.c78
-rw-r--r--libnetdata/ebpf/ebpf.h44
2 files changed, 82 insertions, 40 deletions
diff --git a/libnetdata/ebpf/ebpf.c b/libnetdata/ebpf/ebpf.c
index b980d09e..6793f403 100644
--- a/libnetdata/ebpf/ebpf.c
+++ b/libnetdata/ebpf/ebpf.c
@@ -44,7 +44,6 @@ static int clean_kprobe_event(FILE *out, char *filename, char *father_pid, netda
int clean_kprobe_events(FILE *out, int pid, netdata_ebpf_events_t *ptr)
{
- debug(D_EXIT, "Cleaning parent process events.");
char filename[FILENAME_MAX + 1];
snprintf(filename, FILENAME_MAX, "%s%s", NETDATA_DEBUGFS, "kprobe_events");
@@ -183,7 +182,7 @@ static int kernel_is_rejected()
if (read_file("/proc/version", version_string, VERSION_STRING_LEN)) {
struct utsname uname_buf;
if (!uname(&uname_buf)) {
- info("Cannot check kernel version");
+ netdata_log_info("Cannot check kernel version");
return 0;
}
version_string_len =
@@ -230,7 +229,7 @@ static int kernel_is_rejected()
while ((reject_string_len = getline(&reject_string, &buf_len, kernel_reject_list) - 1) > 0) {
if (version_string_len >= reject_string_len) {
if (!strncmp(version_string, reject_string, reject_string_len)) {
- info("A buggy kernel is detected");
+ netdata_log_info("A buggy kernel is detected");
fclose(kernel_reject_list);
freez(reject_string);
return 1;
@@ -392,9 +391,10 @@ static void ebpf_mount_name(char *out, size_t len, char *path, uint32_t kver, co
* Count the information from targets.
*
* @param report the output structure
- * @param targets vector with information about the eBPF plugin.
+ * @param targets vector with information about the eBPF plugin.
+ * @param value factor used to update calculation
*/
-static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets_t *targets)
+static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets_t *targets, int value)
{
if (!targets) {
report->probes = report->tracepoints = report->trampolines = 0;
@@ -405,19 +405,19 @@ static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets
while (targets[i].name) {
switch (targets[i].mode) {
case EBPF_LOAD_PROBE: {
- report->probes++;
+ report->probes += value;
break;
}
case EBPF_LOAD_RETPROBE: {
- report->retprobes++;
+ report->retprobes += value;
break;
}
case EBPF_LOAD_TRACEPOINT: {
- report->tracepoints++;
+ report->tracepoints += value;
break;
}
case EBPF_LOAD_TRAMPOLINE: {
- report->trampolines++;
+ report->trampolines += value;
break;
}
}
@@ -438,27 +438,30 @@ static void ebpf_stats_targets(ebpf_plugin_stats_t *report, netdata_ebpf_targets
*/
void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
{
- report->threads++;
+ int value;
// It is not necessary to report more information.
- if (em->enabled != NETDATA_THREAD_EBPF_RUNNING)
- return;
+ if (em->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING)
+ value = -1;
+ else
+ value = 1;
- report->running++;
+ report->threads += value;
+ report->running += value;
// In theory the `else if` is useless, because when this function is called, the module should not stay in
// EBPF_LOAD_PLAY_DICE. We have this additional condition to detect errors from developers.
if (em->load & EBPF_LOAD_LEGACY)
- report->legacy++;
+ report->legacy += value;
else if (em->load & EBPF_LOAD_CORE)
- report->core++;
+ report->core += value;
if (em->maps_per_core)
- report->hash_percpu++;
+ report->hash_percpu += value;
else
- report->hash_unique++;
+ report->hash_unique += value;
- ebpf_stats_targets(report, em->targets);
+ ebpf_stats_targets(report, em->targets, value);
}
/**
@@ -477,7 +480,7 @@ void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *m
snprintfz(filename, FILENAME_MAX, "/proc/self/fdinfo/%d", map->map_fd);
procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) {
- error("Cannot open %s", filename);
+ netdata_log_error("Cannot open %s", filename);
return;
}
@@ -496,7 +499,7 @@ void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *m
report->memlock_kern += memsize;
report->hash_tables += 1;
#ifdef NETDATA_DEV_MODE
- info("Hash table %u: %s (FD = %d) is consuming %lu bytes totalizing %lu bytes",
+ netdata_log_info("Hash table %u: %s (FD = %d) is consuming %lu bytes totalizing %lu bytes",
report->hash_tables, map->name, map->map_fd, memsize, report->memlock_kern);
#endif
break;
@@ -505,7 +508,7 @@ void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *m
report->memlock_kern -= memsize;
report->hash_tables -= 1;
#ifdef NETDATA_DEV_MODE
- info("Hash table %s (FD = %d) was removed releasing %lu bytes, now we have %u tables loaded totalizing %lu bytes.",
+ netdata_log_info("Hash table %s (FD = %d) was removed releasing %lu bytes, now we have %u tables loaded totalizing %lu bytes.",
map->name, map->map_fd, memsize, report->hash_tables, report->memlock_kern);
#endif
break;
@@ -529,8 +532,11 @@ void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *m
*
* @param report the output structure
* @param map pointer to a map. Last map must fish with name = NULL
+ * @param action should plugin add or remove values from amount.
*/
-void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps)
+void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report,
+ ebpf_local_maps_t *maps,
+ ebpf_stats_action_t action)
{
if (!maps)
return;
@@ -542,7 +548,7 @@ void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_loc
if (fd == ND_EBPF_MAP_FD_NOT_INITIALIZED)
continue;
- ebpf_update_kernel_memory(report, map, EBPF_ACTION_STAT_ADD);
+ ebpf_update_kernel_memory(report, map, action);
}
}
@@ -570,7 +576,7 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
if (lmap->user_input && lmap->user_input != lmap->internal_input) {
define_size = lmap->internal_input;
#ifdef NETDATA_INTERNAL_CHECKS
- info("Changing map %s from size %u to %u ", map_name, lmap->internal_input, lmap->user_input);
+ netdata_log_info("Changing map %s from size %u to %u ", map_name, lmap->internal_input, lmap->user_input);
#endif
} else if (((lmap->type & apps_type) == apps_type) && (!em->apps_charts) && (!em->cgroup_charts)) {
lmap->user_input = ND_EBPF_DEFAULT_MIN_PID;
@@ -613,7 +619,7 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w)
{
if (bpf_map__set_type(map, w->map_type)) {
- error("Cannot modify map type for %s", w->name);
+ netdata_log_error("Cannot modify map type for %s", w->name);
}
}
@@ -794,7 +800,7 @@ void ebpf_update_controller(int fd, ebpf_module_t *em)
for (key = NETDATA_CONTROLLER_APPS_ENABLED; key < end; key++) {
int ret = bpf_map_update_elem(fd, &key, &values[key], 0);
if (ret)
- error("Add key(%u) for controller table failed.", key);
+ netdata_log_error("Add key(%u) for controller table failed.", key);
}
}
@@ -867,7 +873,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv
ebpf_update_legacy_map(*obj, em);
if (bpf_object__load(*obj)) {
- error("ERROR: loading BPF object file failed %s\n", lpath);
+ netdata_log_error("ERROR: loading BPF object file failed %s\n", lpath);
bpf_object__close(*obj);
return NULL;
}
@@ -878,7 +884,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv
size_t count_programs = ebpf_count_programs(*obj);
#ifdef NETDATA_INTERNAL_CHECKS
- info("eBPF program %s loaded with success!", lpath);
+ netdata_log_info("eBPF program %s loaded with success!", lpath);
#endif
return ebpf_attach_programs(*obj, count_programs, em->names);
@@ -891,7 +897,7 @@ char *ebpf_find_symbol(char *search)
snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS);
procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) {
- error("Cannot open %s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS);
+ netdata_log_error("Cannot open %s%s", netdata_configured_host_prefix, NETDATA_KALLSYMS);
return ret;
}
@@ -1107,7 +1113,7 @@ struct btf *ebpf_load_btf_file(char *path, char *filename)
snprintfz(fullpath, PATH_MAX, "%s/%s", path, filename);
struct btf *ret = ebpf_parse_btf_file(fullpath);
if (!ret)
- info("Your environment does not have BTF file %s/%s. The plugin will work with 'legacy' code.",
+ netdata_log_info("Your environment does not have BTF file %s/%s. The plugin will work with 'legacy' code.",
path, filename);
return ret;
@@ -1239,6 +1245,9 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
modules->pid_map_size);
+ modules->lifetime = (uint32_t) appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION,
+ EBPF_CFG_LIFETIME, EBPF_DEFAULT_LIFETIME);
+
char *value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
char *type_format = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(type_format);
@@ -1259,7 +1268,7 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
modules->maps_per_core = CONFIG_BOOLEAN_NO;
#ifdef NETDATA_DEV_MODE
- info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s",
+ netdata_log_info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s, lifetime=%u",
modules->thread_name,
load_mode,
modules->update_every,
@@ -1268,7 +1277,8 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
type_format,
core_attach,
collect_pid,
- (modules->maps_per_core)?"enabled":"disabled"
+ (modules->maps_per_core)?"enabled":"disabled",
+ modules->lifetime
);
#endif
}
@@ -1295,7 +1305,7 @@ void ebpf_update_module(ebpf_module_t *em, struct btf *btf_file, int kver, int i
if (!ebpf_load_config(em->cfg, filename)) {
ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, em->config_file);
if (!ebpf_load_config(em->cfg, filename)) {
- error("Cannot load the ebpf configuration file %s", em->config_file);
+ netdata_log_error("Cannot load the ebpf configuration file %s", em->config_file);
return;
}
// If user defined data globally, we will have here EBPF_LOADED_FROM_USER, we need to consider this, to avoid
@@ -1512,7 +1522,7 @@ int ebpf_is_tracepoint_enabled(char *subsys, char *eventname)
static int ebpf_change_tracing_values(char *subsys, char *eventname, char *value)
{
if (strcmp("0", value) && strcmp("1", value)) {
- error("Invalid value given to either enable or disable a tracepoint.");
+ netdata_log_error("Invalid value given to either enable or disable a tracepoint.");
return -1;
}
diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h
index e82aaedd..88dbca37 100644
--- a/libnetdata/ebpf/ebpf.h
+++ b/libnetdata/ebpf/ebpf.h
@@ -43,6 +43,7 @@
#define EBPF_CFG_MAPS_PER_CORE "maps per core"
#define EBPF_CFG_UPDATE_EVERY "update every"
+#define EBPF_CFG_LIFETIME "lifetime"
#define EBPF_CFG_UPDATE_APPS_EVERY_DEFAULT 10
#define EBPF_CFG_PID_SIZE "pid table size"
#define EBPF_CFG_APPLICATION "apps"
@@ -270,15 +271,17 @@ typedef enum netdata_apps_integration_flags {
#define NETDATA_EBPF_STAT_DIMENSION_ARAL "aral"
enum ebpf_threads_status {
- NETDATA_THREAD_EBPF_RUNNING,
- NETDATA_THREAD_EBPF_STOPPING,
- NETDATA_THREAD_EBPF_STOPPED,
- NETDATA_THREAD_EBPF_NOT_RUNNING
+ NETDATA_THREAD_EBPF_RUNNING, // started by plugin
+ NETDATA_THREAD_EBPF_FUNCTION_RUNNING, // started by function
+ NETDATA_THREAD_EBPF_STOPPING, // stopping thread
+ NETDATA_THREAD_EBPF_STOPPED, // thread stopped
+ NETDATA_THREAD_EBPF_NOT_RUNNING // thread was never started
};
typedef struct ebpf_module {
const char *thread_name;
const char *config_name;
+ const char *thread_description;
enum ebpf_threads_status enabled;
void *(*start_routine)(void *);
int update_every;
@@ -306,8 +309,16 @@ typedef struct ebpf_module {
char memory_usage[NETDATA_EBPF_CHART_MEM_LENGTH];
char memory_allocations[NETDATA_EBPF_CHART_MEM_LENGTH];
int maps_per_core;
+
+ // period to run
+ uint32_t running_time; // internal usage, this is used to reset a value when a new request happens.
+ uint32_t lifetime;
} ebpf_module_t;
+#define EBPF_DEFAULT_LIFETIME 300
+// This will be present until all functions are merged
+#define EBPF_NON_FUNCTION_LIFE_TIME 86400
+
int ebpf_get_kernel_version();
int get_redhat_release();
int has_condition_to_run(int version);
@@ -336,10 +347,21 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
typedef struct netdata_ebpf_histogram {
char *name;
char *title;
+ char *ctx;
int order;
uint64_t histogram[NETDATA_EBPF_HIST_MAX_BINS];
} netdata_ebpf_histogram_t;
+enum fs_btf_counters {
+ NETDATA_KEY_BTF_READ,
+ NETDATA_KEY_BTF_WRITE,
+ NETDATA_KEY_BTF_OPEN,
+ NETDATA_KEY_BTF_SYNC_ATTR,
+ NETDATA_KEY_BTF_OPEN2,
+
+ NETDATA_FS_BTF_END
+};
+
typedef struct ebpf_filesystem_partitions {
char *filesystem;
char *optional_filesystem;
@@ -359,6 +381,14 @@ typedef struct ebpf_filesystem_partitions {
ebpf_addresses_t addresses;
uint64_t kernels;
ebpf_local_maps_t *fs_maps;
+
+ // BPF structure
+#ifdef LIBBPF_MAJOR_VERSION
+ struct filesystem_bpf *fs_obj;
+#else
+ void *fs_obj;
+#endif
+ const char *functions[NETDATA_FS_BTF_END];
} ebpf_filesystem_partitions_t;
typedef struct ebpf_sync_syscalls {
@@ -407,9 +437,11 @@ void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w);
void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver);
#endif
-void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps);
+void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps,
+ ebpf_stats_action_t action);
void ebpf_update_kernel_memory(ebpf_plugin_stats_t *report, ebpf_local_maps_t *map, ebpf_stats_action_t action);
-void ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em);
+int ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em);
+void ebpf_statistic_obsolete_aral_chart(ebpf_module_t *em, int prio);
void ebpf_send_data_aral_chart(ARAL *memory, ebpf_module_t *em);
#endif /* NETDATA_EBPF_H */