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 {