summaryrefslogtreecommitdiffstats
path: root/collectors/ebpf.plugin/ebpf_dcstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/ebpf.plugin/ebpf_dcstat.c')
-rw-r--r--collectors/ebpf.plugin/ebpf_dcstat.c224
1 files changed, 216 insertions, 8 deletions
diff --git a/collectors/ebpf.plugin/ebpf_dcstat.c b/collectors/ebpf.plugin/ebpf_dcstat.c
index fba87007..619d8520 100644
--- a/collectors/ebpf.plugin/ebpf_dcstat.c
+++ b/collectors/ebpf.plugin/ebpf_dcstat.c
@@ -49,6 +49,179 @@ static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_look
.retprobe = CONFIG_BOOLEAN_NO},
{.program_name = NULL}};
+netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOAD_TRAMPOLINE},
+ {.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
+
+#ifdef LIBBPF_MAJOR_VERSION
+#include "includes/dc.skel.h" // BTF code
+
+static struct dc_bpf *bpf_obj = NULL;
+
+/**
+ * Disable probe
+ *
+ * Disable all probes to use exclusively another method.
+ *
+ * @param obj is the main structure for bpf objects
+ */
+static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
+{
+ bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
+ bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
+}
+
+/*
+ * Disable trampoline
+ *
+ * Disable all trampoline to use exclusively another method.
+ *
+ * @param obj is the main structure for bpf objects.
+ */
+static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
+{
+ bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
+ bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
+}
+
+/**
+ * Set trampoline target
+ *
+ * Set the targets we will monitor.
+ *
+ * @param obj is the main structure for bpf objects.
+ */
+static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
+{
+ bpf_program__set_attach_target(obj->progs.netdata_lookup_fast_fentry, 0,
+ dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name);
+
+ bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
+ dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
+}
+
+/**
+ * Mount Attach Probe
+ *
+ * Attach probes to target
+ *
+ * @param obj is the main structure for bpf objects.
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+static int ebpf_dc_attach_probes(struct dc_bpf *obj)
+{
+ obj->links.netdata_d_lookup_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_d_lookup_kretprobe,
+ true,
+ dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
+ int ret = libbpf_get_error(obj->links.netdata_d_lookup_kretprobe);
+ if (ret)
+ return -1;
+
+ char *lookup_name = (dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional) ?
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional :
+ dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name ;
+
+ obj->links.netdata_lookup_fast_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_lookup_fast_kprobe,
+ false,
+ lookup_name);
+ ret = libbpf_get_error(obj->links.netdata_lookup_fast_kprobe);
+ if (ret)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Adjust Map Size
+ *
+ * Resize maps according input from users.
+ *
+ * @param obj is the main structure for bpf objects.
+ * @param em structure with configuration
+ */
+static void ebpf_dc_adjust_map_size(struct dc_bpf *obj, ebpf_module_t *em)
+{
+ ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
+ em, bpf_map__name(obj->maps.dcstat_pid));
+}
+
+/**
+ * Set hash tables
+ *
+ * Set the values for maps according the value given by kernel.
+ *
+ * @param obj is the main structure for bpf objects.
+ */
+static void ebpf_dc_set_hash_tables(struct dc_bpf *obj)
+{
+ dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_global);
+ dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_pid);
+ dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd = bpf_map__fd(obj->maps.dcstat_ctrl);
+}
+
+/**
+ * Update Load
+ *
+ * For directory cache, some distributions change the function name, and we do not have condition to use
+ * TRAMPOLINE like other functions.
+ *
+ * @param em structure with configuration
+ *
+ * @return When then symbols were not modified, it returns TRAMPOLINE, else it returns RETPROBE.
+ */
+netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
+{
+ if (!strcmp(dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional,
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach))
+ return EBPF_LOAD_TRAMPOLINE;
+
+ if (em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode != EBPF_LOAD_RETPROBE)
+ info("When your kernel was compiled the symbol %s was modified, instead to use `trampoline`, the plugin will use `probes`.",
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach);
+
+ return EBPF_LOAD_RETPROBE;
+}
+
+/**
+ * Load and attach
+ *
+ * Load and attach the eBPF code in kernel.
+ *
+ * @param obj is the main structure for bpf objects.
+ * @param em structure with configuration
+ *
+ * @return it returns 0 on succes and -1 otherwise
+ */
+static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
+{
+ netdata_ebpf_program_loaded_t test = ebpf_dc_update_load(em);
+ if (test == EBPF_LOAD_TRAMPOLINE) {
+ ebpf_dc_disable_probes(obj);
+
+ ebpf_dc_set_trampoline_target(obj);
+ } else {
+ ebpf_dc_disable_trampoline(obj);
+ }
+
+ int ret = dc_bpf__load(obj);
+ if (ret) {
+ return ret;
+ }
+
+ ebpf_dc_adjust_map_size(obj, em);
+
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj);
+ if (!ret) {
+ ebpf_dc_set_hash_tables(obj);
+
+ ebpf_update_controller(dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd, em);
+ }
+
+ return ret;
+}
+#endif
+
/*****************************************************************
*
* COMMON FUNCTIONS
@@ -141,6 +314,10 @@ static void ebpf_dcstat_cleanup(void *ptr)
}
bpf_object__close(objects);
}
+#ifdef LIBBPF_MAJOR_VERSION
+ else if (bpf_obj)
+ dc_bpf__destroy(bpf_obj);
+#endif
}
/*****************************************************************
@@ -937,6 +1114,38 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
*
*****************************************************************/
+/*
+ * Load BPF
+ *
+ * Load BPF files.
+ *
+ * @param em the structure with configuration
+ */
+static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
+{
+ int ret = 0;
+ if (em->load == EBPF_LOAD_LEGACY) {
+ probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
+ if (!probe_links) {
+ ret = -1;
+ }
+ }
+#ifdef LIBBPF_MAJOR_VERSION
+ else {
+ bpf_obj = dc_bpf__open();
+ if (!bpf_obj)
+ ret = -1;
+ else
+ ret = ebpf_dc_load_and_attach(bpf_obj, em);
+ }
+#endif
+
+ if (ret)
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
+
+ return ret;
+}
+
/**
* Directory Cache thread
*
@@ -960,17 +1169,16 @@ void *ebpf_dcstat_thread(void *ptr)
if (!em->enabled)
goto enddcstat;
- ebpf_dcstat_allocate_global_vectors(em->apps_charts);
-
- pthread_mutex_lock(&lock);
-
- probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
- if (!probe_links) {
- pthread_mutex_unlock(&lock);
+#ifdef LIBBPF_MAJOR_VERSION
+ ebpf_adjust_thread_load(em, default_btf);
+#endif
+ if (ebpf_dcstat_load_bpf(em)) {
em->enabled = CONFIG_BOOLEAN_NO;
goto enddcstat;
}
+ ebpf_dcstat_allocate_global_vectors(em->apps_charts);
+
int algorithms[NETDATA_DCSTAT_IDX_END] = {
NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
NETDATA_EBPF_ABSOLUTE_IDX
@@ -980,9 +1188,9 @@ void *ebpf_dcstat_thread(void *ptr)
dcstat_counter_dimension_name, dcstat_counter_dimension_name,
algorithms, NETDATA_DCSTAT_IDX_END);
+ pthread_mutex_lock(&lock);
ebpf_create_filesystem_charts(em->update_every);
ebpf_update_stats(&plugin_statistics, em);
-
pthread_mutex_unlock(&lock);
dcstat_collector(em);