Memory CO-RE (#12684)
thiagoftsm committed
Apr 26, 2022 at 11:40 UTC
2244973a9b587c499b5f8b5f241ba08a39b5327b
12 files changed
+765
-27
collectors/ebpf.plugin/ebpf.c
+3
-3
@@ -60,7 +60,7 @@ ebpf_module_t ebpf_modules[] = {
60
.config_file = NETDATA_CACHESTAT_CONFIG_FILE,
61
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
62
NETDATA_V5_4 | NETDATA_V5_15 | NETDATA_V5_16,
63
- .load = EBPF_LOAD_LEGACY, .targets = NULL},
63
+ .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets},
64
{ .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
65
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
66
.cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
@@ -76,7 +76,7 @@ ebpf_module_t ebpf_modules[] = {
76
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
77
.config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
78
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
79
- .load = EBPF_LOAD_LEGACY, .targets = NULL},
79
+ .load = EBPF_LOAD_LEGACY, .targets = dc_targets},
80
{ .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
81
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
82
.cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -84,7 +84,7 @@ ebpf_module_t ebpf_modules[] = {
84
.pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
85
.config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
86
.kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
87
- .load = EBPF_LOAD_LEGACY, .targets = NULL},
87
+ .load = EBPF_LOAD_LEGACY, .targets = swap_targets},
88
{ .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
89
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
90
.cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
collectors/ebpf.plugin/ebpf.d/cachestat.conf
+12
-1
@@ -10,10 +10,21 @@
10
#
11
# The `pid table size` defines the maximum number of PIDs stored inside the application hash table.
12
#
13
+# The `ebpf type format` option accepts the following values :
14
+# `auto` : The eBPF collector will investigate hardware and select between the two next options.
15
+# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
16
+# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
17
+#
18
+# The `ebpf co-re tracing` option accepts the following values:
19
+# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
20
+# `probe` : This is the same as legacy code.
21
+#
22
# Uncomment lines to define specific options for thread.
14
-#[global]
23
+[global]
24
# ebpf load mode = entry
25
# apps = yes
26
# cgroups = no
27
# update every = 10
28
# pid table size = 32768
29
+ ebpf type format = auto
30
+ ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/dcstat.conf
+12
-1
@@ -8,10 +8,21 @@
8
# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9
# the setting `apps` and `cgroups` to 'no'.
10
#
11
+# The `ebpf type format` option accepts the following values :
12
+# `auto` : The eBPF collector will investigate hardware and select between the two next options.
13
+# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
14
+# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
15
+#
16
+# The `ebpf co-re tracing` option accepts the following values:
17
+# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
18
+# `probe` : This is the same as legacy code.
19
+#
20
# Uncomment lines to define specific options for thread.
12
-#[global]
21
+[global]
22
# ebpf load mode = entry
23
# apps = yes
24
# cgroups = no
25
# update every = 10
26
# pid table size = 32768
27
+ ebpf type format = auto
28
+ ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/swap.conf
+12
-1
@@ -8,10 +8,21 @@
8
# If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9
# the setting `apps` and `cgroups` to 'no'.
10
#
11
+# The `ebpf type format` option accepts the following values :
12
+# `auto` : The eBPF collector will investigate hardware and select between the two next options.
13
+# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
14
+# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
15
+#
16
+# The `ebpf co-re tracing` option accepts the following values:
17
+# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
18
+# `probe` : This is the same as legacy code.
19
+#
20
# Uncomment lines to define specific options for thread.
12
-#[global]
21
+[global]
22
# ebpf load mode = entry
23
# apps = yes
24
# cgroups = no
25
# update every = 10
26
# pid table size = 32768
27
+ ebpf type format = auto
28
+ ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf_cachestat.c
+302
-7
@@ -45,6 +45,248 @@ struct config cachestat_config = { .first_section = NULL,
45
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
46
.rwlock = AVL_LOCK_INITIALIZER } };
47
48
+netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE},
49
+ {.name = "mark_page_accessed", .mode = EBPF_LOAD_TRAMPOLINE},
50
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE},
51
+ {.name = "mark_buffer_dirty", .mode = EBPF_LOAD_TRAMPOLINE},
52
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
53
+
54
+#ifdef LIBBPF_MAJOR_VERSION
55
+#include "includes/cachestat.skel.h" // BTF code
56
+
57
+static struct cachestat_bpf *bpf_obj = NULL;
58
+
59
+/**
60
+ * Disable probe
61
+ *
62
+ * Disable all probes to use exclusively another method.
63
+ *
64
+ * @param obj is the main structure for bpf objects
65
+ */
66
+static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj)
67
+{
68
+ bpf_program__set_autoload(obj->progs.netdata_add_to_page_cache_lru_kprobe, false);
69
+ bpf_program__set_autoload(obj->progs.netdata_mark_page_accessed_kprobe, false);
70
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
71
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
72
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
73
+ bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_kprobe, false);
74
+}
75
+
76
+/*
77
+ * Disable specific probe
78
+ *
79
+ * Disable probes according the kernel version
80
+ *
81
+ * @param obj is the main structure for bpf objects
82
+ */
83
+static void ebpf_cachestat_disable_specific_probe(struct cachestat_bpf *obj)
84
+{
85
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
86
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
87
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
88
+ } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
89
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
90
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
91
+ } else {
92
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
93
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
94
+ }
95
+}
96
+
97
+/*
98
+ * Disable trampoline
99
+ *
100
+ * Disable all trampoline to use exclusively another method.
101
+ *
102
+ * @param obj is the main structure for bpf objects.
103
+ */
104
+static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj)
105
+{
106
+ bpf_program__set_autoload(obj->progs.netdata_add_to_page_cache_lru_fentry, false);
107
+ bpf_program__set_autoload(obj->progs.netdata_mark_page_accessed_fentry, false);
108
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
109
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
110
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
111
+ bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_fentry, false);
112
+}
113
+
114
+/*
115
+ * Disable specific trampoline
116
+ *
117
+ * Disable trampoline according to kernel version.
118
+ *
119
+ * @param obj is the main structure for bpf objects.
120
+ */
121
+static void ebpf_cachestat_disable_specific_trampoline(struct cachestat_bpf *obj)
122
+{
123
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
124
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
125
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
126
+ } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
127
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
128
+ bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
129
+ } else {
130
+ bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
131
+ bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
132
+ }
133
+}
134
+
135
+/**
136
+ * Set trampoline target
137
+ *
138
+ * Set the targets we will monitor.
139
+ *
140
+ * @param obj is the main structure for bpf objects.
141
+ */
142
+static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj)
143
+{
144
+ bpf_program__set_attach_target(obj->progs.netdata_add_to_page_cache_lru_fentry, 0,
145
+ cachestat_targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].name);
146
+
147
+ bpf_program__set_attach_target(obj->progs.netdata_mark_page_accessed_fentry, 0,
148
+ cachestat_targets[NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED].name);
149
+
150
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
151
+ bpf_program__set_attach_target(obj->progs.netdata_folio_mark_dirty_fentry, 0,
152
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
153
+ } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
154
+ bpf_program__set_attach_target(obj->progs.netdata_set_page_dirty_fentry, 0,
155
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
156
+ } else {
157
+ bpf_program__set_attach_target(obj->progs.netdata_account_page_dirtied_fentry, 0,
158
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
159
+ }
160
+
161
+ bpf_program__set_attach_target(obj->progs.netdata_mark_buffer_dirty_fentry, 0,
162
+ cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
163
+}
164
+
165
+/**
166
+ * Mount Attach Probe
167
+ *
168
+ * Attach probes to target
169
+ *
170
+ * @param obj is the main structure for bpf objects.
171
+ *
172
+ * @return It returns 0 on success and -1 otherwise.
173
+ */
174
+static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
175
+{
176
+ obj->links.netdata_add_to_page_cache_lru_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_add_to_page_cache_lru_kprobe,
177
+ false,
178
+ cachestat_targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].name);
179
+ int ret = libbpf_get_error(obj->links.netdata_add_to_page_cache_lru_kprobe);
180
+ if (ret)
181
+ return -1;
182
+
183
+ obj->links.netdata_mark_page_accessed_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_mark_page_accessed_kprobe,
184
+ false,
185
+ cachestat_targets[NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED].name);
186
+ ret = libbpf_get_error(obj->links.netdata_mark_page_accessed_kprobe);
187
+ if (ret)
188
+ return -1;
189
+
190
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
191
+ obj->links.netdata_folio_mark_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_folio_mark_dirty_kprobe,
192
+ false,
193
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
194
+ ret = libbpf_get_error(obj->links.netdata_folio_mark_dirty_kprobe);
195
+ } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
196
+ obj->links.netdata_set_page_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_set_page_dirty_kprobe,
197
+ false,
198
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
199
+ ret = libbpf_get_error(obj->links.netdata_set_page_dirty_kprobe);
200
+ } else {
201
+ obj->links.netdata_account_page_dirtied_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_account_page_dirtied_kprobe,
202
+ false,
203
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
204
+ ret = libbpf_get_error(obj->links.netdata_account_page_dirtied_kprobe);
205
+ }
206
+
207
+ if (ret)
208
+ return -1;
209
+
210
+ obj->links.netdata_mark_buffer_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_mark_buffer_dirty_kprobe,
211
+ false,
212
+ cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
213
+ ret = libbpf_get_error(obj->links.netdata_mark_buffer_dirty_kprobe);
214
+ if (ret)
215
+ return -1;
216
+
217
+ return 0;
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_cachestat_adjust_map_size(struct cachestat_bpf *obj, ebpf_module_t *em)
229
+{
230
+ ebpf_update_map_size(obj->maps.cstat_pid, &cachestat_maps[NETDATA_CACHESTAT_PID_STATS],
231
+ em, bpf_map__name(obj->maps.cstat_pid));
232
+}
233
+
234
+/**
235
+ * Set hash tables
236
+ *
237
+ * Set the values for maps according the value given by kernel.
238
+ *
239
+ * @param obj is the main structure for bpf objects.
240
+ */
241
+static void ebpf_cachestat_set_hash_tables(struct cachestat_bpf *obj)
242
+{
243
+ cachestat_maps[NETDATA_CACHESTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.cstat_global);
244
+ cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.cstat_pid);
245
+ cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd = bpf_map__fd(obj->maps.cstat_ctrl);
246
+}
247
+
248
+/**
249
+ * Load and attach
250
+ *
251
+ * Load and attach the eBPF code in kernel.
252
+ *
253
+ * @param obj is the main structure for bpf objects.
254
+ * @param em structure with configuration
255
+ *
256
+ * @return it returns 0 on succes and -1 otherwise
257
+ */
258
+static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf_module_t *em)
259
+{
260
+ netdata_ebpf_targets_t *mt = em->targets;
261
+ netdata_ebpf_program_loaded_t test = mt[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode;
262
+
263
+ if (test == EBPF_LOAD_TRAMPOLINE) {
264
+ ebpf_cachestat_disable_probe(obj);
265
+ ebpf_cachestat_disable_specific_trampoline(obj);
266
+
267
+ netdata_set_trampoline_target(obj);
268
+ } else {
269
+ ebpf_cachestat_disable_trampoline(obj);
270
+ ebpf_cachestat_disable_specific_probe(obj);
271
+ }
272
+
273
+ int ret = cachestat_bpf__load(obj);
274
+ if (ret) {
275
+ return ret;
276
+ }
277
+
278
+ ebpf_cachestat_adjust_map_size(obj, em);
279
+
280
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? cachestat_bpf__attach(obj) : ebpf_cachestat_attach_probe(obj);
281
+ if (!ret) {
282
+ ebpf_cachestat_set_hash_tables(obj);
283
+
284
+ ebpf_update_controller(cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
285
+ }
286
+
287
+ return ret;
288
+}
289
+#endif
290
/*****************************************************************
291
*
292
* FUNCTIONS TO CLOSE THE THREAD
@@ -98,6 +340,10 @@ static void ebpf_cachestat_cleanup(void *ptr)
340
}
341
bpf_object__close(objects);
342
}
343
+#ifdef LIBBPF_MAJOR_VERSION
344
+ else if (bpf_obj)
345
+ cachestat_bpf__destroy(bpf_obj);
346
+#endif
347
}
348
349
/*****************************************************************
@@ -961,6 +1207,54 @@ static void ebpf_cachestat_allocate_global_vectors(int apps)
1207
*
1208
*****************************************************************/
1209
1210
+/**
1211
+ * Update Internal value
1212
+ *
1213
+ * Update values used during runtime.
1214
+ */
1215
+static void ebpf_cachestat_set_internal_value()
1216
+{
1217
+ static char *account_page[] = { "account_page_dirtied", "__set_page_dirty", "__folio_mark_dirty" };
1218
+ if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16)
1219
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_FOLIO_DIRTY];
1220
+ else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15)
1221
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY];
1222
+ else
1223
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY];
1224
+}
1225
+
1226
+/*
1227
+ * Load BPF
1228
+ *
1229
+ * Load BPF files.
1230
+ *
1231
+ * @param em the structure with configuration
1232
+ */
1233
+static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1234
+{
1235
+ int ret = 0;
1236
+ if (em->load == EBPF_LOAD_LEGACY) {
1237
+ probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1238
+ if (!probe_links) {
1239
+ ret = -1;
1240
+ }
1241
+ }
1242
+#ifdef LIBBPF_MAJOR_VERSION
1243
+ else {
1244
+ bpf_obj = cachestat_bpf__open();
1245
+ if (!bpf_obj)
1246
+ ret = -1;
1247
+ else
1248
+ ret = ebpf_cachestat_load_and_attach(bpf_obj, em);
1249
+ }
1250
+#endif
1251
+
1252
+ if (ret)
1253
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1254
+
1255
+ return ret;
1256
+}
1257
+
1258
/**
1259
* Cachestat thread
1260
*
@@ -982,17 +1276,17 @@ void *ebpf_cachestat_thread(void *ptr)
1276
if (!em->enabled)
1277
goto endcachestat;
1278
985
- pthread_mutex_lock(&lock);
986
- ebpf_cachestat_allocate_global_vectors(em->apps_charts);
1279
+ ebpf_cachestat_set_internal_value();
1280
988
- probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
989
- if (!probe_links) {
990
- pthread_mutex_unlock(&lock);
1281
+#ifdef LIBBPF_MAJOR_VERSION
1282
+ ebpf_adjust_thread_load(em, default_btf);
1283
+#endif
1284
+ if (ebpf_cachestat_load_bpf(em)) {
1285
em->enabled = CONFIG_BOOLEAN_NO;
1286
goto endcachestat;
1287
}
1288
995
- ebpf_update_stats(&plugin_statistics, em);
1289
+ ebpf_cachestat_allocate_global_vectors(em->apps_charts);
1290
1291
int algorithms[NETDATA_CACHESTAT_END] = {
1292
NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
@@ -1002,8 +1296,9 @@ void *ebpf_cachestat_thread(void *ptr)
1296
cachestat_counter_dimension_name, cachestat_counter_dimension_name,
1297
algorithms, NETDATA_CACHESTAT_END);
1298
1299
+ pthread_mutex_lock(&lock);
1300
+ ebpf_update_stats(&plugin_statistics, em);
1301
ebpf_create_memory_charts(em);
1006
-
1302
pthread_mutex_unlock(&lock);
1303
1304
cachestat_collector(em);
collectors/ebpf.plugin/ebpf_cachestat.h
+9
-1
@@ -45,6 +45,12 @@ enum cachestat_counters {
45
NETDATA_CACHESTAT_END
46
};
47
48
+enum cachestat_account_dirty_pages {
49
+ NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY,
50
+ NETDATA_CACHESTAT_SET_PAGE_DIRTY,
51
+ NETDATA_CACHESTAT_FOLIO_DIRTY
52
+};
53
+
54
enum cachestat_indexes {
55
NETDATA_CACHESTAT_IDX_RATIO,
56
NETDATA_CACHESTAT_IDX_DIRTY,
@@ -54,7 +60,8 @@ enum cachestat_indexes {
60
61
enum cachestat_tables {
62
NETDATA_CACHESTAT_GLOBAL_STATS,
57
- NETDATA_CACHESTAT_PID_STATS
63
+ NETDATA_CACHESTAT_PID_STATS,
64
+ NETDATA_CACHESTAT_CTRL
65
};
66
67
typedef struct netdata_publish_cachestat_pid {
@@ -78,5 +85,6 @@ extern void *ebpf_cachestat_thread(void *ptr);
85
extern void clean_cachestat_pid_structures();
86
87
extern struct config cachestat_config;
88
+extern netdata_ebpf_targets_t cachestat_targets[];
89
90
#endif // NETDATA_EBPF_CACHESTAT_H
collectors/ebpf.plugin/ebpf_dcstat.c
+216
-8
@@ -49,6 +49,179 @@ static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_look
49
.retprobe = CONFIG_BOOLEAN_NO},
50
{.program_name = NULL}};
51
52
+netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOAD_TRAMPOLINE},
53
+ {.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
54
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
55
+
56
+#ifdef LIBBPF_MAJOR_VERSION
57
+#include "includes/dc.skel.h" // BTF code
58
+
59
+static struct dc_bpf *bpf_obj = NULL;
60
+
61
+/**
62
+ * Disable probe
63
+ *
64
+ * Disable all probes to use exclusively another method.
65
+ *
66
+ * @param obj is the main structure for bpf objects
67
+ */
68
+static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
69
+{
70
+ bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
71
+ bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
72
+}
73
+
74
+/*
75
+ * Disable trampoline
76
+ *
77
+ * Disable all trampoline to use exclusively another method.
78
+ *
79
+ * @param obj is the main structure for bpf objects.
80
+ */
81
+static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
82
+{
83
+ bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
84
+ bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
85
+}
86
+
87
+/**
88
+ * Set trampoline target
89
+ *
90
+ * Set the targets we will monitor.
91
+ *
92
+ * @param obj is the main structure for bpf objects.
93
+ */
94
+static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
95
+{
96
+ bpf_program__set_attach_target(obj->progs.netdata_lookup_fast_fentry, 0,
97
+ dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name);
98
+
99
+ bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
100
+ dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
101
+}
102
+
103
+/**
104
+ * Mount Attach Probe
105
+ *
106
+ * Attach probes to target
107
+ *
108
+ * @param obj is the main structure for bpf objects.
109
+ *
110
+ * @return It returns 0 on success and -1 otherwise.
111
+ */
112
+static int ebpf_dc_attach_probes(struct dc_bpf *obj)
113
+{
114
+ obj->links.netdata_d_lookup_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_d_lookup_kretprobe,
115
+ true,
116
+ dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
117
+ int ret = libbpf_get_error(obj->links.netdata_d_lookup_kretprobe);
118
+ if (ret)
119
+ return -1;
120
+
121
+ char *lookup_name = (dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional) ?
122
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional :
123
+ dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name ;
124
+
125
+ obj->links.netdata_lookup_fast_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_lookup_fast_kprobe,
126
+ false,
127
+ lookup_name);
128
+ ret = libbpf_get_error(obj->links.netdata_lookup_fast_kprobe);
129
+ if (ret)
130
+ return -1;
131
+
132
+ return 0;
133
+}
134
+
135
+/**
136
+ * Adjust Map Size
137
+ *
138
+ * Resize maps according input from users.
139
+ *
140
+ * @param obj is the main structure for bpf objects.
141
+ * @param em structure with configuration
142
+ */
143
+static void ebpf_dc_adjust_map_size(struct dc_bpf *obj, ebpf_module_t *em)
144
+{
145
+ ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
146
+ em, bpf_map__name(obj->maps.dcstat_pid));
147
+}
148
+
149
+/**
150
+ * Set hash tables
151
+ *
152
+ * Set the values for maps according the value given by kernel.
153
+ *
154
+ * @param obj is the main structure for bpf objects.
155
+ */
156
+static void ebpf_dc_set_hash_tables(struct dc_bpf *obj)
157
+{
158
+ dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_global);
159
+ dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_pid);
160
+ dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd = bpf_map__fd(obj->maps.dcstat_ctrl);
161
+}
162
+
163
+/**
164
+ * Update Load
165
+ *
166
+ * For directory cache, some distributions change the function name, and we do not have condition to use
167
+ * TRAMPOLINE like other functions.
168
+ *
169
+ * @param em structure with configuration
170
+ *
171
+ * @return When then symbols were not modified, it returns TRAMPOLINE, else it returns RETPROBE.
172
+ */
173
+netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
174
+{
175
+ if (!strcmp(dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional,
176
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach))
177
+ return EBPF_LOAD_TRAMPOLINE;
178
+
179
+ if (em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode != EBPF_LOAD_RETPROBE)
180
+ info("When your kernel was compiled the symbol %s was modified, instead to use `trampoline`, the plugin will use `probes`.",
181
+ dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach);
182
+
183
+ return EBPF_LOAD_RETPROBE;
184
+}
185
+
186
+/**
187
+ * Load and attach
188
+ *
189
+ * Load and attach the eBPF code in kernel.
190
+ *
191
+ * @param obj is the main structure for bpf objects.
192
+ * @param em structure with configuration
193
+ *
194
+ * @return it returns 0 on succes and -1 otherwise
195
+ */
196
+static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
197
+{
198
+ netdata_ebpf_program_loaded_t test = ebpf_dc_update_load(em);
199
+ if (test == EBPF_LOAD_TRAMPOLINE) {
200
+ ebpf_dc_disable_probes(obj);
201
+
202
+ ebpf_dc_set_trampoline_target(obj);
203
+ } else {
204
+ ebpf_dc_disable_trampoline(obj);
205
+ }
206
+
207
+ int ret = dc_bpf__load(obj);
208
+ if (ret) {
209
+ return ret;
210
+ }
211
+
212
+ ebpf_dc_adjust_map_size(obj, em);
213
+
214
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj);
215
+ if (!ret) {
216
+ ebpf_dc_set_hash_tables(obj);
217
+
218
+ ebpf_update_controller(dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd, em);
219
+ }
220
+
221
+ return ret;
222
+}
223
+#endif
224
+
225
/*****************************************************************
226
*
227
* COMMON FUNCTIONS
@@ -141,6 +314,10 @@ static void ebpf_dcstat_cleanup(void *ptr)
314
}
315
bpf_object__close(objects);
316
}
317
+#ifdef LIBBPF_MAJOR_VERSION
318
+ else if (bpf_obj)
319
+ dc_bpf__destroy(bpf_obj);
320
+#endif
321
}
322
323
/*****************************************************************
@@ -937,6 +1114,38 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
1114
*
1115
*****************************************************************/
1116
1117
+/*
1118
+ * Load BPF
1119
+ *
1120
+ * Load BPF files.
1121
+ *
1122
+ * @param em the structure with configuration
1123
+ */
1124
+static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1125
+{
1126
+ int ret = 0;
1127
+ if (em->load == EBPF_LOAD_LEGACY) {
1128
+ probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1129
+ if (!probe_links) {
1130
+ ret = -1;
1131
+ }
1132
+ }
1133
+#ifdef LIBBPF_MAJOR_VERSION
1134
+ else {
1135
+ bpf_obj = dc_bpf__open();
1136
+ if (!bpf_obj)
1137
+ ret = -1;
1138
+ else
1139
+ ret = ebpf_dc_load_and_attach(bpf_obj, em);
1140
+ }
1141
+#endif
1142
+
1143
+ if (ret)
1144
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1145
+
1146
+ return ret;
1147
+}
1148
+
1149
/**
1150
* Directory Cache thread
1151
*
@@ -960,17 +1169,16 @@ void *ebpf_dcstat_thread(void *ptr)
1169
if (!em->enabled)
1170
goto enddcstat;
1171
963
- ebpf_dcstat_allocate_global_vectors(em->apps_charts);
964
-
965
- pthread_mutex_lock(&lock);
966
-
967
- probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
968
- if (!probe_links) {
969
- pthread_mutex_unlock(&lock);
1172
+#ifdef LIBBPF_MAJOR_VERSION
1173
+ ebpf_adjust_thread_load(em, default_btf);
1174
+#endif
1175
+ if (ebpf_dcstat_load_bpf(em)) {
1176
em->enabled = CONFIG_BOOLEAN_NO;
1177
goto enddcstat;
1178
}
1179
1180
+ ebpf_dcstat_allocate_global_vectors(em->apps_charts);
1181
+
1182
int algorithms[NETDATA_DCSTAT_IDX_END] = {
1183
NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
1184
NETDATA_EBPF_ABSOLUTE_IDX
@@ -980,9 +1188,9 @@ void *ebpf_dcstat_thread(void *ptr)
1188
dcstat_counter_dimension_name, dcstat_counter_dimension_name,
1189
algorithms, NETDATA_DCSTAT_IDX_END);
1190
1191
+ pthread_mutex_lock(&lock);
1192
ebpf_create_filesystem_charts(em->update_every);
1193
ebpf_update_stats(&plugin_statistics, em);
985
-
1194
pthread_mutex_unlock(&lock);
1195
1196
dcstat_collector(em);
collectors/ebpf.plugin/ebpf_dcstat.h
+8
-1
@@ -42,7 +42,8 @@ enum directory_cache_indexes {
42
43
enum directory_cache_tables {
44
NETDATA_DCSTAT_GLOBAL_STATS,
45
- NETDATA_DCSTAT_PID_STATS
45
+ NETDATA_DCSTAT_PID_STATS,
46
+ NETDATA_DCSTAT_CTRL
47
};
48
49
// variables
@@ -55,6 +56,11 @@ enum directory_cache_counters {
56
NETDATA_DIRECTORY_CACHE_END
57
};
58
59
+enum directory_cache_targets {
60
+ NETDATA_DC_TARGET_LOOKUP_FAST,
61
+ NETDATA_DC_TARGET_D_LOOKUP
62
+};
63
+
64
typedef struct netdata_publish_dcstat_pid {
65
uint64_t cache_access;
66
uint64_t file_system;
@@ -73,5 +79,6 @@ extern void *ebpf_dcstat_thread(void *ptr);
79
extern void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr);
80
extern void clean_dcstat_pid_structures();
81
extern struct config dcstat_config;
82
+extern netdata_ebpf_targets_t dc_targets[];
83
84
#endif // NETDATA_EBPF_DCSTAT_H
collectors/ebpf.plugin/ebpf_swap.c
+188
-2
@@ -41,6 +41,154 @@ static struct bpf_object *objects = NULL;
41
struct netdata_static_thread swap_threads = {"SWAP KERNEL", NULL, NULL, 1,
42
NULL, NULL, NULL};
43
44
+netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
45
+ {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
46
+ {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
47
+
48
+#ifdef LIBBPF_MAJOR_VERSION
49
+#include "includes/swap.skel.h" // BTF code
50
+
51
+static struct swap_bpf *bpf_obj = NULL;
52
+
53
+/**
54
+ * Disable probe
55
+ *
56
+ * Disable all probes to use exclusively another method.
57
+ *
58
+ * @param obj is the main structure for bpf objects
59
+ */
60
+static void ebpf_swap_disable_probe(struct swap_bpf *obj)
61
+{
62
+ bpf_program__set_autoload(obj->progs.netdata_swap_readpage_probe, false);
63
+ bpf_program__set_autoload(obj->progs.netdata_swap_writepage_probe, false);
64
+}
65
+
66
+/*
67
+ * Disable trampoline
68
+ *
69
+ * Disable all trampoline to use exclusively another method.
70
+ *
71
+ * @param obj is the main structure for bpf objects.
72
+ */
73
+static void ebpf_swap_disable_trampoline(struct swap_bpf *obj)
74
+{
75
+ bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false);
76
+ bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false);
77
+}
78
+
79
+/**
80
+ * Set trampoline target
81
+ *
82
+ * Set the targets we will monitor.
83
+ *
84
+ * @param obj is the main structure for bpf objects.
85
+ */
86
+static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj)
87
+{
88
+ bpf_program__set_attach_target(obj->progs.netdata_swap_readpage_fentry, 0,
89
+ swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
90
+
91
+ bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0,
92
+ swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
93
+}
94
+
95
+/**
96
+ * Mount Attach Probe
97
+ *
98
+ * Attach probes to target
99
+ *
100
+ * @param obj is the main structure for bpf objects.
101
+ *
102
+ * @return It returns 0 on success and -1 otherwise.
103
+ */
104
+static int ebpf_swap_attach_kprobe(struct swap_bpf *obj)
105
+{
106
+ obj->links.netdata_swap_readpage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_readpage_probe,
107
+ false,
108
+ swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
109
+ int ret = libbpf_get_error(obj->links.netdata_swap_readpage_probe);
110
+ if (ret)
111
+ return -1;
112
+
113
+ obj->links.netdata_swap_writepage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_writepage_probe,
114
+ false,
115
+ swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
116
+ ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe);
117
+ if (ret)
118
+ return -1;
119
+
120
+ return 0;
121
+}
122
+
123
+/**
124
+ * Set hash tables
125
+ *
126
+ * Set the values for maps according the value given by kernel.
127
+ *
128
+ * @param obj is the main structure for bpf objects.
129
+ */
130
+static void ebpf_swap_set_hash_tables(struct swap_bpf *obj)
131
+{
132
+ swap_maps[NETDATA_PID_SWAP_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_pid_swap);
133
+ swap_maps[NETDATA_SWAP_CONTROLLER].map_fd = bpf_map__fd(obj->maps.swap_ctrl);
134
+ swap_maps[NETDATA_SWAP_GLOBAL_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_swap);
135
+}
136
+
137
+/**
138
+ * Adjust Map Size
139
+ *
140
+ * Resize maps according input from users.
141
+ *
142
+ * @param obj is the main structure for bpf objects.
143
+ * @param em structure with configuration
144
+ */
145
+static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em)
146
+{
147
+ ebpf_update_map_size(obj->maps.tbl_pid_swap, &swap_maps[NETDATA_PID_SWAP_TABLE],
148
+ em, bpf_map__name(obj->maps.tbl_pid_swap));
149
+}
150
+
151
+/**
152
+ * Load and attach
153
+ *
154
+ * Load and attach the eBPF code in kernel.
155
+ *
156
+ * @param obj is the main structure for bpf objects.
157
+ * @param em structure with configuration
158
+ *
159
+ * @return it returns 0 on succes and -1 otherwise
160
+ */
161
+static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t *em)
162
+{
163
+ netdata_ebpf_targets_t *mt = em->targets;
164
+ netdata_ebpf_program_loaded_t test = mt[NETDATA_KEY_SWAP_READPAGE_CALL].mode;
165
+
166
+ if (test == EBPF_LOAD_TRAMPOLINE) {
167
+ ebpf_swap_disable_probe(obj);
168
+
169
+ ebpf_swap_set_trampoline_target(obj);
170
+ } else {
171
+ ebpf_swap_disable_trampoline(obj);
172
+ }
173
+
174
+ int ret = swap_bpf__load(obj);
175
+ if (ret) {
176
+ return ret;
177
+ }
178
+
179
+ ebpf_swap_adjust_map_size(obj, em);
180
+
181
+ ret = (test == EBPF_LOAD_TRAMPOLINE) ? swap_bpf__attach(obj) : ebpf_swap_attach_kprobe(obj);
182
+ if (!ret) {
183
+ ebpf_swap_set_hash_tables(obj);
184
+
185
+ ebpf_update_controller(swap_maps[NETDATA_SWAP_CONTROLLER].map_fd, em);
186
+ }
187
+
188
+ return ret;
189
+}
190
+#endif
191
+
192
/*****************************************************************
193
*
194
* FUNCTIONS TO CLOSE THE THREAD
@@ -92,6 +240,10 @@ static void ebpf_swap_cleanup(void *ptr)
240
}
241
bpf_object__close(objects);
242
}
243
+#ifdef LIBBPF_MAJOR_VERSION
244
+ else if (bpf_obj)
245
+ swap_bpf__destroy(bpf_obj);
246
+#endif
247
}
248
249
/*****************************************************************
@@ -654,6 +806,38 @@ static void ebpf_create_swap_charts(int update_every)
806
update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
807
}
808
809
+/*
810
+ * Load BPF
811
+ *
812
+ * Load BPF files.
813
+ *
814
+ * @param em the structure with configuration
815
+ */
816
+static int ebpf_swap_load_bpf(ebpf_module_t *em)
817
+{
818
+ int ret = 0;
819
+ if (em->load == EBPF_LOAD_LEGACY) {
820
+ probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
821
+ if (!probe_links) {
822
+ ret = -1;
823
+ }
824
+ }
825
+#ifdef LIBBPF_MAJOR_VERSION
826
+ else {
827
+ bpf_obj = swap_bpf__open();
828
+ if (!bpf_obj)
829
+ ret = -1;
830
+ else
831
+ ret = ebpf_swap_load_and_attach(bpf_obj, em);
832
+ }
833
+#endif
834
+
835
+ if (ret)
836
+ error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
837
+
838
+ return ret;
839
+}
840
+
841
/**
842
* SWAP thread
843
*
@@ -675,8 +859,10 @@ void *ebpf_swap_thread(void *ptr)
859
if (!em->enabled)
860
goto endswap;
861
678
- probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
679
- if (!probe_links) {
862
+#ifdef LIBBPF_MAJOR_VERSION
863
+ ebpf_adjust_thread_load(em, default_btf);
864
+#endif
865
+ if (ebpf_swap_load_bpf(em)) {
866
em->enabled = CONFIG_BOOLEAN_NO;
867
goto endswap;
868
}
collectors/ebpf.plugin/ebpf_swap.h
+1
@@ -49,5 +49,6 @@ extern void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr);
49
extern void clean_swap_pid_structures();
50
51
extern struct config swap_config;
52
+extern netdata_ebpf_targets_t swap_targets[];
53
54
#endif
packaging/ebpf-co-re.checksums
+1
-1
@@ -1 +1 @@
1
-0e3a6928a9b69a1a1e7911635b6d6fda44e78b67a3e38daad9d8cc3babfcdfee netdata-ebpf-co-re-glibc-v0.9.3.2.tar.xz
1
+9181063ec4a40f1b2ce5d7ac702eb9de233d127c6e21aac8a3d3f7c185502726 netdata-ebpf-co-re-glibc-v0.9.3.3.tar.xz
packaging/ebpf-co-re.version
+1
-1
@@ -1 +1 @@
1
-v0.9.3.2
1
+v0.9.3.3