@cryptotaxi247 / netdata-1 / commits / 5518445f5

Split eBPF programs (#11401)

thiagoftsm committed Aug 11, 2021 at 19:12 UTC 5518445f5e69a8c88684f1dcb4e78ff0f425bad0
23 files changed +774 -225
CMakeLists.txt
+2
@@ -492,6 +492,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
492 collectors/ebpf.plugin/ebpf_dcstat.h
493 collectors/ebpf.plugin/ebpf_disk.c
494 collectors/ebpf.plugin/ebpf_disk.h
495 + collectors/ebpf.plugin/ebpf_fd.c
496 + collectors/ebpf.plugin/ebpf_fd.h
497 collectors/ebpf.plugin/ebpf_mount.c
498 collectors/ebpf.plugin/ebpf_mount.h
499 collectors/ebpf.plugin/ebpf_filesystem.c
Makefile.am
+2
@@ -295,6 +295,8 @@ EBPF_PLUGIN_FILES = \
295 collectors/ebpf.plugin/ebpf_dcstat.h \
296 collectors/ebpf.plugin/ebpf_disk.c \
297 collectors/ebpf.plugin/ebpf_disk.h \
298 + collectors/ebpf.plugin/ebpf_fd.c \
299 + collectors/ebpf.plugin/ebpf_fd.h \
300 collectors/ebpf.plugin/ebpf_filesystem.c \
301 collectors/ebpf.plugin/ebpf_filesystem.h \
302 collectors/ebpf.plugin/ebpf_mount.c \
collectors/all.h
+5 -1
@@ -154,7 +154,11 @@
154 #define NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS 2160
155
156 // Mount Points
157 -#define NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS 2195
157 +#define NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS 2190
158 +
159 +// File descriptor
160 +#define NETDATA_CHART_PRIO_EBPF_FD_CHARTS 2195
161 +
162
163 // NFS (server)
164
collectors/ebpf.plugin/Makefile.am
+1
@@ -35,6 +35,7 @@ dist_ebpfconfig_DATA = \
35 ebpf.d/cachestat.conf \
36 ebpf.d/dcstat.conf \
37 ebpf.d/disk.conf \
38 + ebpf.d/fd.conf \
39 ebpf.d/filesystem.conf \
40 ebpf.d/mount.conf \
41 ebpf.d/network.conf \
collectors/ebpf.plugin/README.md
+13 -7
@@ -210,6 +210,16 @@ When the integration is enabled, eBPF collector allocates memory for each proces
210
211 The eBPF collector enables and runs the following eBPF programs by default:
212
213 +- `fd` : This eBPF program creates charts that show information about calls to open files.
214 +- `mount`: This eBPF program creates charts that show calls for syscalls mount(2) and umount(2).
215 +- `sync`: Montitor calls for syscalls sync(2), fsync(2), fdatasync(2), syncfs(2), msync(2), and sync_file_range(2).
216 +- `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
217 + bandwidth consumed by each.
218 +- `vfs`: This eBPF program creates charts that show information about VFS (Virtual File System) functions.
219 +- `process`: This eBPF program creates charts that show information about process life.
220 + When in `return` mode, it also creates charts showing errors when these operations are executed.
221 +
222 +You can also enable the following eBPF programs:
223 - `cachestat`: Netdata's eBPF data collector creates charts about the memory page cache. When the integration with
224 [`apps.plugin`](/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
225 for each application.
@@ -217,13 +227,8 @@ The eBPF collector enables and runs the following eBPF programs by default:
227 `kprobes` for `lookup_fast()` and `d_lookup()` to identify if files are inside directory cache, outside and
228 files are not found.
229 - `disk` : This eBPF program creates charts that show information about disk latency independent of filesystem.
220 -- `filesystem`: This eBPF program creates charts that show latency information for selected filesystem.
221 -- `process`: This eBPF program creates charts that show information about process creation, calls to open files.
222 - When in `return` mode, it also creates charts showing errors when these operations are executed.
223 -- `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
224 - bandwidth consumed by each.
225 -- `sync`: Montitor calls for syscalls sync(2), fsync(2), fdatasync(2), syncfs(2), msync(2), and sync_file_range(2).
226 -- `vfs`: This eBPF program creates charts that show information about VFS (Virtual File System) functions.
230 +- `filesystem` : This eBPF program creates charts that show information about some filesystem latency.
231 +- `swap` : This eBPF program creates charts that show information about swap access.
232
233 ## Thread configuration
234
@@ -242,6 +247,7 @@ The following configuration files are available:
247 - `cachestat.conf`: Configuration for the `cachestat` thread.
248 - `dcstat.conf`: Configuration for the `dcstat` thread.
249 - `disk.conf`: Configuration for the `disk` thread.
250 +- `fd.conf`: Configuration for the `file descriptor` thread.
251 - `filesystem.conf`: Configuration for the `filesystem` thread.
252 - `process.conf`: Configuration for the `process` thread.
253 - `network.conf`: Configuration for the `network viewer` thread. This config file overwrites the global options and
collectors/ebpf.plugin/ebpf.c
+48 -19
@@ -105,7 +105,7 @@ ebpf_module_t ebpf_modules[] = {
105 .optional = 0, .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
106 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
107 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE},
108 - { .thread_name = "vfs", .config_name = "swap", .enabled = 0, .start_routine = ebpf_vfs_thread,
108 + { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
109 .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
110 .optional = 0, .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
111 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
@@ -114,17 +114,22 @@ ebpf_module_t ebpf_modules[] = {
114 .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
115 .optional = 0, .apps_routine = NULL, .maps = NULL,
116 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
117 - .config_file = NETDATA_SYNC_CONFIG_FILE},
117 + .config_file = NETDATA_FILESYSTEM_CONFIG_FILE},
118 { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
119 .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
120 .optional = 0, .apps_routine = NULL, .maps = NULL,
121 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
122 - .config_file = NETDATA_SYNC_CONFIG_FILE},
122 + .config_file = NETDATA_DISK_CONFIG_FILE},
123 { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
124 .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
125 .optional = 0, .apps_routine = NULL, .maps = NULL,
126 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
127 - .config_file = NETDATA_SYNC_CONFIG_FILE},
127 + .config_file = NETDATA_MOUNT_CONFIG_FILE},
128 + { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
129 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
130 + .optional = 0, .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
131 + .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
132 + .config_file = NETDATA_FD_CONFIG_FILE},
133 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
134 .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
135 .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
@@ -199,6 +204,12 @@ static void ebpf_exit(int sig)
204 freez(vfs_pid);
205 }
206
207 + if (ebpf_modules[EBPF_MODULE_FD_IDX].enabled) {
208 + ebpf_modules[EBPF_MODULE_FD_IDX].enabled = 0;
209 + clean_fd_pid_structures();
210 + freez(fd_pid);
211 + }
212 +
213 /*
214 int ret = fork();
215 if (ret < 0) // error
@@ -1040,6 +1051,13 @@ static void read_collector_values(int *disable_apps)
1051 started++;
1052 }
1053
1054 + enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "fd",
1055 + CONFIG_BOOLEAN_YES);
1056 + if (enabled) {
1057 + ebpf_enable_chart(EBPF_MODULE_FD_IDX, *disable_apps);
1058 + started++;
1059 + }
1060 +
1061 if (!started){
1062 ebpf_enable_all_charts(*disable_apps);
1063 // Read network viewer section
@@ -1118,21 +1136,22 @@ static void parse_args(int argc, char **argv)
1136 int freq = 0;
1137 int option_index = 0;
1138 static struct option long_options[] = {
1121 - {"help", no_argument, 0, 'h' },
1122 - {"version", no_argument, 0, 'v' },
1123 - {"global", no_argument, 0, 'g' },
1124 - {"all", no_argument, 0, 'a' },
1125 - {"cachestat", no_argument, 0, 'c' },
1126 - {"dcstat", no_argument, 0, 'd' },
1127 - {"disk", no_argument, 0, 'k' },
1128 - {"filesystem", no_argument, 0, 'i' },
1129 - {"mount", no_argument, 0, 'm' },
1130 - {"net", no_argument, 0, 'n' },
1131 - {"process", no_argument, 0, 'p' },
1132 - {"return", no_argument, 0, 'r' },
1133 - {"sync", no_argument, 0, 's' },
1134 - {"swap", no_argument, 0, 'w' },
1135 - {"vfs", no_argument, 0, 'f' },
1139 + {"help", no_argument, 0, 'h' },
1140 + {"version", no_argument, 0, 'v' },
1141 + {"global", no_argument, 0, 'g' },
1142 + {"all", no_argument, 0, 'a' },
1143 + {"cachestat", no_argument, 0, 'c' },
1144 + {"dcstat", no_argument, 0, 'd' },
1145 + {"disk", no_argument, 0, 'k' },
1146 + {"filesystem", no_argument, 0, 'i' },
1147 + {"filedescriptor", no_argument, 0, 'e' },
1148 + {"mount", no_argument, 0, 'm' },
1149 + {"net", no_argument, 0, 'n' },
1150 + {"process", no_argument, 0, 'p' },
1151 + {"return", no_argument, 0, 'r' },
1152 + {"sync", no_argument, 0, 's' },
1153 + {"swap", no_argument, 0, 'w' },
1154 + {"vfs", no_argument, 0, 'f' },
1155 {0, 0, 0, 0}
1156 };
1157
@@ -1215,6 +1234,14 @@ static void parse_args(int argc, char **argv)
1234 ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, disable_apps);
1235 #ifdef NETDATA_INTERNAL_CHECKS
1236 info("EBPF enabling \"mount\" chart, because it was started with the option \"--mount\" or \"-m\".");
1237 +#endif
1238 + break;
1239 + }
1240 + case 'e': {
1241 + enabled = 1;
1242 + ebpf_enable_chart(EBPF_MODULE_FD_IDX, disable_apps);
1243 +#ifdef NETDATA_INTERNAL_CHECKS
1244 + info("EBPF enabling \"filedescriptor\" chart, because it was started with the option \"--filedescriptor\" or \"-e\".");
1245 #endif
1246 break;
1247 }
@@ -1544,6 +1571,8 @@ int main(int argc, char **argv)
1571 NULL, NULL, ebpf_modules[EBPF_MODULE_DISK_IDX].start_routine},
1572 {"EBPF MOUNT" , NULL, NULL, 1,
1573 NULL, NULL, ebpf_modules[EBPF_MODULE_MOUNT_IDX].start_routine},
1574 + {"EBPF FD" , NULL, NULL, 1,
1575 + NULL, NULL, ebpf_modules[EBPF_MODULE_FD_IDX].start_routine},
1576 {NULL , NULL, NULL, 0,
1577 NULL, NULL, NULL}
1578 };
collectors/ebpf.plugin/ebpf.d.conf
+3 -1
@@ -28,9 +28,10 @@
28 # `cachestat` : Make charts for kernel functions related to page cache.
29 # `dcstat` : Make charts for kernel functions related to directory cache.
30 # `disk` : Monitor I/O latencies for disks
31 +# `fd` : This eBPF program creates charts that show information about file manipulation.
32 # `mount` : Monitor calls for syscalls mount and umount
33 # `filesystem`: Monitor calls for functions used to manipulate specific filesystems
33 -# `process` : This eBPF program creates charts that show information about process creation, and file manipulation.
34 +# `process` : This eBPF program creates charts that show information about process life.
35 # `socket` : This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
36 # bandwidth consumed by each.
37 # `sync` : Montitor calls for syscall sync(2).
@@ -41,6 +42,7 @@
42 cachestat = no
43 dcstat = no
44 disk = no
45 + fd = yes
46 filesystem = no
47 mount = yes
48 process = yes
collectors/ebpf.plugin/ebpf.d/fd.conf new
+17
@@ -0,0 +1,17 @@
1 +# The `ebpf load mode` option accepts the following values :
2 +# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3 +# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 +# new charts for the return of these functions, such as errors.
5 +#
6 +# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 +# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 +# 'no'.
9 +#
10 +# The `pid table size` defines the maximum number of PIDs stored inside the hash table.
11 +#
12 +# Uncomment lines to define specific options for thread.
13 +[global]
14 +# ebpf load mode = entry
15 +# apps = yes
16 + update every = 1
17 +# pid table size = 32768
collectors/ebpf.plugin/ebpf.h
+2 -1
@@ -83,7 +83,8 @@ enum ebpf_module_indexes {
83 EBPF_MODULE_VFS_IDX,
84 EBPF_MODULE_FILESYSTEM_IDX,
85 EBPF_MODULE_DISK_IDX,
86 - EBPF_MODULE_MOUNT_IDX
86 + EBPF_MODULE_MOUNT_IDX,
87 + EBPF_MODULE_FD_IDX
88 };
89
90 // Copied from musl header
collectors/ebpf.plugin/ebpf_apps.c
+6
@@ -945,6 +945,12 @@ void cleanup_variables_from_other_threads(uint32_t pid)
945 freez(vfs_pid[pid]);
946 vfs_pid[pid] = NULL;
947 }
948 +
949 + // Clean fd structure
950 + if (fd_pid) {
951 + freez(fd_pid[pid]);
952 + fd_pid[pid] = NULL;
953 + }
954 }
955
956 /**
collectors/ebpf.plugin/ebpf_apps.h
+3 -1
@@ -11,7 +11,7 @@
11 #include "libnetdata/ebpf/ebpf.h"
12
13 #define NETDATA_APPS_FAMILY "apps"
14 -#define NETDATA_APPS_FILE_GROUP "file (eBPF)"
14 +#define NETDATA_APPS_FILE_GROUP "file_access"
15 #define NETDATA_APPS_VFS_GROUP "vfs (eBPF)"
16 #define NETDATA_APPS_PROCESS_GROUP "process (eBPF)"
17 #define NETDATA_APPS_NET_GROUP "net (eBPF)"
@@ -21,6 +21,7 @@
21 #include "ebpf_process.h"
22 #include "ebpf_dcstat.h"
23 #include "ebpf_disk.h"
24 +#include "ebpf_fd.h"
25 #include "ebpf_filesystem.h"
26 #include "ebpf_cachestat.h"
27 #include "ebpf_mount.h"
@@ -120,6 +121,7 @@ struct target {
121 netdata_publish_dcstat_t dcstat;
122 netdata_publish_swap_t swap;
123 netdata_publish_vfs_t vfs;
124 + netdata_fd_stat_t fd;
125
126 /* These variables are not necessary for eBPF collector
127 kernel_uint_t minflt;
collectors/ebpf.plugin/ebpf_disk.h
+3
@@ -13,6 +13,9 @@
13
14 #define NETDATA_LATENCY_DISK_SLEEP_MS 650000ULL
15
16 +// Process configuration name
17 +#define NETDATA_DISK_CONFIG_FILE "disk.conf"
18 +
19 // Decode function extracted from: https://elixir.bootlin.com/linux/v5.10.8/source/include/linux/kdev_t.h#L7
20 #define MINORBITS 20
21 #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
collectors/ebpf.plugin/ebpf_fd.c new
+533
@@ -0,0 +1,533 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "ebpf.h"
4 +#include "ebpf_fd.h"
5 +
6 +static char *fd_dimension_names[NETDATA_FD_SYSCALL_END] = { "open", "close" };
7 +static char *fd_id_names[NETDATA_FD_SYSCALL_END] = { "do_sys_open", "__close_fd" };
8 +
9 +static netdata_syscall_stat_t fd_aggregated_data[NETDATA_FD_SYSCALL_END];
10 +static netdata_publish_syscall_t fd_publish_aggregated[NETDATA_FD_SYSCALL_END];
11 +
12 +static ebpf_local_maps_t fd_maps[] = {{.name = "tbl_fd_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
13 + .user_input = 0,
14 + .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
15 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
16 + {.name = "tbl_fd_global", .internal_input = NETDATA_KEY_END_VECTOR,
17 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
18 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
19 + {.name = "fd_ctrl", .internal_input = NETDATA_CONTROLLER_END,
20 + .user_input = 0,
21 + .type = NETDATA_EBPF_MAP_CONTROLLER,
22 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
23 + {.name = NULL, .internal_input = 0, .user_input = 0,
24 + .type = NETDATA_EBPF_MAP_CONTROLLER,
25 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
26 +
27 +
28 +struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
29 + .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
30 + .rwlock = AVL_LOCK_INITIALIZER } };
31 +
32 +static ebpf_data_t fd_data;
33 +static struct bpf_link **probe_links = NULL;
34 +static struct bpf_object *objects = NULL;
35 +
36 +struct netdata_static_thread fd_thread = {"FD KERNEL", NULL, NULL, 1, NULL,
37 + NULL, NULL};
38 +static int read_thread_closed = 1;
39 +static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
40 +static netdata_idx_t *fd_values = NULL;
41 +
42 +netdata_fd_stat_t *fd_vector = NULL;
43 +netdata_fd_stat_t **fd_pid;
44 +
45 +/*****************************************************************
46 + *
47 + * FUNCTIONS TO CLOSE THE THREAD
48 + *
49 + *****************************************************************/
50 +
51 +/**
52 + * Clean PID structures
53 + *
54 + * Clean the allocated structures.
55 + */
56 +void clean_fd_pid_structures() {
57 + struct pid_stat *pids = root_of_pids;
58 + while (pids) {
59 + freez(fd_pid[pids->pid]);
60 +
61 + pids = pids->next;
62 + }
63 +}
64 +
65 +/**
66 + * Clean up the main thread.
67 + *
68 + * @param ptr thread data.
69 + */
70 +static void ebpf_fd_cleanup(void *ptr)
71 +{
72 + ebpf_module_t *em = (ebpf_module_t *)ptr;
73 + if (!em->enabled)
74 + return;
75 +
76 + heartbeat_t hb;
77 + heartbeat_init(&hb);
78 + uint32_t tick = 2 * USEC_PER_MS;
79 + while (!read_thread_closed) {
80 + usec_t dt = heartbeat_next(&hb, tick);
81 + UNUSED(dt);
82 + }
83 +
84 + ebpf_cleanup_publish_syscall(fd_publish_aggregated);
85 + freez(fd_data.map_fd);
86 + freez(fd_thread.thread);
87 + freez(fd_values);
88 + freez(fd_vector);
89 +
90 + if (probe_links) {
91 + struct bpf_program *prog;
92 + size_t i = 0 ;
93 + bpf_object__for_each_program(prog, objects) {
94 + bpf_link__destroy(probe_links[i]);
95 + i++;
96 + }
97 + bpf_object__close(objects);
98 + }
99 +}
100 +
101 +/*****************************************************************
102 + *
103 + * MAIN LOOP
104 + *
105 + *****************************************************************/
106 +
107 +/**
108 + * Send data to Netdata calling auxiliar functions.
109 + *
110 + * @param em the structure with thread information
111 + */
112 +static void ebpf_fd_send_data(ebpf_module_t *em)
113 +{
114 + fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].ncall = fd_hash_values[NETDATA_KEY_CALLS_DO_SYS_OPEN];
115 + fd_publish_aggregated[NETDATA_FD_SYSCALL_OPEN].nerr = fd_hash_values[NETDATA_KEY_ERROR_DO_SYS_OPEN];
116 +
117 + fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].ncall = fd_hash_values[NETDATA_KEY_CALLS_CLOSE_FD];
118 + fd_publish_aggregated[NETDATA_FD_SYSCALL_CLOSE].nerr = fd_hash_values[NETDATA_KEY_ERROR_CLOSE_FD];
119 +
120 + write_count_chart(NETDATA_FILE_OPEN_CLOSE_COUNT, NETDATA_FILESYSTEM_FAMILY, fd_publish_aggregated,
121 + NETDATA_FD_SYSCALL_END);
122 +
123 + if (em->mode < MODE_ENTRY) {
124 + write_err_chart(NETDATA_FILE_OPEN_ERR_COUNT, NETDATA_FILESYSTEM_FAMILY,
125 + fd_publish_aggregated, NETDATA_FD_SYSCALL_END);
126 + }
127 +}
128 +
129 +/**
130 + * Read global counter
131 + *
132 + * Read the table with number of calls for all functions
133 + */
134 +static void read_global_table()
135 +{
136 + uint32_t idx;
137 + netdata_idx_t *val = fd_hash_values;
138 + netdata_idx_t *stored = fd_values;
139 + int fd = fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd;
140 +
141 + for (idx = NETDATA_KEY_CALLS_DO_SYS_OPEN; idx < NETDATA_FD_COUNTER; idx++) {
142 + if (!bpf_map_lookup_elem(fd, &idx, stored)) {
143 + int i;
144 + int end = ebpf_nprocs;
145 + netdata_idx_t total = 0;
146 + for (i = 0; i < end; i++)
147 + total += stored[i];
148 +
149 + val[idx] = total;
150 + }
151 + }
152 +}
153 +
154 +/**
155 + * File descriptor read hash
156 + *
157 + * This is the thread callback.
158 + * This thread is necessary, because we cannot freeze the whole plugin to read the data.
159 + *
160 + * @param ptr It is a NULL value for this thread.
161 + *
162 + * @return It always returns NULL.
163 + */
164 +void *ebpf_fd_read_hash(void *ptr)
165 +{
166 + read_thread_closed = 0;
167 +
168 + heartbeat_t hb;
169 + heartbeat_init(&hb);
170 +
171 + ebpf_module_t *em = (ebpf_module_t *)ptr;
172 + usec_t step = NETDATA_FD_SLEEP_MS * em->update_time;
173 + while (!close_ebpf_plugin) {
174 + usec_t dt = heartbeat_next(&hb, step);
175 + (void)dt;
176 +
177 + read_global_table();
178 + }
179 +
180 + read_thread_closed = 1;
181 + return NULL;
182 +}
183 +
184 +/**
185 + * Apps Accumulator
186 + *
187 + * Sum all values read from kernel and store in the first address.
188 + *
189 + * @param out the vector with read values.
190 + */
191 +static void fd_apps_accumulator(netdata_fd_stat_t *out)
192 +{
193 + int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
194 + netdata_fd_stat_t *total = &out[0];
195 + for (i = 1; i < end; i++) {
196 + netdata_fd_stat_t *w = &out[i];
197 + total->open_call += w->open_call;
198 + total->close_call += w->close_call;
199 + total->open_err += w->open_err;
200 + total->close_err += w->close_err;
201 + }
202 +}
203 +
204 +/**
205 + * Fill PID
206 + *
207 + * Fill PID structures
208 + *
209 + * @param current_pid pid that we are collecting data
210 + * @param out values read from hash tables;
211 + */
212 +static void fd_fill_pid(uint32_t current_pid, netdata_fd_stat_t *publish)
213 +{
214 + netdata_fd_stat_t *curr = fd_pid[current_pid];
215 + if (!curr) {
216 + curr = callocz(1, sizeof(netdata_fd_stat_t));
217 + fd_pid[current_pid] = curr;
218 + }
219 +
220 + memcpy(curr, &publish[0], sizeof(netdata_fd_stat_t));
221 +}
222 +
223 +/**
224 + * Read APPS table
225 + *
226 + * Read the apps table and store data inside the structure.
227 + */
228 +static void read_apps_table()
229 +{
230 + netdata_fd_stat_t *fv = fd_vector;
231 + uint32_t key;
232 + struct pid_stat *pids = root_of_pids;
233 + int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
234 + size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
235 + while (pids) {
236 + key = pids->pid;
237 +
238 + if (bpf_map_lookup_elem(fd, &key, fv)) {
239 + pids = pids->next;
240 + continue;
241 + }
242 +
243 + fd_apps_accumulator(fv);
244 +
245 + fd_fill_pid(key, fv);
246 +
247 + // We are cleaning to avoid passing data read from one process to other.
248 + memset(fv, 0, length);
249 +
250 + pids = pids->next;
251 + }
252 +}
253 +
254 +/**
255 + * Sum PIDs
256 + *
257 + * Sum values for all targets.
258 + *
259 + * @param fd the output
260 + * @param root list of pids
261 + */
262 +static void ebpf_fd_sum_pids(netdata_fd_stat_t *fd, struct pid_on_target *root)
263 +{
264 + uint32_t open_call = 0;
265 + uint32_t close_call = 0;
266 + uint32_t open_err = 0;
267 + uint32_t close_err = 0;
268 +
269 + while (root) {
270 + int32_t pid = root->pid;
271 + netdata_fd_stat_t *w = fd_pid[pid];
272 + if (w) {
273 + open_call += w->open_call;
274 + close_call += w->close_call;
275 + open_err += w->open_err;
276 + close_err += w->close_err;
277 + }
278 +
279 + root = root->next;
280 + }
281 +
282 + // These conditions were added, because we are using incremental algorithm
283 + fd->open_call = (open_call >= fd->open_call) ? open_call : fd->open_call;
284 + fd->close_call = (close_call >= fd->close_call) ? close_call : fd->close_call;
285 + fd->open_err = (open_err >= fd->open_err) ? open_err : fd->open_err;
286 + fd->close_err = (close_err >= fd->close_err) ? close_err : fd->close_err;
287 +}
288 +
289 +/**
290 + * Send data to Netdata calling auxiliar functions.
291 + *
292 + * @param em the structure with thread information
293 + * @param root the target list.
294 +*/
295 +void ebpf_fd_send_apps_data(ebpf_module_t *em, struct target *root)
296 +{
297 + struct target *w;
298 + for (w = root; w; w = w->next) {
299 + if (unlikely(w->exposed && w->processes)) {
300 + ebpf_fd_sum_pids(&w->fd, w->root_pid);
301 + }
302 + }
303 +
304 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
305 + for (w = root; w; w = w->next) {
306 + if (unlikely(w->exposed && w->processes)) {
307 + write_chart_dimension(w->name, w->fd.open_call);
308 + }
309 + }
310 + write_end_chart();
311 +
312 + if (em->mode < MODE_ENTRY) {
313 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
314 + for (w = root; w; w = w->next) {
315 + if (unlikely(w->exposed && w->processes)) {
316 + write_chart_dimension(w->name, w->fd.open_err);
317 + }
318 + }
319 + write_end_chart();
320 + }
321 +
322 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
323 + for (w = root; w; w = w->next) {
324 + if (unlikely(w->exposed && w->processes)) {
325 + write_chart_dimension(w->name, w->fd.close_call);
326 + }
327 + }
328 + write_end_chart();
329 +
330 + if (em->mode < MODE_ENTRY) {
331 + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
332 + for (w = root; w; w = w->next) {
333 + if (unlikely(w->exposed && w->processes)) {
334 + write_chart_dimension(w->name, w->fd.close_err);
335 + }
336 + }
337 + write_end_chart();
338 + }
339 +}
340 +
341 +/**
342 +* Main loop for this collector.
343 +*/
344 +static void fd_collector(ebpf_module_t *em)
345 +{
346 + fd_thread.thread = mallocz(sizeof(netdata_thread_t));
347 + fd_thread.start_routine = ebpf_fd_read_hash;
348 +
349 + netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
350 + ebpf_fd_read_hash, em);
351 +
352 + int apps = em->apps_charts;
353 + while (!close_ebpf_plugin) {
354 + pthread_mutex_lock(&collect_data_mutex);
355 + pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
356 +
357 + if (apps)
358 + read_apps_table();
359 +
360 + pthread_mutex_lock(&lock);
361 +
362 + ebpf_fd_send_data(em);
363 +
364 + if (apps)
365 + ebpf_fd_send_apps_data(em, apps_groups_root_target);
366 +
367 + pthread_mutex_unlock(&lock);
368 + pthread_mutex_unlock(&collect_data_mutex);
369 + }
370 +}
371 +
372 +/*****************************************************************
373 + *
374 + * CREATE CHARTS
375 + *
376 + *****************************************************************/
377 +
378 +/**
379 + * Create apps charts
380 + *
381 + * Call ebpf_create_chart to create the charts on apps submenu.
382 + *
383 + * @param em a pointer to the structure with the default values.
384 + */
385 +void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr)
386 +{
387 + struct target *root = ptr;
388 + ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN,
389 + "Number of open files",
390 + EBPF_COMMON_DIMENSION_CALL,
391 + NETDATA_APPS_FILE_GROUP,
392 + NETDATA_EBPF_CHART_TYPE_STACKED,
393 + 20061,
394 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
395 + root, NETDATA_EBPF_MODULE_NAME_PROCESS);
396 +
397 + if (em->mode < MODE_ENTRY) {
398 + ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
399 + "Fails to open files",
400 + EBPF_COMMON_DIMENSION_CALL,
401 + NETDATA_APPS_FILE_GROUP,
402 + NETDATA_EBPF_CHART_TYPE_STACKED,
403 + 20062,
404 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
405 + root, NETDATA_EBPF_MODULE_NAME_PROCESS);
406 + }
407 +
408 + ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSED,
409 + "Files closed",
410 + EBPF_COMMON_DIMENSION_CALL,
411 + NETDATA_APPS_FILE_GROUP,
412 + NETDATA_EBPF_CHART_TYPE_STACKED,
413 + 20063,
414 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
415 + root, NETDATA_EBPF_MODULE_NAME_PROCESS);
416 +
417 + if (em->mode < MODE_ENTRY) {
418 + ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
419 + "Fails to close files",
420 + EBPF_COMMON_DIMENSION_CALL,
421 + NETDATA_APPS_FILE_GROUP,
422 + NETDATA_EBPF_CHART_TYPE_STACKED,
423 + 20064,
424 + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
425 + root, NETDATA_EBPF_MODULE_NAME_PROCESS);
426 + }
427 +}
428 +
429 +/**
430 + * Create global charts
431 + *
432 + * Call ebpf_create_chart to create the charts for the collector.
433 + *
434 + * @param em a pointer to the structure with the default values.
435 + */
436 +static void ebpf_create_fd_global_charts(ebpf_module_t *em)
437 +{
438 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
439 + NETDATA_FILE_OPEN_CLOSE_COUNT,
440 + "Open and close calls",
441 + EBPF_COMMON_DIMENSION_CALL,
442 + NETDATA_FILE_GROUP,
443 + NULL,
444 + NETDATA_EBPF_CHART_TYPE_LINE,
445 + NETDATA_CHART_PRIO_EBPF_FD_CHARTS,
446 + ebpf_create_global_dimension,
447 + fd_publish_aggregated,
448 + NETDATA_FD_SYSCALL_END,
449 + NETDATA_EBPF_MODULE_NAME_FD);
450 +
451 + if (em->mode < MODE_ENTRY) {
452 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
453 + NETDATA_FILE_OPEN_ERR_COUNT,
454 + "Open fails",
455 + EBPF_COMMON_DIMENSION_CALL,
456 + NETDATA_FILE_GROUP,
457 + NULL,
458 + NETDATA_EBPF_CHART_TYPE_LINE,
459 + NETDATA_CHART_PRIO_EBPF_FD_CHARTS + 1,
460 + ebpf_create_global_dimension,
461 + fd_publish_aggregated,
462 + NETDATA_FD_SYSCALL_END,
463 + NETDATA_EBPF_MODULE_NAME_FD);
464 + }
465 +}
466 +
467 +/*****************************************************************
468 + *
469 + * MAIN THREAD
470 + *
471 + *****************************************************************/
472 +
473 +/**
474 + * Allocate vectors used with this thread.
475 + *
476 + * We are not testing the return, because callocz does this and shutdown the software
477 + * case it was not possible to allocate.
478 + */
479 +static void ebpf_fd_allocate_global_vectors()
480 +{
481 + fd_pid = callocz((size_t)pid_max, sizeof(netdata_fd_stat_t *));
482 + fd_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_fd_stat_t));
483 +
484 + fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
485 +}
486 +
487 +/**
488 + * Directory Cache thread
489 + *
490 + * Thread used to make dcstat thread
491 + *
492 + * @param ptr a pointer to `struct ebpf_module`
493 + *
494 + * @return It always returns NULL
495 + */
496 +void *ebpf_fd_thread(void *ptr)
497 +{
498 + netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
499 +
500 + ebpf_module_t *em = (ebpf_module_t *)ptr;
501 + em->maps = fd_maps;
502 + fill_ebpf_data(&fd_data);
503 +
504 + if (!em->enabled)
505 + goto endfd;
506 +
507 + if (ebpf_update_kernel(&fd_data))
508 + goto endfd;
509 +
510 + ebpf_fd_allocate_global_vectors();
511 +
512 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, fd_data.map_fd);
513 + if (!probe_links) {
514 + goto endfd;
515 + }
516 +
517 + int algorithms[NETDATA_FD_SYSCALL_END] = {
518 + NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX
519 + };
520 +
521 + ebpf_global_labels(fd_aggregated_data, fd_publish_aggregated, fd_dimension_names, fd_id_names,
522 + algorithms, NETDATA_FD_SYSCALL_END);
523 +
524 + pthread_mutex_lock(&lock);
525 + ebpf_create_fd_global_charts(em);
526 + pthread_mutex_unlock(&lock);
527 +
528 + fd_collector(em);
529 +
530 +endfd:
531 + netdata_thread_cleanup_pop(1);
532 + return NULL;
533 +}
collectors/ebpf.plugin/ebpf_fd.h new
+74
@@ -0,0 +1,74 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_EBPF_FD_H
4 +#define NETDATA_EBPF_FD_H 1
5 +
6 +// Module name
7 +#define NETDATA_EBPF_MODULE_NAME_FD "filedescriptor"
8 +
9 +#define NETDATA_FD_SLEEP_MS 850000ULL
10 +
11 +// Menu group
12 +#define NETDATA_FILE_GROUP "File_access"
13 +
14 +// Global chart name
15 +#define NETDATA_FILE_OPEN_CLOSE_COUNT "file_descriptor"
16 +#define NETDATA_FILE_OPEN_ERR_COUNT "file_error"
17 +
18 +// Charts created on Apps submenu
19 +#define NETDATA_SYSCALL_APPS_FILE_OPEN "file_open"
20 +#define NETDATA_SYSCALL_APPS_FILE_CLOSED "file_closed"
21 +#define NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR "file_open_error"
22 +#define NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR "file_close_error"
23 +
24 +// Process configuration name
25 +#define NETDATA_FD_CONFIG_FILE "fd.conf"
26 +
27 +typedef struct netdata_fd_stat {
28 + uint64_t pid_tgid; // Unique identifier
29 + uint32_t pid; // Process ID
30 +
31 + uint32_t open_call; // Open syscalls (open and openat)
32 + uint32_t close_call; // Close syscall (close)
33 +
34 + // Errors
35 + uint32_t open_err;
36 + uint32_t close_err;
37 +} netdata_fd_stat_t;
38 +
39 +enum fd_tables {
40 + NETDATA_FD_PID_STATS,
41 + NETDATA_FD_GLOBAL_STATS,
42 +
43 + // Keep this as last and don't skip numbers as it is used as element counter
44 + NETDATA_FD_CONTROLLER
45 +};
46 +
47 +enum fd_counters {
48 + NETDATA_KEY_CALLS_DO_SYS_OPEN,
49 + NETDATA_KEY_ERROR_DO_SYS_OPEN,
50 +
51 + NETDATA_KEY_CALLS_CLOSE_FD,
52 + NETDATA_KEY_ERROR_CLOSE_FD,
53 +
54 + // Keep this as last and don't skip numbers as it is used as element counter
55 + NETDATA_FD_COUNTER
56 +};
57 +
58 +enum fd_syscalls {
59 + NETDATA_FD_SYSCALL_OPEN,
60 + NETDATA_FD_SYSCALL_CLOSE,
61 +
62 + // Do not insert nothing after this value
63 + NETDATA_FD_SYSCALL_END
64 +};
65 +
66 +
67 +extern void *ebpf_fd_thread(void *ptr);
68 +extern void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr);
69 +extern struct config fd_config;
70 +extern netdata_fd_stat_t **fd_pid;
71 +extern void clean_fd_pid_structures();
72 +
73 +#endif /* NETDATA_EBPF_FD_H */
74 +
collectors/ebpf.plugin/ebpf_filesystem.h
+3
@@ -13,6 +13,9 @@
13 #define NETDATA_FILESYSTEM_CONFIG_NAME "filesystem"
14 #define NETDATA_FILESYSTEM_READ_SLEEP_MS 600000ULL
15
16 +// Process configuration name
17 +#define NETDATA_FILESYSTEM_CONFIG_FILE "filesystem.conf"
18 +
19 typedef struct netdata_fs_hist {
20 uint32_t hist_id;
21 uint32_t bin;
collectors/ebpf.plugin/ebpf_mount.h
+3
@@ -14,6 +14,9 @@
14 #define NETDATA_EBPF_MOUNT_ERRORS "error"
15 #define NETDATA_EBPF_MOUNT_FAMILY "mount (eBPF)"
16
17 +// Process configuration name
18 +#define NETDATA_MOUNT_CONFIG_FILE "mount.conf"
19 +
20 enum mount_counters {
21 NETDATA_KEY_MOUNT_CALL,
22 NETDATA_KEY_UMOUNT_CALL,
collectors/ebpf.plugin/ebpf_process.c
+13 -145
@@ -11,10 +11,8 @@
11 *
12 *****************************************************************/
13
14 -static char *process_dimension_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "open", "close", "process",
15 - "task", "process", "thread" };
16 -static char *process_id_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "do_sys_open", "__close_fd", "do_exit",
17 - "release_task", "_do_fork", "sys_clone" };
14 +static char *process_dimension_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "process", "task", "process", "thread" };
15 +static char *process_id_names[NETDATA_KEY_PUBLISH_PROCESS_END] = { "do_exit", "release_task", "_do_fork", "sys_clone" };
16 static char *status[] = { "process", "zombie" };
17
18 static ebpf_local_maps_t process_maps[] = {{.name = "tbl_pid_stats", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
@@ -69,24 +67,15 @@ static void ebpf_update_global_publish(netdata_publish_syscall_t *publish, netda
67 netdata_syscall_stat_t *input)
68 {
69 netdata_publish_syscall_t *move = publish;
72 - int selector = NETDATA_KEY_PUBLISH_PROCESS_OPEN;
70 + int selector = NETDATA_KEY_PUBLISH_PROCESS_EXIT;
71 while (move) {
74 - // Until NETDATA_KEY_PUBLISH_PROCESS_EXIT we are creating accumulators, so it is possible
75 - // to use incremental charts, but after this we will do some math with the values, so we are storing
76 - // absolute values
77 - if (selector < NETDATA_KEY_PUBLISH_PROCESS_EXIT) {
78 - move->ncall = input->call;
79 - move->nbyte = input->bytes;
80 - move->nerr = input->ecall;
81 - } else {
82 - move->ncall = (input->call > move->pcall) ? input->call - move->pcall : move->pcall - input->call;
83 - move->nbyte = (input->bytes > move->pbyte) ? input->bytes - move->pbyte : move->pbyte - input->bytes;
84 - move->nerr = (input->ecall > move->nerr) ? input->ecall - move->perr : move->perr - input->ecall;
72 + move->ncall = (input->call > move->pcall) ? input->call - move->pcall : move->pcall - input->call;
73 + move->nbyte = (input->bytes > move->pbyte) ? input->bytes - move->pbyte : move->pbyte - input->bytes;
74 + move->nerr = (input->ecall > move->nerr) ? input->ecall - move->perr : move->perr - input->ecall;
75
86 - move->pcall = input->call;
87 - move->pbyte = input->bytes;
88 - move->perr = input->ecall;
89 - }
76 + move->pcall = input->call;
77 + move->pbyte = input->bytes;
78 + move->perr = input->ecall;
79
80 input = input->next;
81 move = move->next;
@@ -126,8 +115,6 @@ static void ebpf_process_send_data(ebpf_module_t *em)
115 netdata_publish_vfs_common_t pvc;
116 ebpf_update_global_publish(process_publish_aggregated, &pvc, process_aggregated_data);
117
129 - write_count_chart(NETDATA_FILE_OPEN_CLOSE_COUNT, NETDATA_EBPF_FAMILY, process_publish_aggregated, 2);
130 -
118 write_count_chart(NETDATA_EXIT_SYSCALL, NETDATA_EBPF_FAMILY,
119 &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_EXIT], 2);
120 write_count_chart(NETDATA_PROCESS_SYSCALL, NETDATA_EBPF_FAMILY,
@@ -135,8 +122,6 @@ static void ebpf_process_send_data(ebpf_module_t *em)
122
123 write_status_chart(NETDATA_EBPF_FAMILY, &pvc);
124 if (em->mode < MODE_ENTRY) {
138 - write_err_chart(NETDATA_FILE_OPEN_ERR_COUNT, NETDATA_EBPF_FAMILY,
139 - process_publish_aggregated, 2);
125 write_err_chart(NETDATA_PROCESS_ERROR_NAME, NETDATA_EBPF_FAMILY,
126 &process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_FORK], 2);
127 }
@@ -194,56 +179,13 @@ void ebpf_process_remove_pids()
179 /**
180 * Send data to Netdata calling auxiliar functions.
181 *
197 - * @param em the structure with thread information
182 * @param root the target list.
183 */
200 -void ebpf_process_send_apps_data(ebpf_module_t *em, struct target *root)
184 +void ebpf_process_send_apps_data(struct target *root)
185 {
186 struct target *w;
187 collected_number value;
188
205 - write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN);
206 - for (w = root; w; w = w->next) {
207 - if (unlikely(w->exposed && w->processes)) {
208 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t, call_sys_open));
209 - write_chart_dimension(w->name, value);
210 - }
211 - }
212 - write_end_chart();
213 -
214 - if (em->mode < MODE_ENTRY) {
215 - write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR);
216 - for (w = root; w; w = w->next) {
217 - if (unlikely(w->exposed && w->processes)) {
218 - value = ebpf_process_sum_values_for_pids(w->root_pid,
219 - offsetof(ebpf_process_publish_apps_t, ecall_sys_open));
220 - write_chart_dimension(w->name, value);
221 - }
222 - }
223 - write_end_chart();
224 - }
225 -
226 - write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSED);
227 - for (w = root; w; w = w->next) {
228 - if (unlikely(w->exposed && w->processes)) {
229 - value = ebpf_process_sum_values_for_pids(w->root_pid, offsetof(ebpf_process_publish_apps_t, call_close_fd));
230 - write_chart_dimension(w->name, value);
231 - }
232 - }
233 - write_end_chart();
234 -
235 - if (em->mode < MODE_ENTRY) {
236 - write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR);
237 - for (w = root; w; w = w->next) {
238 - if (unlikely(w->exposed && w->processes)) {
239 - value = ebpf_process_sum_values_for_pids(w->root_pid,
240 - offsetof(ebpf_process_publish_apps_t, ecall_close_fd));
241 - write_chart_dimension(w->name, value);
242 - }
243 - }
244 - write_end_chart();
245 - }
246 -
189 write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_TASK_PROCESS);
190 for (w = root; w; w = w->next) {
191 if (unlikely(w->exposed && w->processes)) {
@@ -305,15 +247,11 @@ static void read_hash_global_tables()
247 }
248 }
249
308 - process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_OPEN].call = res[NETDATA_KEY_CALLS_DO_SYS_OPEN];
309 - process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLOSE].call = res[NETDATA_KEY_CALLS_CLOSE_FD];
250 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_EXIT].call = res[NETDATA_KEY_CALLS_DO_EXIT];
251 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].call = res[NETDATA_KEY_CALLS_RELEASE_TASK];
252 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_FORK].call = res[NETDATA_KEY_CALLS_DO_FORK];
253 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLONE].call = res[NETDATA_KEY_CALLS_SYS_CLONE];
254
315 - process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_OPEN].ecall = res[NETDATA_KEY_ERROR_DO_SYS_OPEN];
316 - process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLOSE].ecall = res[NETDATA_KEY_ERROR_CLOSE_FD];
255 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_FORK].ecall = res[NETDATA_KEY_ERROR_DO_FORK];
256 process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_CLONE].ecall = res[NETDATA_KEY_ERROR_SYS_CLONE];
257 }
@@ -339,15 +277,11 @@ static void ebpf_process_update_apps_data()
277 }
278
279 //Read data
342 - cad->call_sys_open = ps->open_call;
343 - cad->call_close_fd = ps->close_call;
280 cad->call_do_exit = ps->exit_call;
281 cad->call_release_task = ps->release_call;
282 cad->call_do_fork = ps->fork_call;
283 cad->call_sys_clone = ps->clone_call;
284
349 - cad->ecall_sys_open = ps->open_err;
350 - cad->ecall_close_fd = ps->close_err;
285 cad->ecall_do_fork = ps->fork_err;
286 cad->ecall_sys_clone = ps->clone_err;
287
@@ -394,32 +328,6 @@ static void ebpf_process_status_chart(char *family, char *name, char *axis,
328 */
329 static void ebpf_create_global_charts(ebpf_module_t *em)
330 {
397 - ebpf_create_chart(NETDATA_EBPF_FAMILY,
398 - NETDATA_FILE_OPEN_CLOSE_COUNT,
399 - "Open and close calls",
400 - EBPF_COMMON_DIMENSION_CALL,
401 - NETDATA_FILE_GROUP,
402 - NULL,
403 - NETDATA_EBPF_CHART_TYPE_LINE,
404 - 21000,
405 - ebpf_create_global_dimension,
406 - process_publish_aggregated,
407 - 2, NETDATA_EBPF_MODULE_NAME_PROCESS);
408 -
409 - if (em->mode < MODE_ENTRY) {
410 - ebpf_create_chart(NETDATA_EBPF_FAMILY,
411 - NETDATA_FILE_OPEN_ERR_COUNT,
412 - "Open fails",
413 - EBPF_COMMON_DIMENSION_CALL,
414 - NETDATA_FILE_GROUP,
415 - NULL,
416 - NETDATA_EBPF_CHART_TYPE_LINE,
417 - 21001,
418 - ebpf_create_global_dimension,
419 - process_publish_aggregated,
420 - 2, NETDATA_EBPF_MODULE_NAME_PROCESS);
421 - }
422 -
331 ebpf_create_chart(NETDATA_EBPF_FAMILY,
332 NETDATA_PROCESS_SYSCALL,
333 "Start process",
@@ -476,47 +384,8 @@ static void ebpf_create_global_charts(ebpf_module_t *em)
384 */
385 void ebpf_process_create_apps_charts(struct ebpf_module *em, void *ptr)
386 {
387 + UNUSED(em);
388 struct target *root = ptr;
480 - ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN,
481 - "Number of open files",
482 - EBPF_COMMON_DIMENSION_CALL,
483 - NETDATA_APPS_FILE_GROUP,
484 - NETDATA_EBPF_CHART_TYPE_STACKED,
485 - 20061,
486 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
487 - root, NETDATA_EBPF_MODULE_NAME_PROCESS);
488 -
489 - if (em->mode < MODE_ENTRY) {
490 - ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR,
491 - "Fails to open files",
492 - EBPF_COMMON_DIMENSION_CALL,
493 - NETDATA_APPS_FILE_GROUP,
494 - NETDATA_EBPF_CHART_TYPE_STACKED,
495 - 20062,
496 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
497 - root, NETDATA_EBPF_MODULE_NAME_PROCESS);
498 - }
499 -
500 - ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSED,
501 - "Files closed",
502 - EBPF_COMMON_DIMENSION_CALL,
503 - NETDATA_APPS_FILE_GROUP,
504 - NETDATA_EBPF_CHART_TYPE_STACKED,
505 - 20063,
506 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
507 - root, NETDATA_EBPF_MODULE_NAME_PROCESS);
508 -
509 - if (em->mode < MODE_ENTRY) {
510 - ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR,
511 - "Fails to close files",
512 - EBPF_COMMON_DIMENSION_CALL,
513 - NETDATA_APPS_FILE_GROUP,
514 - NETDATA_EBPF_CHART_TYPE_STACKED,
515 - 20064,
516 - ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
517 - root, NETDATA_EBPF_MODULE_NAME_PROCESS);
518 - }
519 -
389 ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_TASK_PROCESS,
390 "Process started",
391 EBPF_COMMON_DIMENSION_CALL,
@@ -640,7 +509,7 @@ static void process_collector(usec_t step, ebpf_module_t *em)
509 }
510
511 if (publish_apps) {
643 - ebpf_process_send_apps_data(em, apps_groups_root_target);
512 + ebpf_process_send_apps_data(apps_groups_root_target);
513 }
514 pthread_mutex_unlock(&lock);
515
@@ -814,8 +683,7 @@ void *ebpf_process_thread(void *ptr)
683 }
684
685 int algorithms[NETDATA_KEY_PUBLISH_PROCESS_END] = {
817 - NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
818 - NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
686 + NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
687 };
688
689 ebpf_global_labels(
collectors/ebpf.plugin/ebpf_process.h
-23
@@ -7,38 +7,24 @@
7 #define NETDATA_EBPF_MODULE_NAME_PROCESS "process"
8
9 // Groups used on Dashboard
10 -#define NETDATA_FILE_GROUP "File"
10 #define NETDATA_PROCESS_GROUP "Process"
11
12 // Global chart name
14 -#define NETDATA_FILE_OPEN_CLOSE_COUNT "file_descriptor"
15 -#define NETDATA_FILE_OPEN_ERR_COUNT "file_error"
16 -
13 #define NETDATA_EXIT_SYSCALL "exit"
14 #define NETDATA_PROCESS_SYSCALL "process_thread"
15 #define NETDATA_PROCESS_ERROR_NAME "task_error"
16 #define NETDATA_PROCESS_STATUS_NAME "process_status"
17
18 // Charts created on Apps submenu
23 -#define NETDATA_SYSCALL_APPS_FILE_OPEN "file_open"
24 -#define NETDATA_SYSCALL_APPS_FILE_CLOSED "file_closed"
19 #define NETDATA_SYSCALL_APPS_TASK_PROCESS "process_create"
20 #define NETDATA_SYSCALL_APPS_TASK_THREAD "thread_create"
21 #define NETDATA_SYSCALL_APPS_TASK_CLOSE "task_close"
22
29 -// Charts created on Apps submenu, if and only if, the return mode is active
30 -
31 -#define NETDATA_SYSCALL_APPS_FILE_OPEN_ERROR "file_open_error"
32 -#define NETDATA_SYSCALL_APPS_FILE_CLOSE_ERROR "file_close_error"
33 -
23 // Process configuration name
24 #define NETDATA_PROCESS_CONFIG_FILE "process.conf"
25
26 // Index from kernel
27 typedef enum ebpf_process_index {
39 - NETDATA_KEY_CALLS_DO_SYS_OPEN,
40 - NETDATA_KEY_ERROR_DO_SYS_OPEN,
41 -
28 NETDATA_KEY_CALLS_DO_EXIT,
29
30 NETDATA_KEY_CALLS_RELEASE_TASK,
@@ -46,9 +32,6 @@ typedef enum ebpf_process_index {
32 NETDATA_KEY_CALLS_DO_FORK,
33 NETDATA_KEY_ERROR_DO_FORK,
34
49 - NETDATA_KEY_CALLS_CLOSE_FD,
50 - NETDATA_KEY_ERROR_CLOSE_FD,
51 -
35 NETDATA_KEY_CALLS_SYS_CLONE,
36 NETDATA_KEY_ERROR_SYS_CLONE,
37
@@ -61,8 +44,6 @@ typedef enum ebpf_process_index {
44 // values (the three initial positions) and absolute values
45 // (the remaining charts).
46 typedef enum netdata_publish_process {
64 - NETDATA_KEY_PUBLISH_PROCESS_OPEN,
65 - NETDATA_KEY_PUBLISH_PROCESS_CLOSE,
47 NETDATA_KEY_PUBLISH_PROCESS_EXIT,
48 NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK,
49 NETDATA_KEY_PUBLISH_PROCESS_FORK,
@@ -73,16 +54,12 @@ typedef enum netdata_publish_process {
54
55 typedef struct ebpf_process_publish_apps {
56 // Number of calls during the last read
76 - uint64_t call_sys_open;
77 - uint64_t call_close_fd;
57 uint64_t call_do_exit;
58 uint64_t call_release_task;
59 uint64_t call_do_fork;
60 uint64_t call_sys_clone;
61
62 // Number of errors during the last read
84 - uint64_t ecall_sys_open;
85 - uint64_t ecall_close_fd;
63 uint64_t ecall_do_fork;
64 uint64_t ecall_sys_clone;
65 } ebpf_process_publish_apps_t;
libnetdata/ebpf/ebpf.c
+12 -4
@@ -541,10 +541,16 @@ static netdata_run_mode_t ebpf_select_mode(char *mode)
541 return MODE_ENTRY;
542 }
543
544 -void ebpf_update_module_using_config(ebpf_module_t *modules)
544 +/**
545 + * @param modules structure that will be updated
546 + * @param user_cfg is this an user configuration?
547 + */
548 +void ebpf_update_module_using_config(ebpf_module_t *modules, int user_cfg)
549 {
546 - char *mode = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, EBPF_CFG_LOAD_MODE_DEFAULT);
547 - modules->mode = ebpf_select_mode(mode);
550 + if (user_cfg) {
551 + char *mode = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, EBPF_CFG_LOAD_MODE_DEFAULT);
552 + modules->mode = ebpf_select_mode(mode);
553 + }
554
555 modules->update_time = (int)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION,
556 EBPF_CFG_UPDATE_EVERY, modules->update_time);
@@ -571,15 +577,17 @@ void ebpf_update_module(ebpf_module_t *em)
577 {
578 char filename[FILENAME_MAX+1];
579 ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, em->config_file);
580 + int from_user = 1;
581 if (!ebpf_load_config(em->cfg, filename)) {
582 ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, em->config_file);
583 + from_user = 0;
584 if (!ebpf_load_config(em->cfg, filename)) {
585 error("Cannot load the ebpf configuration file %s", em->config_file);
586 return;
587 }
588 }
589
582 - ebpf_update_module_using_config(em);
590 + ebpf_update_module_using_config(em, from_user);
591 }
592
593 //----------------------------------------------------------------------------------------------------------------------
libnetdata/ebpf/ebpf.h
-1
@@ -178,7 +178,6 @@ extern struct bpf_link **ebpf_load_program(char *plugins_dir,
178
179 extern void ebpf_mount_config_name(char *filename, size_t length, char *path, const char *config);
180 extern int ebpf_load_config(struct config *config, char *filename);
181 -extern void ebpf_update_module_using_config(ebpf_module_t *modules);
181 extern void ebpf_update_module(ebpf_module_t *em);
182 extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em);
183 extern void ebpf_load_addresses(ebpf_addresses_t *fa, int fd);
packaging/ebpf.checksums
+3 -3
@@ -1,3 +1,3 @@
1 -0e5d9bbbffeef735534edaf5efa73e2f44b705699268bcc3028e48434e7fe8d0 netdata-kernel-collector-glibc-v0.7.6.tar.xz
2 -ee189fd82dae3c9e68756f88364bfdb97a29adb134ea7d95ae22f6059db4a632 netdata-kernel-collector-musl-v0.7.6.tar.xz
3 -98a31a53b9f7ca7b95c44ec12126357dc7d4c4d4a547142c8573a886ac6de430 netdata-kernel-collector-static-v0.7.6.tar.xz
1 +c04f3832933315669b009d629fe9cbef33d8202aa9b57d45e3777e2385ae0c5b netdata-kernel-collector-glibc-v0.7.6.1.tar.xz
2 +25e9ea852b5ec593be0d6329f1c62e0b6aa872ebc835462d3514a2c9fb9294ef netdata-kernel-collector-musl-v0.7.6.1.tar.xz
3 +6704049d192bb47d2f26fee1ce9add0e93cfde62b0672c56cf4b5ea6bd6bf5e9 netdata-kernel-collector-static-v0.7.6.1.tar.xz
packaging/ebpf.version
+1 -1
@@ -1 +1 @@
1 -v0.7.6
1 +v0.7.6.1
web/gui/dashboard_info.js
+27 -18
@@ -825,6 +825,16 @@ netdataDashboard.submenu = {
825 'filesystem.BTRFS_latency': {
826 title: 'BTRFS Latency',
827 info: 'Latency is the time it takes for an event to be completed. We calculate the difference between the calling and return times, we get the logarithmic for the final result and we sum one value to the respective bin. Based on the eBPF <a href="https://github.com/iovisor/bcc/blob/master/tools/btrfsdist_example.txt" target="_blank">btrfsdist</a> from BCC tools.'
828 + },
829 +
830 + 'filesystem.File_access': {
831 + title: 'File Access',
832 + info: 'When integration with apps is <a href="https://learn.netdata.cloud/guides/troubleshoot/monitor-debug-applications-ebpf" target="_blank">enabled</a>, Netdata also shows file access per <a href="#menu_apps_submenu_file_access">application</a>.'
833 + },
834 +
835 + 'apps.file_access': {
836 + title: 'File Access',
837 + info: 'Netdata also gives a summary for this chart on <a href="#menu_filesystem_submenu_File_access">Filesystem submenu</a> (more details on <a href="https://learn.netdata.cloud/docs/agent/collectors/ebpf.plugin#file" target="_blank">eBPF plugin file chart section</a>).'
838 }
839 };
840
@@ -3609,6 +3619,23 @@ netdataDashboard.context = {
3619 info: 'Monitor errors in calls to syscalls <code>mount(2)</code> and <code>umount(2)</code>.'
3620 },
3621
3622 + 'filesystem.file_descriptor': {
3623 + info: 'Calls for internal functions on Linux kernel. The open dimension is attached to the kernel internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from'+
3624 + ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3625 + ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. ' +
3626 + ' The close dimension is attached to the function <code>__close_fd</code> or <code>close_fd</code> according to your kernel version, which is called from system call' +
3627 + ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3628 + },
3629 +
3630 + 'filesystem.file_error': {
3631 + info: 'Failed calls to the kernel internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from'+
3632 + ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3633 + ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. ' +
3634 + ' The close dimension is attached to the function <code>__close_fd</code> or <code>close_fd</code> according to your kernel version, which is called from system call' +
3635 + ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3636 + },
3637 +
3638 +
3639 // ------------------------------------------------------------------------
3640 // eBPF
3641
@@ -3642,24 +3669,6 @@ netdataDashboard.context = {
3669 info: 'Bytes sent and received for functions <code>udp_sendmsg</code> and <code>udp_recvmsg</code>.'
3670 },
3671
3645 - 'ebpf.file_descriptor': {
3646 - title : 'File access',
3647 - info: 'Calls for internal functions on Linux kernel. The open dimension is attached to the kernel internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from'+
3648 - ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3649 - ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. ' +
3650 - ' The close dimension is attached to the function <code>__close_fd</code> or <code>close_fd</code> according to your kernel version, which is called from system call' +
3651 - ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3652 - },
3653 -
3654 - 'ebpf.file_error': {
3655 - title : 'File access error',
3656 - info: 'Failed calls to the kernel internal function <code>do_sys_open</code> ( For kernels newer than <code>5.5.19</code> we add a kprobe to <code>do_sys_openat2</code>. ), which is the common function called from'+
3657 - ' <a href="https://www.man7.org/linux/man-pages/man2/open.2.html" target="_blank">open(2)</a> ' +
3658 - ' and <a href="https://www.man7.org/linux/man-pages/man2/openat.2.html" target="_blank">openat(2)</a>. ' +
3659 - ' The close dimension is attached to the function <code>__close_fd</code> or <code>close_fd</code> according to your kernel version, which is called from system call' +
3660 - ' <a href="https://www.man7.org/linux/man-pages/man2/close.2.html" target="_blank">close(2)</a>. '
3661 - },
3662 -
3672 'ebpf.process_thread': {
3673 title : 'Task creation',
3674 info: 'Number of times that either <a href="https://www.ece.uic.edu/~yshi1/linux/lkse/node4.html#SECTION00421000000000000000" target="_blank">do_fork</a>, or <code>kernel_clone</code> if you are running kernel newer than 5.9.16, is called to create a new task, which is the common name used to define process and tasks inside the kernel. Netdata identifies the threads by counting the number of calls for <a href="https://linux.die.net/man/2/clone" target="_blank">sys_clone</a> that has the flag <code>CLONE_THREAD</code> set.'