Improve PID monitoring (step 2) (#13530)
thiagoftsm committed
Aug 23, 2022 at 12:44 UTC
575986a692003638f09c975da847062637b915f4
23 files changed
+1018
-77
collectors/ebpf.plugin/README.md
+19
@@ -137,6 +137,25 @@ If you do not need to monitor specific metrics for your `cgroups`, you can enabl
137
`ebpf.d.conf`, and then disable the plugin for a specific `thread` by following the steps in the
138
[Configuration](#configuring-ebpfplugin) section.
139
140
+#### Collect PID
141
+
142
+When one of the previous integrations is enabled, `ebpf.plugin` will use Process Identifier (`PID`) to identify the
143
+process group for which it needs to plot data.
144
+
145
+There are different ways to collect PID, and you can select the way `ebpf.plugin` collects data with the following
146
+values:
147
+
148
+- `real parent`: This is the default mode. Collection will aggregate data for the real parent, the thread that creates
149
+ child threads.
150
+- `parent`: Parent and real parent are the same when a process starts, but this value can be changed during run time.
151
+- `all`: This option will store all PIDs that run on the host. Note, this method can be expensive for the host,
152
+ because more memory needs to be allocated and parsed.
153
+
154
+The threads that have integration with other collectors have an internal clean up wherein they attach either a
155
+`trampoline` or a `kprobe` to `release_task` internal function. To avoid `overload` on this function, `ebpf.plugin`
156
+will only enable these threads integrated with other collectors when the kernel is compiled with
157
+`CONFIG_DEBUG_INFO_BTF`, unless you enable them manually.
158
+
159
#### Integration Dashboard Elements
160
161
When an integration is enabled, your dashboard will also show the following cgroups and apps charts using low-level
collectors/ebpf.plugin/ebpf.c
+29
-29
@@ -77,7 +77,7 @@ ebpf_module_t ebpf_modules[] = {
77
.load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL},
78
{ .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
79
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
80
- .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
80
+ .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
81
.apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
82
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
83
.config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
@@ -85,12 +85,12 @@ ebpf_module_t ebpf_modules[] = {
85
.load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL},
86
{ .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
87
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
88
- .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
88
+ .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
89
.apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
90
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
91
.config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
92
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
93
- .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
93
+ .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL},
94
{ .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
95
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
96
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -114,13 +114,13 @@ ebpf_module_t ebpf_modules[] = {
114
.load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL},
115
{ .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
116
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
117
- .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
117
+ .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
118
.apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
119
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
120
.config_file = NETDATA_FD_CONFIG_FILE,
121
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 |
122
NETDATA_V5_14,
123
- .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
123
+ .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL},
124
{ .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
125
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
126
.apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -145,7 +145,7 @@ ebpf_module_t ebpf_modules[] = {
145
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
146
{ .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
147
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
148
- .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
148
+ .apps_level = NETDATA_APPS_LEVEL_ALL, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
149
.apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
150
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
151
.config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
@@ -314,6 +314,8 @@ ebpf_plugin_stats_t plugin_statistics = {.core = 0, .legacy = 0, .running = 0, .
314
315
#ifdef LIBBPF_MAJOR_VERSION
316
struct btf *default_btf = NULL;
317
+#else
318
+void *default_btf = NULL;
319
#endif
320
char *btf_path = NULL;
321
@@ -1263,35 +1265,28 @@ static void ebpf_update_table_size()
1265
/**
1266
* Set Load mode
1267
*
1266
- * @param load default load mode.
1268
+ * @param origin specify the configuration file loaded
1269
*/
1268
-static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load)
1270
+static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load, netdata_ebpf_load_mode_t origin)
1271
{
1270
-#ifdef LIBBPF_MAJOR_VERSION
1271
- if (load == EBPF_LOAD_CORE || load == EBPF_LOAD_PLAY_DICE) {
1272
- load = (!default_btf) ? EBPF_LOAD_LEGACY : EBPF_LOAD_CORE;
1273
- }
1274
-#else
1275
- load = EBPF_LOAD_LEGACY;
1276
-#endif
1277
-
1272
int i;
1273
for (i = 0; ebpf_modules[i].thread_name; i++) {
1280
- // TO DO: Use `load` variable after we change all threads.
1281
- ebpf_modules[i].load = EBPF_LOAD_LEGACY; // load ;
1274
+ ebpf_modules[i].load &= ~NETDATA_EBPF_LOAD_METHODS;
1275
+ ebpf_modules[i].load |= load | origin ;
1276
}
1277
}
1278
1279
/**
1280
* Update mode
1281
*
1288
- * @param str value read from configuration file.
1282
+ * @param str value read from configuration file.
1283
+ * @param origin specify the configuration file loaded
1284
*/
1290
-static inline void epbf_update_load_mode(char *str)
1285
+static inline void epbf_update_load_mode(char *str, netdata_ebpf_load_mode_t origin)
1286
{
1287
netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(str);
1288
1294
- ebpf_set_load_mode(load);
1289
+ ebpf_set_load_mode(load, origin);
1290
}
1291
1292
/**
@@ -1299,9 +1294,11 @@ static inline void epbf_update_load_mode(char *str)
1294
*
1295
* @param disable_apps variable to store information related to apps.
1296
* @param disable_cgroups variable to store information related to cgroups.
1302
- * @param update_every value to overwrite the update frequency set by the server.
1297
+ * @param update_every value to overwrite the update frequency set by the server.
1298
+ * @param origin specify the configuration file loaded
1299
*/
1304
-static void read_collector_values(int *disable_apps, int *disable_cgroups, int update_every)
1300
+static void read_collector_values(int *disable_apps, int *disable_cgroups,
1301
+ int update_every, netdata_ebpf_load_mode_t origin)
1302
{
1303
// Read global section
1304
char *value;
@@ -1323,7 +1320,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u
1320
1321
value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, EBPF_CFG_DEFAULT_PROGRAM);
1322
1326
- epbf_update_load_mode(value);
1323
+ epbf_update_load_mode(value, origin);
1324
1325
ebpf_update_interval(update_every);
1326
@@ -1501,6 +1498,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u
1498
static int load_collector_config(char *path, int *disable_apps, int *disable_cgroups, int update_every)
1499
{
1500
char lpath[4096];
1501
+ netdata_ebpf_load_mode_t origin;
1502
1503
snprintf(lpath, 4095, "%s/%s", path, NETDATA_EBPF_CONFIG_FILE);
1504
if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
@@ -1508,9 +1506,11 @@ static int load_collector_config(char *path, int *disable_apps, int *disable_cgr
1506
if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
1507
return -1;
1508
}
1511
- }
1509
+ origin = EBPF_LOADED_FROM_STOCK;
1510
+ } else
1511
+ origin = EBPF_LOADED_FROM_USER;
1512
1513
- read_collector_values(disable_apps, disable_cgroups, update_every);
1513
+ read_collector_values(disable_apps, disable_cgroups, update_every, origin);
1514
1515
return 0;
1516
}
@@ -1554,7 +1554,7 @@ static inline void ebpf_load_thread_config()
1554
{
1555
int i;
1556
for (i = 0; ebpf_modules[i].thread_name; i++) {
1557
- ebpf_update_module(&ebpf_modules[i]);
1557
+ ebpf_update_module(&ebpf_modules[i], default_btf);
1558
}
1559
}
1560
@@ -1773,14 +1773,14 @@ static void ebpf_parse_args(int argc, char **argv)
1773
break;
1774
}
1775
case EBPF_OPTION_LEGACY: {
1776
- ebpf_set_load_mode(EBPF_LOAD_LEGACY);
1776
+ ebpf_set_load_mode(EBPF_LOAD_LEGACY, EBPF_LOADED_FROM_USER);
1777
#ifdef NETDATA_INTERNAL_CHECKS
1778
info("EBPF running with \"LEGACY\" code, because it was started with the option \"[-]-legacy\".");
1779
#endif
1780
break;
1781
}
1782
case EBPF_OPTION_CORE: {
1783
- ebpf_set_load_mode(EBPF_LOAD_CORE);
1783
+ ebpf_set_load_mode(EBPF_LOAD_CORE, EBPF_LOADED_FROM_USER);
1784
#ifdef NETDATA_INTERNAL_CHECKS
1785
info("EBPF running with \"CO-RE\" code, because it was started with the option \"[-]-core\".");
1786
#endif
collectors/ebpf.plugin/ebpf.d.conf
+7
-4
@@ -26,16 +26,16 @@
26
#
27
# eBPF Programs
28
#
29
-# The eBPF collector enables and runs the following eBPF programs by default:
29
+# The eBPF collector has the following eBPF programs:
30
#
31
# `cachestat` : Make charts for kernel functions related to page cache.
32
# `dcstat` : Make charts for kernel functions related to directory cache.
33
# `disk` : Monitor I/O latencies for disks
34
# `fd` : This eBPF program creates charts that show information about file manipulation.
35
-# `mdflush` : Monitors flush counts for multi-devices.
36
-# `mount` : Monitor calls for syscalls mount and umount
35
# `filesystem`: Monitor calls for functions used to manipulate specific filesystems
36
# `hardirq` : Monitor latency of serving hardware interrupt requests (hard IRQs).
37
+# `mdflush` : Monitors flush counts for multi-devices.
38
+# `mount` : Monitor calls for syscalls mount and umount
39
# `oomkill` : This eBPF program creates a chart that shows which process got OOM killed and when.
40
# `process` : This eBPF program creates charts that show information about process life.
41
# `shm` : Monitor calls for syscalls shmget, shmat, shmdt and shmctl.
@@ -46,6 +46,9 @@
46
# `swap` : Monitor calls for internal swap functions.
47
# `vfs` : This eBPF program creates charts that show information about process VFS IO, VFS file manipulation and
48
# files removed.
49
+#
50
+# When plugin detects that system has support to BTF, it enables integration with apps.plugin.
51
+#
52
[ebpf programs]
53
cachestat = no
54
dcstat = no
@@ -57,7 +60,7 @@
60
mount = yes
61
oomkill = yes
62
process = yes
60
- shm = yes
63
+ shm = no
64
socket = yes
65
softirq = yes
66
sync = yes
collectors/ebpf.plugin/ebpf.d/fd.conf
+3
-1
@@ -11,9 +11,11 @@
11
# The `pid table size` defines the maximum number of PIDs stored inside the hash table.
12
#
13
# Uncomment lines to define specific options for thread.
14
-#[global]
14
+[global]
15
# ebpf load mode = entry
16
# apps = yes
17
# cgroups = no
18
# update every = 10
19
# pid table size = 32768
20
+ ebpf type format = auto
21
+ ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/vfs.conf
+3
-1
@@ -9,9 +9,11 @@
9
# the setting `apps` and `cgroups` to 'no'.
10
#
11
# Uncomment lines to define specific options for thread.
12
-#[global]
12
+[global]
13
# ebpf load mode = entry
14
# apps = yes
15
# cgroups = no
16
# update every = 10
17
# pid table size = 32768
18
+ ebpf type format = auto
19
+ ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.h
+4
@@ -271,7 +271,11 @@ extern sem_t *shm_sem_ebpf_cgroup;
271
extern pthread_mutex_t mutex_cgroup_shm;
272
extern size_t all_pids_count;
273
extern ebpf_plugin_stats_t plugin_statistics;
274
+#ifdef LIBBPF_MAJOR_VERSION
275
extern struct btf *default_btf;
276
+#else
277
+extern void *default_btf;
278
+#endif
279
280
// Socket functions and variables
281
// Common functions
collectors/ebpf.plugin/ebpf_cachestat.c
+30
-1
@@ -67,6 +67,7 @@ static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj)
67
bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
68
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
69
bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_kprobe, false);
70
+ bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false);
71
}
72
73
/*
@@ -105,6 +106,7 @@ static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj)
106
bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
107
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
108
bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_fentry, false);
109
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
110
}
111
112
/*
@@ -156,6 +158,9 @@ static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj)
158
159
bpf_program__set_attach_target(obj->progs.netdata_mark_buffer_dirty_fentry, 0,
160
cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
161
+
162
+ bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0,
163
+ EBPF_COMMON_FNCT_CLEAN_UP);
164
}
165
166
/**
@@ -210,6 +215,13 @@ static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
215
if (ret)
216
return -1;
217
218
+ obj->links.netdata_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_kprobe,
219
+ false,
220
+ EBPF_COMMON_FNCT_CLEAN_UP);
221
+ ret = libbpf_get_error(obj->links.netdata_release_task_kprobe);
222
+ if (ret)
223
+ return -1;
224
+
225
return 0;
226
}
227
@@ -241,6 +253,19 @@ static void ebpf_cachestat_set_hash_tables(struct cachestat_bpf *obj)
253
cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd = bpf_map__fd(obj->maps.cstat_ctrl);
254
}
255
256
+/**
257
+ * Disable Release Task
258
+ *
259
+ * Disable release task when apps is not enabled.
260
+ *
261
+ * @param obj is the main structure for bpf objects.
262
+ */
263
+static void ebpf_cachestat_disable_release_task(struct cachestat_bpf *obj)
264
+{
265
+ bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false);
266
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
267
+}
268
+
269
/**
270
* Load and attach
271
*
@@ -268,6 +293,9 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
293
294
ebpf_cachestat_adjust_map_size(obj, em);
295
296
+ if (!em->apps_charts && !em->cgroup_charts)
297
+ ebpf_cachestat_disable_release_task(obj);
298
+
299
int ret = cachestat_bpf__load(obj);
300
if (ret) {
301
return ret;
@@ -1227,7 +1255,8 @@ static void ebpf_cachestat_set_internal_value()
1255
static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1256
{
1257
int ret = 0;
1230
- if (em->load == EBPF_LOAD_LEGACY) {
1258
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode);
1259
+ if (em->load & EBPF_LOAD_LEGACY) {
1260
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1261
if (!em->probe_links) {
1262
ret = -1;
collectors/ebpf.plugin/ebpf_dcstat.c
+30
-1
@@ -65,6 +65,7 @@ static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
65
{
66
bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
67
bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
68
+ bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
69
}
70
71
/*
@@ -78,6 +79,7 @@ static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
79
{
80
bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
81
bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
82
+ bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
83
}
84
85
/**
@@ -94,6 +96,9 @@ static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
96
97
bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
98
dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
99
+
100
+ bpf_program__set_attach_target(obj->progs.netdata_dcstat_release_task_fentry, 0,
101
+ EBPF_COMMON_FNCT_CLEAN_UP);
102
}
103
104
/**
@@ -125,6 +130,13 @@ static int ebpf_dc_attach_probes(struct dc_bpf *obj)
130
if (ret)
131
return -1;
132
133
+ obj->links.netdata_dcstat_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_dcstat_release_task_kprobe,
134
+ false,
135
+ EBPF_COMMON_FNCT_CLEAN_UP);
136
+ ret = libbpf_get_error(obj->links.netdata_dcstat_release_task_kprobe);
137
+ if (ret)
138
+ return -1;
139
+
140
return 0;
141
}
142
@@ -179,6 +191,19 @@ netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
191
return EBPF_LOAD_RETPROBE;
192
}
193
194
+/**
195
+ * Disable Release Task
196
+ *
197
+ * Disable release task when apps is not enabled.
198
+ *
199
+ * @param obj is the main structure for bpf objects.
200
+ */
201
+static void ebpf_dc_disable_release_task(struct dc_bpf *obj)
202
+{
203
+ bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
204
+ bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
205
+}
206
+
207
/**
208
* Load and attach
209
*
@@ -202,6 +227,9 @@ static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
227
228
ebpf_dc_adjust_map_size(obj, em);
229
230
+ if (!em->apps_charts && !em->cgroup_charts)
231
+ ebpf_dc_disable_release_task(obj);
232
+
233
int ret = dc_bpf__load(obj);
234
if (ret) {
235
return ret;
@@ -1116,7 +1144,8 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
1144
static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1145
{
1146
int ret = 0;
1119
- if (em->load == EBPF_LOAD_LEGACY) {
1147
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
1148
+ if (em->load & EBPF_LOAD_LEGACY) {
1149
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1150
if (!em->probe_links) {
1151
ret = -1;
collectors/ebpf.plugin/ebpf_fd.c
+325
-6
@@ -38,6 +38,286 @@ static netdata_idx_t *fd_values = NULL;
38
netdata_fd_stat_t *fd_vector = NULL;
39
netdata_fd_stat_t **fd_pid = NULL;
40
41
+netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMPOLINE},
42
+ {.name = "close", .mode = EBPF_LOAD_TRAMPOLINE},
43
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
44
+
45
+#ifdef LIBBPF_MAJOR_VERSION
46
+#include "includes/fd.skel.h" // BTF code
47
+
48
+static struct fd_bpf *bpf_obj = NULL;
49
+
50
+/**
51
+ * Disable probe
52
+ *
53
+ * Disable all probes to use exclusively another method.
54
+ *
55
+ * @param obj is the main structure for bpf objects
56
+*/
57
+static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
58
+{
59
+ bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false);
60
+ bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false);
61
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
62
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
63
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
64
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
65
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
66
+ } else {
67
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
68
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
69
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
70
+ }
71
+}
72
+
73
+/*
74
+ * Disable specific probe
75
+ *
76
+ * Disable probes according the kernel version
77
+ *
78
+ * @param obj is the main structure for bpf objects
79
+ */
80
+static inline void ebpf_disable_specific_probes(struct fd_bpf *obj)
81
+{
82
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
83
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
84
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
85
+ } else {
86
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
87
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
88
+ }
89
+}
90
+
91
+/*
92
+ * Disable trampoline
93
+ *
94
+ * Disable all trampoline to use exclusively another method.
95
+ *
96
+ * @param obj is the main structure for bpf objects.
97
+ */
98
+static inline void ebpf_disable_trampoline(struct fd_bpf *obj)
99
+{
100
+ bpf_program__set_autoload(obj->progs.netdata_sys_open_fentry, false);
101
+ bpf_program__set_autoload(obj->progs.netdata_sys_open_fexit, false);
102
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
103
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
104
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
105
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
106
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
107
+}
108
+
109
+/*
110
+ * Disable specific trampoline
111
+ *
112
+ * Disable trampoline according to kernel version.
113
+ *
114
+ * @param obj is the main structure for bpf objects.
115
+ */
116
+static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj)
117
+{
118
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
119
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
120
+ bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
121
+ } else {
122
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
123
+ bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
124
+ }
125
+}
126
+
127
+/**
128
+ * Set trampoline target
129
+ *
130
+ * Set the targets we will monitor.
131
+ *
132
+ * @param obj is the main structure for bpf objects.
133
+ */
134
+static void ebpf_set_trampoline_target(struct fd_bpf *obj)
135
+{
136
+ bpf_program__set_attach_target(obj->progs.netdata_sys_open_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
137
+ bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
138
+ bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
139
+
140
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
141
+ bpf_program__set_attach_target(
142
+ obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
143
+ bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
144
+ } else {
145
+ bpf_program__set_attach_target(
146
+ obj->progs.netdata___close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
147
+ bpf_program__set_attach_target(
148
+ obj->progs.netdata___close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
149
+ }
150
+}
151
+
152
+/**
153
+ * Mount Attach Probe
154
+ *
155
+ * Attach probes to target
156
+ *
157
+ * @param obj is the main structure for bpf objects.
158
+ *
159
+ * @return It returns 0 on success and -1 otherwise.
160
+ */
161
+static int ebpf_fd_attach_probe(struct fd_bpf *obj)
162
+{
163
+ obj->links.netdata_sys_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kprobe, false,
164
+ fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
165
+ int ret = libbpf_get_error(obj->links.netdata_sys_open_kprobe);
166
+ if (ret)
167
+ return -1;
168
+
169
+ obj->links.netdata_sys_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kretprobe, true,
170
+ fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
171
+ ret = libbpf_get_error(obj->links.netdata_sys_open_kretprobe);
172
+ if (ret)
173
+ return -1;
174
+
175
+ obj->links.netdata_release_task_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_fd_kprobe,
176
+ false,
177
+ EBPF_COMMON_FNCT_CLEAN_UP);
178
+ ret = libbpf_get_error(obj->links.netdata_release_task_fd_kprobe);
179
+ if (ret)
180
+ return -1;
181
+
182
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
183
+ obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true,
184
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
185
+ ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe);
186
+ if (ret)
187
+ return -1;
188
+
189
+ obj->links.netdata_close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kprobe, false,
190
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
191
+ ret = libbpf_get_error(obj->links.netdata_close_fd_kprobe);
192
+ if (ret)
193
+ return -1;
194
+ } else {
195
+ obj->links.netdata___close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kretprobe,
196
+ true,
197
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
198
+ ret = libbpf_get_error(obj->links.netdata___close_fd_kretprobe);
199
+ if (ret)
200
+ return -1;
201
+
202
+ obj->links.netdata___close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kprobe,
203
+ false,
204
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
205
+ ret = libbpf_get_error(obj->links.netdata___close_fd_kprobe);
206
+ if (ret)
207
+ return -1;
208
+ }
209
+
210
+ return 0;
211
+}
212
+
213
+/**
214
+ * Set target values
215
+ *
216
+ * Set pointers used to laod data.
217
+ */
218
+static void ebpf_fd_set_target_values()
219
+{
220
+ static char *close_targets[] = {"close_fd", "__close_fd"};
221
+ static char *open_targets[] = {"do_sys_openat2", "do_sys_open"};
222
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
223
+ fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[0];
224
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[0];
225
+ } else {
226
+ fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[1];
227
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[1];
228
+ }
229
+}
230
+
231
+/**
232
+ * Set hash tables
233
+ *
234
+ * Set the values for maps according the value given by kernel.
235
+ *
236
+ * @param obj is the main structure for bpf objects.
237
+ */
238
+static void ebpf_fd_set_hash_tables(struct fd_bpf *obj)
239
+{
240
+ fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_global);
241
+ fd_maps[NETDATA_FD_PID_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_pid);
242
+ fd_maps[NETDATA_FD_CONTROLLER].map_fd = bpf_map__fd(obj->maps.fd_ctrl);
243
+}
244
+
245
+/**
246
+ * Adjust Map Size
247
+ *
248
+ * Resize maps according input from users.
249
+ *
250
+ * @param obj is the main structure for bpf objects.
251
+ * @param em structure with configuration
252
+ */
253
+static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em)
254
+{
255
+ ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS],
256
+ em, bpf_map__name(obj->maps.tbl_fd_pid));
257
+}
258
+
259
+/**
260
+ * Disable Release Task
261
+ *
262
+ * Disable release task when apps is not enabled.
263
+ *
264
+ * @param obj is the main structure for bpf objects.
265
+ */
266
+static void ebpf_fd_disable_release_task(struct fd_bpf *obj)
267
+{
268
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
269
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
270
+}
271
+
272
+/**
273
+ * Load and attach
274
+ *
275
+ * Load and attach the eBPF code in kernel.
276
+ *
277
+ * @param obj is the main structure for bpf objects.
278
+ * @param em structure with configuration
279
+ *
280
+ * @return it returns 0 on succes and -1 otherwise
281
+ */
282
+static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
283
+{
284
+ netdata_ebpf_targets_t *mt = em->targets;
285
+ netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode;
286
+
287
+ ebpf_fd_set_target_values();
288
+ if (test == EBPF_LOAD_TRAMPOLINE) {
289
+ ebpf_fd_disable_probes(obj);
290
+ ebpf_disable_specific_trampoline(obj);
291
+
292
+ ebpf_set_trampoline_target(obj);
293
+ // TODO: Remove this in next PR, because this specific trampoline has an error.
294
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
295
+ } else {
296
+ ebpf_disable_trampoline(obj);
297
+ ebpf_disable_specific_probes(obj);
298
+ }
299
+
300
+ ebpf_fd_adjust_map_size(obj, em);
301
+
302
+ if (!em->apps_charts && !em->cgroup_charts)
303
+ ebpf_fd_disable_release_task(obj);
304
+
305
+ int ret = fd_bpf__load(obj);
306
+ if (ret) {
307
+ return ret;
308
+ }
309
+
310
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? fd_bpf__attach(obj) : ebpf_fd_attach_probe(obj);
311
+ if (!ret) {
312
+ ebpf_fd_set_hash_tables(obj);
313
+
314
+ ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
315
+ }
316
+
317
+ return ret;
318
+}
319
+#endif
320
+
321
/*****************************************************************
322
*
323
* FUNCTIONS TO CLOSE THE THREAD
@@ -78,6 +358,11 @@ static void ebpf_fd_cleanup(void *ptr)
358
freez(fd_values);
359
freez(fd_vector);
360
361
+#ifdef LIBBPF_MAJOR_VERSION
362
+ if (bpf_obj)
363
+ fd_bpf__destroy(bpf_obj);
364
+#endif
365
+
366
fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
367
em->enabled = NETDATA_MAIN_THREAD_EXITED;
368
}
@@ -810,6 +1095,40 @@ static void ebpf_fd_allocate_global_vectors(int apps)
1095
fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
1096
}
1097
1098
+/*
1099
+ * Load BPF
1100
+ *
1101
+ * Load BPF files.
1102
+ *
1103
+ * @param em the structure with configuration
1104
+ */
1105
+static int ebpf_fd_load_bpf(ebpf_module_t *em)
1106
+{
1107
+ int ret = 0;
1108
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode);
1109
+ if (em->load & EBPF_LOAD_LEGACY) {
1110
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1111
+ if (!em->probe_links) {
1112
+ em->enabled = CONFIG_BOOLEAN_NO;
1113
+ ret = -1;
1114
+ }
1115
+ }
1116
+#ifdef LIBBPF_MAJOR_VERSION
1117
+ else {
1118
+ bpf_obj = fd_bpf__open();
1119
+ if (!bpf_obj)
1120
+ ret = -1;
1121
+ else
1122
+ ret = ebpf_fd_load_and_attach(bpf_obj, em);
1123
+ }
1124
+#endif
1125
+
1126
+ if (ret)
1127
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1128
+
1129
+ return ret;
1130
+}
1131
+
1132
/**
1133
* Directory Cache thread
1134
*
@@ -829,13 +1148,13 @@ void *ebpf_fd_thread(void *ptr)
1148
if (!em->enabled)
1149
goto endfd;
1150
832
- ebpf_fd_allocate_global_vectors(em->apps_charts);
833
-
834
- em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
835
- if (!em->probe_links) {
836
- em->enabled = CONFIG_BOOLEAN_NO;
1151
+#ifdef LIBBPF_MAJOR_VERSION
1152
+ ebpf_adjust_thread_load(em, default_btf);
1153
+#endif
1154
+ if (ebpf_fd_load_bpf(em))
1155
goto endfd;
838
- }
1156
+
1157
+ ebpf_fd_allocate_global_vectors(em->apps_charts);
1158
1159
int algorithms[NETDATA_FD_SYSCALL_END] = {
1160
NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX
collectors/ebpf.plugin/ebpf_fd.h
+1
@@ -79,6 +79,7 @@ extern void *ebpf_fd_thread(void *ptr);
79
extern void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr);
80
extern struct config fd_config;
81
extern netdata_fd_stat_t **fd_pid;
82
+extern netdata_ebpf_targets_t fd_targets[];
83
84
#endif /* NETDATA_EBPF_FD_H */
85
collectors/ebpf.plugin/ebpf_mount.c
+1
-1
@@ -435,7 +435,7 @@ static void ebpf_create_mount_charts(int update_every)
435
static int ebpf_mount_load_bpf(ebpf_module_t *em)
436
{
437
int ret = 0;
438
- if (em->load == EBPF_LOAD_LEGACY) {
438
+ if (em->load & EBPF_LOAD_LEGACY) {
439
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
440
if (!em->probe_links) {
441
em->enabled = CONFIG_BOOLEAN_NO;
collectors/ebpf.plugin/ebpf_shm.c
+46
-1
@@ -83,6 +83,7 @@ static void ebpf_disable_probe(struct shm_bpf *obj)
83
bpf_program__set_autoload(obj->progs.netdata_shmat_probe, false);
84
bpf_program__set_autoload(obj->progs.netdata_shmdt_probe, false);
85
bpf_program__set_autoload(obj->progs.netdata_shmctl_probe, false);
86
+ bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
87
}
88
89
/*
@@ -98,6 +99,7 @@ static void ebpf_disable_trampoline(struct shm_bpf *obj)
99
bpf_program__set_autoload(obj->progs.netdata_shmat_fentry, false);
100
bpf_program__set_autoload(obj->progs.netdata_shmdt_fentry, false);
101
bpf_program__set_autoload(obj->progs.netdata_shmctl_fentry, false);
102
+ bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
103
}
104
105
/**
@@ -130,6 +132,9 @@ static void ebpf_set_trampoline_target(struct shm_bpf *obj)
132
shm_targets[NETDATA_KEY_SHMCTL_CALL].name, running_on_kernel);
133
bpf_program__set_attach_target(obj->progs.netdata_shmctl_fentry, 0,
134
syscall);
135
+
136
+ bpf_program__set_attach_target(obj->progs.netdata_shm_release_task_fentry, 0,
137
+ EBPF_COMMON_FNCT_CLEAN_UP);
138
}
139
140
/**
@@ -177,6 +182,13 @@ static int ebpf_shm_attach_probe(struct shm_bpf *obj)
182
if (ret)
183
return -1;
184
185
+ obj->links.netdata_shm_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_shm_release_task_probe,
186
+ false, EBPF_COMMON_FNCT_CLEAN_UP);
187
+ ret = (int)libbpf_get_error(obj->links.netdata_shm_release_task_probe);
188
+ if (ret)
189
+ return -1;
190
+
191
+
192
return 0;
193
}
194
@@ -192,6 +204,33 @@ static void ebpf_shm_set_hash_tables(struct shm_bpf *obj)
204
shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_shm);
205
}
206
207
+/**
208
+ * Disable Release Task
209
+ *
210
+ * Disable release task when apps is not enabled.
211
+ *
212
+ * @param obj is the main structure for bpf objects.
213
+ */
214
+static void ebpf_shm_disable_release_task(struct shm_bpf *obj)
215
+{
216
+ bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
217
+ bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
218
+}
219
+
220
+/**
221
+ * Adjust Map Size
222
+ *
223
+ * Resize maps according input from users.
224
+ *
225
+ * @param obj is the main structure for bpf objects.
226
+ * @param em structure with configuration
227
+ */
228
+static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em)
229
+{
230
+ ebpf_update_map_size(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE],
231
+ em, bpf_map__name(obj->maps.tbl_pid_shm));
232
+}
233
+
234
/**
235
* Load and attach
236
*
@@ -221,6 +260,10 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
260
ebpf_disable_trampoline(obj);
261
}
262
263
+ ebpf_shm_adjust_map_size(obj, em);
264
+ if (!em->apps_charts && !em->cgroup_charts)
265
+ ebpf_shm_disable_release_task(obj);
266
+
267
int ret = shm_bpf__load(obj);
268
if (!ret) {
269
if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE)
@@ -1008,7 +1051,9 @@ static void ebpf_create_shm_charts(int update_every)
1051
static int ebpf_shm_load_bpf(ebpf_module_t *em)
1052
{
1053
int ret = 0;
1011
- if (em->load == EBPF_LOAD_LEGACY) {
1054
+
1055
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode);
1056
+ if (em->load & EBPF_LOAD_LEGACY) {
1057
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1058
if (!em->probe_links) {
1059
em->enabled = CONFIG_BOOLEAN_NO;
collectors/ebpf.plugin/ebpf_socket.c
+1
-1
@@ -3875,7 +3875,7 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
3875
{
3876
int ret = 0;
3877
3878
- if (em->load == EBPF_LOAD_LEGACY) {
3878
+ if (em->load & EBPF_LOAD_LEGACY) {
3879
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
3880
if (!em->probe_links) {
3881
ret = -1;
collectors/ebpf.plugin/ebpf_swap.c
+31
-3
@@ -71,6 +71,7 @@ static void ebpf_swap_disable_trampoline(struct swap_bpf *obj)
71
{
72
bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false);
73
bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false);
74
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
75
}
76
77
/**
@@ -87,6 +88,9 @@ static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj)
88
89
bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0,
90
swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
91
+
92
+ bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0,
93
+ EBPF_COMMON_FNCT_CLEAN_UP);
94
}
95
96
/**
@@ -114,6 +118,13 @@ static int ebpf_swap_attach_kprobe(struct swap_bpf *obj)
118
if (ret)
119
return -1;
120
121
+ obj->links.netdata_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_probe,
122
+ false,
123
+ EBPF_COMMON_FNCT_CLEAN_UP);
124
+ ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe);
125
+ if (ret)
126
+ return -1;
127
+
128
return 0;
129
}
130
@@ -145,6 +156,19 @@ static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em)
156
em, bpf_map__name(obj->maps.tbl_pid_swap));
157
}
158
159
+/**
160
+ * Disable Release Task
161
+ *
162
+ * Disable release task when apps is not enabled.
163
+ *
164
+ * @param obj is the main structure for bpf objects.
165
+ */
166
+static void ebpf_swap_disable_release_task(struct swap_bpf *obj)
167
+{
168
+ bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
169
+ bpf_program__set_autoload(obj->progs.netdata_release_task_probe, false);
170
+}
171
+
172
/**
173
* Load and attach
174
*
@@ -168,13 +192,16 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
192
ebpf_swap_disable_trampoline(obj);
193
}
194
195
+ ebpf_swap_adjust_map_size(obj, em);
196
+
197
+ if (!em->apps_charts && !em->cgroup_charts)
198
+ ebpf_swap_disable_release_task(obj);
199
+
200
int ret = swap_bpf__load(obj);
201
if (ret) {
202
return ret;
203
}
204
176
- ebpf_swap_adjust_map_size(obj, em);
177
-
205
ret = (test == EBPF_LOAD_TRAMPOLINE) ? swap_bpf__attach(obj) : ebpf_swap_attach_kprobe(obj);
206
if (!ret) {
207
ebpf_swap_set_hash_tables(obj);
@@ -812,7 +839,8 @@ static void ebpf_create_swap_charts(int update_every)
839
static int ebpf_swap_load_bpf(ebpf_module_t *em)
840
{
841
int ret = 0;
815
- if (em->load == EBPF_LOAD_LEGACY) {
842
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SWAP_READPAGE_CALL].mode);
843
+ if (em->load & EBPF_LOAD_LEGACY) {
844
em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
845
if (!em->probe_links) {
846
ret = -1;
collectors/ebpf.plugin/ebpf_sync.c
+1
-1
@@ -291,7 +291,7 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em)
291
for (i = 0; local_syscalls[i].syscall; i++) {
292
ebpf_sync_syscalls_t *w = &local_syscalls[i];
293
if (w->enabled) {
294
- if (em->load == EBPF_LOAD_LEGACY) {
294
+ if (em->load & EBPF_LOAD_LEGACY) {
295
if (ebpf_sync_load_legacy(w, em))
296
errors++;
297
collectors/ebpf.plugin/ebpf_vfs.c
+387
-2
@@ -39,6 +39,354 @@ struct netdata_static_thread vfs_threads = {"VFS KERNEL",
39
NULL, NULL};
40
static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING;
41
42
+netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE},
43
+ {.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE},
44
+ {.name = "vfs_read", .mode = EBPF_LOAD_TRAMPOLINE},
45
+ {.name = "vfs_readv", .mode = EBPF_LOAD_TRAMPOLINE},
46
+ {.name = "vfs_unlink", .mode = EBPF_LOAD_TRAMPOLINE},
47
+ {.name = "vfs_fsync", .mode = EBPF_LOAD_TRAMPOLINE},
48
+ {.name = "vfs_open", .mode = EBPF_LOAD_TRAMPOLINE},
49
+ {.name = "vfs_create", .mode = EBPF_LOAD_TRAMPOLINE},
50
+ {.name = "release_task", .mode = EBPF_LOAD_TRAMPOLINE},
51
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
52
+
53
+#ifdef LIBBPF_MAJOR_VERSION
54
+#include "includes/vfs.skel.h" // BTF code
55
+
56
+static struct vfs_bpf *bpf_obj = NULL;
57
+
58
+/**
59
+ * Disable probe
60
+ *
61
+ * Disable all probes to use exclusively another method.
62
+ *
63
+ * @param obj is the main structure for bpf objects
64
+ */
65
+static void ebpf_vfs_disable_probes(struct vfs_bpf *obj)
66
+{
67
+ bpf_program__set_autoload(obj->progs.netdata_vfs_write_kprobe, false);
68
+ bpf_program__set_autoload(obj->progs.netdata_vfs_write_kretprobe, false);
69
+ bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kprobe, false);
70
+ bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kretprobe, false);
71
+ bpf_program__set_autoload(obj->progs.netdata_vfs_read_kprobe, false);
72
+ bpf_program__set_autoload(obj->progs.netdata_vfs_read_kretprobe, false);
73
+ bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kprobe, false);
74
+ bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kretprobe, false);
75
+ bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kprobe, false);
76
+ bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kretprobe, false);
77
+ bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kprobe, false);
78
+ bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kretprobe, false);
79
+ bpf_program__set_autoload(obj->progs.netdata_vfs_open_kprobe, false);
80
+ bpf_program__set_autoload(obj->progs.netdata_vfs_open_kretprobe, false);
81
+ bpf_program__set_autoload(obj->progs.netdata_vfs_create_kprobe, false);
82
+ bpf_program__set_autoload(obj->progs.netdata_vfs_create_kretprobe, false);
83
+ bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false);
84
+}
85
+
86
+/*
87
+ * Disable trampoline
88
+ *
89
+ * Disable all trampoline to use exclusively another method.
90
+ *
91
+ * @param obj is the main structure for bpf objects.
92
+ */
93
+static void ebpf_vfs_disable_trampoline(struct vfs_bpf *obj)
94
+{
95
+ bpf_program__set_autoload(obj->progs.netdata_vfs_write_fentry, false);
96
+ bpf_program__set_autoload(obj->progs.netdata_vfs_write_fexit, false);
97
+ bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fentry, false);
98
+ bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fexit, false);
99
+ bpf_program__set_autoload(obj->progs.netdata_vfs_read_fentry, false);
100
+ bpf_program__set_autoload(obj->progs.netdata_vfs_read_fexit, false);
101
+ bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fentry, false);
102
+ bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fexit, false);
103
+ bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_fentry, false);
104
+ bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fentry, false);
105
+ bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fexit, false);
106
+ bpf_program__set_autoload(obj->progs.netdata_vfs_open_fentry, false);
107
+ bpf_program__set_autoload(obj->progs.netdata_vfs_open_fexit, false);
108
+ bpf_program__set_autoload(obj->progs.netdata_vfs_create_fentry, false);
109
+ bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false);
110
+}
111
+
112
+/**
113
+ * Set trampoline target
114
+ *
115
+ * Set the targets we will monitor.
116
+ *
117
+ * @param obj is the main structure for bpf objects.
118
+ */
119
+static void ebpf_vfs_set_trampoline_target(struct vfs_bpf *obj)
120
+{
121
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
122
+
123
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
124
+
125
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
126
+
127
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
128
+
129
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
130
+
131
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
132
+
133
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
134
+
135
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
136
+
137
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_unlink_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
138
+
139
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
140
+
141
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
142
+
143
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
144
+
145
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
146
+
147
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_create_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
148
+
149
+ bpf_program__set_attach_target(obj->progs.netdata_vfs_release_task_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
150
+}
151
+
152
+/**
153
+ * Attach Probe
154
+ *
155
+ * Attach probes to target
156
+ *
157
+ * @param obj is the main structure for bpf objects.
158
+ *
159
+ * @return It returns 0 on success and -1 otherwise.
160
+ */
161
+static int ebpf_vfs_attach_probe(struct vfs_bpf *obj)
162
+{
163
+ obj->links.netdata_vfs_write_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kprobe, false,
164
+ vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
165
+ int ret = libbpf_get_error(obj->links.netdata_vfs_write_kprobe);
166
+ if (ret)
167
+ return -1;
168
+
169
+ obj->links.netdata_vfs_write_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kretprobe, true,
170
+ vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
171
+ ret = libbpf_get_error(obj->links.netdata_vfs_write_kretprobe);
172
+ if (ret)
173
+ return -1;
174
+
175
+ obj->links.netdata_vfs_writev_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kprobe, false,
176
+ vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
177
+ ret = libbpf_get_error(obj->links.netdata_vfs_writev_kprobe);
178
+ if (ret)
179
+ return -1;
180
+
181
+ obj->links.netdata_vfs_writev_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kretprobe, true,
182
+ vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
183
+ ret = libbpf_get_error(obj->links.netdata_vfs_writev_kretprobe);
184
+ if (ret)
185
+ return -1;
186
+
187
+ obj->links.netdata_vfs_read_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kprobe, false,
188
+ vfs_targets[NETDATA_EBPF_VFS_READ].name);
189
+ ret = libbpf_get_error(obj->links.netdata_vfs_read_kprobe);
190
+ if (ret)
191
+ return -1;
192
+
193
+ obj->links.netdata_vfs_read_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kretprobe, true,
194
+ vfs_targets[NETDATA_EBPF_VFS_READ].name);
195
+ ret = libbpf_get_error(obj->links.netdata_vfs_read_kretprobe);
196
+ if (ret)
197
+ return -1;
198
+
199
+ obj->links.netdata_vfs_readv_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kprobe, false,
200
+ vfs_targets[NETDATA_EBPF_VFS_READV].name);
201
+ ret = libbpf_get_error(obj->links.netdata_vfs_readv_kprobe);
202
+ if (ret)
203
+ return -1;
204
+
205
+ obj->links.netdata_vfs_readv_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kretprobe, true,
206
+ vfs_targets[NETDATA_EBPF_VFS_READV].name);
207
+ ret = libbpf_get_error(obj->links.netdata_vfs_readv_kretprobe);
208
+ if (ret)
209
+ return -1;
210
+
211
+ obj->links.netdata_vfs_unlink_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kprobe, false,
212
+ vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
213
+ ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kprobe);
214
+ if (ret)
215
+ return -1;
216
+
217
+ obj->links.netdata_vfs_unlink_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kretprobe, true,
218
+ vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
219
+ ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kretprobe);
220
+ if (ret)
221
+ return -1;
222
+
223
+ obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false,
224
+ vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
225
+ ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe);
226
+ if (ret)
227
+ return -1;
228
+
229
+ obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true,
230
+ vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
231
+ ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe);
232
+ if (ret)
233
+ return -1;
234
+
235
+ obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false,
236
+ vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
237
+ ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe);
238
+ if (ret)
239
+ return -1;
240
+
241
+ obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true,
242
+ vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
243
+ ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe);
244
+ if (ret)
245
+ return -1;
246
+
247
+ obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false,
248
+ vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
249
+ ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe);
250
+ if (ret)
251
+ return -1;
252
+
253
+ obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true,
254
+ vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
255
+ ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe);
256
+ if (ret)
257
+ return -1;
258
+
259
+ obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false,
260
+ vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
261
+ ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe);
262
+ if (ret)
263
+ return -1;
264
+
265
+ obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true,
266
+ vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
267
+ ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe);
268
+ if (ret)
269
+ return -1;
270
+
271
+ obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false,
272
+ vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
273
+ ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe);
274
+ if (ret)
275
+ return -1;
276
+
277
+ obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true,
278
+ vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
279
+ ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe);
280
+ if (ret)
281
+ return -1;
282
+
283
+ obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false,
284
+ vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
285
+ ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe);
286
+ if (ret)
287
+ return -1;
288
+
289
+ obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true,
290
+ vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
291
+ ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe);
292
+ if (ret)
293
+ return -1;
294
+
295
+ obj->links.netdata_vfs_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_release_task_fentry,
296
+ true,
297
+ EBPF_COMMON_FNCT_CLEAN_UP);
298
+ ret = libbpf_get_error(obj->links.netdata_vfs_release_task_kprobe);
299
+ if (ret)
300
+ return -1;
301
+
302
+ return 0;
303
+}
304
+
305
+/**
306
+ * Adjust Map Size
307
+ *
308
+ * Resize maps according input from users.
309
+ *
310
+ * @param obj is the main structure for bpf objects.
311
+ * @param em structure with configuration
312
+ */
313
+static void ebpf_vfs_adjust_map_size(struct vfs_bpf *obj, ebpf_module_t *em)
314
+{
315
+ ebpf_update_map_size(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID],
316
+ em, bpf_map__name(obj->maps.tbl_vfs_pid));
317
+}
318
+
319
+/**
320
+ * Set hash tables
321
+ *
322
+ * Set the values for maps according the value given by kernel.
323
+ *
324
+ * @param obj is the main structure for bpf objects.
325
+ */
326
+static void ebpf_vfs_set_hash_tables(struct vfs_bpf *obj)
327
+{
328
+ vfs_maps[NETDATA_VFS_ALL].map_fd = bpf_map__fd(obj->maps.tbl_vfs_stats);
329
+ vfs_maps[NETDATA_VFS_PID].map_fd = bpf_map__fd(obj->maps.tbl_vfs_pid);
330
+ vfs_maps[NETDATA_VFS_CTRL].map_fd = bpf_map__fd(obj->maps.vfs_ctrl);
331
+}
332
+
333
+/**
334
+ * Disable Release Task
335
+ *
336
+ * Disable release task when apps is not enabled.
337
+ *
338
+ * @param obj is the main structure for bpf objects.
339
+ */
340
+static void ebpf_vfs_disable_release_task(struct vfs_bpf *obj)
341
+{
342
+ bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false);
343
+ bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false);
344
+}
345
+
346
+/**
347
+ * Load and attach
348
+ *
349
+ * Load and attach the eBPF code in kernel.
350
+ *
351
+ * @param obj is the main structure for bpf objects.
352
+ * @param em structure with configuration
353
+ *
354
+ * @return it returns 0 on succes and -1 otherwise
355
+ */
356
+static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *em)
357
+{
358
+ netdata_ebpf_targets_t *mt = em->targets;
359
+ netdata_ebpf_program_loaded_t test = mt[NETDATA_EBPF_VFS_WRITE].mode;
360
+
361
+ if (test == EBPF_LOAD_TRAMPOLINE) {
362
+ ebpf_vfs_disable_probes(obj);
363
+
364
+ ebpf_vfs_set_trampoline_target(obj);
365
+ } else {
366
+ ebpf_vfs_disable_trampoline(obj);
367
+ }
368
+
369
+ ebpf_vfs_adjust_map_size(obj, em);
370
+
371
+ if (!em->apps_charts && !em->cgroup_charts)
372
+ ebpf_vfs_disable_release_task(obj);
373
+
374
+ int ret = vfs_bpf__load(obj);
375
+ if (ret) {
376
+ return ret;
377
+ }
378
+
379
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? vfs_bpf__attach(obj) : ebpf_vfs_attach_probe(obj);
380
+ if (!ret) {
381
+ ebpf_vfs_set_hash_tables(obj);
382
+
383
+ ebpf_update_controller(vfs_maps[NETDATA_VFS_CTRL].map_fd, em);
384
+ }
385
+
386
+ return ret;
387
+}
388
+#endif
389
+
390
/*****************************************************************
391
*
392
* FUNCTIONS TO CLOSE THE THREAD
@@ -77,6 +425,11 @@ static void ebpf_vfs_cleanup(void *ptr)
425
freez(vfs_vector);
426
freez(vfs_threads.thread);
427
428
+#ifdef LIBBPF_MAJOR_VERSION
429
+ if (bpf_obj)
430
+ vfs_bpf__destroy(bpf_obj);
431
+#endif
432
+
433
vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
434
em->enabled = NETDATA_MAIN_THREAD_EXITED;
435
}
@@ -1543,6 +1896,36 @@ static void ebpf_vfs_allocate_global_vectors(int apps)
1896
*
1897
*****************************************************************/
1898
1899
+/*
1900
+ * Load BPF
1901
+ *
1902
+ * Load BPF files.
1903
+ *
1904
+ * @param em the structure with configuration
1905
+ */
1906
+static int ebpf_vfs_load_bpf(ebpf_module_t *em)
1907
+{
1908
+ int ret = 0;
1909
+ ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_EBPF_VFS_WRITE].mode);
1910
+ if (em->load & EBPF_LOAD_LEGACY) {
1911
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1912
+ if (!em->probe_links) {
1913
+ ret = -1;
1914
+ }
1915
+ }
1916
+#ifdef LIBBPF_MAJOR_VERSION
1917
+ else {
1918
+ bpf_obj = vfs_bpf__open();
1919
+ if (!bpf_obj)
1920
+ ret = -1;
1921
+ else
1922
+ ret = ebpf_vfs_load_and_attach(bpf_obj, em);
1923
+ }
1924
+#endif
1925
+
1926
+ return ret;
1927
+}
1928
+
1929
/**
1930
* Process thread
1931
*
@@ -1566,8 +1949,10 @@ void *ebpf_vfs_thread(void *ptr)
1949
if (!em->enabled)
1950
goto endvfs;
1951
1569
- em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1570
- if (!em->probe_links) {
1952
+#ifdef LIBBPF_MAJOR_VERSION
1953
+ ebpf_adjust_thread_load(em, default_btf);
1954
+#endif
1955
+ if (ebpf_vfs_load_bpf(em)) {
1956
em->enabled = CONFIG_BOOLEAN_NO;
1957
goto endvfs;
1958
}
collectors/ebpf.plugin/ebpf_vfs.h
+16
-1
@@ -149,13 +149,28 @@ enum vfs_counters {
149
150
enum netdata_vfs_tables {
151
NETDATA_VFS_PID,
152
- NETDATA_VFS_ALL
152
+ NETDATA_VFS_ALL,
153
+ NETDATA_VFS_CTRL
154
+};
155
+
156
+enum netdata_vfs_calls_name {
157
+ NETDATA_EBPF_VFS_WRITE,
158
+ NETDATA_EBPF_VFS_WRITEV,
159
+ NETDATA_EBPF_VFS_READ,
160
+ NETDATA_EBPF_VFS_READV,
161
+ NETDATA_EBPF_VFS_UNLINK,
162
+ NETDATA_EBPF_VFS_FSYNC,
163
+ NETDATA_EBPF_VFS_OPEN,
164
+ NETDATA_EBPF_VFS_CREATE,
165
+
166
+ NETDATA_VFS_END_LIST
167
};
168
169
extern netdata_publish_vfs_t **vfs_pid;
170
171
extern void *ebpf_vfs_thread(void *ptr);
172
extern void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr);
173
+extern netdata_ebpf_targets_t vfs_targets[];
174
175
extern struct config vfs_config;
176
libnetdata/ebpf/ebpf.c
+68
-13
@@ -444,9 +444,9 @@ void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
444
445
// In theory the `else if` is useless, because when this function is called, the module should not stay in
446
// EBPF_LOAD_PLAY_DICE. We have this additional condition to detect errors from developers.
447
- if (em->load == EBPF_LOAD_LEGACY)
447
+ if (em->load & EBPF_LOAD_LEGACY)
448
report->legacy++;
449
- else if (em->load == EBPF_LOAD_CORE)
449
+ else if (em->load & EBPF_LOAD_CORE)
450
report->core++;
451
452
ebpf_stats_targets(report, em->targets);
@@ -826,9 +826,9 @@ netdata_ebpf_load_mode_t epbf_convert_string_to_load_mode(char *str)
826
*/
827
static char *ebpf_convert_load_mode_to_string(netdata_ebpf_load_mode_t mode)
828
{
829
- if (mode == EBPF_LOAD_CORE)
829
+ if (mode & EBPF_LOAD_CORE)
830
return EBPF_CFG_CORE_PROGRAM;
831
- else if (mode == EBPF_LOAD_LEGACY)
831
+ else if (mode & EBPF_LOAD_LEGACY)
832
return EBPF_CFG_LEGACY_PROGRAM;
833
834
return EBPF_CFG_DEFAULT_PROGRAM;
@@ -850,7 +850,7 @@ static char *ebpf_convert_collect_pid_to_string(netdata_apps_level_t level)
850
else if (level == NETDATA_APPS_LEVEL_ALL)
851
return EBPF_CFG_PID_ALL;
852
853
- return EBPF_CFG_PID_ALL;
853
+ return EBPF_CFG_PID_INTERNAL_USAGE;
854
}
855
856
/**
@@ -903,9 +903,11 @@ netdata_ebpf_program_loaded_t ebpf_convert_core_type(char *str, netdata_run_mode
903
void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file)
904
{
905
if (!file) {
906
- mod->load = EBPF_LOAD_LEGACY;
906
+ mod->load &= ~EBPF_LOAD_CORE;
907
+ mod->load |= EBPF_LOAD_LEGACY;
908
} else if (mod->load == EBPF_LOAD_PLAY_DICE && file) {
908
- mod->load = EBPF_LOAD_CORE;
909
+ mod->load &= ~EBPF_LOAD_LEGACY;
910
+ mod->load |= EBPF_LOAD_CORE;
911
}
912
}
913
@@ -1018,14 +1020,39 @@ static void ebpf_update_target_with_conf(ebpf_module_t *em, netdata_ebpf_program
1020
}
1021
}
1022
1023
+/**
1024
+ * Select Load Mode
1025
+ *
1026
+ * Select the load mode according the given inputs.
1027
+ *
1028
+ * @param btf_file a pointer to the loaded btf file.
1029
+ * @parma load current value.
1030
+ *
1031
+ * @return it returns the new load mode.
1032
+ */
1033
+static netdata_ebpf_load_mode_t ebpf_select_load_mode(struct btf *btf_file, netdata_ebpf_load_mode_t load)
1034
+{
1035
+#ifdef LIBBPF_MAJOR_VERSION
1036
+ if ((load & EBPF_LOAD_CORE) || (load & EBPF_LOAD_PLAY_DICE)) {
1037
+ load = (!btf_file) ? EBPF_LOAD_LEGACY : EBPF_LOAD_CORE;
1038
+ }
1039
+#else
1040
+ load = EBPF_LOAD_LEGACY;
1041
+#endif
1042
+
1043
+ return load;
1044
+}
1045
+
1046
/**
1047
* Update Module using config
1048
*
1049
* Update configuration for a specific thread.
1050
*
1051
* @param modules structure that will be updated
1052
+ * @oaram origin specify the configuration file loaded
1053
+ * @param btf_file a pointer to the loaded btf file.
1054
*/
1028
-void ebpf_update_module_using_config(ebpf_module_t *modules)
1055
+void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_mode_t origin, struct btf *btf_file)
1056
{
1057
char default_value[EBPF_MAX_MODE_LENGTH + 1];
1058
ebpf_select_mode_string(default_value, EBPF_MAX_MODE_LENGTH, modules->mode);
@@ -1044,9 +1071,11 @@ void ebpf_update_module_using_config(ebpf_module_t *modules)
1071
modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
1072
modules->pid_map_size);
1073
1047
- value = ebpf_convert_load_mode_to_string(modules->load);
1074
+ value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
1075
value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
1049
- modules->load = epbf_convert_string_to_load_mode(value);
1076
+ netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(value);
1077
+ load = ebpf_select_load_mode(btf_file, load);
1078
+ modules->load = origin | load;
1079
1080
value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CORE_ATTACH, EBPF_CFG_ATTACH_TRAMPOLINE);
1081
netdata_ebpf_program_loaded_t fill_lm = ebpf_convert_core_type(value, modules->mode);
@@ -1066,10 +1095,13 @@ void ebpf_update_module_using_config(ebpf_module_t *modules)
1095
* update the variables.
1096
*
1097
* @param em the module structure
1098
+ * @param btf_file a pointer to the loaded btf file.
1099
*/
1070
-void ebpf_update_module(ebpf_module_t *em)
1100
+void ebpf_update_module(ebpf_module_t *em, struct btf *btf_file)
1101
{
1102
char filename[FILENAME_MAX+1];
1103
+ netdata_ebpf_load_mode_t origin;
1104
+
1105
ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, em->config_file);
1106
if (!ebpf_load_config(em->cfg, filename)) {
1107
ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, em->config_file);
@@ -1077,9 +1109,32 @@ void ebpf_update_module(ebpf_module_t *em)
1109
error("Cannot load the ebpf configuration file %s", em->config_file);
1110
return;
1111
}
1080
- }
1112
+ // If user defined data globaly, we will have here EBPF_LOADED_FROM_USER, we need to consider this, to avoid
1113
+ // forcing users to configure thread by thread.
1114
+ origin = (!(em->load & NETDATA_EBPF_LOAD_SOURCE)) ? EBPF_LOADED_FROM_STOCK : em->load & NETDATA_EBPF_LOAD_SOURCE;
1115
+ } else
1116
+ origin = EBPF_LOADED_FROM_USER;
1117
1082
- ebpf_update_module_using_config(em);
1118
+ ebpf_update_module_using_config(em, origin, btf_file);
1119
+}
1120
+
1121
+/**
1122
+ * Adjust Apps Cgroup
1123
+ *
1124
+ * Apps and cgroup has internal cleanup that needs attaching tracers to release_task, to avoid overload the function
1125
+ * we will enable this integration by default, if and only if, we are running with trampolines.
1126
+ *
1127
+ * @param em a poiter to the main thread structure.
1128
+ * @param mode is the mode used with different
1129
+ */
1130
+void ebpf_adjust_apps_cgroup(ebpf_module_t *em, netdata_ebpf_program_loaded_t mode)
1131
+{
1132
+ if ((em->load & EBPF_LOADED_FROM_STOCK) &&
1133
+ (em->apps_charts || em->cgroup_charts) &&
1134
+ mode != EBPF_LOAD_TRAMPOLINE) {
1135
+ em->apps_charts = NETDATA_EBPF_APPS_FLAG_NO;
1136
+ em->cgroup_charts = 0;
1137
+ }
1138
}
1139
1140
//----------------------------------------------------------------------------------------------------------------------
libnetdata/ebpf/ebpf.h
+10
-5
@@ -30,6 +30,7 @@
30
#define EBPF_CFG_PID_REAL_PARENT "real parent"
31
#define EBPF_CFG_PID_PARENT "parent"
32
#define EBPF_CFG_PID_ALL "all"
33
+#define EBPF_CFG_PID_INTERNAL_USAGE "not used"
34
35
#define EBPF_CFG_CORE_ATTACH "ebpf co-re tracing"
36
#define EBPF_CFG_ATTACH_TRAMPOLINE "trampoline"
@@ -201,11 +202,14 @@ typedef struct ebpf_specify_name {
202
} ebpf_specify_name_t;
203
204
typedef enum netdata_ebpf_load_mode {
204
- EBPF_LOAD_LEGACY, // Select legacy mode, this means we will load binaries
205
- EBPF_LOAD_CORE, // When CO-RE is used, it is necessary to use the souce code
206
-
207
- EBPF_LOAD_PLAY_DICE // Take a look on environment and choose the best option
205
+ EBPF_LOAD_LEGACY = 1<<0, // Select legacy mode, this means we will load binaries
206
+ EBPF_LOAD_CORE = 1<<1, // When CO-RE is used, it is necessary to use the souce code
207
+ EBPF_LOAD_PLAY_DICE = 1<<2, // Take a look on environment and choose the best option
208
+ EBPF_LOADED_FROM_STOCK = 1<<3, // Configuration loaded from Stock file
209
+ EBPF_LOADED_FROM_USER = 1<<4 // Configuration loaded from user
210
} netdata_ebpf_load_mode_t;
211
+#define NETDATA_EBPF_LOAD_METHODS (EBPF_LOAD_LEGACY|EBPF_LOAD_CORE|EBPF_LOAD_PLAY_DICE)
212
+#define NETDATA_EBPF_LOAD_SOURCE (EBPF_LOADED_FROM_STOCK|EBPF_LOADED_FROM_USER)
213
214
typedef enum netdata_ebpf_program_loaded {
215
EBPF_LOAD_PROBE, // Attach probes on targets
@@ -274,8 +278,9 @@ extern struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em,
278
279
extern void ebpf_mount_config_name(char *filename, size_t length, char *path, const char *config);
280
extern int ebpf_load_config(struct config *config, char *filename);
277
-extern void ebpf_update_module(ebpf_module_t *em);
281
+extern void ebpf_update_module(ebpf_module_t *em, struct btf *btf_file);
282
extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em);
283
+extern void ebpf_adjust_apps_cgroup(ebpf_module_t *em, netdata_ebpf_program_loaded_t mode);
284
extern char *ebpf_find_symbol(char *search);
285
extern void ebpf_load_addresses(ebpf_addresses_t *fa, int fd);
286
extern void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm);
packaging/ebpf-co-re.checksums
+1
-1
@@ -1 +1 @@
1
-26e6244242bb744adf2ff8640e267d54931d28fdd8150a967f9acedbd569a47b netdata-ebpf-co-re-glibc-v0.9.4.1.tar.xz
1
+ab36f617b045d4740536769f84b7a527714431c02e80e15aa7fa2fe84c64d0cc netdata-ebpf-co-re-glibc-v0.9.5.tar.xz
packaging/ebpf-co-re.version
+1
-1
@@ -1 +1 @@
1
-v0.9.4.1
1
+v0.9.5
packaging/ebpf.checksums
+3
-3
@@ -1,3 +1,3 @@
1
-49a4ab9eae3c519e6869ea414e63ea765d40ea41fb4c2cc8802a96a94a47ff74 ./netdata-kernel-collector-glibc-v0.9.4.tar.xz
2
-2284eb53ff61de823800585f993f13707d24ccd4d335b8bb39bbbd43b47cde75 ./netdata-kernel-collector-musl-v0.9.4.tar.xz
3
-46663fab8e5a279e8f2d4b76400f0e27552929ef6dee92a3ed81608250a1198b ./netdata-kernel-collector-static-v0.9.4.tar.xz
1
+e7408cbfe77d570edea4c562efd631e914827a5d5ad51dab0638d7aa3e999a99 ./netdata-kernel-collector-glibc-v0.9.5.tar.xz
2
+8a0f5117d71d3b1975ad31fe51c1e2a887d66e676aa53cd5939d22192cb581a6 ./netdata-kernel-collector-musl-v0.9.5.tar.xz
3
+472e2b6cb473cea69efd1645a35589904db4eddc162a372833bde156b53ec44b ./netdata-kernel-collector-static-v0.9.5.tar.xz
packaging/ebpf.version
+1
-1
@@ -1 +1 @@
1
-v0.9.4
1
+v0.9.5