summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthiagoftsm <thiagoftsm@gmail.com>2023-07-06 12:03:16 +0000
committerGitHub <noreply@github.com>2023-07-06 12:03:16 +0000
commitc805baef80d53cba5a10e77448e973f2cc61ca1e (patch)
treed88de3a1258c71a9e0d1b9287a922d25f40aedd9
parent6526a34f86e646610eed4a26215f5b40dfe718ab (diff)
Additional CO-RE code (eBPF.plugin) (#15078)
-rw-r--r--collectors/ebpf.plugin/ebpf.c47
-rw-r--r--collectors/ebpf.plugin/ebpf.h6
-rw-r--r--collectors/ebpf.plugin/ebpf_disk.c76
-rw-r--r--collectors/ebpf.plugin/ebpf_disk.h5
-rw-r--r--collectors/ebpf.plugin/ebpf_filesystem.c226
-rw-r--r--collectors/ebpf.plugin/ebpf_filesystem.h3
-rw-r--r--collectors/ebpf.plugin/ebpf_hardirq.c70
-rw-r--r--collectors/ebpf.plugin/ebpf_hardirq.h5
-rw-r--r--collectors/ebpf.plugin/ebpf_mdflush.c139
-rw-r--r--collectors/ebpf.plugin/ebpf_mdflush.h7
-rw-r--r--libnetdata/ebpf/ebpf.h18
11 files changed, 576 insertions, 26 deletions
diff --git a/collectors/ebpf.plugin/ebpf.c b/collectors/ebpf.plugin/ebpf.c
index d4f51992e2..a9afad803e 100644
--- a/collectors/ebpf.plugin/ebpf.c
+++ b/collectors/ebpf.plugin/ebpf.c
@@ -186,7 +186,7 @@ ebpf_module_t ebpf_modules[] = {
.apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
.config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
- .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
+ .load = EBPF_LOAD_LEGACY, .targets = mdflush_targets, .probe_links = NULL, .objects = NULL,
.thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
{ .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
.global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .apps_level = NETDATA_APPS_NOT_SET,
@@ -378,7 +378,13 @@ ebpf_filesystem_partitions_t localfs[] =
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = NULL, .addr = 0},
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
- .fs_maps = NULL},
+ .fs_maps = NULL,
+ .fs_obj = NULL,
+ .functions = { "ext4_file_read_iter",
+ "ext4_file_write_iter",
+ "ext4_file_open",
+ "ext4_sync_file",
+ NULL }},
{.filesystem = "xfs",
.optional_filesystem = NULL,
.family = "xfs",
@@ -388,7 +394,13 @@ ebpf_filesystem_partitions_t localfs[] =
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = NULL, .addr = 0},
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
- .fs_maps = NULL},
+ .fs_maps = NULL,
+ .fs_obj = NULL,
+ .functions = { "xfs_file_read_iter",
+ "xfs_file_write_iter",
+ "xfs_file_open",
+ "xfs_file_fsync",
+ NULL }},
{.filesystem = "nfs",
.optional_filesystem = "nfs4",
.family = "nfs",
@@ -398,7 +410,13 @@ ebpf_filesystem_partitions_t localfs[] =
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = NULL, .addr = 0},
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
- .fs_maps = NULL},
+ .fs_maps = NULL,
+ .fs_obj = NULL,
+ .functions = { "nfs_file_read",
+ "nfs_file_write",
+ "nfs_open",
+ "nfs_getattr",
+ NULL }}, // // "nfs4_file_open" - not present on all kernels
{.filesystem = "zfs",
.optional_filesystem = NULL,
.family = "zfs",
@@ -408,7 +426,13 @@ ebpf_filesystem_partitions_t localfs[] =
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = NULL, .addr = 0},
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
- .fs_maps = NULL},
+ .fs_maps = NULL,
+ .fs_obj = NULL,
+ .functions = { "zpl_iter_read",
+ "zpl_iter_write",
+ "zpl_open",
+ "zpl_fsync",
+ NULL }},
{.filesystem = "btrfs",
.optional_filesystem = NULL,
.family = "btrfs",
@@ -418,7 +442,13 @@ ebpf_filesystem_partitions_t localfs[] =
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = "btrfs_file_operations", .addr = 0},
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10,
- .fs_maps = NULL},
+ .fs_maps = NULL,
+ .fs_obj = NULL,
+ .functions = { "btrfs_file_read_iter",
+ "btrfs_file_write_iter",
+ "btrfs_file_open",
+ "btrfs_sync_file",
+ NULL }},
{.filesystem = NULL,
.optional_filesystem = NULL,
.family = NULL,
@@ -427,7 +457,7 @@ ebpf_filesystem_partitions_t localfs[] =
.flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
.enabled = CONFIG_BOOLEAN_YES,
.addresses = {.function = NULL, .addr = 0},
- .kernels = 0, .fs_maps = NULL}};
+ .kernels = 0, .fs_maps = NULL, .fs_obj = NULL}};
ebpf_sync_syscalls_t local_syscalls[] = {
{.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
@@ -493,7 +523,10 @@ ebpf_plugin_stats_t plugin_statistics = {.core = 0, .legacy = 0, .running = 0, .
struct btf *default_btf = NULL;
struct cachestat_bpf *cachestat_bpf_obj = NULL;
struct dc_bpf *dc_bpf_obj = NULL;
+struct disk_bpf *disk_bpf_obj = NULL;
struct fd_bpf *fd_bpf_obj = NULL;
+struct hardirq_bpf *hardirq_bpf_obj = NULL;
+struct mdflush_bpf *mdflush_bpf_obj = NULL;
struct mount_bpf *mount_bpf_obj = NULL;
struct shm_bpf *shm_bpf_obj = NULL;
struct socket_bpf *socket_bpf_obj = NULL;
diff --git a/collectors/ebpf.plugin/ebpf.h b/collectors/ebpf.plugin/ebpf.h
index ae24c302c5..a8a2f27a92 100644
--- a/collectors/ebpf.plugin/ebpf.h
+++ b/collectors/ebpf.plugin/ebpf.h
@@ -39,7 +39,10 @@
#ifdef LIBBPF_MAJOR_VERSION // BTF code
#include "includes/cachestat.skel.h"
#include "includes/dc.skel.h"
+#include "includes/disk.skel.h"
#include "includes/fd.skel.h"
+#include "includes/hardirq.skel.h"
+#include "includes/mdflush.skel.h"
#include "includes/mount.skel.h"
#include "includes/shm.skel.h"
#include "includes/socket.skel.h"
@@ -48,8 +51,11 @@
extern struct cachestat_bpf *cachestat_bpf_obj;
extern struct dc_bpf *dc_bpf_obj;
+extern struct disk_bpf *disk_bpf_obj;
extern struct fd_bpf *fd_bpf_obj;
+extern struct hardirq_bpf *hardirq_bpf_obj;
extern struct mount_bpf *mount_bpf_obj;
+extern struct mdflush_bpf *mdflush_bpf_obj;
extern struct shm_bpf *shm_bpf_obj;
extern struct socket_bpf *socket_bpf_obj;
extern struct swap_bpf *bpf_obj;
diff --git a/collectors/ebpf.plugin/ebpf_disk.c b/collectors/ebpf.plugin/ebpf_disk.c
index 0e2b6154bc..026e44ec89 100644
--- a/collectors/ebpf.plugin/ebpf_disk.c
+++ b/collectors/ebpf.plugin/ebpf_disk.c
@@ -52,6 +52,39 @@ static netdata_idx_t *disk_hash_values = NULL;
ebpf_publish_disk_t *plot_disks = NULL;
pthread_mutex_t plot_mutex;
+#ifdef LIBBPF_MAJOR_VERSION
+/**
+ * Set hash table
+ *
+ * Set the values for maps according the value given by kernel.
+ *
+ * @param obj is the main structure for bpf objects.
+ */
+static inline void ebpf_disk_set_hash_table(struct disk_bpf *obj)
+ {
+ disk_maps[NETDATA_DISK_IO].map_fd = bpf_map__fd(obj->maps.tbl_disk_iocall);
+ }
+
+/**
+ * Load and attach
+ *
+ * Load and attach the eBPF code in kernel.
+ *
+ * @param obj is the main structure for bpf objects.
+ *
+ * @return it returns 0 on success and -1 otherwise
+ */
+static inline int ebpf_disk_load_and_attach(struct disk_bpf *obj)
+{
+ int ret = disk_bpf__load(obj);
+ if (ret) {
+ return ret;
+ }
+
+ return disk_bpf__attach(obj);
+}
+#endif
+
/*****************************************************************
*
* FUNCTIONS TO MANIPULATE HARD DISKS
@@ -702,7 +735,7 @@ static void disk_collector(ebpf_module_t *em)
continue;
counter = 0;
- read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd, maps_per_core);
+ read_hard_disk_tables(disk_maps[NETDATA_DISK_IO].map_fd, maps_per_core);
pthread_mutex_lock(&lock);
ebpf_remove_pointer_from_plot_disk(em);
ebpf_latency_send_hd_data(update_every);
@@ -749,6 +782,43 @@ static int ebpf_disk_enable_tracepoints()
return 0;
}
+/*
+ * Load BPF
+ *
+ * Load BPF files.
+ *
+ * @param em the structure with configuration
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+static int ebpf_disk_load_bpf(ebpf_module_t *em)
+{
+ int ret = 0;
+ if (em->load & EBPF_LOAD_LEGACY) {
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+ if (!em->probe_links) {
+ ret = -1;
+ }
+ }
+#ifdef LIBBPF_MAJOR_VERSION
+ else {
+ disk_bpf_obj = disk_bpf__open();
+ if (!disk_bpf_obj)
+ ret = -1;
+ else {
+ ret = ebpf_disk_load_and_attach(disk_bpf_obj);
+ if (!ret)
+ ebpf_disk_set_hash_table(disk_bpf_obj);
+ }
+ }
+#endif
+
+ if (ret)
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
+
+ return ret;
+}
+
/**
* Disk thread
*
@@ -781,9 +851,9 @@ void *ebpf_disk_thread(void *ptr)
#ifdef LIBBPF_MAJOR_VERSION
ebpf_define_map_type(disk_maps, em->maps_per_core, running_on_kernel);
+ ebpf_adjust_thread_load(em, default_btf);
#endif
- em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
- if (!em->probe_links) {
+ if (ebpf_disk_load_bpf(em)) {
goto enddisk;
}
diff --git a/collectors/ebpf.plugin/ebpf_disk.h b/collectors/ebpf.plugin/ebpf_disk.h
index 69c7058758..ebe6709ae9 100644
--- a/collectors/ebpf.plugin/ebpf_disk.h
+++ b/collectors/ebpf.plugin/ebpf_disk.h
@@ -54,10 +54,7 @@ typedef struct netdata_ebpf_disks {
struct netdata_ebpf_disks *next;
} netdata_ebpf_disks_t;
-enum ebpf_disk_tables {
- NETDATA_DISK_READ,
- NETDATA_DISK_TMP
-};
+enum ebpf_disk_tables { NETDATA_DISK_IO };
typedef struct block_key {
uint32_t bin;
diff --git a/collectors/ebpf.plugin/ebpf_filesystem.c b/collectors/ebpf.plugin/ebpf_filesystem.c
index a613ec705f..ab39db972b 100644
--- a/collectors/ebpf.plugin/ebpf_filesystem.c
+++ b/collectors/ebpf.plugin/ebpf_filesystem.c
@@ -131,6 +131,202 @@ static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST
char **dimensions = NULL;
static netdata_idx_t *filesystem_hash_values = NULL;
+#ifdef LIBBPF_MAJOR_VERSION
+/**
+ * FS disable kprobe
+ *
+ * Disable kprobes, because system will use trampolines.
+ * We are not calling this function for while, because we are prioritizing kprobes. We opted by this road, because
+ * distribution are still not deliverying necessary btf files per FS.
+ *
+ * @param obj FS object loaded.
+ */
+static void ebpf_fs_disable_kprobe(struct filesystem_bpf *obj)
+ {
+ // kprobe
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_read_probe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_write_probe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_open_probe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_probe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_getattr_probe, false);
+ // kretprobe
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_read_retprobe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_write_retprobe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_open_retprobe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_retprobe, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_getattr_retprobe, false);
+ }
+
+ /**
+ * Disable trampoline
+ *
+ * Disable trampolines to use kprobes.
+ *
+ * @param obj FS object loaded.
+ */
+ static void ebpf_fs_disable_trampoline(struct filesystem_bpf *obj)
+ {
+ // entry
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_read_entry, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_write_entry, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_open_entry, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_getattr_entry, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false);
+
+ // exit
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_read_exit, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_write_exit, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_file_open_exit, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_getattr_exit, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false);
+ }
+
+ /**
+ * Set targets
+ *
+ * Set targets for each objects.
+ *
+ * @param obj FS object loaded.
+ * @param functions array with function names.
+ */
+ static void ebpf_fs_set_target(struct filesystem_bpf *obj, const char **functions)
+{
+ // entry
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_entry, 0,
+ functions[NETDATA_KEY_BTF_READ]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_entry, 0,
+ functions[NETDATA_KEY_BTF_WRITE]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_entry, 0,
+ functions[NETDATA_KEY_BTF_OPEN]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_entry, 0,
+ functions[NETDATA_KEY_BTF_SYNC_ATTR]);
+
+ // exit
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_exit, 0,
+ functions[NETDATA_KEY_BTF_READ]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_exit, 0,
+ functions[NETDATA_KEY_BTF_WRITE]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_exit, 0,
+ functions[NETDATA_KEY_BTF_OPEN]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_exit, 0,
+ functions[NETDATA_KEY_BTF_SYNC_ATTR]);
+
+ if (functions[NETDATA_KEY_BTF_OPEN2]) {
+ bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_entry, 0,
+ functions[NETDATA_KEY_BTF_OPEN2]);
+ bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_exit, 0,
+ functions[NETDATA_KEY_BTF_OPEN2]);
+ } else {
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false);
+ bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false);
+ }
+}
+
+/**
+ * Attach Kprobe
+ *
+ * Attach kprobe on targets
+ *
+ * @param obj FS object loaded.
+ * @param functions array with function names.
+ */
+static int ebpf_fs_attach_kprobe(struct filesystem_bpf *obj, const char **functions)
+{
+ // kprobe
+ obj->links.netdata_fs_file_read_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_probe,
+ false, functions[NETDATA_KEY_BTF_READ]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_read_probe))
+ return -1;
+
+ obj->links.netdata_fs_file_write_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_probe,
+ false, functions[NETDATA_KEY_BTF_WRITE]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_write_probe))
+ return -1;
+
+ obj->links.netdata_fs_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_probe,
+ false, functions[NETDATA_KEY_BTF_OPEN]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_open_probe))
+ return -1;
+
+ obj->links.netdata_fs_getattr_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_probe,
+ false, functions[NETDATA_KEY_BTF_SYNC_ATTR]);
+ if (libbpf_get_error(obj->links.netdata_fs_getattr_probe))
+ return -1;
+
+ // kretprobe
+ obj->links.netdata_fs_file_read_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_retprobe,
+ false, functions[NETDATA_KEY_BTF_READ]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_read_retprobe))
+ return -1;
+
+ obj->links.netdata_fs_file_write_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_retprobe,
+ false, functions[NETDATA_KEY_BTF_WRITE]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_write_retprobe))
+ return -1;
+
+ obj->links.netdata_fs_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_retprobe,
+ false, functions[NETDATA_KEY_BTF_OPEN]);
+ if (libbpf_get_error(obj->links.netdata_fs_file_open_retprobe))
+ return -1;
+
+ obj->links.netdata_fs_getattr_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_retprobe,
+ false, functions[NETDATA_KEY_BTF_SYNC_ATTR]);
+ if (libbpf_get_error(obj->links.netdata_fs_getattr_retprobe))
+ return -1;
+
+ if (functions[NETDATA_KEY_BTF_OPEN2]) {
+ obj->links.netdata_fs_2nd_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_probe,
+ false, functions[NETDATA_KEY_BTF_OPEN2]);
+ if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_probe))
+ return -1;
+
+ obj->links.netdata_fs_2nd_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_retprobe,
+ false, functions[NETDATA_KEY_BTF_OPEN2]);
+ if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_retprobe))
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Load and Attach
+ *
+ * Load binary and attach to targets.
+ *
+ * @param map Structure with information about maps.
+ * @param obj FS object loaded.
+ * @param functions array with function names.
+ * @param bf sttruct with btf file loaded.
+ */
+static inline int ebpf_fs_load_and_attach(ebpf_local_maps_t *map, struct filesystem_bpf *obj,
+ const char **functions, struct btf *bf)
+{
+ if (bf) {
+ ebpf_fs_disable_kprobe(obj);
+ ebpf_fs_set_target(obj, functions);
+ } else {
+ ebpf_fs_disable_trampoline(obj);
+ }
+
+ int ret = filesystem_bpf__load(obj);
+ if (ret) {
+ fprintf(stderr, "failed to load BPF object: %d\n", ret);
+ return -1;
+ }
+
+ if (bf)
+ ret = filesystem_bpf__attach(obj);
+ else
+ ret = ebpf_fs_attach_kprobe(obj, functions);
+
+ if (!ret)
+ map->map_fd = bpf_map__fd(obj->maps.tbl_fs);;
+
+ return ret;
+}
+#endif
+
/*****************************************************************
*
* COMMON FUNCTIONS
@@ -275,13 +471,28 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
#ifdef LIBBPF_MAJOR_VERSION
ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
#endif
- efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
- if (!efp->probe_links) {
- em->thread_name = saved_name;
- em->kernels = kernels;
- em->maps = NULL;
- return -1;
+ if (em->load & EBPF_LOAD_LEGACY) {
+ efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
+ if (!efp->probe_links) {
+ em->thread_name = saved_name;
+ em->kernels = kernels;
+ return -1;
+ }
+ }
+#ifdef LIBBPF_MAJOR_VERSION
+ else {
+ efp->fs_obj = filesystem_bpf__open();
+ if (!efp->fs_obj) {
+ em->thread_name = saved_name;
+ em->kernels = kernels;
+ return -1;
+ } else {
+ if (ebpf_fs_load_and_attach(em->maps, efp->fs_obj,
+ efp->functions, NULL))
+ return -1;
+ }
}
+#endif
efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
pthread_mutex_lock(&lock);
ebpf_update_kernel_memory(&plugin_statistics, efp->fs_maps, EBPF_ACTION_STAT_ADD);
@@ -683,6 +894,9 @@ void *ebpf_filesystem_thread(void *ptr)
// Initialize optional as zero, to identify when there are not partitions to monitor
em->optional = 0;
+#ifdef LIBBPF_MAJOR_VERSION
+ ebpf_adjust_thread_load(em, default_btf);
+#endif
if (ebpf_update_partitions(em)) {
if (em->optional)
netdata_log_info("Netdata cannot monitor the filesystems used on this host.");
diff --git a/collectors/ebpf.plugin/ebpf_filesystem.h b/collectors/ebpf.plugin/ebpf_filesystem.h
index b1126badb6..04c0e74c40 100644
--- a/collectors/ebpf.plugin/ebpf_filesystem.h
+++ b/collectors/ebpf.plugin/ebpf_filesystem.h
@@ -7,6 +7,9 @@
#define NETDATA_EBPF_MODULE_NAME_FILESYSTEM "filesystem"
#include "ebpf.h"
+#ifdef LIBBPF_MAJOR_VERSION
+#include "includes/filesystem.skel.h"
+#endif
#define NETDATA_FS_MAX_DIST_NAME 64UL
diff --git a/collectors/ebpf.plugin/ebpf_hardirq.c b/collectors/ebpf.plugin/ebpf_hardirq.c
index f714c261c0..6dd19e313d 100644
--- a/collectors/ebpf.plugin/ebpf_hardirq.c
+++ b/collectors/ebpf.plugin/ebpf_hardirq.c
@@ -9,8 +9,6 @@ struct config hardirq_config = { .first_section = NULL,
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
-#define HARDIRQ_MAP_LATENCY 0
-#define HARDIRQ_MAP_LATENCY_STATIC 1
static ebpf_local_maps_t hardirq_maps[] = {
{
.name = "tbl_hardirq",
@@ -138,6 +136,36 @@ static hardirq_static_val_t hardirq_static_vals[] = {
// thread will write to netdata agent.
static avl_tree_lock hardirq_pub;
+#ifdef LIBBPF_MAJOR_VERSION
+/**
+ * Set hash table
+ *
+ * Set the values for maps according the value given by kernel.
+ *
+ * @param obj is the main structure for bpf objects.
+ */
+static inline void ebpf_hardirq_set_hash_table(struct hardirq_bpf *obj)
+{
+ hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd = bpf_map__fd(obj->maps.tbl_hardirq);
+ hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd = bpf_map__fd(obj->maps.tbl_hardirq_static);
+}
+
+/**
+ * Load and Attach
+ *
+ * Load and attach bpf software.
+ */
+static inline int ebpf_hardirq_load_and_attach(struct hardirq_bpf *obj)
+{
+ int ret = hardirq_bpf__load(obj);
+ if (ret) {
+ return -1;
+ }
+
+ return hardirq_bpf__attach(obj);
+}
+#endif
+
/*****************************************************************
*
* ARAL SECTION
@@ -540,6 +568,40 @@ static void hardirq_collector(ebpf_module_t *em)
* EBPF HARDIRQ THREAD
*****************************************************************/
+/*
+ * Load BPF
+ *
+ * Load BPF files.
+ *
+ * @param em the structure with configuration
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+static int ebpf_hardirq_load_bpf(ebpf_module_t *em)
+{
+ int ret = 0;
+ if (em->load & EBPF_LOAD_LEGACY) {
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+ if (!em->probe_links) {
+ ret = -1;
+ }
+ }
+#ifdef LIBBPF_MAJOR_VERSION
+ else {
+ hardirq_bpf_obj = hardirq_bpf__open();
+ if (!hardirq_bpf_obj)
+ ret = -1;
+ else {
+ ret = ebpf_hardirq_load_and_attach(hardirq_bpf_obj);
+ if (!ret)
+ ebpf_hardirq_set_hash_table(hardirq_bpf_obj);
+ }
+ }
+#endif
+
+ return ret;
+}
+
/**
* Hard IRQ latency thread.
*
@@ -559,9 +621,9 @@ void *ebpf_hardirq_thread(void *ptr)
#ifdef LIBBPF_MAJOR_VERSION
ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
+ ebpf_adjust_thread_load(em, default_btf);
#endif
- em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
- if (!em->probe_links) {
+ if (ebpf_hardirq_load_bpf(em)) {
goto endhardirq;
}
diff --git a/collectors/ebpf.plugin/ebpf_hardirq.h b/collectors/ebpf.plugin/ebpf_hardirq.h
index 52dea1e560..d727ed3ae5 100644
--- a/collectors/ebpf.plugin/ebpf_hardirq.h
+++ b/collectors/ebpf.plugin/ebpf_hardirq.h
@@ -34,6 +34,11 @@ enum hardirq_ebpf_static {
HARDIRQ_EBPF_STATIC_END
};
+enum hardirq_maps {
+ HARDIRQ_MAP_LATENCY,
+ HARDIRQ_MAP_LATENCY_STATIC
+};
+
typedef struct hardirq_ebpf_static_val {
uint64_t latency;
uint64_t ts;
diff --git a/collectors/ebpf.plugin/ebpf_mdflush.c b/collectors/ebpf.plugin/ebpf_mdflush.c
index 65ed860a46..7179e5e7ce 100644
--- a/collectors/ebpf.plugin/ebpf_mdflush.c
+++ b/collectors/ebpf.plugin/ebpf_mdflush.c
@@ -31,6 +31,10 @@ static ebpf_local_maps_t mdflush_maps[] = {
}
};
+netdata_ebpf_targets_t mdflush_targets[] = { {.name = "md_flush_request", .mode = EBPF_LOAD_TRAMPOLINE},
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
+
+
// store for "published" data from the reader thread, which the collector
// thread will write to netdata agent.
static avl_tree_lock mdflush_pub;
@@ -38,6 +42,93 @@ static avl_tree_lock mdflush_pub;
// tmp store for mdflush values we get from a per-CPU eBPF map.
static mdflush_ebpf_val_t *mdflush_ebpf_vals = NULL;
+#ifdef LIBBPF_MAJOR_VERSION
+/**
+ * Disable probes
+ *
+ * Disable probes to use trampolines.
+ *
+ * @param obj the loaded object structure.
+ */
+static inline void ebpf_disable_probes(struct mdflush_bpf *obj)
+{
+ bpf_program__set_autoload(obj->progs.netdata_md_flush_request_kprobe, false);
+}
+
+/**
+ * Disable trampolines
+ *
+ * Disable trampoliness to use probes.
+ *
+ * @param obj the loaded object structure.
+ */
+static inline void ebpf_disable_trampoline(struct mdflush_bpf *obj)
+{
+ bpf_program__set_autoload(obj->progs.netdata_md_flush_request_fentry, false);
+}
+
+/**
+ * Set Trampoline
+ *
+ * Define target to attach trampoline
+ *
+ * @param obj the loaded object structure.
+ */
+static void ebpf_set_trampoline_target(struct mdflush_bpf *obj)
+{
+ bpf_program__set_attach_target(obj->progs.netdata_md_flush_request_fentry, 0,
+ mdflush_targets[NETDATA_MD_FLUSH_REQUEST].name);
+}
+
+/**
+ * Load probe
+ *
+ * Load probe to monitor internal function.
+ *
+ * @param obj the loaded object structure.
+ */
+static inline int ebpf_load_probes(struct mdflush_bpf *obj)
+{
+ obj->links.netdata_md_flush_request_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_md_flush_request_kprobe,
+ false,
+ mdflush_targets[NETDATA_MD_FLUSH_REQUEST].name);
+ return libbpf_get_error(obj->links.netdata_md_flush_request_kprobe);
+}
+
+/**
+ * Load and Attach
+ *
+ * Load and attach bpf codes according user selection.
+ *
+ * @param obj the loaded object structure.
+ * @param em the structure with configuration
+ */
+static inline int ebpf_mdflush_load_and_attach(struct mdflush_bpf *obj, ebpf_module_t *em)
+{
+ int mode = em->targets[NETDATA_MD_FLUSH_REQUEST].mode;
+ if (mode == EBPF_LOAD_TRAMPOLINE) { // trampoline
+ ebpf_disable_probes(obj);
+
+ ebpf_set_trampoline_target(obj);
+ } else // kprobe
+ ebpf_disable_trampoline(obj);
+
+ int ret = mdflush_bpf__load(obj);
+ if (ret) {
+ fprintf(stderr, "failed to load BPF object: %d\n", ret);
+ return -1;
+ }
+
+ if (mode == EBPF_LOAD_TRAMPOLINE)
+ ret = mdflush_bpf__attach(obj);
+ else
+ ret = ebpf_load_probes(obj);
+
+ return ret;
+}
+
+#endif
+
/**
* MDflush exit
*
@@ -235,6 +326,49 @@ static void mdflush_collector(ebpf_module_t *em)
}
}
+/*
+ * Load BPF
+ *
+ * Load BPF files.
+ *
+ * @param em the structure with configuration
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+static int ebpf_mdflush_load_bpf(ebpf_module_t *em)
+{
+ int ret = 0;
+ if (em->load & EBPF_LOAD_LEGACY) {
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+ if (!em->probe_links) {
+ ret = -1;
+ }
+ }
+#ifdef LIBBPF_MAJOR_VERSION
+ else {
+ mdflush_bpf_obj = mdflush_bpf__open();
+ if (!mdflush_bpf_obj)
+ ret = -1;
+ else {
+ ret = ebpf_mdflush_load_and_attach(mdflush_bpf_obj, em);
+ if (ret && em->targets[NETDATA_MD_FLUSH_REQUEST].mode == EBPF_LOAD_TRAMPOLINE) {
+ mdflush_bpf__destroy(mdflush_bpf_obj);
+ mdflush_bpf_obj = mdflush_bpf__open();
+ if (!mdflush_bpf_obj)
+ ret = -1;
+ else {
+ em->targets[NETDATA_MD_FLUSH_REQUEST].mode = EBPF_LOAD_PROBE;
+ ret = ebpf_mdflush_load_and_attach(mdflush_bpf_obj, em);
+ }
+ }
+ }
+ }
+#endif
+
+ return ret;
+}
+
+
/**
* mdflush thread.
*
@@ -256,9 +390,10 @@ void *ebpf_mdflush_thread(void *ptr)
#ifdef LIBBPF_MAJOR_VERSION
ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
+ ebpf_adjust_thread_load(em, default_btf);
#endif
- em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
- if (!em->probe_links) {
+ if (ebpf_mdflush_load_bpf(em)) {
+ error("Cannot load eBPF software.");
goto endmdflush;
}
diff --git a/collectors/ebpf.plugin/ebpf_mdflush.h b/collectors/ebpf.plugin/ebpf_mdflush.h
index 4913ad019d..c0b0eca682 100644
--- a/collectors/ebpf.plugin/ebpf_mdflush.h
+++ b/collectors/ebpf.plugin/ebpf_mdflush.h
@@ -33,8 +33,15 @@ typedef struct netdata_mdflush {
uint64_t cnt;
} netdata_mdflush_t;
+enum netdata_mdflush_targets {
+ NETDATA_MD_FLUSH_REQUEST,
+
+ NETDATA_MD_FLUSH_END
+};
+
void *ebpf_mdflush_thread(void *ptr);
extern struct config mdflush_config;
+extern netdata_ebpf_targets_t mdflush_targets[];
#endif
diff --git a/libnetdata/ebpf/ebpf.h b/libnetdata/ebpf/ebpf.h
index e82aaedd47..455372753d 100644
--- a/libnetdata/ebpf/ebpf.h
+++ b/libnetdata/ebpf/ebpf.h
@@ -340,6 +340,16 @@ typedef struct netdata_ebpf_histogram {
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 +369,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