@cryptotaxi247 / netdata-1 / commits / c805baef8

Additional CO-RE code (eBPF.plugin) (#15078)

thiagoftsm committed Jul 6, 2023 at 12:03 UTC c805baef80d53cba5a10e77448e973f2cc61ca1e
11 files changed +576 -26
collectors/ebpf.plugin/ebpf.c
+40 -7
@@ -186,7 +186,7 @@ ebpf_module_t ebpf_modules[] = {
186 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
187 .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
188 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
189 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
189 + .load = EBPF_LOAD_LEGACY, .targets = mdflush_targets, .probe_links = NULL, .objects = NULL,
190 .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
191 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
192 .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[] =
378 .enabled = CONFIG_BOOLEAN_YES,
379 .addresses = {.function = NULL, .addr = 0},
380 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
381 - .fs_maps = NULL},
381 + .fs_maps = NULL,
382 + .fs_obj = NULL,
383 + .functions = { "ext4_file_read_iter",
384 + "ext4_file_write_iter",
385 + "ext4_file_open",
386 + "ext4_sync_file",
387 + NULL }},
388 {.filesystem = "xfs",
389 .optional_filesystem = NULL,
390 .family = "xfs",
@@ -388,7 +394,13 @@ ebpf_filesystem_partitions_t localfs[] =
394 .enabled = CONFIG_BOOLEAN_YES,
395 .addresses = {.function = NULL, .addr = 0},
396 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
391 - .fs_maps = NULL},
397 + .fs_maps = NULL,
398 + .fs_obj = NULL,
399 + .functions = { "xfs_file_read_iter",
400 + "xfs_file_write_iter",
401 + "xfs_file_open",
402 + "xfs_file_fsync",
403 + NULL }},
404 {.filesystem = "nfs",
405 .optional_filesystem = "nfs4",
406 .family = "nfs",
@@ -398,7 +410,13 @@ ebpf_filesystem_partitions_t localfs[] =
410 .enabled = CONFIG_BOOLEAN_YES,
411 .addresses = {.function = NULL, .addr = 0},
412 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
401 - .fs_maps = NULL},
413 + .fs_maps = NULL,
414 + .fs_obj = NULL,
415 + .functions = { "nfs_file_read",
416 + "nfs_file_write",
417 + "nfs_open",
418 + "nfs_getattr",
419 + NULL }}, // // "nfs4_file_open" - not present on all kernels
420 {.filesystem = "zfs",
421 .optional_filesystem = NULL,
422 .family = "zfs",
@@ -408,7 +426,13 @@ ebpf_filesystem_partitions_t localfs[] =
426 .enabled = CONFIG_BOOLEAN_YES,
427 .addresses = {.function = NULL, .addr = 0},
428 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
411 - .fs_maps = NULL},
429 + .fs_maps = NULL,
430 + .fs_obj = NULL,
431 + .functions = { "zpl_iter_read",
432 + "zpl_iter_write",
433 + "zpl_open",
434 + "zpl_fsync",
435 + NULL }},
436 {.filesystem = "btrfs",
437 .optional_filesystem = NULL,
438 .family = "btrfs",
@@ -418,7 +442,13 @@ ebpf_filesystem_partitions_t localfs[] =
442 .enabled = CONFIG_BOOLEAN_YES,
443 .addresses = {.function = "btrfs_file_operations", .addr = 0},
444 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10,
421 - .fs_maps = NULL},
445 + .fs_maps = NULL,
446 + .fs_obj = NULL,
447 + .functions = { "btrfs_file_read_iter",
448 + "btrfs_file_write_iter",
449 + "btrfs_file_open",
450 + "btrfs_sync_file",
451 + NULL }},
452 {.filesystem = NULL,
453 .optional_filesystem = NULL,
454 .family = NULL,
@@ -427,7 +457,7 @@ ebpf_filesystem_partitions_t localfs[] =
457 .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
458 .enabled = CONFIG_BOOLEAN_YES,
459 .addresses = {.function = NULL, .addr = 0},
430 - .kernels = 0, .fs_maps = NULL}};
460 + .kernels = 0, .fs_maps = NULL, .fs_obj = NULL}};
461
462 ebpf_sync_syscalls_t local_syscalls[] = {
463 {.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, .
523 struct btf *default_btf = NULL;
524 struct cachestat_bpf *cachestat_bpf_obj = NULL;
525 struct dc_bpf *dc_bpf_obj = NULL;
526 +struct disk_bpf *disk_bpf_obj = NULL;
527 struct fd_bpf *fd_bpf_obj = NULL;
528 +struct hardirq_bpf *hardirq_bpf_obj = NULL;
529 +struct mdflush_bpf *mdflush_bpf_obj = NULL;
530 struct mount_bpf *mount_bpf_obj = NULL;
531 struct shm_bpf *shm_bpf_obj = NULL;
532 struct socket_bpf *socket_bpf_obj = NULL;
collectors/ebpf.plugin/ebpf.h
+6
@@ -39,7 +39,10 @@
39 #ifdef LIBBPF_MAJOR_VERSION // BTF code
40 #include "includes/cachestat.skel.h"
41 #include "includes/dc.skel.h"
42 +#include "includes/disk.skel.h"
43 #include "includes/fd.skel.h"
44 +#include "includes/hardirq.skel.h"
45 +#include "includes/mdflush.skel.h"
46 #include "includes/mount.skel.h"
47 #include "includes/shm.skel.h"
48 #include "includes/socket.skel.h"
@@ -48,8 +51,11 @@
51
52 extern struct cachestat_bpf *cachestat_bpf_obj;
53 extern struct dc_bpf *dc_bpf_obj;
54 +extern struct disk_bpf *disk_bpf_obj;
55 extern struct fd_bpf *fd_bpf_obj;
56 +extern struct hardirq_bpf *hardirq_bpf_obj;
57 extern struct mount_bpf *mount_bpf_obj;
58 +extern struct mdflush_bpf *mdflush_bpf_obj;
59 extern struct shm_bpf *shm_bpf_obj;
60 extern struct socket_bpf *socket_bpf_obj;
61 extern struct swap_bpf *bpf_obj;
collectors/ebpf.plugin/ebpf_disk.c
+73 -3
@@ -52,6 +52,39 @@ static netdata_idx_t *disk_hash_values = NULL;
52 ebpf_publish_disk_t *plot_disks = NULL;
53 pthread_mutex_t plot_mutex;
54
55 +#ifdef LIBBPF_MAJOR_VERSION
56 +/**
57 + * Set hash table
58 + *
59 + * Set the values for maps according the value given by kernel.
60 + *
61 + * @param obj is the main structure for bpf objects.
62 + */
63 +static inline void ebpf_disk_set_hash_table(struct disk_bpf *obj)
64 + {
65 + disk_maps[NETDATA_DISK_IO].map_fd = bpf_map__fd(obj->maps.tbl_disk_iocall);
66 + }
67 +
68 +/**
69 + * Load and attach
70 + *
71 + * Load and attach the eBPF code in kernel.
72 + *
73 + * @param obj is the main structure for bpf objects.
74 + *
75 + * @return it returns 0 on success and -1 otherwise
76 + */
77 +static inline int ebpf_disk_load_and_attach(struct disk_bpf *obj)
78 +{
79 + int ret = disk_bpf__load(obj);
80 + if (ret) {
81 + return ret;
82 + }
83 +
84 + return disk_bpf__attach(obj);
85 +}
86 +#endif
87 +
88 /*****************************************************************
89 *
90 * FUNCTIONS TO MANIPULATE HARD DISKS
@@ -702,7 +735,7 @@ static void disk_collector(ebpf_module_t *em)
735 continue;
736
737 counter = 0;
705 - read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd, maps_per_core);
738 + read_hard_disk_tables(disk_maps[NETDATA_DISK_IO].map_fd, maps_per_core);
739 pthread_mutex_lock(&lock);
740 ebpf_remove_pointer_from_plot_disk(em);
741 ebpf_latency_send_hd_data(update_every);
@@ -749,6 +782,43 @@ static int ebpf_disk_enable_tracepoints()
782 return 0;
783 }
784
785 +/*
786 + * Load BPF
787 + *
788 + * Load BPF files.
789 + *
790 + * @param em the structure with configuration
791 + *
792 + * @return It returns 0 on success and -1 otherwise.
793 + */
794 +static int ebpf_disk_load_bpf(ebpf_module_t *em)
795 +{
796 + int ret = 0;
797 + if (em->load & EBPF_LOAD_LEGACY) {
798 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
799 + if (!em->probe_links) {
800 + ret = -1;
801 + }
802 + }
803 +#ifdef LIBBPF_MAJOR_VERSION
804 + else {
805 + disk_bpf_obj = disk_bpf__open();
806 + if (!disk_bpf_obj)
807 + ret = -1;
808 + else {
809 + ret = ebpf_disk_load_and_attach(disk_bpf_obj);
810 + if (!ret)
811 + ebpf_disk_set_hash_table(disk_bpf_obj);
812 + }
813 + }
814 +#endif
815 +
816 + if (ret)
817 + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
818 +
819 + return ret;
820 +}
821 +
822 /**
823 * Disk thread
824 *
@@ -781,9 +851,9 @@ void *ebpf_disk_thread(void *ptr)
851
852 #ifdef LIBBPF_MAJOR_VERSION
853 ebpf_define_map_type(disk_maps, em->maps_per_core, running_on_kernel);
854 + ebpf_adjust_thread_load(em, default_btf);
855 #endif
785 - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
786 - if (!em->probe_links) {
856 + if (ebpf_disk_load_bpf(em)) {
857 goto enddisk;
858 }
859
collectors/ebpf.plugin/ebpf_disk.h
+1 -4
@@ -54,10 +54,7 @@ typedef struct netdata_ebpf_disks {
54 struct netdata_ebpf_disks *next;
55 } netdata_ebpf_disks_t;
56
57 -enum ebpf_disk_tables {
58 - NETDATA_DISK_READ,
59 - NETDATA_DISK_TMP
60 -};
57 +enum ebpf_disk_tables { NETDATA_DISK_IO };
58
59 typedef struct block_key {
60 uint32_t bin;
collectors/ebpf.plugin/ebpf_filesystem.c
+220 -6
@@ -131,6 +131,202 @@ static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST
131 char **dimensions = NULL;
132 static netdata_idx_t *filesystem_hash_values = NULL;
133
134 +#ifdef LIBBPF_MAJOR_VERSION
135 +/**
136 + * FS disable kprobe
137 + *
138 + * Disable kprobes, because system will use trampolines.
139 + * We are not calling this function for while, because we are prioritizing kprobes. We opted by this road, because
140 + * distribution are still not deliverying necessary btf files per FS.
141 + *
142 + * @param obj FS object loaded.
143 + */
144 +static void ebpf_fs_disable_kprobe(struct filesystem_bpf *obj)
145 + {
146 + // kprobe
147 + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_probe, false);
148 + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_probe, false);
149 + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_probe, false);
150 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_probe, false);
151 + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_probe, false);
152 + // kretprobe
153 + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_retprobe, false);
154 + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_retprobe, false);
155 + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_retprobe, false);
156 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_retprobe, false);
157 + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_retprobe, false);
158 + }
159 +
160 + /**
161 + * Disable trampoline
162 + *
163 + * Disable trampolines to use kprobes.
164 + *
165 + * @param obj FS object loaded.
166 + */
167 + static void ebpf_fs_disable_trampoline(struct filesystem_bpf *obj)
168 + {
169 + // entry
170 + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_entry, false);
171 + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_entry, false);
172 + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_entry, false);
173 + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_entry, false);
174 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false);
175 +
176 + // exit
177 + bpf_program__set_autoload(obj->progs.netdata_fs_file_read_exit, false);
178 + bpf_program__set_autoload(obj->progs.netdata_fs_file_write_exit, false);
179 + bpf_program__set_autoload(obj->progs.netdata_fs_file_open_exit, false);
180 + bpf_program__set_autoload(obj->progs.netdata_fs_getattr_exit, false);
181 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false);
182 + }
183 +
184 + /**
185 + * Set targets
186 + *
187 + * Set targets for each objects.
188 + *
189 + * @param obj FS object loaded.
190 + * @param functions array with function names.
191 + */
192 + static void ebpf_fs_set_target(struct filesystem_bpf *obj, const char **functions)
193 +{
194 + // entry
195 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_entry, 0,
196 + functions[NETDATA_KEY_BTF_READ]);
197 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_entry, 0,
198 + functions[NETDATA_KEY_BTF_WRITE]);
199 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_entry, 0,
200 + functions[NETDATA_KEY_BTF_OPEN]);
201 + bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_entry, 0,
202 + functions[NETDATA_KEY_BTF_SYNC_ATTR]);
203 +
204 + // exit
205 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_read_exit, 0,
206 + functions[NETDATA_KEY_BTF_READ]);
207 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_write_exit, 0,
208 + functions[NETDATA_KEY_BTF_WRITE]);
209 + bpf_program__set_attach_target(obj->progs.netdata_fs_file_open_exit, 0,
210 + functions[NETDATA_KEY_BTF_OPEN]);
211 + bpf_program__set_attach_target(obj->progs.netdata_fs_getattr_exit, 0,
212 + functions[NETDATA_KEY_BTF_SYNC_ATTR]);
213 +
214 + if (functions[NETDATA_KEY_BTF_OPEN2]) {
215 + bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_entry, 0,
216 + functions[NETDATA_KEY_BTF_OPEN2]);
217 + bpf_program__set_attach_target(obj->progs.netdata_fs_2nd_file_open_exit, 0,
218 + functions[NETDATA_KEY_BTF_OPEN2]);
219 + } else {
220 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_entry, false);
221 + bpf_program__set_autoload(obj->progs.netdata_fs_2nd_file_open_exit, false);
222 + }
223 +}
224 +
225 +/**
226 + * Attach Kprobe
227 + *
228 + * Attach kprobe on targets
229 + *
230 + * @param obj FS object loaded.
231 + * @param functions array with function names.
232 + */
233 +static int ebpf_fs_attach_kprobe(struct filesystem_bpf *obj, const char **functions)
234 +{
235 + // kprobe
236 + obj->links.netdata_fs_file_read_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_probe,
237 + false, functions[NETDATA_KEY_BTF_READ]);
238 + if (libbpf_get_error(obj->links.netdata_fs_file_read_probe))
239 + return -1;
240 +
241 + obj->links.netdata_fs_file_write_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_probe,
242 + false, functions[NETDATA_KEY_BTF_WRITE]);
243 + if (libbpf_get_error(obj->links.netdata_fs_file_write_probe))
244 + return -1;
245 +
246 + obj->links.netdata_fs_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_probe,
247 + false, functions[NETDATA_KEY_BTF_OPEN]);
248 + if (libbpf_get_error(obj->links.netdata_fs_file_open_probe))
249 + return -1;
250 +
251 + obj->links.netdata_fs_getattr_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_probe,
252 + false, functions[NETDATA_KEY_BTF_SYNC_ATTR]);
253 + if (libbpf_get_error(obj->links.netdata_fs_getattr_probe))
254 + return -1;
255 +
256 + // kretprobe
257 + obj->links.netdata_fs_file_read_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_read_retprobe,
258 + false, functions[NETDATA_KEY_BTF_READ]);
259 + if (libbpf_get_error(obj->links.netdata_fs_file_read_retprobe))
260 + return -1;
261 +
262 + obj->links.netdata_fs_file_write_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_write_retprobe,
263 + false, functions[NETDATA_KEY_BTF_WRITE]);
264 + if (libbpf_get_error(obj->links.netdata_fs_file_write_retprobe))
265 + return -1;
266 +
267 + obj->links.netdata_fs_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_file_open_retprobe,
268 + false, functions[NETDATA_KEY_BTF_OPEN]);
269 + if (libbpf_get_error(obj->links.netdata_fs_file_open_retprobe))
270 + return -1;
271 +
272 + obj->links.netdata_fs_getattr_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_getattr_retprobe,
273 + false, functions[NETDATA_KEY_BTF_SYNC_ATTR]);
274 + if (libbpf_get_error(obj->links.netdata_fs_getattr_retprobe))
275 + return -1;
276 +
277 + if (functions[NETDATA_KEY_BTF_OPEN2]) {
278 + obj->links.netdata_fs_2nd_file_open_probe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_probe,
279 + false, functions[NETDATA_KEY_BTF_OPEN2]);
280 + if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_probe))
281 + return -1;
282 +
283 + obj->links.netdata_fs_2nd_file_open_retprobe = bpf_program__attach_kprobe(obj->progs.netdata_fs_2nd_file_open_retprobe,
284 + false, functions[NETDATA_KEY_BTF_OPEN2]);
285 + if (libbpf_get_error(obj->links.netdata_fs_2nd_file_open_retprobe))
286 + return -1;
287 + }
288 +
289 + return 0;
290 +}
291 +
292 +/**
293 + * Load and Attach
294 + *
295 + * Load binary and attach to targets.
296 + *
297 + * @param map Structure with information about maps.
298 + * @param obj FS object loaded.
299 + * @param functions array with function names.
300 + * @param bf sttruct with btf file loaded.
301 + */
302 +static inline int ebpf_fs_load_and_attach(ebpf_local_maps_t *map, struct filesystem_bpf *obj,
303 + const char **functions, struct btf *bf)
304 +{
305 + if (bf) {
306 + ebpf_fs_disable_kprobe(obj);
307 + ebpf_fs_set_target(obj, functions);
308 + } else {
309 + ebpf_fs_disable_trampoline(obj);
310 + }
311 +
312 + int ret = filesystem_bpf__load(obj);
313 + if (ret) {
314 + fprintf(stderr, "failed to load BPF object: %d\n", ret);
315 + return -1;
316 + }
317 +
318 + if (bf)
319 + ret = filesystem_bpf__attach(obj);
320 + else
321 + ret = ebpf_fs_attach_kprobe(obj, functions);
322 +
323 + if (!ret)
324 + map->map_fd = bpf_map__fd(obj->maps.tbl_fs);;
325 +
326 + return ret;
327 +}
328 +#endif
329 +
330 /*****************************************************************
331 *
332 * COMMON FUNCTIONS
@@ -275,13 +471,28 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
471 #ifdef LIBBPF_MAJOR_VERSION
472 ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
473 #endif
278 - efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
279 - if (!efp->probe_links) {
280 - em->thread_name = saved_name;
281 - em->kernels = kernels;
282 - em->maps = NULL;
283 - return -1;
474 + if (em->load & EBPF_LOAD_LEGACY) {
475 + efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
476 + if (!efp->probe_links) {
477 + em->thread_name = saved_name;
478 + em->kernels = kernels;
479 + return -1;
480 + }
481 + }
482 +#ifdef LIBBPF_MAJOR_VERSION
483 + else {
484 + efp->fs_obj = filesystem_bpf__open();
485 + if (!efp->fs_obj) {
486 + em->thread_name = saved_name;
487 + em->kernels = kernels;
488 + return -1;
489 + } else {
490 + if (ebpf_fs_load_and_attach(em->maps, efp->fs_obj,
491 + efp->functions, NULL))
492 + return -1;
493 + }
494 }
495 +#endif
496 efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
497 pthread_mutex_lock(&lock);
498 ebpf_update_kernel_memory(&plugin_statistics, efp->fs_maps, EBPF_ACTION_STAT_ADD);
@@ -683,6 +894,9 @@ void *ebpf_filesystem_thread(void *ptr)
894 // Initialize optional as zero, to identify when there are not partitions to monitor
895 em->optional = 0;
896
897 +#ifdef LIBBPF_MAJOR_VERSION
898 + ebpf_adjust_thread_load(em, default_btf);
899 +#endif
900 if (ebpf_update_partitions(em)) {
901 if (em->optional)
902 netdata_log_info("Netdata cannot monitor the filesystems used on this host.");
collectors/ebpf.plugin/ebpf_filesystem.h
+3
@@ -7,6 +7,9 @@
7 #define NETDATA_EBPF_MODULE_NAME_FILESYSTEM "filesystem"
8
9 #include "ebpf.h"
10 +#ifdef LIBBPF_MAJOR_VERSION
11 +#include "includes/filesystem.skel.h"
12 +#endif
13
14 #define NETDATA_FS_MAX_DIST_NAME 64UL
15
collectors/ebpf.plugin/ebpf_hardirq.c
+66 -4
@@ -9,8 +9,6 @@ struct config hardirq_config = { .first_section = NULL,
9 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
10 .rwlock = AVL_LOCK_INITIALIZER } };
11
12 -#define HARDIRQ_MAP_LATENCY 0
13 -#define HARDIRQ_MAP_LATENCY_STATIC 1
12 static ebpf_local_maps_t hardirq_maps[] = {
13 {
14 .name = "tbl_hardirq",
@@ -138,6 +136,36 @@ static hardirq_static_val_t hardirq_static_vals[] = {
136 // thread will write to netdata agent.
137 static avl_tree_lock hardirq_pub;
138
139 +#ifdef LIBBPF_MAJOR_VERSION
140 +/**
141 + * Set hash table
142 + *
143 + * Set the values for maps according the value given by kernel.
144 + *
145 + * @param obj is the main structure for bpf objects.
146 + */
147 +static inline void ebpf_hardirq_set_hash_table(struct hardirq_bpf *obj)
148 +{
149 + hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd = bpf_map__fd(obj->maps.tbl_hardirq);
150 + hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd = bpf_map__fd(obj->maps.tbl_hardirq_static);
151 +}
152 +
153 +/**
154 + * Load and Attach
155 + *
156 + * Load and attach bpf software.
157 + */
158 +static inline int ebpf_hardirq_load_and_attach(struct hardirq_bpf *obj)
159 +{
160 + int ret = hardirq_bpf__load(obj);
161 + if (ret) {
162 + return -1;
163 + }
164 +
165 + return hardirq_bpf__attach(obj);
166 +}
167 +#endif
168 +
169 /*****************************************************************
170 *
171 * ARAL SECTION
@@ -540,6 +568,40 @@ static void hardirq_collector(ebpf_module_t *em)
568 * EBPF HARDIRQ THREAD
569 *****************************************************************/
570
571 +/*
572 + * Load BPF
573 + *
574 + * Load BPF files.
575 + *
576 + * @param em the structure with configuration
577 + *
578 + * @return It returns 0 on success and -1 otherwise.
579 + */
580 +static int ebpf_hardirq_load_bpf(ebpf_module_t *em)
581 +{
582 + int ret = 0;
583 + if (em->load & EBPF_LOAD_LEGACY) {
584 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
585 + if (!em->probe_links) {
586 + ret = -1;
587 + }
588 + }
589 +#ifdef LIBBPF_MAJOR_VERSION
590 + else {
591 + hardirq_bpf_obj = hardirq_bpf__open();
592 + if (!hardirq_bpf_obj)
593 + ret = -1;
594 + else {
595 + ret = ebpf_hardirq_load_and_attach(hardirq_bpf_obj);
596 + if (!ret)
597 + ebpf_hardirq_set_hash_table(hardirq_bpf_obj);
598 + }
599 + }
600 +#endif
601 +
602 + return ret;
603 +}
604 +
605 /**
606 * Hard IRQ latency thread.
607 *
@@ -559,9 +621,9 @@ void *ebpf_hardirq_thread(void *ptr)
621
622 #ifdef LIBBPF_MAJOR_VERSION
623 ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
624 + ebpf_adjust_thread_load(em, default_btf);
625 #endif
563 - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
564 - if (!em->probe_links) {
626 + if (ebpf_hardirq_load_bpf(em)) {
627 goto endhardirq;
628 }
629
collectors/ebpf.plugin/ebpf_hardirq.h
+5
@@ -34,6 +34,11 @@ enum hardirq_ebpf_static {
34 HARDIRQ_EBPF_STATIC_END
35 };
36
37 +enum hardirq_maps {
38 + HARDIRQ_MAP_LATENCY,
39 + HARDIRQ_MAP_LATENCY_STATIC
40 +};
41 +
42 typedef struct hardirq_ebpf_static_val {
43 uint64_t latency;
44 uint64_t ts;
collectors/ebpf.plugin/ebpf_mdflush.c
+137 -2
@@ -31,6 +31,10 @@ static ebpf_local_maps_t mdflush_maps[] = {
31 }
32 };
33
34 +netdata_ebpf_targets_t mdflush_targets[] = { {.name = "md_flush_request", .mode = EBPF_LOAD_TRAMPOLINE},
35 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
36 +
37 +
38 // store for "published" data from the reader thread, which the collector
39 // thread will write to netdata agent.
40 static avl_tree_lock mdflush_pub;
@@ -38,6 +42,93 @@ static avl_tree_lock mdflush_pub;
42 // tmp store for mdflush values we get from a per-CPU eBPF map.
43 static mdflush_ebpf_val_t *mdflush_ebpf_vals = NULL;
44
45 +#ifdef LIBBPF_MAJOR_VERSION
46 +/**
47 + * Disable probes
48 + *
49 + * Disable probes to use trampolines.
50 + *
51 + * @param obj the loaded object structure.
52 + */
53 +static inline void ebpf_disable_probes(struct mdflush_bpf *obj)
54 +{
55 + bpf_program__set_autoload(obj->progs.netdata_md_flush_request_kprobe, false);
56 +}
57 +
58 +/**
59 + * Disable trampolines
60 + *
61 + * Disable trampoliness to use probes.
62 + *
63 + * @param obj the loaded object structure.
64 + */
65 +static inline void ebpf_disable_trampoline(struct mdflush_bpf *obj)
66 +{
67 + bpf_program__set_autoload(obj->progs.netdata_md_flush_request_fentry, false);
68 +}
69 +
70 +/**
71 + * Set Trampoline
72 + *
73 + * Define target to attach trampoline
74 + *
75 + * @param obj the loaded object structure.
76 + */
77 +static void ebpf_set_trampoline_target(struct mdflush_bpf *obj)
78 +{
79 + bpf_program__set_attach_target(obj->progs.netdata_md_flush_request_fentry, 0,
80 + mdflush_targets[NETDATA_MD_FLUSH_REQUEST].name);
81 +}
82 +
83 +/**
84 + * Load probe
85 + *
86 + * Load probe to monitor internal function.
87 + *
88 + * @param obj the loaded object structure.
89 + */
90 +static inline int ebpf_load_probes(struct mdflush_bpf *obj)
91 +{
92 + obj->links.netdata_md_flush_request_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_md_flush_request_kprobe,
93 + false,
94 + mdflush_targets[NETDATA_MD_FLUSH_REQUEST].name);
95 + return libbpf_get_error(obj->links.netdata_md_flush_request_kprobe);
96 +}
97 +
98 +/**
99 + * Load and Attach
100 + *
101 + * Load and attach bpf codes according user selection.
102 + *
103 + * @param obj the loaded object structure.
104 + * @param em the structure with configuration
105 + */
106 +static inline int ebpf_mdflush_load_and_attach(struct mdflush_bpf *obj, ebpf_module_t *em)
107 +{
108 + int mode = em->targets[NETDATA_MD_FLUSH_REQUEST].mode;
109 + if (mode == EBPF_LOAD_TRAMPOLINE) { // trampoline
110 + ebpf_disable_probes(obj);
111 +
112 + ebpf_set_trampoline_target(obj);
113 + } else // kprobe
114 + ebpf_disable_trampoline(obj);
115 +
116 + int ret = mdflush_bpf__load(obj);
117 + if (ret) {
118 + fprintf(stderr, "failed to load BPF object: %d\n", ret);
119 + return -1;
120 + }
121 +
122 + if (mode == EBPF_LOAD_TRAMPOLINE)
123 + ret = mdflush_bpf__attach(obj);
124 + else
125 + ret = ebpf_load_probes(obj);
126 +
127 + return ret;
128 +}
129 +
130 +#endif
131 +
132 /**
133 * MDflush exit
134 *
@@ -235,6 +326,49 @@ static void mdflush_collector(ebpf_module_t *em)
326 }
327 }
328
329 +/*
330 + * Load BPF
331 + *
332 + * Load BPF files.
333 + *
334 + * @param em the structure with configuration
335 + *
336 + * @return It returns 0 on success and -1 otherwise.
337 + */
338 +static int ebpf_mdflush_load_bpf(ebpf_module_t *em)
339 +{
340 + int ret = 0;
341 + if (em->load & EBPF_LOAD_LEGACY) {
342 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
343 + if (!em->probe_links) {
344 + ret = -1;
345 + }
346 + }
347 +#ifdef LIBBPF_MAJOR_VERSION
348 + else {
349 + mdflush_bpf_obj = mdflush_bpf__open();
350 + if (!mdflush_bpf_obj)
351 + ret = -1;
352 + else {
353 + ret = ebpf_mdflush_load_and_attach(mdflush_bpf_obj, em);
354 + if (ret && em->targets[NETDATA_MD_FLUSH_REQUEST].mode == EBPF_LOAD_TRAMPOLINE) {
355 + mdflush_bpf__destroy(mdflush_bpf_obj);
356 + mdflush_bpf_obj = mdflush_bpf__open();
357 + if (!mdflush_bpf_obj)
358 + ret = -1;
359 + else {
360 + em->targets[NETDATA_MD_FLUSH_REQUEST].mode = EBPF_LOAD_PROBE;
361 + ret = ebpf_mdflush_load_and_attach(mdflush_bpf_obj, em);
362 + }
363 + }
364 + }
365 + }
366 +#endif
367 +
368 + return ret;
369 +}
370 +
371 +
372 /**
373 * mdflush thread.
374 *
@@ -256,9 +390,10 @@ void *ebpf_mdflush_thread(void *ptr)
390
391 #ifdef LIBBPF_MAJOR_VERSION
392 ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
393 + ebpf_adjust_thread_load(em, default_btf);
394 #endif
260 - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
261 - if (!em->probe_links) {
395 + if (ebpf_mdflush_load_bpf(em)) {
396 + error("Cannot load eBPF software.");
397 goto endmdflush;
398 }
399
collectors/ebpf.plugin/ebpf_mdflush.h
+7
@@ -33,8 +33,15 @@ typedef struct netdata_mdflush {
33 uint64_t cnt;
34 } netdata_mdflush_t;
35
36 +enum netdata_mdflush_targets {
37 + NETDATA_MD_FLUSH_REQUEST,
38 +
39 + NETDATA_MD_FLUSH_END
40 +};
41 +
42 void *ebpf_mdflush_thread(void *ptr);
43
44 extern struct config mdflush_config;
45 +extern netdata_ebpf_targets_t mdflush_targets[];
46
47 #endif
libnetdata/ebpf/ebpf.h
+18
@@ -340,6 +340,16 @@ typedef struct netdata_ebpf_histogram {
340 uint64_t histogram[NETDATA_EBPF_HIST_MAX_BINS];
341 } netdata_ebpf_histogram_t;
342
343 +enum fs_btf_counters {
344 + NETDATA_KEY_BTF_READ,
345 + NETDATA_KEY_BTF_WRITE,
346 + NETDATA_KEY_BTF_OPEN,
347 + NETDATA_KEY_BTF_SYNC_ATTR,
348 + NETDATA_KEY_BTF_OPEN2,
349 +
350 + NETDATA_FS_BTF_END
351 +};
352 +
353 typedef struct ebpf_filesystem_partitions {
354 char *filesystem;
355 char *optional_filesystem;
@@ -359,6 +369,14 @@ typedef struct ebpf_filesystem_partitions {
369 ebpf_addresses_t addresses;
370 uint64_t kernels;
371 ebpf_local_maps_t *fs_maps;
372 +
373 + // BPF structure
374 +#ifdef LIBBPF_MAJOR_VERSION
375 + struct filesystem_bpf *fs_obj;
376 +#else
377 + void *fs_obj;
378 +#endif
379 + const char *functions[NETDATA_FS_BTF_END];
380 } ebpf_filesystem_partitions_t;
381
382 typedef struct ebpf_sync_syscalls {