master
h 334 lines 9.89 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_EBPF_APPS_H
4 #define NETDATA_EBPF_APPS_H 1
5
6 #include "libnetdata/libnetdata.h"
7 #include "collectors/collectors-ipc/ebpf-ipc.h"
8 #include "libbpf_api/ebpf.h"
9
10 #define NETDATA_APPS_FAMILY "apps"
11 #define NETDATA_APP_FAMILY "app"
12 #define NETDATA_APPS_FILE_GROUP "file_access"
13 #define NETDATA_APPS_FILE_FDS "fds"
14 #define NETDATA_APPS_PROCESS_GROUP "process"
15 #define NETDATA_APPS_NET_GROUP "net"
16 #define NETDATA_APPS_IPC_SHM_GROUP "ipc shm"
17
18 #include "ebpf_process.h"
19 #include "ebpf_dcstat.h"
20 #include "ebpf_disk.h"
21 #include "ebpf_fd.h"
22 #include "ebpf_filesystem.h"
23 #include "ebpf_functions.h"
24 #include "ebpf_hardirq.h"
25 #include "ebpf_cachestat.h"
26 #include "ebpf_mdflush.h"
27 #include "ebpf_mount.h"
28 #include "ebpf_oomkill.h"
29 #include "ebpf_shm.h"
30 #include "ebpf_socket.h"
31 #include "ebpf_softirq.h"
32 #include "ebpf_sync.h"
33 #include "ebpf_swap.h"
34 #include "ebpf_vfs.h"
35
36 #include "ebpf_socket_ipc.h"
37
38 #define EBPF_MAX_COMPARE_NAME 95
39 #define EBPF_MAX_NAME 100
40
41 #define EBPF_CLEANUP_FACTOR 2
42
43 enum ebpf_main_index {
44 EBPF_MODULE_PROCESS_IDX,
45 EBPF_MODULE_SOCKET_IDX,
46 EBPF_MODULE_CACHESTAT_IDX,
47 EBPF_MODULE_SYNC_IDX,
48 EBPF_MODULE_DCSTAT_IDX,
49 EBPF_MODULE_SWAP_IDX,
50 EBPF_MODULE_VFS_IDX,
51 EBPF_MODULE_FILESYSTEM_IDX,
52 EBPF_MODULE_DISK_IDX,
53 EBPF_MODULE_MOUNT_IDX,
54 EBPF_MODULE_FD_IDX,
55 EBPF_MODULE_HARDIRQ_IDX,
56 EBPF_MODULE_SOFTIRQ_IDX,
57 EBPF_MODULE_OOMKILL_IDX,
58 EBPF_MODULE_SHM_IDX,
59 EBPF_MODULE_MDFLUSH_IDX,
60 EBPF_MODULE_FUNCTION_IDX,
61 /* THREADS MUST BE INCLUDED BEFORE THIS COMMENT */
62 EBPF_OPTION_ALL_CHARTS,
63 EBPF_OPTION_VERSION,
64 EBPF_OPTION_HELP,
65 EBPF_OPTION_GLOBAL_CHART,
66 EBPF_OPTION_RETURN_MODE,
67 EBPF_OPTION_LEGACY,
68 EBPF_OPTION_CORE,
69 EBPF_OPTION_UNITTEST
70 };
71
72 // ----------------------------------------------------------------------------
73 // pid_stat
74 //
75 struct ebpf_target {
76 char compare[EBPF_MAX_COMPARE_NAME + 1];
77 uint32_t comparehash;
78 size_t comparelen;
79
80 char id[EBPF_MAX_NAME + 1];
81 uint32_t idhash;
82 uint32_t charts_created;
83
84 char name[EBPF_MAX_NAME + 1];
85 char clean_name[EBPF_MAX_NAME + 1]; // sanitized name used in chart id (need to replace at least dots)
86
87 // Changes made to simplify integration between apps and eBPF.
88 netdata_publish_cachestat_t cachestat;
89 netdata_publish_dcstat_t dcstat;
90 netdata_publish_swap_t swap;
91 netdata_publish_vfs_t vfs;
92 netdata_fd_stat_t fd;
93 netdata_publish_shm_t shm;
94 ebpf_process_stat_t process;
95 ebpf_socket_publish_apps_t socket;
96
97 kernel_uint_t starttime;
98 kernel_uint_t collected_starttime;
99
100 unsigned int processes; // how many processes have been merged to this
101 int exposed; // if set, we have sent this to netdata
102 int hidden; // if set, we set the hidden flag on the dimension
103 int debug_enabled;
104 int ends_with;
105 int starts_with; // if set, the compare string matches only the
106 // beginning of the command
107
108 struct ebpf_pid_on_target *root_pid; // list of aggregated pids for target debugging
109
110 struct ebpf_target *target; // the one that will be reported to netdata
111 struct ebpf_target *next;
112 };
113 extern struct ebpf_target *apps_groups_default_target;
114 extern struct ebpf_target *apps_groups_root_target;
115 extern struct ebpf_target *users_root_target;
116 extern struct ebpf_target *groups_root_target;
117 extern uint64_t collect_pids;
118
119 void ebpf_reset_pid_map_fds(void);
120 void ebpf_set_pid_map_fd(int idx, int fd);
121 int ebpf_get_pid_map_fd(int idx);
122
123 // ebpf_pid_data
124 typedef struct __attribute__((packed)) ebpf_pid_data {
125 uint32_t pid;
126 uint32_t ppid;
127 uint64_t thread_collecting;
128
129 char comm[EBPF_MAX_COMPARE_NAME + 1];
130 char *cmdline;
131
132 uint32_t has_proc_file;
133 uint32_t not_updated;
134 int children_count; // number of processes directly referencing this
135 int merged;
136 int sortlist; // higher numbers = top on the process tree
137
138 struct ebpf_target *target; // the one that will be reported to netdata
139 struct ebpf_pid_data *parent;
140 struct ebpf_pid_data *prev;
141 struct ebpf_pid_data *next;
142
143 netdata_publish_fd_stat_t *fd;
144 netdata_publish_swap_t *swap;
145 netdata_publish_shm_t *shm;
146 netdata_publish_dcstat_t *dc;
147 netdata_publish_vfs_t *vfs;
148 netdata_publish_cachestat_t *cachestat;
149 ebpf_publish_process_t *process;
150 ebpf_socket_publish_apps_t *socket;
151
152 } ebpf_pid_data_t;
153
154 extern ebpf_pid_data_t *ebpf_pids_link_list;
155 extern size_t ebpf_all_pids_count;
156 extern size_t ebpf_hash_table_pids_count;
157 void ebpf_del_pid_entry(pid_t pid);
158
159 ebpf_pid_data_t *ebpf_find_or_create_pid_data(pid_t pid);
160
161 static inline ebpf_pid_data_t *ebpf_get_pid_data(uint32_t pid, uint32_t tgid, char *name, uint32_t idx)
162 {
163 ebpf_pid_data_t *ptr = ebpf_find_or_create_pid_data(pid);
164 ptr->thread_collecting |= 1 << idx;
165 // The caller is getting data to work.
166 if (!name && idx != NETDATA_EBPF_PIDS_PROC_FILE)
167 return ptr;
168
169 if (ptr->pid == pid) {
170 return ptr;
171 }
172
173 ptr->pid = pid;
174 ptr->ppid = tgid;
175
176 if (name)
177 strncpyz(ptr->comm, name, EBPF_MAX_COMPARE_NAME);
178
179 if (likely(ebpf_pids_link_list))
180 ebpf_pids_link_list->prev = ptr;
181
182 ptr->next = ebpf_pids_link_list;
183 ebpf_pids_link_list = ptr;
184 if (idx == NETDATA_EBPF_PIDS_PROC_FILE) {
185 ebpf_all_pids_count++;
186 }
187
188 return ptr;
189 }
190
191 // The only caller of ebpf_get_pid_data() passes NETDATA_EBPF_PIDS_PROC_FILE,
192 // so `thread_collecting` in an ebpf_pid_data_t only ever has that single high
193 // bit set. The per-module (idx < PROC_FILE) branch in the old
194 // ebpf_reset_specific_pid_data() was therefore unreachable. Collapse the
195 // function to its effective behaviour so a future reader is not confused by
196 // dead BPF/freez housekeeping that never ran.
197 static inline void ebpf_reset_specific_pid_data(ebpf_pid_data_t *ptr)
198 {
199 ebpf_del_pid_entry(ptr->pid);
200 }
201
202 typedef struct ebpf_pid_stat {
203 uint32_t pid;
204 uint64_t thread_collecting;
205 char comm[EBPF_MAX_COMPARE_NAME + 1];
206 char *cmdline;
207
208 uint32_t log_thrown;
209
210 uint32_t ppid;
211
212 int children_count; // number of processes directly referencing this
213 unsigned char keep : 1; // 1 when we need to keep this process in memory even after it exited
214 int keeploops; // increases by 1 every time keep is 1 and updated 0
215 unsigned char updated : 1; // 1 when the process is currently running
216 unsigned char updated_twice : 1; // 1 when the process was running in the previous iteration
217 unsigned char merged : 1; // 1 when it has been merged to its parent
218 unsigned char read : 1; // 1 when we have already read this process for this iteration
219
220 int sortlist; // higher numbers = top on the process tree
221
222 // each process gets a unique number
223 netdata_publish_cachestat_t cachestat;
224 netdata_publish_dcstat_t dc;
225 netdata_fd_stat_t fd;
226 ebpf_process_stat_t process;
227 netdata_publish_shm_t shm;
228 netdata_publish_swap_t swap;
229 ebpf_socket_publish_apps_t socket;
230 netdata_publish_vfs_t vfs;
231
232 int not_updated;
233
234 struct ebpf_target *target; // app_groups.conf targets
235 struct ebpf_target *user_target; // uid based targets
236 struct ebpf_target *group_target; // gid based targets
237
238 usec_t stat_collected_usec;
239 usec_t last_stat_collected_usec;
240
241 netdata_publish_cachestat_t cache;
242
243 char *stat_filename;
244 char *status_filename;
245 char *io_filename;
246 char *cmdline_filename;
247
248 struct ebpf_pid_stat *parent;
249 struct ebpf_pid_stat *prev;
250 struct ebpf_pid_stat *next;
251 } ebpf_pid_stat_t;
252
253 // ----------------------------------------------------------------------------
254 // target
255 //
256 // target is the structure that processes are aggregated to be reported
257 // to netdata.
258 //
259 // - Each entry in /etc/apps_groups.conf creates a target.
260 // - Each user and group used by a process in the system, creates a target.
261 struct ebpf_pid_on_target {
262 int32_t pid;
263 struct ebpf_pid_on_target *next;
264 };
265
266 /**
267 * Internal function used to write debug messages.
268 *
269 * @param fmt the format to create the message.
270 * @param ... the arguments to fill the format.
271 */
272 static inline void debug_log_int(const char *fmt, ...)
273 {
274 va_list args;
275
276 fprintf(stderr, "apps.plugin: ");
277 va_start(args, fmt);
278 vfprintf(stderr, fmt, args);
279 va_end(args);
280
281 fputc('\n', stderr);
282 }
283
284 // ----------------------------------------------------------------------------
285 // Exported variabled and functions
286 //
287 int ebpf_read_apps_groups_conf(
288 struct ebpf_target **apps_groups_default_target,
289 struct ebpf_target **apps_groups_root_target,
290 const char *path,
291 const char *file);
292
293 void clean_apps_groups_target(struct ebpf_target *apps_groups_root_target);
294
295 size_t zero_all_targets(struct ebpf_target *root);
296
297 void cleanup_exited_pids();
298
299 int ebpf_read_hash_table(void *ep, int fd, uint32_t pid);
300
301 int get_pid_comm(pid_t pid, size_t n, char *dest);
302
303 void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core);
304 void ebpf_process_apps_accumulator(ebpf_process_stat_t *out, int maps_per_core);
305
306 // The default value is at least 32 times smaller than maximum number of PIDs allowed on system,
307 // this is only possible because we are using ARAL (https://github.com/netdata/netdata/tree/master/src/libnetdata/aral).
308 #ifndef NETDATA_EBPF_ALLOC_MAX_PID
309 #define NETDATA_EBPF_ALLOC_MAX_PID 1024
310 #endif
311 #define NETDATA_EBPF_ALLOC_MIN_ELEMENTS 256
312
313 // ARAL Sectiion
314 void ebpf_aral_init(void);
315 extern ebpf_process_stat_t *process_stat_vector;
316
317 extern ARAL *ebpf_aral_vfs_pid;
318 void ebpf_vfs_aral_init();
319 netdata_publish_vfs_t *ebpf_vfs_get(void);
320 void ebpf_vfs_release(netdata_publish_vfs_t *stat);
321
322 extern ARAL *ebpf_aral_shm_pid;
323 void ebpf_shm_aral_init();
324 netdata_publish_shm_t *ebpf_shm_stat_get(void);
325 void ebpf_shm_release(netdata_publish_shm_t *stat);
326 void ebpf_parse_proc_files();
327
328 // ARAL Section end
329
330 // Threads integrated with apps
331
332 #include "libnetdata/threads/threads.h"
333
334 #endif /* NETDATA_EBPF_APPS_H */