master
h 440 lines 12.8 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_COLLECTOR_EBPF_H
4 #define NETDATA_COLLECTOR_EBPF_H 1
5
6 #ifndef __FreeBSD__
7 #include <linux/perf_event.h>
8 #endif
9 #include <stdatomic.h>
10 #include <stdint.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 #include <unistd.h>
18 #include <dlfcn.h>
19
20 #include <fcntl.h>
21 #include <ctype.h>
22 #include <dirent.h>
23
24 #include "libbpf_api/ebpf.h"
25
26 #include "collectors/cgroups.plugin/sys_fs_cgroup.h"
27 #include "libnetdata/netipc/netipc_netdata.h"
28
29 #include "ebpf_apps.h"
30 #include "ebpf_functions.h"
31 #include "ebpf_cgroup.h"
32
33 #define NETDATA_EBPF_OLD_CONFIG_FILE "ebpf.conf"
34 #define NETDATA_EBPF_CONFIG_FILE "ebpf.d.conf"
35
36 extern size_t ebpf_hash_table_pids_count;
37 #ifdef LIBBPF_MAJOR_VERSION // BTF code
38 #include "cachestat.skel.h"
39 #include "dc.skel.h"
40 #include "disk.skel.h"
41 #include "fd.skel.h"
42 #include "filesystem.skel.h"
43 #include "hardirq.skel.h"
44 #include "mdflush.skel.h"
45 #include "mount.skel.h"
46 #include "process.skel.h"
47 #include "shm.skel.h"
48 #include "sync.skel.h"
49 #include "socket.skel.h"
50 #include "swap.skel.h"
51 #include "vfs.skel.h"
52
53 extern struct cachestat_bpf *cachestat_bpf_obj;
54 extern struct dc_bpf *dc_bpf_obj;
55 extern struct disk_bpf *disk_bpf_obj;
56 extern struct fd_bpf *fd_bpf_obj;
57 extern struct hardirq_bpf *hardirq_bpf_obj;
58 extern struct mount_bpf *mount_bpf_obj;
59 extern struct mdflush_bpf *mdflush_bpf_obj;
60 extern struct shm_bpf *shm_bpf_obj;
61 extern struct socket_bpf *socket_bpf_obj;
62 extern struct swap_bpf *swap_bpf_obj;
63 extern struct vfs_bpf *vfs_bpf_obj;
64 extern struct process_bpf *process_bpf_obj;
65 #endif
66
67 typedef struct netdata_syscall_stat {
68 unsigned long bytes; // total number of bytes
69 uint64_t call; // total number of calls
70 uint64_t ecall; // number of calls that returned error
71 struct netdata_syscall_stat *next; // Link list
72 } netdata_syscall_stat_t;
73
74 typedef struct netdata_publish_syscall {
75 char *dimension;
76 char *name;
77 char *algorithm;
78 unsigned long nbyte;
79 unsigned long pbyte;
80 uint64_t ncall;
81 uint64_t pcall;
82 uint64_t nerr;
83 uint64_t perr;
84 struct netdata_publish_syscall *next;
85 } netdata_publish_syscall_t;
86
87 typedef struct netdata_publish_vfs_common {
88 long write;
89 long read;
90
91 long running;
92 long zombie;
93 } netdata_publish_vfs_common_t;
94
95 typedef struct netdata_error_report {
96 char comm[16];
97 __u32 pid;
98
99 int type;
100 int err;
101 } netdata_error_report_t;
102
103 typedef struct netdata_ebpf_judy_pid {
104 ARAL *pid_table;
105
106 // Index for PIDs
107 struct { // support for multiple indexing engines
108 Pvoid_t JudyLArray; // the hash table
109 RW_SPINLOCK rw_spinlock; // protect the index
110 } index;
111 } netdata_ebpf_judy_pid_t;
112
113 typedef struct netdata_ebpf_judy_pid_stats {
114 char *cmdline;
115
116 // Index for Socket timestamp
117 struct { // support for multiple indexing engines
118 Pvoid_t JudyLArray; // the hash table
119 RW_SPINLOCK rw_spinlock; // protect the index
120 } socket_stats;
121 } netdata_ebpf_judy_pid_stats_t;
122
123 extern ebpf_module_t ebpf_modules[];
124 extern bool ebpf_program_loaded_any;
125
126 typedef struct ebpf_tracepoint {
127 bool enabled;
128 char *class;
129 char *event;
130 } ebpf_tracepoint_t;
131
132 // Copied from musl header
133 #ifndef offsetof
134 #if __GNUC__ > 3
135 #define offsetof(type, member) __builtin_offsetof(type, member)
136 #else
137 #define offsetof(type, member) ((size_t)((char *)&(((type *)0)->member) - (char *)0))
138 #endif
139 #endif
140
141 // Messages
142 #define NETDATA_EBPF_DEFAULT_FNT_NOT_FOUND "Cannot find the necessary functions to monitor"
143
144 // Chart definitions
145 #define NETDATA_EBPF_FAMILY "ebpf"
146 #define NETDATA_EBPF_IP_FAMILY "ip"
147 #define NETDATA_FILESYSTEM_FAMILY "filesystem"
148 #define NETDATA_EBPF_MOUNT_GLOBAL_FAMILY "mount_points"
149 #define NETDATA_EBPF_CHART_TYPE_LINE "line"
150 #define NETDATA_EBPF_CHART_TYPE_STACKED "stacked"
151 #define NETDATA_EBPF_MEMORY_GROUP "mem"
152 #define NETDATA_EBPF_SYSTEM_GROUP "system"
153 #define NETDATA_SYSTEM_SWAP_SUBMENU "swap"
154 #define NETDATA_SYSTEM_IPC_SHM_SUBMENU "ipc shared memory"
155 #define NETDATA_MONITORING_FAMILY "netdata"
156
157 // Statistics charts
158 #define NETDATA_EBPF_THREADS "ebpf_threads"
159 #define NETDATA_EBPF_LIFE_TIME "ebpf_life_time"
160 #define NETDATA_EBPF_LOAD_METHOD "ebpf_load_methods"
161 #define NETDATA_EBPF_IPC_USAGE "ebpf_ipc_usage"
162 #define NETDATA_EBPF_KERNEL_MEMORY "ebpf_kernel_memory"
163 #define NETDATA_EBPF_HASH_TABLES_LOADED "ebpf_hash_tables_count"
164 #define NETDATA_EBPF_HASH_TABLES_PER_CORE "ebpf_hash_tables_per_core"
165 #define NETDATA_EBPF_HASH_TABLES_GLOBAL_ELEMENTS "ebpf_hash_tables_global_elements"
166 #define NETDATA_EBPF_HASH_TABLES_INSERT_PID_ELEMENTS "ebpf_hash_tables_insert_pid_elements"
167 #define NETDATA_EBPF_HASH_TABLES_REMOVE_PID_ELEMENTS "ebpf_hash_tables_remove_pid_elements"
168
169 // Log file
170 #define NETDATA_DEVELOPER_LOG_FILE "developer.log"
171
172 // Maximum number of processors monitored on perf events
173 #define NETDATA_MAX_PROCESSOR 512
174
175 // Kernel versions calculated with the formula:
176 // R = MAJOR*65536 + MINOR*256 + PATCH
177 #define NETDATA_KERNEL_V5_3 328448
178 #define NETDATA_KERNEL_V4_15 265984
179
180 #define EBPF_SYS_CLONE_IDX 11
181 #define EBPF_MAX_MAPS 32
182
183 #define EBPF_DEFAULT_UPDATE_EVERY 10
184
185 enum ebpf_algorithms_list { NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_INCREMENTAL_IDX };
186
187 // Threads
188 void ebpf_process_thread(void *ptr);
189 void ebpf_socket_thread(void *ptr);
190
191 // Common variables
192 extern netdata_mutex_t lock;
193 extern netdata_mutex_t ebpf_exit_cleanup;
194 extern int ebpf_nprocs;
195 extern int running_on_kernel;
196 extern int isrh;
197 extern char *ebpf_plugin_dir;
198 extern int process_pid_fd;
199
200 extern netdata_mutex_t collect_data_mutex;
201
202 // Common functions
203 void ebpf_global_labels(
204 netdata_syscall_stat_t *is,
205 netdata_publish_syscall_t *pio,
206 char **dim,
207 char **name,
208 int *algorithm,
209 int end);
210
211 /**
212 * Create Chart labels
213 *
214 * @param name the label name.
215 * @param value the label value.
216 * @param origin the labeel source.
217 */
218 static inline void ebpf_create_chart_labels(char *name, char *value, int source)
219 {
220 fprintf(stdout, "CLABEL '%s' '%s' %d\n", name, value, source);
221 }
222
223 /**
224 * Commit label
225 *
226 * Write commit label to stdout
227 */
228 static inline void ebpf_commit_label()
229 {
230 fprintf(stdout, "CLABEL_COMMIT\n");
231 }
232
233 /**
234 * Write begin command on standard output
235 *
236 * @param family the chart family name
237 * @param name the chart name
238 * @param metric the chart suffix (used with apps and cgroups)
239 */
240 static inline void ebpf_write_begin_chart(const char *family, const char *name, const char *metric)
241 {
242 printf("BEGIN %s.%s%s\n", family, name, metric);
243 }
244
245 /**
246 * Write END command on stdout.
247 */
248 static inline void ebpf_write_end_chart()
249 {
250 printf("END\n");
251 }
252
253 int ebpf_enable_tracepoint(ebpf_tracepoint_t *tp);
254 int ebpf_disable_tracepoint(ebpf_tracepoint_t *tp);
255 uint32_t ebpf_enable_tracepoints(ebpf_tracepoint_t *tps);
256
257 void ebpf_pid_file(char *filename, size_t length);
258
259 #define EBPF_PROGRAMS_SECTION "ebpf programs"
260
261 #define EBPF_COMMON_UNITS_PERCENTAGE "%"
262 #define EBPF_COMMON_UNITS_CALLS_PER_SEC "calls/s"
263 #define EBPF_COMMON_UNITS_CALLS "calls"
264 #define EBPF_COMMON_UNITS_MILLISECONDS "milliseconds"
265
266 #define EBPF_CHART_ALGORITHM_ABSOLUTE "absolute"
267 #define EBPF_CHART_ALGORITHM_INCREMENTAL "incremental"
268
269 // Common variables
270 extern int debug_enabled;
271 extern struct ebpf_pid_stat *ebpf_root_of_pids;
272 extern ebpf_cgroup_target_t *ebpf_cgroup_pids;
273 extern char *ebpf_algorithms[];
274 extern struct config collector_config;
275 extern _Atomic int ebpf_cgroup_systemd_enabled;
276 extern _Atomic int ebpf_cgroup_integration_active;
277 extern _Atomic int send_cgroup_chart;
278 extern netdata_mutex_t mutex_cgroup_shm;
279 extern size_t ebpf_all_pids_count;
280 extern ebpf_plugin_stats_t plugin_statistics;
281 #ifdef LIBBPF_MAJOR_VERSION
282 extern struct btf *default_btf;
283 #else
284 extern void *default_btf;
285 #endif
286
287 extern uint32_t integration_with_collectors;
288 extern int running_on_kernel;
289 extern int isrh;
290 extern const char *btf_path;
291
292 // Socket functions and variables
293 // Common functions
294 void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr);
295 void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr);
296 void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *root);
297
298 // BPF teardown callbacks — called by main thread after all module threads have been joined
299 void ebpf_unload_legacy_bpf(ebpf_module_t *em); // legacy-only modules: process, disk, softirq, oomkill, mdflush
300 void ebpf_cachestat_unload_bpf(ebpf_module_t *em);
301 void ebpf_dcstat_unload_bpf(ebpf_module_t *em);
302 void ebpf_swap_unload_bpf(ebpf_module_t *em);
303 void ebpf_vfs_unload_bpf(ebpf_module_t *em);
304 void ebpf_filesystem_unload_bpf(ebpf_module_t *em);
305 void ebpf_mount_unload_bpf(ebpf_module_t *em);
306 void ebpf_fd_unload_bpf(ebpf_module_t *em);
307 void ebpf_shm_unload_bpf(ebpf_module_t *em);
308 void ebpf_sync_unload_bpf(ebpf_module_t *em);
309 collected_number get_value_from_structure(char *basis, size_t offset);
310 void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em);
311 void ebpf_update_disabled_plugin_stats(ebpf_module_t *em);
312 ARAL *ebpf_allocate_pid_aral(char *name, size_t size);
313 void ebpf_unload_legacy_code(struct bpf_object *objects, struct bpf_link **probe_links);
314 void ebpf_read_global_table_stats(
315 netdata_idx_t *stats,
316 netdata_idx_t *values,
317 int map_fd,
318 int maps_per_core,
319 uint32_t begin,
320 uint32_t end);
321 void **ebpf_judy_insert_unsafe(PPvoid_t arr, Word_t key);
322 netdata_ebpf_judy_pid_stats_t *ebpf_get_pid_from_judy_unsafe(PPvoid_t judy_array, uint32_t pid);
323
324 void ebpf_clean_ip_structure(ebpf_network_viewer_ip_list_t **clean);
325 void ebpf_clean_port_structure(ebpf_network_viewer_port_list_t **clean);
326 void ebpf_read_local_addresses_unsafe();
327
328 extern ebpf_filesystem_partitions_t localfs[];
329 extern ebpf_sync_syscalls_t local_syscalls[];
330 extern volatile sig_atomic_t ebpf_stop_signal;
331 extern bool ebpf_plugin_exit;
332 extern uint64_t collect_pids;
333
334 static inline void ebpf_cgroup_systemd_enabled_set(int value)
335 {
336 atomic_store_explicit(&ebpf_cgroup_systemd_enabled, value, memory_order_release);
337 }
338
339 static inline int ebpf_cgroup_systemd_enabled_get(void)
340 {
341 return atomic_load_explicit(&ebpf_cgroup_systemd_enabled, memory_order_acquire);
342 }
343
344 static inline void ebpf_cgroup_integration_active_set(int value)
345 {
346 atomic_store_explicit(&ebpf_cgroup_integration_active, value, memory_order_release);
347 }
348
349 static inline int ebpf_cgroup_integration_active_get(void)
350 {
351 return atomic_load_explicit(&ebpf_cgroup_integration_active, memory_order_acquire);
352 }
353
354 static inline void ebpf_send_cgroup_chart_set(int value)
355 {
356 atomic_store_explicit(&send_cgroup_chart, value, memory_order_release);
357 }
358
359 static inline int ebpf_send_cgroup_chart_get(void)
360 {
361 return atomic_load_explicit(&send_cgroup_chart, memory_order_acquire);
362 }
363
364 static inline bool ebpf_plugin_stop(void)
365 {
366 return __atomic_load_n(&ebpf_plugin_exit, __ATOMIC_ACQUIRE) ||
367 ebpf_stop_signal ||
368 nd_thread_signaled_to_cancel();
369 }
370
371 static inline void ebpf_mark_program_loaded(void)
372 {
373 __atomic_store_n(&ebpf_program_loaded_any, true, __ATOMIC_RELEASE);
374 }
375
376 static inline bool ebpf_program_loaded(void)
377 {
378 return __atomic_load_n(&ebpf_program_loaded_any, __ATOMIC_ACQUIRE);
379 }
380
381 // `enabled` is sampled from stats/shutdown paths without a single shared mutex.
382 // Keep those state transitions defined without changing the plugin's lock layout.
383 static inline enum ebpf_threads_status ebpf_module_enabled_get(ebpf_module_t *em)
384 {
385 return __atomic_load_n(&em->enabled, __ATOMIC_RELAXED);
386 }
387
388 static inline void ebpf_module_enabled_set(ebpf_module_t *em, enum ebpf_threads_status enabled)
389 {
390 __atomic_store_n(&em->enabled, enabled, __ATOMIC_RELAXED);
391 }
392
393 static inline bool ebpf_module_thread_has_valid_state(ebpf_module_t *em)
394 {
395 enum ebpf_threads_status enabled = ebpf_module_enabled_get(em);
396
397 if (likely(enabled == NETDATA_THREAD_EBPF_RUNNING || enabled == NETDATA_THREAD_EBPF_FUNCTION_RUNNING))
398 return true;
399
400 collector_error("Cannot start thread %s with invalid state %u.", em->info.thread_name, (unsigned int)enabled);
401 return false;
402 }
403
404 static inline bool ebpf_shm_sem_wait_or_stop(sem_t *sem)
405 {
406 if (unlikely(!sem || sem == SEM_FAILED)) {
407 errno = EINVAL;
408 return false;
409 }
410
411 while (!ebpf_plugin_stop()) {
412 struct timespec ts;
413 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
414 return false;
415
416 ts.tv_nsec += 200 * 1000 * 1000;
417 if (ts.tv_nsec >= 1000000000L) {
418 ts.tv_sec += ts.tv_nsec / 1000000000L;
419 ts.tv_nsec %= 1000000000L;
420 }
421
422 if (sem_timedwait(sem, &ts) == 0)
423 return true;
424
425 if (errno == ETIMEDOUT || errno == EINTR)
426 continue;
427
428 return false;
429 }
430
431 errno = ECANCELED;
432 return false;
433 }
434
435 void ebpf_stop_threads(int sig);
436 extern netdata_ebpf_judy_pid_t ebpf_judy_pid;
437
438 #define EBPF_MAX_SYNCHRONIZATION_TIME 300
439
440 #endif /* NETDATA_COLLECTOR_EBPF_H */