@cryptotaxi247 / netdata-1 / commits / db535e9fd

New eBPF option (#14691)

thiagoftsm committed May 24, 2023 at 16:38 UTC db535e9fd82d09d5101804ecb6a3e2a9208aacf0
36 files changed +1296 -338
collectors/ebpf.plugin/README.md
+32 -12
@@ -99,8 +99,6 @@ accepts the following values:
99 - `return`: In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates new
100 charts for the return of these functions, such as errors. Monitoring function returns can help in debugging software,
101 such as failing to close file descriptors or creating zombie processes.
102 -- `update every`: Number of seconds used for eBPF to send data for Netdata.
103 -- `pid table size`: Defines the maximum number of PIDs stored inside the application hash table.
102
103 #### Integration with `apps.plugin`
104
@@ -115,11 +113,6 @@ If you want to enable `apps.plugin` integration, change the "apps" setting to "y
113 apps = yes
114 ```
115
118 -When the integration is enabled, eBPF collector allocates memory for each process running. The total allocated memory
119 -has direct relationship with the kernel version. When the eBPF plugin is running on kernels newer than `4.15`, it uses
120 -per-cpu maps to speed up the update of hash tables. This also implies storing data for the same PID for each processor
121 -it runs.
122 -
116 #### Integration with `cgroups.plugin`
117
118 The eBPF collector also creates charts for each cgroup through an integration with the
@@ -138,6 +131,13 @@ If you do not need to monitor specific metrics for your `cgroups`, you can enabl
131 `ebpf.d.conf`, and then disable the plugin for a specific `thread` by following the steps in the
132 [Configuration](#configuring-ebpfplugin) section.
133
134 +#### Maps per Core
135 +
136 +When netdata is running on kernels newer than `4.6` users are allowed to modify how the `ebpf.plugin` creates maps (hash or
137 +array). When `maps per core` is defined as `yes`, plugin will create a map per core on host, on the other hand,
138 +when the value is set as `no` only one hash table will be created, this option will use less memory, but it also can
139 +increase overhead for processes.
140 +
141 #### Collect PID
142
143 When one of the previous integrations is enabled, `ebpf.plugin` will use Process Identifier (`PID`) to identify the
@@ -157,6 +157,16 @@ The threads that have integration with other collectors have an internal clean u
157 will only enable these threads integrated with other collectors when the kernel is compiled with
158 `CONFIG_DEBUG_INFO_BTF`, unless you enable them manually.
159
160 +#### Collection period
161 +
162 +The plugin uses the option `update every` to define the number of seconds used for eBPF to send data for Netdata. The default value
163 +is 5 seconds.
164 +
165 +#### PID table size
166 +
167 +The option `pid table size` defines the maximum number of PIDs stored inside the application hash table. The default value
168 +is defined according [kernel](https://elixir.bootlin.com/linux/v6.0.19/source/include/linux/threads.h#L28) source code.
169 +
170 #### Integration Dashboard Elements
171
172 When an integration is enabled, your dashboard will also show the following cgroups and apps charts using low-level
@@ -880,14 +890,24 @@ These are tracepoints related to [OOM](https://en.wikipedia.org/wiki/Out_of_memo
890 eBPF monitoring is complex and produces a large volume of metrics. We've discovered scenarios where the eBPF plugin
891 significantly increases kernel memory usage by several hundred MB.
892
883 -If your node is experiencing high memory usage and there is no obvious culprit to be found in the `apps.mem` chart,
884 -consider testing for high kernel memory usage by [disabling eBPF monitoring](#configuring-ebpfplugin). Next,
885 -[restart Netdata](https://github.com/netdata/netdata/blob/master/docs/configure/start-stop-restart.md) with `sudo systemctl restart netdata` to see if system memory
886 -usage (see the `system.ram` chart) has dropped significantly.
893 +When the integration with apps or cgroup is enabled, the eBPF collector allocates memory for each process running. If your
894 +node is experiencing high memory usage and there is no obvious culprit to be found in the `apps.mem` chart, consider:
895 +
896 +- Modify [maps per core](#maps-per-core) to use only one map.
897 +- Disable [integration with apps](#integration-with-appsplugin).
898 +- Disable [integration with cgroup](#integration-with-cgroupsplugin).
899
888 -Beginning with `v1.31`, kernel memory usage is configurable via the [`pid table size` setting](#ebpf-load-mode)
900 +If with these changes you still suspect eBPF using too much memory, and there is no obvious culprit to be found
901 +in the `apps.mem` chart, consider testing for high kernel memory usage by [disabling eBPF monitoring](#configuring-ebpfplugin).
902 +Next, [restart Netdata](https://github.com/netdata/netdata/blob/master/docs/configure/start-stop-restart.md) with
903 +`sudo systemctl restart netdata` to see if system memory usage (see the `system.ram` chart) has dropped significantly.
904 +
905 +Beginning with `v1.31`, kernel memory usage is configurable via the [`pid table size` setting](#pid-table-size)
906 in `ebpf.conf`.
907
908 +The total memory usage is a well known [issue](https://lore.kernel.org/all/167821082315.1693.6957546778534183486.git-patchwork-notify@kernel.org/)
909 +for eBPF, this is not a bug present in plugin.
910 +
911 ### SELinux
912
913 When [SELinux](https://www.redhat.com/en/topics/linux/what-is-selinux) is enabled, it may prevent `ebpf.plugin` from
collectors/ebpf.plugin/ebpf.c
+78 -31
@@ -54,7 +54,8 @@ ebpf_module_t ebpf_modules[] = {
54 .config_file = NETDATA_PROCESS_CONFIG_FILE,
55 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10 |
56 NETDATA_V5_14,
57 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
57 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
58 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
59 { .thread_name = "socket", .config_name = "socket", .enabled = 0, .start_routine = ebpf_socket_thread,
60 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
61 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -62,7 +63,8 @@ ebpf_module_t ebpf_modules[] = {
63 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config,
64 .config_file = NETDATA_NETWORK_CONFIG_FILE,
65 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
65 - .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
66 + .load = EBPF_LOAD_LEGACY, .targets = socket_targets, .probe_links = NULL, .objects = NULL,
67 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
68 { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread,
69 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
70 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -71,7 +73,8 @@ ebpf_module_t ebpf_modules[] = {
73 .config_file = NETDATA_CACHESTAT_CONFIG_FILE,
74 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
75 NETDATA_V5_4 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16,
74 - .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
76 + .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets, .probe_links = NULL, .objects = NULL,
77 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
78 { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
79 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
80 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -79,7 +82,8 @@ ebpf_module_t ebpf_modules[] = {
82 .config_file = NETDATA_SYNC_CONFIG_FILE,
83 // All syscalls have the same kernels
84 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
82 - .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
85 + .load = EBPF_LOAD_LEGACY, .targets = sync_targets, .probe_links = NULL, .objects = NULL,
86 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
87 { .thread_name = "dc", .config_name = "dc", .enabled = 0, .start_routine = ebpf_dcstat_thread,
88 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
89 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -87,7 +91,8 @@ ebpf_module_t ebpf_modules[] = {
91 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
92 .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
93 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
90 - .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
94 + .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL,
95 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
96 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
97 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
98 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -95,7 +100,8 @@ ebpf_module_t ebpf_modules[] = {
100 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
101 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
102 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
98 - .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
103 + .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL,
104 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
105 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
106 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
107 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -103,28 +109,32 @@ ebpf_module_t ebpf_modules[] = {
109 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
110 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
111 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
106 - .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
112 + .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL,
113 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
114 { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
115 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
116 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
117 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
118 .config_file = NETDATA_FILESYSTEM_CONFIG_FILE,
119 //We are setting kernels as zero, because we load eBPF programs according the kernel running.
113 - .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL },
120 + .kernels = 0, .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
121 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES },
122 { .thread_name = "disk", .config_name = "disk", .enabled = 0, .start_routine = ebpf_disk_thread,
123 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
124 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
125 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
126 .config_file = NETDATA_DISK_CONFIG_FILE,
127 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
120 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
128 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
129 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
130 { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
131 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
132 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
133 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
134 .config_file = NETDATA_MOUNT_CONFIG_FILE,
135 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
127 - .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
136 + .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL,
137 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
138 { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
139 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
140 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -133,21 +143,24 @@ ebpf_module_t ebpf_modules[] = {
143 .config_file = NETDATA_FD_CONFIG_FILE,
144 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 |
145 NETDATA_V5_14,
136 - .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
146 + .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL,
147 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
148 { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
149 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
150 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
151 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &hardirq_config,
152 .config_file = NETDATA_HARDIRQ_CONFIG_FILE,
153 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
143 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
154 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
155 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
156 { .thread_name = "softirq", .config_name = "softirq", .enabled = 0, .start_routine = ebpf_softirq_thread,
157 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
158 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
159 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &softirq_config,
160 .config_file = NETDATA_SOFTIRQ_CONFIG_FILE,
161 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
150 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
162 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
163 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
164 { .thread_name = "oomkill", .config_name = "oomkill", .enabled = 0, .start_routine = ebpf_oomkill_thread,
165 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
166 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -155,7 +168,8 @@ ebpf_module_t ebpf_modules[] = {
168 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &oomkill_config,
169 .config_file = NETDATA_OOMKILL_CONFIG_FILE,
170 .kernels = NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
158 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
171 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
172 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
173 { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
174 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
175 .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -163,19 +177,21 @@ ebpf_module_t ebpf_modules[] = {
177 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
178 .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
179 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
166 - .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL, .thread = NULL},
180 + .load = EBPF_LOAD_LEGACY, .targets = shm_targets, .probe_links = NULL, .objects = NULL,
181 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
182 { .thread_name = "mdflush", .config_name = "mdflush", .enabled = 0, .start_routine = ebpf_mdflush_thread,
183 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
184 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
185 .apps_routine = NULL, .maps = NULL, .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mdflush_config,
186 .config_file = NETDATA_DIRECTORY_MDFLUSH_CONFIG_FILE,
187 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
173 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
188 + .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
189 + .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
190 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_every = EBPF_DEFAULT_UPDATE_EVERY,
191 .global_charts = 0, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO, .apps_level = NETDATA_APPS_NOT_SET,
192 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
193 .pid_map_size = 0, .names = NULL, .cfg = NULL, .config_name = NULL, .kernels = 0, .load = EBPF_LOAD_LEGACY,
178 - .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL},
194 + .targets = NULL, .probe_links = NULL, .objects = NULL, .thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES},
195 };
196
197 struct netdata_static_thread ebpf_threads[] = {
@@ -360,7 +376,8 @@ ebpf_filesystem_partitions_t localfs[] =
376 .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
377 .enabled = CONFIG_BOOLEAN_YES,
378 .addresses = {.function = NULL, .addr = 0},
363 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
379 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
380 + .fs_maps = NULL},
381 {.filesystem = "xfs",
382 .optional_filesystem = NULL,
383 .family = "xfs",
@@ -369,7 +386,8 @@ ebpf_filesystem_partitions_t localfs[] =
386 .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
387 .enabled = CONFIG_BOOLEAN_YES,
388 .addresses = {.function = NULL, .addr = 0},
372 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
389 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
390 + .fs_maps = NULL},
391 {.filesystem = "nfs",
392 .optional_filesystem = "nfs4",
393 .family = "nfs",
@@ -378,7 +396,8 @@ ebpf_filesystem_partitions_t localfs[] =
396 .flags = NETDATA_FILESYSTEM_ATTR_CHARTS,
397 .enabled = CONFIG_BOOLEAN_YES,
398 .addresses = {.function = NULL, .addr = 0},
381 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
399 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
400 + .fs_maps = NULL},
401 {.filesystem = "zfs",
402 .optional_filesystem = NULL,
403 .family = "zfs",
@@ -387,7 +406,8 @@ ebpf_filesystem_partitions_t localfs[] =
406 .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
407 .enabled = CONFIG_BOOLEAN_YES,
408 .addresses = {.function = NULL, .addr = 0},
390 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4},
409 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
410 + .fs_maps = NULL},
411 {.filesystem = "btrfs",
412 .optional_filesystem = NULL,
413 .family = "btrfs",
@@ -396,7 +416,8 @@ ebpf_filesystem_partitions_t localfs[] =
416 .flags = NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE,
417 .enabled = CONFIG_BOOLEAN_YES,
418 .addresses = {.function = "btrfs_file_operations", .addr = 0},
399 - .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10},
419 + .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_10,
420 + .fs_maps = NULL},
421 {.filesystem = NULL,
422 .optional_filesystem = NULL,
423 .family = NULL,
@@ -405,43 +426,50 @@ ebpf_filesystem_partitions_t localfs[] =
426 .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
427 .enabled = CONFIG_BOOLEAN_YES,
428 .addresses = {.function = NULL, .addr = 0},
408 - .kernels = 0}};
429 + .kernels = 0, .fs_maps = NULL}};
430
431 ebpf_sync_syscalls_t local_syscalls[] = {
432 {.syscall = NETDATA_SYSCALLS_SYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
433 #ifdef LIBBPF_MAJOR_VERSION
413 - .sync_obj = NULL
434 + .sync_obj = NULL,
435 #endif
436 + .sync_maps = NULL
437 },
438 {.syscall = NETDATA_SYSCALLS_SYNCFS, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
439 #ifdef LIBBPF_MAJOR_VERSION
418 - .sync_obj = NULL
440 + .sync_obj = NULL,
441 #endif
442 + .sync_maps = NULL
443 },
444 {.syscall = NETDATA_SYSCALLS_MSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
445 #ifdef LIBBPF_MAJOR_VERSION
423 - .sync_obj = NULL
446 + .sync_obj = NULL,
447 #endif
448 + .sync_maps = NULL
449 },
450 {.syscall = NETDATA_SYSCALLS_FSYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
451 #ifdef LIBBPF_MAJOR_VERSION
428 - .sync_obj = NULL
452 + .sync_obj = NULL,
453 #endif
454 + .sync_maps = NULL
455 },
456 {.syscall = NETDATA_SYSCALLS_FDATASYNC, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
457 #ifdef LIBBPF_MAJOR_VERSION
433 - .sync_obj = NULL
458 + .sync_obj = NULL,
459 #endif
460 + .sync_maps = NULL
461 },
462 {.syscall = NETDATA_SYSCALLS_SYNC_FILE_RANGE, .enabled = CONFIG_BOOLEAN_YES, .objects = NULL, .probe_links = NULL,
463 #ifdef LIBBPF_MAJOR_VERSION
438 - .sync_obj = NULL
464 + .sync_obj = NULL,
465 #endif
466 + .sync_maps = NULL
467 },
468 {.syscall = NULL, .enabled = CONFIG_BOOLEAN_NO, .objects = NULL, .probe_links = NULL,
469 #ifdef LIBBPF_MAJOR_VERSION
443 - .sync_obj = NULL
470 + .sync_obj = NULL,
471 #endif
472 + .sync_maps = NULL
473 }
474 };
475
@@ -1737,6 +1765,21 @@ static inline void epbf_update_load_mode(char *str, netdata_ebpf_load_mode_t ori
1765 ebpf_set_load_mode(load, origin);
1766 }
1767
1768 +/**
1769 + * Update Map per core
1770 + *
1771 + * Define the map type used with some hash tables.
1772 + */
1773 +static void ebpf_update_map_per_core()
1774 +{
1775 + int i;
1776 + int value = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION,
1777 + EBPF_CFG_MAPS_PER_CORE, CONFIG_BOOLEAN_YES);
1778 + for (i = 0; ebpf_modules[i].thread_name; i++) {
1779 + ebpf_modules[i].maps_per_core = value;
1780 + }
1781 +}
1782 +
1783 /**
1784 * Read collector values
1785 *
@@ -1790,6 +1833,8 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
1833 enabled = appconfig_get_boolean(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_CGROUP, CONFIG_BOOLEAN_NO);
1834 *disable_cgroups = (enabled == CONFIG_BOOLEAN_NO)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_NO;
1835
1836 + ebpf_update_map_per_core();
1837 +
1838 // Read ebpf programs section
1839 enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION,
1840 ebpf_modules[EBPF_MODULE_PROCESS_IDX].config_name, CONFIG_BOOLEAN_YES);
@@ -2540,6 +2585,7 @@ int main(int argc, char **argv)
2585 heartbeat_init(&hb);
2586 int update_apps_every = (int) EBPF_CFG_UPDATE_APPS_EVERY_DEFAULT;
2587 int update_apps_list = update_apps_every - 1;
2588 + int process_maps_per_core = ebpf_modules[EBPF_MODULE_PROCESS_IDX].maps_per_core;
2589 //Plugin will be killed when it receives a signal
2590 while (!ebpf_exit_plugin) {
2591 (void)heartbeat_next(&hb, step);
@@ -2550,7 +2596,7 @@ int main(int argc, char **argv)
2596 if (++update_apps_list == update_apps_every) {
2597 update_apps_list = 0;
2598 cleanup_exited_pids();
2553 - collect_data_for_all_processes(process_pid_fd);
2599 + collect_data_for_all_processes(process_pid_fd, process_maps_per_core);
2600
2601 pthread_mutex_lock(&lock);
2602 ebpf_create_apps_charts(apps_groups_root_target);
@@ -2565,3 +2611,4 @@ int main(int argc, char **argv)
2611
2612 return 0;
2613 }
2614 +
collectors/ebpf.plugin/ebpf.d.conf
+5
@@ -15,6 +15,10 @@
15 #
16 # The `pid table size` defines the maximum number of PIDs stored in the application hash tables.
17 #
18 +# The `btf path` specifies where to find the BTF files.
19 +#
20 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.15.
21 +#
22 [global]
23 ebpf load mode = entry
24 apps = no
@@ -22,6 +26,7 @@
26 update every = 5
27 pid table size = 32768
28 btf path = /sys/kernel/btf/
29 + maps per core = yes
30
31 #
32 # eBPF Programs
collectors/ebpf.plugin/ebpf.d/cachestat.conf
+3
@@ -24,6 +24,8 @@
24 # `parent` : Only stores parent PID.
25 # `all` : Stores all PIDs used by software. This is the most expensive option.
26 #
27 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
28 +#
29 # Uncomment lines to define specific options for thread.
30 [global]
31 # ebpf load mode = entry
@@ -34,3 +36,4 @@
36 ebpf type format = auto
37 ebpf co-re tracing = trampoline
38 collect pid = real parent
39 +# maps per core = yes
collectors/ebpf.plugin/ebpf.d/dcstat.conf
+3
@@ -22,6 +22,8 @@
22 # `parent` : Only stores parent PID.
23 # `all` : Stores all PIDs used by software. This is the most expensive option.
24 #
25 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
26 +#
27 # Uncomment lines to define specific options for thread.
28 [global]
29 # ebpf load mode = entry
@@ -32,3 +34,4 @@
34 ebpf type format = auto
35 ebpf co-re tracing = trampoline
36 collect pid = real parent
37 +# maps per core = yes
collectors/ebpf.plugin/ebpf.d/fd.conf
+3
@@ -10,6 +10,8 @@
10 #
11 # The `pid table size` defines the maximum number of PIDs stored inside the hash table.
12 #
13 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
14 +#
15 # Uncomment lines to define specific options for thread.
16 [global]
17 # ebpf load mode = entry
@@ -19,3 +21,4 @@
21 # pid table size = 32768
22 ebpf type format = auto
23 ebpf co-re tracing = trampoline
24 +# maps per core = yes
collectors/ebpf.plugin/ebpf.d/network.conf
+4
@@ -24,6 +24,9 @@
24 # `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall.
25 # `probe` : This is the same as legacy code.
26 #
27 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
28 +#
29 +# Uncomment lines to define specific options for thread.
30 [global]
31 # ebpf load mode = entry
32 # apps = yes
@@ -35,6 +38,7 @@
38 udp connection table size = 4096
39 ebpf type format = auto
40 ebpf co-re tracing = trampoline
41 + maps per core = no
42
43 #
44 # Network Connection
collectors/ebpf.plugin/ebpf.d/process.conf
+5 -2
@@ -15,11 +15,14 @@
15 # `parent` : Only stores parent PID.
16 # `all` : Stores all PIDs used by software. This is the most expensive option.
17 #
18 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
19 +#
20 # Uncomment lines to define specific options for thread.
19 -#[global]
21 +[global]
22 # ebpf load mode = entry
23 # apps = yes
24 # cgroups = no
25 # update every = 10
26 # pid table size = 32768
25 -# collect pid = real parent
27 + collect pid = real parent
28 +# maps per core = yes
collectors/ebpf.plugin/ebpf.d/shm.conf
+3
@@ -18,6 +18,8 @@
18 # `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall.
19 # `probe` : This is the same as legacy code.
20 #
21 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22 +#
23 # Uncomment lines to define specific options for thread.
24 [global]
25 # ebpf load mode = entry
@@ -27,6 +29,7 @@
29 # pid table size = 32768
30 ebpf type format = auto
31 ebpf co-re tracing = trampoline
32 +# maps per core = yes
33
34 # List of monitored syscalls
35 [syscalls]
collectors/ebpf.plugin/ebpf.d/swap.conf
+3
@@ -17,6 +17,8 @@
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 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
21 +#
22 # Uncomment lines to define specific options for thread.
23 [global]
24 # ebpf load mode = entry
@@ -26,3 +28,4 @@
28 # pid table size = 32768
29 ebpf type format = auto
30 ebpf co-re tracing = trampoline
31 +# maps per core = yes
collectors/ebpf.plugin/ebpf.d/sync.conf
+4
@@ -17,7 +17,10 @@
17 # `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
18 # `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall.
19 # `probe` : This is the same as legacy code.
20 +#
21 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22 #
23 +# Uncomment lines to define specific options for thread.
24 [global]
25 # ebpf load mode = entry
26 # apps = yes
@@ -25,6 +28,7 @@
28 # update every = 10
29 ebpf type format = auto
30 ebpf co-re tracing = trampoline
31 +# maps per core = yes
32
33 # List of monitored syscalls
34 [syscalls]
collectors/ebpf.plugin/ebpf.d/vfs.conf
+13
@@ -8,6 +8,18 @@
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 +# `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall.
19 +# `probe` : This is the same as legacy code.
20 +#
21 +# The `maps per core` defines if hash tables will be per core or not. This option is ignored on kernels older than 4.6.
22 +#
23 # Uncomment lines to define specific options for thread.
24 [global]
25 # ebpf load mode = entry
@@ -17,3 +29,4 @@
29 # pid table size = 32768
30 ebpf type format = auto
31 ebpf co-re tracing = trampoline
32 +# maps per core = yes
collectors/ebpf.plugin/ebpf.h
+1
@@ -159,6 +159,7 @@ typedef struct ebpf_tracepoint {
159 #define NETDATA_EBPF_LOAD_METHOD "ebpf_load_methods"
160 #define NETDATA_EBPF_KERNEL_MEMORY "ebpf_kernel_memory"
161 #define NETDATA_EBPF_HASH_TABLES_LOADED "ebpf_hash_tables_count"
162 +#define NETDATA_EBPF_HASH_TABLES_PER_CORE "ebpf_hash_tables_per_core"
163
164 // Log file
165 #define NETDATA_DEVELOPER_LOG_FILE "developer.log"
collectors/ebpf.plugin/ebpf_apps.c
+35 -2
@@ -1414,6 +1414,28 @@ static inline void aggregate_pid_on_target(struct ebpf_target *w, struct ebpf_pi
1414 w->root_pid = pid_on_target;
1415 }
1416
1417 +/**
1418 + * Process Accumulator
1419 + *
1420 + * Sum all values read from kernel and store in the first address.
1421 + *
1422 + * @param out the vector with read values.
1423 + * @param maps_per_core do I need to read all cores?
1424 + */
1425 +void ebpf_process_apps_accumulator(ebpf_process_stat_t *out, int maps_per_core)
1426 +{
1427 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
1428 + ebpf_process_stat_t *total = &out[0];
1429 + for (i = 1; i < end; i++) {
1430 + ebpf_process_stat_t *w = &out[i];
1431 + total->exit_call += w->exit_call;
1432 + total->task_err += w->task_err;
1433 + total->create_thread += w->create_thread;
1434 + total->create_process += w->create_process;
1435 + total->release_call += w->release_call;
1436 + }
1437 +}
1438 +
1439 /**
1440 * Collect data for all process
1441 *
@@ -1421,8 +1443,9 @@ static inline void aggregate_pid_on_target(struct ebpf_target *w, struct ebpf_pi
1443 * It also creates the link between targets and PIDs.
1444 *
1445 * @param tbl_pid_stats_fd The mapped file descriptor for the hash table.
1446 + * @param maps_per_core do I have hash maps per core?
1447 */
1425 -void collect_data_for_all_processes(int tbl_pid_stats_fd)
1448 +void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core)
1449 {
1450 if (unlikely(!ebpf_all_pids))
1451 return;
@@ -1448,6 +1471,10 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1471 uint32_t key;
1472 pids = ebpf_root_of_pids; // global list of all processes running
1473 // while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
1474 + size_t length = sizeof(ebpf_process_stat_t);
1475 + if (maps_per_core)
1476 + length *= ebpf_nprocs;
1477 +
1478 while (pids) {
1479 key = pids->pid;
1480 ebpf_process_stat_t *w = global_process_stats[key];
@@ -1456,7 +1483,7 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1483 global_process_stats[key] = w;
1484 }
1485
1459 - if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, w)) {
1486 + if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, process_stat_vector)) {
1487 // Clean Process structures
1488 ebpf_process_stat_release(w);
1489 global_process_stats[key] = NULL;
@@ -1467,6 +1494,12 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd)
1494 continue;
1495 }
1496
1497 + ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
1498 +
1499 + memcpy(w, process_stat_vector, sizeof(ebpf_process_stat_t));
1500 +
1501 + memset(process_stat_vector, 0, length);
1502 +
1503 pids = pids->next;
1504 }
1505
collectors/ebpf.plugin/ebpf_apps.h
+3 -1
@@ -213,7 +213,8 @@ size_t read_processes_statistic_using_pid_on_target(ebpf_process_stat_t **ep,
213
214 size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct ebpf_pid_on_target *pids);
215
216 -void collect_data_for_all_processes(int tbl_pid_stats_fd);
216 +void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core);
217 +void ebpf_process_apps_accumulator(ebpf_process_stat_t *out, int maps_per_core);
218
219 extern ebpf_process_stat_t **global_process_stats;
220 extern netdata_publish_cachestat_t **cachestat_pid;
@@ -235,6 +236,7 @@ extern void ebpf_aral_init(void);
236
237 extern ebpf_process_stat_t *ebpf_process_stat_get(void);
238 extern void ebpf_process_stat_release(ebpf_process_stat_t *stat);
239 +extern ebpf_process_stat_t *process_stat_vector;
240
241 extern ARAL *ebpf_aral_socket_pid;
242 void ebpf_socket_aral_init();
collectors/ebpf.plugin/ebpf_cachestat.c
+64 -28
@@ -14,19 +14,34 @@ static netdata_idx_t cachestat_hash_values[NETDATA_CACHESTAT_END];
14 static netdata_idx_t *cachestat_values = NULL;
15
16 ebpf_local_maps_t cachestat_maps[] = {{.name = "cstat_global", .internal_input = NETDATA_CACHESTAT_END,
17 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
18 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
19 - {.name = "cstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
20 - .user_input = 0,
21 - .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
22 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
23 - {.name = "cstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
24 - .user_input = 0,
25 - .type = NETDATA_EBPF_MAP_CONTROLLER,
26 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
27 - {.name = NULL, .internal_input = 0, .user_input = 0,
28 - .type = NETDATA_EBPF_MAP_CONTROLLER,
29 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
17 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
18 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
19 +#ifdef LIBBPF_MAJOR_VERSION
20 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
21 +#endif
22 + },
23 + {.name = "cstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
24 + .user_input = 0,
25 + .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
26 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
27 +#ifdef LIBBPF_MAJOR_VERSION
28 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
29 +#endif
30 + },
31 + {.name = "cstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
32 + .user_input = 0,
33 + .type = NETDATA_EBPF_MAP_CONTROLLER,
34 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
35 +#ifdef LIBBPF_MAJOR_VERSION
36 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
37 +#endif
38 + },
39 + {.name = NULL, .internal_input = 0, .user_input = 0,
40 + .type = NETDATA_EBPF_MAP_CONTROLLER,
41 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
42 +#ifdef LIBBPF_MAJOR_VERSION
43 +#endif
44 + }};
45
46 struct config cachestat_config = { .first_section = NULL,
47 .last_section = NULL,
@@ -233,10 +248,14 @@ static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
248 * @param obj is the main structure for bpf objects.
249 * @param em structure with configuration
250 */
236 -static void ebpf_cachestat_adjust_map_size(struct cachestat_bpf *obj, ebpf_module_t *em)
251 +static void ebpf_cachestat_adjust_map(struct cachestat_bpf *obj, ebpf_module_t *em)
252 {
253 ebpf_update_map_size(obj->maps.cstat_pid, &cachestat_maps[NETDATA_CACHESTAT_PID_STATS],
254 em, bpf_map__name(obj->maps.cstat_pid));
255 +
256 + ebpf_update_map_type(obj->maps.cstat_global, &cachestat_maps[NETDATA_CACHESTAT_GLOBAL_STATS]);
257 + ebpf_update_map_type(obj->maps.cstat_pid, &cachestat_maps[NETDATA_CACHESTAT_PID_STATS]);
258 + ebpf_update_map_type(obj->maps.cstat_ctrl, &cachestat_maps[NETDATA_CACHESTAT_CTRL]);
259 }
260
261 /**
@@ -291,7 +310,7 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
310 ebpf_cachestat_disable_specific_probe(obj);
311 }
312
294 - ebpf_cachestat_adjust_map_size(obj, em);
313 + ebpf_cachestat_adjust_map(obj, em);
314
315 if (!em->apps_charts && !em->cgroup_charts)
316 ebpf_cachestat_disable_release_task(obj);
@@ -445,10 +464,11 @@ static void calculate_stats(netdata_publish_cachestat_t *publish) {
464 * Sum all values read from kernel and store in the first address.
465 *
466 * @param out the vector with read values.
467 + * @param maps_per_core do I need to read all cores?
468 */
449 -static void cachestat_apps_accumulator(netdata_cachestat_pid_t *out)
469 +static void cachestat_apps_accumulator(netdata_cachestat_pid_t *out, int maps_per_core)
470 {
451 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
471 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
472 netdata_cachestat_pid_t *total = &out[0];
473 for (i = 1; i < end; i++) {
474 netdata_cachestat_pid_t *w = &out[i];
@@ -504,14 +524,19 @@ static void cachestat_fill_pid(uint32_t current_pid, netdata_cachestat_pid_t *pu
524 * Read APPS table
525 *
526 * Read the apps table and store data inside the structure.
527 + *
528 + * @param maps_per_core do I need to read all cores?
529 */
508 -static void read_apps_table()
530 +static void ebpf_read_cachestat_apps_table(int maps_per_core)
531 {
532 netdata_cachestat_pid_t *cv = cachestat_vector;
533 uint32_t key;
534 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
535 int fd = cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd;
514 - size_t length = sizeof(netdata_cachestat_pid_t)*ebpf_nprocs;
536 + size_t length = sizeof(netdata_cachestat_pid_t);
537 + if (maps_per_core)
538 + length *= ebpf_nprocs;
539 +
540 while (pids) {
541 key = pids->pid;
542
@@ -520,7 +545,7 @@ static void read_apps_table()
545 continue;
546 }
547
523 - cachestat_apps_accumulator(cv);
548 + cachestat_apps_accumulator(cv, maps_per_core);
549
550 cachestat_fill_pid(key, cv);
551
@@ -535,12 +560,16 @@ static void read_apps_table()
560 * Update cgroup
561 *
562 * Update cgroup data based in
563 + *
564 + * @param maps_per_core do I need to read all cores?
565 */
539 -static void ebpf_update_cachestat_cgroup()
566 +static void ebpf_update_cachestat_cgroup(int maps_per_core)
567 {
568 netdata_cachestat_pid_t *cv = cachestat_vector;
569 int fd = cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd;
543 - size_t length = sizeof(netdata_cachestat_pid_t) * ebpf_nprocs;
570 + size_t length = sizeof(netdata_cachestat_pid_t);
571 + if (maps_per_core)
572 + length *= ebpf_nprocs;
573
574 ebpf_cgroup_target_t *ect;
575 pthread_mutex_lock(&mutex_cgroup_shm);
@@ -559,7 +588,7 @@ static void ebpf_update_cachestat_cgroup()
588 continue;
589 }
590
562 - cachestat_apps_accumulator(cv);
591 + cachestat_apps_accumulator(cv, maps_per_core);
592
593 memcpy(out, cv, sizeof(netdata_cachestat_pid_t));
594 }
@@ -627,8 +656,10 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
656 * Read global counter
657 *
658 * Read the table with number of calls for all functions
659 + *
660 + * @param maps_per_core do I need to read all cores?
661 */
631 -static void ebpf_cachestat_read_global_table()
662 +static void ebpf_cachestat_read_global_table(int maps_per_core)
663 {
664 uint32_t idx;
665 netdata_idx_t *val = cachestat_hash_values;
@@ -638,7 +669,7 @@ static void ebpf_cachestat_read_global_table()
669 for (idx = NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU; idx < NETDATA_CACHESTAT_END; idx++) {
670 if (!bpf_map_lookup_elem(fd, &idx, stored)) {
671 int i;
641 - int end = ebpf_nprocs;
672 + int end = (maps_per_core) ? ebpf_nprocs: 1;
673 netdata_idx_t total = 0;
674 for (i = 0; i < end; i++)
675 total += stored[i];
@@ -1053,6 +1084,7 @@ static void cachestat_collector(ebpf_module_t *em)
1084 memset(&publish, 0, sizeof(publish));
1085 int cgroups = em->cgroup_charts;
1086 int update_every = em->update_every;
1087 + int maps_per_core = em->maps_per_core;
1088 heartbeat_t hb;
1089 heartbeat_init(&hb);
1090 int counter = update_every - 1;
@@ -1065,13 +1097,13 @@ static void cachestat_collector(ebpf_module_t *em)
1097
1098 counter = 0;
1099 netdata_apps_integration_flags_t apps = em->apps_charts;
1068 - ebpf_cachestat_read_global_table();
1100 + ebpf_cachestat_read_global_table(maps_per_core);
1101 pthread_mutex_lock(&collect_data_mutex);
1102 if (apps)
1071 - read_apps_table();
1103 + ebpf_read_cachestat_apps_table(maps_per_core);
1104
1105 if (cgroups)
1074 - ebpf_update_cachestat_cgroup();
1106 + ebpf_update_cachestat_cgroup(maps_per_core);
1107
1108 pthread_mutex_lock(&lock);
1109
@@ -1216,6 +1248,10 @@ static int ebpf_cachestat_set_internal_value()
1248 */
1249 static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1250 {
1251 +#ifdef LIBBPF_MAJOR_VERSION
1252 + ebpf_define_map_type(cachestat_maps, em->maps_per_core, running_on_kernel);
1253 +#endif
1254 +
1255 int ret = 0;
1256 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode);
1257 if (em->load & EBPF_LOAD_LEGACY) {
collectors/ebpf.plugin/ebpf_dcstat.c
+64 -29
@@ -19,19 +19,35 @@ struct config dcstat_config = { .first_section = NULL,
19 .rwlock = AVL_LOCK_INITIALIZER } };
20
21 ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
22 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
23 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
24 - {.name = "dcstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
25 - .user_input = 0,
26 - .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
28 - {.name = "dcstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
29 - .user_input = 0,
30 - .type = NETDATA_EBPF_MAP_CONTROLLER,
31 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
32 - {.name = NULL, .internal_input = 0, .user_input = 0,
33 - .type = NETDATA_EBPF_MAP_CONTROLLER,
34 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
22 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
23 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
24 +#ifdef LIBBPF_MAJOR_VERSION
25 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
26 +#endif
27 + },
28 + {.name = "dcstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
29 + .user_input = 0,
30 + .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
31 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
32 +#ifdef LIBBPF_MAJOR_VERSION
33 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
34 +#endif
35 + },
36 + {.name = "dcstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
37 + .user_input = 0,
38 + .type = NETDATA_EBPF_MAP_CONTROLLER,
39 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
40 +#ifdef LIBBPF_MAJOR_VERSION
41 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
42 +#endif
43 + },
44 + {.name = NULL, .internal_input = 0, .user_input = 0,
45 + .type = NETDATA_EBPF_MAP_CONTROLLER,
46 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
47 +#ifdef LIBBPF_MAJOR_VERSION
48 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
49 +#endif
50 + }};
51
52 static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_lookup_fast",
53 .function_to_attach = "lookup_fast",
@@ -138,10 +154,14 @@ static int ebpf_dc_attach_probes(struct dc_bpf *obj)
154 * @param obj is the main structure for bpf objects.
155 * @param em structure with configuration
156 */
141 -static void ebpf_dc_adjust_map_size(struct dc_bpf *obj, ebpf_module_t *em)
157 +static void ebpf_dc_adjust_map(struct dc_bpf *obj, ebpf_module_t *em)
158 {
159 ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
160 em, bpf_map__name(obj->maps.dcstat_pid));
161 +
162 + ebpf_update_map_type(obj->maps.dcstat_global, &dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS]);
163 + ebpf_update_map_type(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS]);
164 + ebpf_update_map_type(obj->maps.dcstat_ctrl, &dcstat_maps[NETDATA_DCSTAT_CTRL]);
165 }
166
167 /**
@@ -215,7 +235,7 @@ static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
235 ebpf_dc_disable_trampoline(obj);
236 }
237
218 - ebpf_dc_adjust_map_size(obj, em);
238 + ebpf_dc_adjust_map(obj, em);
239
240 if (!em->apps_charts && !em->cgroup_charts)
241 ebpf_dc_disable_release_task(obj);
@@ -382,10 +402,11 @@ void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
402 * Sum all values read from kernel and store in the first address.
403 *
404 * @param out the vector with read values.
405 + * @param maps_per_core do I need to read all cores?
406 */
386 -static void dcstat_apps_accumulator(netdata_dcstat_pid_t *out)
407 +static void dcstat_apps_accumulator(netdata_dcstat_pid_t *out, int maps_per_core)
408 {
388 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
409 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
410 netdata_dcstat_pid_t *total = &out[0];
411 for (i = 1; i < end; i++) {
412 netdata_dcstat_pid_t *w = &out[i];
@@ -428,17 +449,22 @@ static void dcstat_fill_pid(uint32_t current_pid, netdata_dcstat_pid_t *publish)
449 }
450
451 /**
431 - * Read APPS table
452 + * Read Directory Cache APPS table
453 *
454 * Read the apps table and store data inside the structure.
455 + *
456 + * @param maps_per_core do I need to read all cores?
457 */
435 -static void read_apps_table()
458 +static void read_dc_apps_table(int maps_per_core)
459 {
460 netdata_dcstat_pid_t *cv = dcstat_vector;
461 uint32_t key;
462 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
463 int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
441 - size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
464 + size_t length = sizeof(netdata_dcstat_pid_t);
465 + if (maps_per_core)
466 + length *= ebpf_nprocs;
467 +
468 while (pids) {
469 key = pids->pid;
470
@@ -447,7 +473,7 @@ static void read_apps_table()
473 continue;
474 }
475
450 - dcstat_apps_accumulator(cv);
476 + dcstat_apps_accumulator(cv, maps_per_core);
477
478 dcstat_fill_pid(key, cv);
479
@@ -461,9 +487,11 @@ static void read_apps_table()
487 /**
488 * Update cgroup
489 *
464 - * Update cgroup data based in
490 + * Update cgroup data based in collected PID.
491 + *
492 + * @param maps_per_core do I need to read all cores?
493 */
466 -static void ebpf_update_dc_cgroup()
494 +static void ebpf_update_dc_cgroup(int maps_per_core)
495 {
496 netdata_dcstat_pid_t *cv = dcstat_vector;
497 int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
@@ -486,7 +514,7 @@ static void ebpf_update_dc_cgroup()
514 continue;
515 }
516
489 - dcstat_apps_accumulator(cv);
517 + dcstat_apps_accumulator(cv, maps_per_core);
518
519 memcpy(out, cv, sizeof(netdata_dcstat_pid_t));
520 }
@@ -499,8 +527,10 @@ static void ebpf_update_dc_cgroup()
527 * Read global table
528 *
529 * Read the table with number of calls for all functions
530 + *
531 + * @param maps_per_core do I need to read all cores?
532 */
503 -static void ebpf_dc_read_global_table()
533 +static void ebpf_dc_read_global_table(int maps_per_core)
534 {
535 uint32_t idx;
536 netdata_idx_t *val = dcstat_hash_values;
@@ -510,7 +540,7 @@ static void ebpf_dc_read_global_table()
540 for (idx = NETDATA_KEY_DC_REFERENCE; idx < NETDATA_DIRECTORY_CACHE_END; idx++) {
541 if (!bpf_map_lookup_elem(fd, &idx, stored)) {
542 int i;
513 - int end = ebpf_nprocs;
543 + int end = (maps_per_core) ? ebpf_nprocs: 1;
544 netdata_idx_t total = 0;
545 for (i = 0; i < end; i++)
546 total += stored[i];
@@ -974,6 +1004,7 @@ static void dcstat_collector(ebpf_module_t *em)
1004 heartbeat_t hb;
1005 heartbeat_init(&hb);
1006 int counter = update_every - 1;
1007 + int maps_per_core = em->maps_per_core;
1008 while (!ebpf_exit_plugin) {
1009 (void)heartbeat_next(&hb, USEC_PER_SEC);
1010
@@ -982,13 +1013,13 @@ static void dcstat_collector(ebpf_module_t *em)
1013
1014 counter = 0;
1015 netdata_apps_integration_flags_t apps = em->apps_charts;
985 - ebpf_dc_read_global_table();
1016 + ebpf_dc_read_global_table(maps_per_core);
1017 pthread_mutex_lock(&collect_data_mutex);
1018 if (apps)
988 - read_apps_table();
1019 + read_dc_apps_table(maps_per_core);
1020
1021 if (cgroups)
991 - ebpf_update_dc_cgroup();
1022 + ebpf_update_dc_cgroup(maps_per_core);
1023
1024 pthread_mutex_lock(&lock);
1025
@@ -1084,6 +1115,10 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
1115 */
1116 static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1117 {
1118 +#ifdef LIBBPF_MAJOR_VERSION
1119 + ebpf_define_map_type(dcstat_maps, em->maps_per_core, running_on_kernel);
1120 +#endif
1121 +
1122 int ret = 0;
1123 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
1124 if (em->load & EBPF_LOAD_LEGACY) {
collectors/ebpf.plugin/ebpf_disk.c
+27 -7
@@ -14,10 +14,25 @@ struct config disk_config = { .first_section = NULL,
14
15 static ebpf_local_maps_t disk_maps[] = {{.name = "tbl_disk_iocall", .internal_input = NETDATA_DISK_HISTOGRAM_LENGTH,
16 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
17 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
17 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
18 +#ifdef LIBBPF_MAJOR_VERSION
19 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
20 +#endif
21 + },
22 + {.name = "tmp_disk_tp_stat", .internal_input = 8192, .user_input = 8192,
23 + .type = NETDATA_EBPF_MAP_STATIC,
24 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
25 +#ifdef LIBBPF_MAJOR_VERSION
26 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
27 +#endif
28 + },
29 {.name = NULL, .internal_input = 0, .user_input = 0,
30 .type = NETDATA_EBPF_MAP_CONTROLLER,
20 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
31 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
32 +#ifdef LIBBPF_MAJOR_VERSION
33 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
34 +#endif
35 + }};
36 static avl_tree_lock disk_tree;
37 netdata_ebpf_disks_t *disk_list = NULL;
38
@@ -503,11 +518,12 @@ static void ebpf_fill_plot_disks(netdata_ebpf_disks_t *ptr)
518 /**
519 * Read hard disk table
520 *
506 - * @param table file descriptor for table
507 - *
521 * Read the table with number of calls for all functions
522 + *
523 + * @param table file descriptor for table
524 + * @param maps_per_core do I need to read all cores?
525 */
510 -static void read_hard_disk_tables(int table)
526 +static void read_hard_disk_tables(int table, int maps_per_core)
527 {
528 netdata_idx_t *values = disk_hash_values;
529 block_key_t key = {};
@@ -548,7 +564,7 @@ static void read_hard_disk_tables(int table)
564
565 uint64_t total = 0;
566 int i;
551 - int end = (running_on_kernel < NETDATA_KERNEL_V4_15) ? 1 : ebpf_nprocs;
567 + int end = (maps_per_core) ? 1 : ebpf_nprocs;
568 for (i = 0; i < end; i++) {
569 total += values[i];
570 }
@@ -690,6 +706,7 @@ static void disk_collector(ebpf_module_t *em)
706 heartbeat_t hb;
707 heartbeat_init(&hb);
708 int counter = update_every - 1;
709 + int maps_per_core = em->maps_per_core;
710 while (!ebpf_exit_plugin) {
711 (void)heartbeat_next(&hb, USEC_PER_SEC);
712
@@ -697,7 +714,7 @@ static void disk_collector(ebpf_module_t *em)
714 continue;
715
716 counter = 0;
700 - read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
717 + read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd, maps_per_core);
718 pthread_mutex_lock(&lock);
719 ebpf_remove_pointer_from_plot_disk(em);
720 ebpf_latency_send_hd_data(update_every);
@@ -774,6 +791,9 @@ void *ebpf_disk_thread(void *ptr)
791 goto enddisk;
792 }
793
794 +#ifdef LIBBPF_MAJOR_VERSION
795 + ebpf_define_map_type(disk_maps, em->maps_per_core, running_on_kernel);
796 +#endif
797 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
798 if (!em->probe_links) {
799 goto enddisk;
collectors/ebpf.plugin/ebpf_disk.h
+2 -1
@@ -55,7 +55,8 @@ typedef struct netdata_ebpf_disks {
55 } netdata_ebpf_disks_t;
56
57 enum ebpf_disk_tables {
58 - NETDATA_DISK_READ
58 + NETDATA_DISK_READ,
59 + NETDATA_DISK_TMP
60 };
61
62 typedef struct block_key {
collectors/ebpf.plugin/ebpf_fd.c
+58 -23
@@ -15,17 +15,33 @@ static netdata_publish_syscall_t fd_publish_aggregated[NETDATA_FD_SYSCALL_END];
15 static ebpf_local_maps_t fd_maps[] = {{.name = "tbl_fd_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
16 .user_input = 0,
17 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
18 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
18 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
19 +#ifdef LIBBPF_MAJOR_VERSION
20 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
21 +#endif
22 + },
23 {.name = "tbl_fd_global", .internal_input = NETDATA_KEY_END_VECTOR,
24 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
21 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
25 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
26 +#ifdef LIBBPF_MAJOR_VERSION
27 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
28 +#endif
29 + },
30 {.name = "fd_ctrl", .internal_input = NETDATA_CONTROLLER_END,
31 .user_input = 0,
32 .type = NETDATA_EBPF_MAP_CONTROLLER,
25 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
33 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
34 +#ifdef LIBBPF_MAJOR_VERSION
35 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
36 +#endif
37 + },
38 {.name = NULL, .internal_input = 0, .user_input = 0,
39 .type = NETDATA_EBPF_MAP_CONTROLLER,
28 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
40 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
41 +#ifdef LIBBPF_MAJOR_VERSION
42 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
43 +#endif
44 + }};
45
46
47 struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
@@ -271,10 +287,14 @@ static void ebpf_fd_set_hash_tables(struct fd_bpf *obj)
287 * @param obj is the main structure for bpf objects.
288 * @param em structure with configuration
289 */
274 -static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em)
290 +static void ebpf_fd_adjust_map(struct fd_bpf *obj, ebpf_module_t *em)
291 {
292 ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS],
293 em, bpf_map__name(obj->maps.tbl_fd_pid));
294 +
295 + ebpf_update_map_type(obj->maps.tbl_fd_global, &fd_maps[NETDATA_FD_GLOBAL_STATS]);
296 + ebpf_update_map_type(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS]);
297 + ebpf_update_map_type(obj->maps.fd_ctrl, &fd_maps[NETDATA_FD_CONTROLLER]);
298 }
299
300 /**
@@ -322,7 +342,7 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
342 ebpf_disable_specific_probes(obj);
343 }
344
325 - ebpf_fd_adjust_map_size(obj, em);
345 + ebpf_fd_adjust_map(obj, em);
346
347 if (!em->apps_charts && !em->cgroup_charts)
348 ebpf_fd_disable_release_task(obj);
@@ -415,8 +435,10 @@ static void ebpf_fd_send_data(ebpf_module_t *em)
435 * Read global counter
436 *
437 * Read the table with number of calls for all functions
438 + *
439 + * @param maps_per_core do I need to read all cores?
440 */
419 -static void ebpf_fd_read_global_table()
441 +static void ebpf_fd_read_global_table(int maps_per_core)
442 {
443 uint32_t idx;
444 netdata_idx_t *val = fd_hash_values;
@@ -426,7 +448,7 @@ static void ebpf_fd_read_global_table()
448 for (idx = NETDATA_KEY_CALLS_DO_SYS_OPEN; idx < NETDATA_FD_COUNTER; idx++) {
449 if (!bpf_map_lookup_elem(fd, &idx, stored)) {
450 int i;
429 - int end = ebpf_nprocs;
451 + int end = (maps_per_core) ? ebpf_nprocs: 1;
452 netdata_idx_t total = 0;
453 for (i = 0; i < end; i++)
454 total += stored[i];
@@ -442,10 +464,11 @@ static void ebpf_fd_read_global_table()
464 * Sum all values read from kernel and store in the first address.
465 *
466 * @param out the vector with read values.
467 + * @param maps_per_core do I need to read all cores?
468 */
446 -static void fd_apps_accumulator(netdata_fd_stat_t *out)
469 +static void fd_apps_accumulator(netdata_fd_stat_t *out, int maps_per_core)
470 {
448 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
471 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
472 netdata_fd_stat_t *total = &out[0];
473 for (i = 1; i < end; i++) {
474 netdata_fd_stat_t *w = &out[i];
@@ -479,14 +502,19 @@ static void fd_fill_pid(uint32_t current_pid, netdata_fd_stat_t *publish)
502 * Read APPS table
503 *
504 * Read the apps table and store data inside the structure.
505 + *
506 + * @param maps_per_core do I need to read all cores?
507 */
483 -static void read_apps_table()
508 +static void read_fd_apps_table(int maps_per_core)
509 {
510 netdata_fd_stat_t *fv = fd_vector;
511 uint32_t key;
512 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
513 int fd = fd_maps[NETDATA_FD_PID_STATS].map_fd;
489 - size_t length = sizeof(netdata_fd_stat_t) * ebpf_nprocs;
514 + size_t length = sizeof(netdata_fd_stat_t);
515 + if (maps_per_core)
516 + length *= ebpf_nprocs;
517 +
518 while (pids) {
519 key = pids->pid;
520
@@ -495,7 +523,7 @@ static void read_apps_table()
523 continue;
524 }
525
498 - fd_apps_accumulator(fv);
526 + fd_apps_accumulator(fv, maps_per_core);
527
528 fd_fill_pid(key, fv);
529
@@ -509,9 +537,11 @@ static void read_apps_table()
537 /**
538 * Update cgroup
539 *
512 - * Update cgroup data based in
540 + * Update cgroup data collected per PID.
541 + *
542 + * @param maps_per_core do I need to read all cores?
543 */
514 -static void ebpf_update_fd_cgroup()
544 +static void ebpf_update_fd_cgroup(int maps_per_core)
545 {
546 ebpf_cgroup_target_t *ect ;
547 netdata_fd_stat_t *fv = fd_vector;
@@ -531,7 +561,7 @@ static void ebpf_update_fd_cgroup()
561 } else {
562 memset(fv, 0, length);
563 if (!bpf_map_lookup_elem(fd, &pid, fv)) {
534 - fd_apps_accumulator(fv);
564 + fd_apps_accumulator(fv, maps_per_core);
565
566 memcpy(out, fv, sizeof(netdata_fd_stat_t));
567 }
@@ -915,6 +945,7 @@ static void fd_collector(ebpf_module_t *em)
945 heartbeat_init(&hb);
946 int update_every = em->update_every;
947 int counter = update_every - 1;
948 + int maps_per_core = em->maps_per_core;
949 while (!ebpf_exit_plugin) {
950 (void)heartbeat_next(&hb, USEC_PER_SEC);
951
@@ -923,21 +954,21 @@ static void fd_collector(ebpf_module_t *em)
954
955 counter = 0;
956 netdata_apps_integration_flags_t apps = em->apps_charts;
926 - ebpf_fd_read_global_table();
957 + ebpf_fd_read_global_table(maps_per_core);
958 pthread_mutex_lock(&collect_data_mutex);
959 if (apps)
929 - read_apps_table();
960 + read_fd_apps_table(maps_per_core);
961 +
962 + if (cgroups)
963 + ebpf_update_fd_cgroup(maps_per_core);
964 +
965 + pthread_mutex_lock(&lock);
966
967 #ifdef NETDATA_DEV_MODE
968 if (ebpf_aral_fd_pid)
969 ebpf_send_data_aral_chart(ebpf_aral_fd_pid, em);
970 #endif
971
936 - if (cgroups)
937 - ebpf_update_fd_cgroup();
938 -
939 - pthread_mutex_lock(&lock);
940 -
972 ebpf_fd_send_data(em);
973
974 if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
@@ -1082,6 +1113,10 @@ static void ebpf_fd_allocate_global_vectors(int apps)
1113 */
1114 static int ebpf_fd_load_bpf(ebpf_module_t *em)
1115 {
1116 +#ifdef LIBBPF_MAJOR_VERSION
1117 + ebpf_define_map_type(fd_maps, em->maps_per_core, running_on_kernel);
1118 +#endif
1119 +
1120 int ret = 0;
1121 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode);
1122 if (em->load & EBPF_LOAD_LEGACY) {
collectors/ebpf.plugin/ebpf_filesystem.c
+150 -32
@@ -8,27 +8,122 @@ struct config fs_config = { .first_section = NULL,
8 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
9 .rwlock = AVL_LOCK_INITIALIZER } };
10
11 -static ebpf_local_maps_t fs_maps[] = {{.name = "tbl_ext4", .internal_input = NETDATA_KEY_CALLS_SYNC,
12 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
13 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
14 - {.name = "tbl_xfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
15 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
16 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
17 - {.name = "tbl_nfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
18 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
19 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
20 - {.name = "tbl_zfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
21 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
22 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
23 - {.name = "tbl_btrfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
24 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
25 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
26 - {.name = "tbl_ext_addr", .internal_input = 1,
27 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
28 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
29 - {.name = NULL, .internal_input = 0, .user_input = 0,
30 - .type = NETDATA_EBPF_MAP_CONTROLLER,
31 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
11 +ebpf_local_maps_t ext4_maps[] = {{.name = "tbl_ext4", .internal_input = NETDATA_KEY_CALLS_SYNC,
12 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
13 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
14 +#ifdef LIBBPF_MAJOR_VERSION
15 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
16 +#endif
17 + },
18 + {.name = "tmp_ext4", .internal_input = 4192, .user_input = 4192,
19 + .type = NETDATA_EBPF_MAP_CONTROLLER,
20 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
21 +#ifdef LIBBPF_MAJOR_VERSION
22 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
23 +#endif
24 + },
25 + {.name = NULL, .internal_input = 0, .user_input = 0,
26 + .type = NETDATA_EBPF_MAP_CONTROLLER,
27 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
28 +#ifdef LIBBPF_MAJOR_VERSION
29 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
30 +#endif
31 + }};
32 +
33 +ebpf_local_maps_t xfs_maps[] = {{.name = "tbl_xfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
34 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
35 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
36 +#ifdef LIBBPF_MAJOR_VERSION
37 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
38 +#endif
39 + },
40 + {.name = "tmp_xfs", .internal_input = 4192, .user_input = 4192,
41 + .type = NETDATA_EBPF_MAP_CONTROLLER,
42 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
43 +#ifdef LIBBPF_MAJOR_VERSION
44 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
45 +#endif
46 + },
47 + {.name = NULL, .internal_input = 0, .user_input = 0,
48 + .type = NETDATA_EBPF_MAP_CONTROLLER,
49 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
50 +#ifdef LIBBPF_MAJOR_VERSION
51 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
52 +#endif
53 + }};
54 +
55 +ebpf_local_maps_t nfs_maps[] = {{.name = "tbl_nfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
56 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
57 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
58 +#ifdef LIBBPF_MAJOR_VERSION
59 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
60 +#endif
61 + },
62 + {.name = "tmp_nfs", .internal_input = 4192, .user_input = 4192,
63 + .type = NETDATA_EBPF_MAP_CONTROLLER,
64 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
65 +#ifdef LIBBPF_MAJOR_VERSION
66 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
67 +#endif
68 + },
69 + {.name = NULL, .internal_input = 0, .user_input = 0,
70 + .type = NETDATA_EBPF_MAP_CONTROLLER,
71 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
72 +#ifdef LIBBPF_MAJOR_VERSION
73 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
74 +#endif
75 + }};
76 +
77 +ebpf_local_maps_t zfs_maps[] = {{.name = "tbl_zfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
78 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
79 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
80 +#ifdef LIBBPF_MAJOR_VERSION
81 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
82 +#endif
83 + },
84 + {.name = "tmp_zfs", .internal_input = 4192, .user_input = 4192,
85 + .type = NETDATA_EBPF_MAP_CONTROLLER,
86 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
87 +#ifdef LIBBPF_MAJOR_VERSION
88 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
89 +#endif
90 + },
91 + {.name = NULL, .internal_input = 0, .user_input = 0,
92 + .type = NETDATA_EBPF_MAP_CONTROLLER,
93 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
94 +#ifdef LIBBPF_MAJOR_VERSION
95 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
96 +#endif
97 + }};
98 +
99 +ebpf_local_maps_t btrfs_maps[] = {{.name = "tbl_btrfs", .internal_input = NETDATA_KEY_CALLS_SYNC,
100 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
101 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
102 +#ifdef LIBBPF_MAJOR_VERSION
103 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
104 +#endif
105 + },
106 + {.name = "tbl_ext_addr", .internal_input = 1, .user_input = 1,
107 + .type = NETDATA_EBPF_MAP_CONTROLLER,
108 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
109 +#ifdef LIBBPF_MAJOR_VERSION
110 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
111 +#endif
112 + },
113 + {.name = "tmp_btrfs", .internal_input = 4192, .user_input = 4192,
114 + .type = NETDATA_EBPF_MAP_CONTROLLER,
115 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
116 +#ifdef LIBBPF_MAJOR_VERSION
117 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
118 +#endif
119 + },
120 + {.name = NULL, .internal_input = 0, .user_input = 0,
121 + .type = NETDATA_EBPF_MAP_CONTROLLER,
122 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
123 +#ifdef LIBBPF_MAJOR_VERSION
124 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
125 +#endif
126 + }};
127
128 static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
129 static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
@@ -176,26 +271,32 @@ int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
271 if (!efp->probe_links && efp->flags & NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM) {
272 em->thread_name = efp->filesystem;
273 em->kernels = efp->kernels;
274 + em->maps = efp->fs_maps;
275 +#ifdef LIBBPF_MAJOR_VERSION
276 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
277 +#endif
278 efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &efp->objects);
279 if (!efp->probe_links) {
280 em->thread_name = saved_name;
281 em->kernels = kernels;
282 + em->maps = NULL;
283 return -1;
284 }
285 efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
286 pthread_mutex_lock(&lock);
187 - ebpf_update_kernel_memory(&plugin_statistics, &fs_maps[i], EBPF_ACTION_STAT_ADD);
287 + ebpf_update_kernel_memory(&plugin_statistics, efp->fs_maps, EBPF_ACTION_STAT_ADD);
288 pthread_mutex_unlock(&lock);
289
290 // Nedeed for filesystems like btrfs
291 if ((efp->flags & NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE) && (efp->addresses.function)) {
192 - ebpf_load_addresses(&efp->addresses, fs_maps[i + 1].map_fd);
292 + ebpf_load_addresses(&efp->addresses, efp->fs_maps[NETDATA_ADDR_FS_TABLE].map_fd);
293 }
294 }
295 efp->flags &= ~NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
296 }
297 em->thread_name = saved_name;
298 em->kernels = kernels;
299 + em->maps = NULL;
300
301 if (!dimensions) {
302 dimensions = ebpf_fill_histogram_dimension(NETDATA_EBPF_HIST_MAX_BINS);
@@ -394,11 +495,13 @@ static inline netdata_ebpf_histogram_t *select_hist(ebpf_filesystem_partitions_t
495 /**
496 * Read hard disk table
497 *
397 - * @param table index for the hash table
498 + * @param efp structure with filesystem monitored
499 + * @param fd file descriptor to get data.
500 + * @param maps_per_core do I need to read all cores?
501 *
502 * Read the table with number of calls for all functions
503 */
401 -static void read_filesystem_table(ebpf_filesystem_partitions_t *efp, int fd)
504 +static void read_filesystem_table(ebpf_filesystem_partitions_t *efp, int fd, int maps_per_core)
505 {
506 netdata_idx_t *values = filesystem_hash_values;
507 uint32_t key;
@@ -416,7 +519,7 @@ static void read_filesystem_table(ebpf_filesystem_partitions_t *efp, int fd)
519
520 uint64_t total = 0;
521 int i;
419 - int end = ebpf_nprocs;
522 + int end = (maps_per_core) ? ebpf_nprocs : 1;
523 for (i = 0; i < end; i++) {
524 total += values[i];
525 }
@@ -430,17 +533,17 @@ static void read_filesystem_table(ebpf_filesystem_partitions_t *efp, int fd)
533 /**
534 * Read hard disk table
535 *
433 - * @param table index for the hash table
434 - *
536 * Read the table with number of calls for all functions
537 + *
538 + * @param maps_per_core do I need to read all cores?
539 */
437 -static void read_filesystem_tables()
540 +static void read_filesystem_tables(int maps_per_core)
541 {
542 int i;
543 for (i = 0; localfs[i].filesystem; i++) {
544 ebpf_filesystem_partitions_t *efp = &localfs[i];
545 if (efp->flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION) {
443 - read_filesystem_table(efp, fs_maps[i].map_fd);
546 + read_filesystem_table(efp, efp->fs_maps[NETDATA_MAIN_FS_TABLE].map_fd, maps_per_core);
547 }
548 }
549 }
@@ -464,7 +567,7 @@ void ebpf_filesystem_read_hash(ebpf_module_t *em)
567 if (em->optional)
568 return;
569
467 - read_filesystem_tables();
570 + read_filesystem_tables(em->maps_per_core);
571 }
572
573 /**
@@ -545,6 +648,21 @@ static void ebpf_update_filesystem()
648 }
649 }
650
651 +/**
652 + * Set maps
653 + *
654 + * When thread is initialized the variable fs_maps is set as null,
655 + * this function fills the variable before to use.
656 + */
657 +static void ebpf_set_maps()
658 +{
659 + localfs[NETDATA_FS_LOCALFS_EXT4].fs_maps = ext4_maps;
660 + localfs[NETDATA_FS_LOCALFS_XFS].fs_maps = xfs_maps;
661 + localfs[NETDATA_FS_LOCALFS_NFS].fs_maps = nfs_maps;
662 + localfs[NETDATA_FS_LOCALFS_ZFS].fs_maps = zfs_maps;
663 + localfs[NETDATA_FS_LOCALFS_BTRFS].fs_maps = btrfs_maps;
664 +}
665 +
666 /**
667 * Filesystem thread
668 *
@@ -559,7 +677,7 @@ void *ebpf_filesystem_thread(void *ptr)
677 netdata_thread_cleanup_push(ebpf_filesystem_exit, ptr);
678
679 ebpf_module_t *em = (ebpf_module_t *)ptr;
562 - em->maps = fs_maps;
680 + ebpf_set_maps();
681 ebpf_update_filesystem();
682
683 // Initialize optional as zero, to identify when there are not partitions to monitor
collectors/ebpf.plugin/ebpf_filesystem.h
+10
@@ -42,6 +42,16 @@ enum netdata_filesystem_table {
42 NETDATA_ADDR_FS_TABLE
43 };
44
45 +enum netdata_filesystem_localfs_idx {
46 + NETDATA_FS_LOCALFS_EXT4,
47 + NETDATA_FS_LOCALFS_XFS,
48 + NETDATA_FS_LOCALFS_NFS,
49 + NETDATA_FS_LOCALFS_ZFS,
50 + NETDATA_FS_LOCALFS_BTRFS,
51 +
52 + NETDATA_FS_LOCALFS_END,
53 +};
54 +
55 void *ebpf_filesystem_thread(void *ptr);
56 extern struct config fs_config;
57
collectors/ebpf.plugin/ebpf_hardirq.c
+15 -3
@@ -17,14 +17,20 @@ static ebpf_local_maps_t hardirq_maps[] = {
17 .internal_input = NETDATA_HARDIRQ_MAX_IRQS,
18 .user_input = 0,
19 .type = NETDATA_EBPF_MAP_STATIC,
20 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
20 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
21 +#ifdef LIBBPF_MAJOR_VERSION
22 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
23 +#endif
24 },
25 {
26 .name = "tbl_hardirq_static",
27 .internal_input = HARDIRQ_EBPF_STATIC_END,
28 .user_input = 0,
29 .type = NETDATA_EBPF_MAP_STATIC,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
30 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
31 +#ifdef LIBBPF_MAJOR_VERSION
32 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
33 +#endif
34 },
35 /* end */
36 {
@@ -32,7 +38,10 @@ static ebpf_local_maps_t hardirq_maps[] = {
38 .internal_input = 0,
39 .user_input = 0,
40 .type = NETDATA_EBPF_MAP_CONTROLLER,
35 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
41 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
42 +#ifdef LIBBPF_MAJOR_VERSION
43 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
44 +#endif
45 }
46 };
47
@@ -555,6 +564,9 @@ void *ebpf_hardirq_thread(void *ptr)
564 goto endhardirq;
565 }
566
567 +#ifdef LIBBPF_MAJOR_VERSION
568 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
569 +#endif
570 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
571 if (!em->probe_links) {
572 goto endhardirq;
collectors/ebpf.plugin/ebpf_mdflush.c
+19 -4
@@ -16,7 +16,10 @@ static ebpf_local_maps_t mdflush_maps[] = {
16 .internal_input = 1024,
17 .user_input = 0,
18 .type = NETDATA_EBPF_MAP_STATIC,
19 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
19 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
20 +#ifdef LIBBPF_MAJOR_VERSION
21 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
22 +#endif
23 },
24 /* end */
25 {
@@ -87,7 +90,14 @@ static int mdflush_val_cmp(void *a, void *b)
90 }
91 }
92
90 -static void mdflush_read_count_map()
93 +/**
94 + * Read count map
95 + *
96 + * Read the hash table and store data to allocated vectors.
97 + *
98 + * @param maps_per_core do I need to read all cores?
99 + */
100 +static void mdflush_read_count_map(int maps_per_core)
101 {
102 int mapfd = mdflush_maps[MDFLUSH_MAP_COUNT].map_fd;
103 mdflush_ebpf_key_t curr_key = (uint32_t)-1;
@@ -137,7 +147,7 @@ static void mdflush_read_count_map()
147 // we must add up count value for this record across all CPUs.
148 uint64_t total_cnt = 0;
149 int i;
140 - int end = (running_on_kernel < NETDATA_KERNEL_V4_15) ? 1 : ebpf_nprocs;
150 + int end = (!maps_per_core) ? 1 : ebpf_nprocs;
151 for (i = 0; i < end; i++) {
152 total_cnt += mdflush_ebpf_vals[i];
153 }
@@ -215,6 +225,7 @@ static void mdflush_collector(ebpf_module_t *em)
225 heartbeat_t hb;
226 heartbeat_init(&hb);
227 int counter = update_every - 1;
228 + int maps_per_core = em->maps_per_core;
229 while (!ebpf_exit_plugin) {
230 (void)heartbeat_next(&hb, USEC_PER_SEC);
231
@@ -222,7 +233,8 @@ static void mdflush_collector(ebpf_module_t *em)
233 continue;
234
235 counter = 0;
225 - mdflush_read_count_map();
236 + mdflush_read_count_map(maps_per_core);
237 + pthread_mutex_lock(&lock);
238 // write dims now for all hitherto discovered devices.
239 write_begin_chart("mdstat", "mdstat_flush");
240 avl_traverse_lock(&mdflush_pub, mdflush_write_dims, NULL);
@@ -251,6 +263,9 @@ void *ebpf_mdflush_thread(void *ptr)
263 goto endmdflush;
264 }
265
266 +#ifdef LIBBPF_MAJOR_VERSION
267 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
268 +#endif
269 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
270 if (!em->probe_links) {
271 goto endmdflush;
collectors/ebpf.plugin/ebpf_mount.c
+27 -5
@@ -5,10 +5,18 @@
5
6 static ebpf_local_maps_t mount_maps[] = {{.name = "tbl_mount", .internal_input = NETDATA_MOUNT_END,
7 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
8 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
8 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
9 +#ifdef LIBBPF_MAJOR_VERSION
10 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
11 +#endif
12 + },
13 {.name = NULL, .internal_input = 0, .user_input = 0,
14 .type = NETDATA_EBPF_MAP_CONTROLLER,
11 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
15 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
16 +#ifdef LIBBPF_MAJOR_VERSION
17 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
18 +#endif
19 + }};
20
21 static char *mount_dimension_name[NETDATA_EBPF_MOUNT_SYSCALL] = { "mount", "umount" };
22 static netdata_syscall_stat_t mount_aggregated_data[NETDATA_EBPF_MOUNT_SYSCALL];
@@ -192,6 +200,8 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
200 ebpf_mount_disable_trampoline(obj);
201 }
202
203 + ebpf_update_map_type(obj->maps.tbl_mount, &mount_maps[NETDATA_KEY_MOUNT_TABLE]);
204 +
205 int ret = mount_bpf__load(obj);
206 if (!ret) {
207 if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE )
@@ -249,8 +259,10 @@ static void ebpf_mount_exit(void *ptr)
259 * Read global table
260 *
261 * Read the table with number of calls for all functions
262 + *
263 + * @param maps_per_core do I need to read all cores?
264 */
253 -static void ebpf_mount_read_global_table()
265 +static void ebpf_mount_read_global_table(int maps_per_core)
266 {
267 static netdata_idx_t *mount_values = NULL;
268 if (!mount_values)
@@ -259,17 +271,22 @@ static void ebpf_mount_read_global_table()
271 uint32_t idx;
272 netdata_idx_t *val = mount_hash_values;
273 netdata_idx_t *stored = mount_values;
274 + size_t length = sizeof(netdata_idx_t);
275 + if (maps_per_core)
276 + length *= ebpf_nprocs;
277 +
278 int fd = mount_maps[NETDATA_KEY_MOUNT_TABLE].map_fd;
279
280 for (idx = NETDATA_KEY_MOUNT_CALL; idx < NETDATA_MOUNT_END; idx++) {
281 if (!bpf_map_lookup_elem(fd, &idx, stored)) {
282 int i;
267 - int end = ebpf_nprocs;
283 + int end = (maps_per_core) ? ebpf_nprocs : 1;
284 netdata_idx_t total = 0;
285 for (i = 0; i < end; i++)
286 total += stored[i];
287
288 val[idx] = total;
289 + memset(stored, 0, length);
290 }
291 }
292 }
@@ -304,13 +321,14 @@ static void mount_collector(ebpf_module_t *em)
321 heartbeat_init(&hb);
322 int update_every = em->update_every;
323 int counter = update_every - 1;
324 + int maps_per_core = em->maps_per_core;
325 while (!ebpf_exit_plugin) {
326 (void)heartbeat_next(&hb, USEC_PER_SEC);
327 if (ebpf_exit_plugin || ++counter != update_every)
328 continue;
329
330 counter = 0;
313 - ebpf_mount_read_global_table();
331 + ebpf_mount_read_global_table(maps_per_core);
332 pthread_mutex_lock(&lock);
333
334 ebpf_mount_send_data();
@@ -372,6 +390,10 @@ static void ebpf_create_mount_charts(int update_every)
390 */
391 static int ebpf_mount_load_bpf(ebpf_module_t *em)
392 {
393 +#ifdef LIBBPF_MAJOR_VERSION
394 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
395 +#endif
396 +
397 int ret = 0;
398 if (em->load & EBPF_LOAD_LEGACY) {
399 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
collectors/ebpf.plugin/ebpf_oomkill.c
+13 -2
@@ -16,7 +16,10 @@ static ebpf_local_maps_t oomkill_maps[] = {
16 .internal_input = NETDATA_OOMKILL_MAX_ENTRIES,
17 .user_input = 0,
18 .type = NETDATA_EBPF_MAP_STATIC,
19 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
19 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
20 +#ifdef LIBBPF_MAJOR_VERSION
21 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
22 +#endif
23 },
24 /* end */
25 {
@@ -24,7 +27,10 @@ static ebpf_local_maps_t oomkill_maps[] = {
27 .internal_input = 0,
28 .user_input = 0,
29 .type = NETDATA_EBPF_MAP_CONTROLLER,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
30 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
31 +#ifdef LIBBPF_MAJOR_VERSION
32 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
33 +#endif
34 }
35 };
36
@@ -285,6 +291,8 @@ static void ebpf_update_oomkill_cgroup(int32_t *keys, uint32_t total)
291
292 /**
293 * Main loop for this collector.
294 + *
295 + * @param em the thread main structure.
296 */
297 static void oomkill_collector(ebpf_module_t *em)
298 {
@@ -384,6 +392,9 @@ void *ebpf_oomkill_thread(void *ptr)
392 goto endoomkill;
393 }
394
395 +#ifdef LIBBPF_MAJOR_VERSION
396 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
397 +#endif
398 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
399 if (!em->probe_links) {
400 goto endoomkill;
collectors/ebpf.plugin/ebpf_process.c
+81 -11
@@ -18,17 +18,33 @@ static char *status[] = { "process", "zombie" };
18 static ebpf_local_maps_t process_maps[] = {{.name = "tbl_pid_stats", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
19 .user_input = 0,
20 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
21 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
21 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
22 +#ifdef LIBBPF_MAJOR_VERSION
23 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
24 +#endif
25 + },
26 {.name = "tbl_total_stats", .internal_input = NETDATA_KEY_END_VECTOR,
27 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
24 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
28 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
29 +#ifdef LIBBPF_MAJOR_VERSION
30 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
31 +#endif
32 + },
33 {.name = "process_ctrl", .internal_input = NETDATA_CONTROLLER_END,
34 .user_input = 0,
35 .type = NETDATA_EBPF_MAP_CONTROLLER,
28 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
36 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
37 +#ifdef LIBBPF_MAJOR_VERSION
38 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
39 +#endif
40 + },
41 {.name = NULL, .internal_input = 0, .user_input = 0,
42 .type = NETDATA_EBPF_MAP_CONTROLLER,
31 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
43 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
44 +#ifdef LIBBPF_MAJOR_VERSION
45 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
46 +#endif
47 + }};
48
49 char *tracepoint_sched_type = { "sched" } ;
50 char *tracepoint_sched_process_exit = { "sched_process_exit" };
@@ -39,6 +55,7 @@ static int was_sched_process_exec_enabled = 0;
55 static int was_sched_process_fork_enabled = 0;
56
57 static netdata_idx_t *process_hash_values = NULL;
58 +ebpf_process_stat_t *process_stat_vector = NULL;
59 static netdata_syscall_stat_t process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_END];
60 static netdata_publish_syscall_t process_publish_aggregated[NETDATA_KEY_PUBLISH_PROCESS_END];
61
@@ -55,6 +72,7 @@ static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
72 static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
73 static char *memlock_stat = {"memory_locked"};
74 static char *hash_table_stat = {"hash_table"};
75 +static char *hash_table_core[NETDATA_EBPF_LOAD_STAT_END] = {"per_core", "unique"};
76
77 /*****************************************************************
78 *
@@ -251,8 +269,10 @@ void ebpf_process_send_apps_data(struct ebpf_target *root, ebpf_module_t *em)
269
270 /**
271 * Read the hash table and store data to allocated vectors.
272 + *
273 + * @param maps_per_core do I need to read all cores?
274 */
255 -static void read_hash_global_tables()
275 +static void ebpf_read_process_hash_global_tables(int maps_per_core)
276 {
277 uint64_t idx;
278 netdata_idx_t res[NETDATA_KEY_END_VECTOR];
@@ -263,7 +283,7 @@ static void read_hash_global_tables()
283 if (!bpf_map_lookup_elem(fd, &idx, val)) {
284 uint64_t total = 0;
285 int i;
266 - int end = ebpf_nprocs;
286 + int end = (maps_per_core) ? ebpf_nprocs : 1;
287 for (i = 0; i < end; i++)
288 total += val[i];
289
@@ -285,13 +305,18 @@ static void read_hash_global_tables()
305 /**
306 * Update cgroup
307 *
288 - * Update cgroup data based in
308 + * Update cgroup data based in PID running.
309 + *
310 + * @param maps_per_core do I need to read all cores?
311 */
290 -static void ebpf_update_process_cgroup()
312 +static void ebpf_update_process_cgroup(int maps_per_core)
313 {
314 ebpf_cgroup_target_t *ect ;
315 int pid_fd = process_maps[NETDATA_PROCESS_PID_TABLE].map_fd;
316
317 + size_t length = sizeof(ebpf_process_stat_t);
318 + if (maps_per_core)
319 + length *= ebpf_nprocs;
320 pthread_mutex_lock(&mutex_cgroup_shm);
321 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
322 struct pid_on_target2 *pids;
@@ -303,9 +328,15 @@ static void ebpf_update_process_cgroup()
328
329 memcpy(out, in, sizeof(ebpf_process_stat_t));
330 } else {
306 - if (bpf_map_lookup_elem(pid_fd, &pid, out)) {
331 + if (bpf_map_lookup_elem(pid_fd, &pid, process_stat_vector)) {
332 memset(out, 0, sizeof(ebpf_process_stat_t));
333 }
334 +
335 + ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
336 +
337 + memcpy(out, process_stat_vector, sizeof(ebpf_process_stat_t));
338 +
339 + memset(process_stat_vector, 0, length);
340 }
341 }
342 }
@@ -506,6 +537,35 @@ static inline void ebpf_create_statistic_hash_tables(ebpf_module_t *em)
537 ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
538 }
539
540 +/**
541 + * Create chart for percpu stats
542 + *
543 + * Write to standard output current values for threads.
544 + *
545 + * @param em a pointer to the structure with the default values.
546 + */
547 +static inline void ebpf_create_statistic_hash_per_core(ebpf_module_t *em)
548 +{
549 + ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
550 + NETDATA_EBPF_HASH_TABLES_PER_CORE,
551 + "How threads are loading hash/array tables.",
552 + "threads",
553 + NETDATA_EBPF_FAMILY,
554 + NETDATA_EBPF_CHART_TYPE_LINE,
555 + NULL,
556 + 140004,
557 + em->update_every,
558 + NETDATA_EBPF_MODULE_NAME_PROCESS);
559 +
560 + ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
561 + hash_table_core[NETDATA_EBPF_THREAD_PER_CORE],
562 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
563 +
564 + ebpf_write_global_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
565 + hash_table_core[NETDATA_EBPF_THREAD_UNIQUE],
566 + ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
567 +}
568 +
569 /**
570 * Update Internal Metric variable
571 *
@@ -541,6 +601,8 @@ static void ebpf_create_statistic_charts(ebpf_module_t *em)
601 ebpf_create_statistic_kernel_memory(em);
602
603 ebpf_create_statistic_hash_tables(em);
604 +
605 + ebpf_create_statistic_hash_per_core(em);
606 }
607
608 /**
@@ -647,6 +709,7 @@ static void ebpf_process_exit(void *ptr)
709 ebpf_module_t *em = (ebpf_module_t *)ptr;
710
711 freez(process_hash_values);
712 + freez(process_stat_vector);
713
714 ebpf_process_disable_tracepoints();
715
@@ -1010,6 +1073,11 @@ void ebpf_send_statistic_data()
1073 write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_LOADED);
1074 write_chart_dimension(hash_table_stat, (long long)plugin_statistics.hash_tables);
1075 write_end_chart();
1076 +
1077 + write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_PER_CORE);
1078 + write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE], (long long)plugin_statistics.hash_percpu);
1079 + write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE], (long long)plugin_statistics.hash_unique);
1080 + write_end_chart();
1081 }
1082
1083 /**
@@ -1032,6 +1100,7 @@ static void process_collector(ebpf_module_t *em)
1100
1101 int update_every = em->update_every;
1102 int counter = update_every - 1;
1103 + int maps_per_core = em->maps_per_core;
1104 while (!ebpf_exit_plugin) {
1105 usec_t dt = heartbeat_next(&hb, USEC_PER_SEC);
1106 (void)dt;
@@ -1041,14 +1110,14 @@ static void process_collector(ebpf_module_t *em)
1110 if (++counter == update_every) {
1111 counter = 0;
1112
1044 - read_hash_global_tables();
1113 + ebpf_read_process_hash_global_tables(maps_per_core);
1114
1115 netdata_apps_integration_flags_t apps_enabled = em->apps_charts;
1116 pthread_mutex_lock(&collect_data_mutex);
1117
1118 if (ebpf_all_pids_count > 0) {
1119 if (cgroups && shm_ebpf_cgroup.header) {
1051 - ebpf_update_process_cgroup();
1120 + ebpf_update_process_cgroup(maps_per_core);
1121 }
1122 }
1123
@@ -1099,6 +1168,7 @@ static void ebpf_process_allocate_global_vectors(size_t length)
1168 memset(process_aggregated_data, 0, length * sizeof(netdata_syscall_stat_t));
1169 memset(process_publish_aggregated, 0, length * sizeof(netdata_publish_syscall_t));
1170 process_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
1171 + process_stat_vector = callocz(ebpf_nprocs, sizeof(ebpf_process_stat_t));
1172
1173 global_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
1174 }
collectors/ebpf.plugin/ebpf_process.h
+7
@@ -56,6 +56,13 @@ enum netdata_ebpf_load_mode_stats{
56 NETDATA_EBPF_LOAD_STAT_END
57 };
58
59 +enum netdata_ebpf_thread_per_core{
60 + NETDATA_EBPF_THREAD_PER_CORE,
61 + NETDATA_EBPF_THREAD_UNIQUE,
62 +
63 + NETDATA_EBPF_PER_CORE_END
64 +};
65 +
66 // Index from kernel
67 typedef enum ebpf_process_index {
68 NETDATA_KEY_CALLS_DO_EXIT,
collectors/ebpf.plugin/ebpf_shm.c
+56 -18
@@ -21,15 +21,27 @@ struct config shm_config = { .first_section = NULL,
21 static ebpf_local_maps_t shm_maps[] = {{.name = "tbl_pid_shm", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
22 .user_input = 0,
23 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
24 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
24 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
25 +#ifdef LIBBPF_MAJOR_VERSION
26 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
27 +#endif
28 + },
29 {.name = "shm_ctrl", .internal_input = NETDATA_CONTROLLER_END,
30 .user_input = 0,
31 .type = NETDATA_EBPF_MAP_CONTROLLER,
28 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
32 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
33 +#ifdef LIBBPF_MAJOR_VERSION
34 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
35 +#endif
36 + },
37 {.name = "tbl_shm", .internal_input = NETDATA_SHM_END,
38 .user_input = 0,
39 .type = NETDATA_EBPF_MAP_STATIC,
32 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
40 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
41 +#ifdef LIBBPF_MAJOR_VERSION
42 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
43 +#endif
44 + },
45 {.name = NULL, .internal_input = 0, .user_input = 0}};
46
47 netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -215,10 +227,14 @@ static void ebpf_shm_disable_release_task(struct shm_bpf *obj)
227 * @param obj is the main structure for bpf objects.
228 * @param em structure with configuration
229 */
218 -static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em)
230 +static void ebpf_shm_adjust_map(struct shm_bpf *obj, ebpf_module_t *em)
231 {
232 ebpf_update_map_size(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE],
233 em, bpf_map__name(obj->maps.tbl_pid_shm));
234 +
235 + ebpf_update_map_type(obj->maps.tbl_shm, &shm_maps[NETDATA_SHM_GLOBAL_TABLE]);
236 + ebpf_update_map_type(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE]);
237 + ebpf_update_map_type(obj->maps.shm_ctrl, &shm_maps[NETDATA_SHM_CONTROLLER]);
238 }
239
240 /**
@@ -250,7 +266,7 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
266 ebpf_disable_trampoline(obj);
267 }
268
253 - ebpf_shm_adjust_map_size(obj, em);
269 + ebpf_shm_adjust_map(obj, em);
270 if (!em->apps_charts && !em->cgroup_charts)
271 ebpf_shm_disable_release_task(obj);
272
@@ -312,10 +328,11 @@ static void ebpf_shm_exit(void *ptr)
328 * Sum all values read from kernel and store in the first address.
329 *
330 * @param out the vector with read values.
331 + * @param maps_per_core do I need to read all cores?
332 */
316 -static void shm_apps_accumulator(netdata_publish_shm_t *out)
333 +static void shm_apps_accumulator(netdata_publish_shm_t *out, int maps_per_core)
334 {
318 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
335 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
336 netdata_publish_shm_t *total = &out[0];
337 for (i = 1; i < end; i++) {
338 netdata_publish_shm_t *w = &out[i];
@@ -349,12 +366,17 @@ static void shm_fill_pid(uint32_t current_pid, netdata_publish_shm_t *publish)
366 * Update cgroup
367 *
368 * Update cgroup data based in
369 + *
370 + * @param maps_per_core do I need to read all cores?
371 */
353 -static void ebpf_update_shm_cgroup()
372 +static void ebpf_update_shm_cgroup(int maps_per_core)
373 {
374 netdata_publish_shm_t *cv = shm_vector;
375 int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
357 - size_t length = sizeof(netdata_publish_shm_t) * ebpf_nprocs;
376 + size_t length = sizeof(netdata_publish_shm_t);
377 + if (maps_per_core)
378 + length *= ebpf_nprocs;
379 +
380 ebpf_cgroup_target_t *ect;
381
382 memset(cv, 0, length);
@@ -371,7 +393,7 @@ static void ebpf_update_shm_cgroup()
393 memcpy(out, in, sizeof(netdata_publish_shm_t));
394 } else {
395 if (!bpf_map_lookup_elem(fd, &pid, cv)) {
374 - shm_apps_accumulator(cv);
396 + shm_apps_accumulator(cv, maps_per_core);
397
398 memcpy(out, cv, sizeof(netdata_publish_shm_t));
399
@@ -389,14 +411,19 @@ static void ebpf_update_shm_cgroup()
411 * Read APPS table
412 *
413 * Read the apps table and store data inside the structure.
414 + *
415 + * @param maps_per_core do I need to read all cores?
416 */
393 -static void read_apps_table()
417 +static void read_shm_apps_table(int maps_per_core)
418 {
419 netdata_publish_shm_t *cv = shm_vector;
420 uint32_t key;
421 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
422 int fd = shm_maps[NETDATA_PID_SHM_TABLE].map_fd;
399 - size_t length = sizeof(netdata_publish_shm_t)*ebpf_nprocs;
423 + size_t length = sizeof(netdata_publish_shm_t);
424 + if (maps_per_core)
425 + length *= ebpf_nprocs;
426 +
427 while (pids) {
428 key = pids->pid;
429
@@ -405,7 +432,7 @@ static void read_apps_table()
432 continue;
433 }
434
408 - shm_apps_accumulator(cv);
435 + shm_apps_accumulator(cv, maps_per_core);
436
437 shm_fill_pid(key, cv);
438
@@ -446,23 +473,29 @@ static void shm_send_global()
473 * Read global counter
474 *
475 * Read the table with number of calls for all functions
476 + *
477 + * @param maps_per_core do I need to read all cores?
478 */
450 -static void ebpf_shm_read_global_table()
479 +static void ebpf_shm_read_global_table(int maps_per_core)
480 {
481 netdata_idx_t *stored = shm_values;
482 netdata_idx_t *val = shm_hash_values;
483 int fd = shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd;
484 + size_t length = sizeof(netdata_idx_t);
485 + if (maps_per_core)
486 + length *= ebpf_nprocs;
487
488 uint32_t i, end = NETDATA_SHM_END;
489 for (i = NETDATA_KEY_SHMGET_CALL; i < end; i++) {
490 if (!bpf_map_lookup_elem(fd, &i, stored)) {
491 int j;
460 - int last = ebpf_nprocs;
492 + int last = (maps_per_core) ? ebpf_nprocs : 1;
493 netdata_idx_t total = 0;
494 for (j = 0; j < last; j++)
495 total += stored[j];
496
497 val[i] = total;
498 + memset(stored, 0 , length);
499 }
500 }
501 }
@@ -831,6 +864,7 @@ static void shm_collector(ebpf_module_t *em)
864 heartbeat_t hb;
865 heartbeat_init(&hb);
866 int counter = update_every - 1;
867 + int maps_per_core = em->maps_per_core;
868 while (!ebpf_exit_plugin) {
869 (void)heartbeat_next(&hb, USEC_PER_SEC);
870 if (ebpf_exit_plugin || ++counter != update_every)
@@ -838,14 +872,14 @@ static void shm_collector(ebpf_module_t *em)
872
873 counter = 0;
874 netdata_apps_integration_flags_t apps = em->apps_charts;
841 - ebpf_shm_read_global_table();
875 + ebpf_shm_read_global_table(maps_per_core);
876 pthread_mutex_lock(&collect_data_mutex);
877 if (apps) {
844 - read_apps_table();
878 + read_shm_apps_table(maps_per_core);
879 }
880
881 if (cgroups) {
848 - ebpf_update_shm_cgroup();
882 + ebpf_update_shm_cgroup(maps_per_core);
883 }
884
885 pthread_mutex_lock(&lock);
@@ -984,6 +1018,10 @@ static void ebpf_create_shm_charts(int update_every)
1018 */
1019 static int ebpf_shm_load_bpf(ebpf_module_t *em)
1020 {
1021 +#ifdef LIBBPF_MAJOR_VERSION
1022 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
1023 +#endif
1024 +
1025 int ret = 0;
1026
1027 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode);
collectors/ebpf.plugin/ebpf_socket.c
+104 -28
@@ -27,35 +27,67 @@ static ebpf_local_maps_t socket_maps[] = {{.name = "tbl_bandwidth",
27 .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED,
28 .user_input = NETDATA_MAXIMUM_CONNECTIONS_ALLOWED,
29 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
30 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
30 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
31 +#ifdef LIBBPF_MAJOR_VERSION
32 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
33 +#endif
34 + },
35 {.name = "tbl_global_sock",
36 .internal_input = NETDATA_SOCKET_COUNTER,
37 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
34 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
38 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
39 +#ifdef LIBBPF_MAJOR_VERSION
40 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
41 +#endif
42 + },
43 {.name = "tbl_lports",
44 .internal_input = NETDATA_SOCKET_COUNTER,
45 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
38 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
46 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
47 +#ifdef LIBBPF_MAJOR_VERSION
48 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
49 +#endif
50 + },
51 {.name = "tbl_conn_ipv4",
52 .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED,
53 .user_input = NETDATA_MAXIMUM_CONNECTIONS_ALLOWED,
54 .type = NETDATA_EBPF_MAP_STATIC,
43 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
55 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
56 +#ifdef LIBBPF_MAJOR_VERSION
57 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
58 +#endif
59 + },
60 {.name = "tbl_conn_ipv6",
61 .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED,
62 .user_input = NETDATA_MAXIMUM_CONNECTIONS_ALLOWED,
63 .type = NETDATA_EBPF_MAP_STATIC,
48 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
64 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
65 +#ifdef LIBBPF_MAJOR_VERSION
66 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
67 +#endif
68 + },
69 {.name = "tbl_nv_udp",
70 .internal_input = NETDATA_COMPILED_UDP_CONNECTIONS_ALLOWED,
71 .user_input = NETDATA_MAXIMUM_UDP_CONNECTIONS_ALLOWED,
72 .type = NETDATA_EBPF_MAP_STATIC,
53 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
73 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
74 +#ifdef LIBBPF_MAJOR_VERSION
75 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
76 +#endif
77 + },
78 {.name = "socket_ctrl", .internal_input = NETDATA_CONTROLLER_END,
79 .user_input = 0,
80 .type = NETDATA_EBPF_MAP_CONTROLLER,
57 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
58 - {.name = NULL, .internal_input = 0, .user_input = 0}};
81 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
82 +#ifdef LIBBPF_MAJOR_VERSION
83 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
84 +#endif
85 + },
86 + {.name = NULL, .internal_input = 0, .user_input = 0,
87 +#ifdef LIBBPF_MAJOR_VERSION
88 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
89 +#endif
90 + }};
91
92 static netdata_idx_t *socket_hash_values = NULL;
93 static netdata_syscall_stat_t socket_aggregated_data[NETDATA_MAX_SOCKET_VECTOR];
@@ -362,7 +394,7 @@ static void ebpf_socket_set_hash_tables(struct socket_bpf *obj)
394 * @param obj is the main structure for bpf objects.
395 * @param em structure with configuration
396 */
365 -static void ebpf_socket_adjust_map_size(struct socket_bpf *obj, ebpf_module_t *em)
397 +static void ebpf_socket_adjust_map(struct socket_bpf *obj, ebpf_module_t *em)
398 {
399 ebpf_update_map_size(obj->maps.tbl_bandwidth, &socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH],
400 em, bpf_map__name(obj->maps.tbl_bandwidth));
@@ -375,6 +407,15 @@ static void ebpf_socket_adjust_map_size(struct socket_bpf *obj, ebpf_module_t *e
407
408 ebpf_update_map_size(obj->maps.tbl_nv_udp, &socket_maps[NETDATA_SOCKET_TABLE_UDP],
409 em, bpf_map__name(obj->maps.tbl_nv_udp));
410 +
411 +
412 + ebpf_update_map_type(obj->maps.tbl_bandwidth, &socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH]);
413 + ebpf_update_map_type(obj->maps.tbl_conn_ipv4, &socket_maps[NETDATA_SOCKET_TABLE_IPV4]);
414 + ebpf_update_map_type(obj->maps.tbl_conn_ipv6, &socket_maps[NETDATA_SOCKET_TABLE_IPV6]);
415 + ebpf_update_map_type(obj->maps.tbl_nv_udp, &socket_maps[NETDATA_SOCKET_TABLE_UDP]);
416 + ebpf_update_map_type(obj->maps.socket_ctrl, &socket_maps[NETDATA_SOCKET_TABLE_CTRL]);
417 + ebpf_update_map_type(obj->maps.tbl_global_sock, &socket_maps[NETDATA_SOCKET_GLOBAL]);
418 + ebpf_update_map_type(obj->maps.tbl_lports, &socket_maps[NETDATA_SOCKET_LPORTS]);
419 }
420
421 /**
@@ -403,14 +444,14 @@ static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_modul
444 ebpf_socket_disable_specific_probe(obj, em->mode);
445 }
446
447 + ebpf_socket_adjust_map(obj, em);
448 +
449 int ret = socket_bpf__load(obj);
450 if (ret) {
451 fprintf(stderr, "failed to load BPF object: %d\n", ret);
452 return ret;
453 }
454
412 - ebpf_socket_adjust_map_size(obj, em);
413 -
455 if (test == EBPF_LOAD_TRAMPOLINE) {
456 ret = socket_bpf__attach(obj);
457 } else {
@@ -1988,17 +2029,23 @@ static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key
2029 *
2030 * @param fd the hash table with data.
2031 * @param family the family associated to the hash table
2032 + * @param maps_per_core do I need to read all cores?
2033 *
2034 * @return it returns 0 on success and -1 otherwise.
2035 */
1994 -static void ebpf_read_socket_hash_table(int fd, int family)
2036 +static void ebpf_read_socket_hash_table(int fd, int family, int maps_per_core)
2037 {
2038 netdata_socket_idx_t key = {};
2039 netdata_socket_idx_t next_key = {};
2040
2041 netdata_socket_t *values = socket_values;
2000 - size_t length = ebpf_nprocs*sizeof(netdata_socket_t);
2001 - int test, end = (running_on_kernel < NETDATA_KERNEL_V4_15) ? 1 : ebpf_nprocs;
2042 + size_t length = sizeof(netdata_socket_t);
2043 + int test, end;
2044 + if (maps_per_core) {
2045 + length *= ebpf_nprocs;
2046 + end = ebpf_nprocs;
2047 + } else
2048 + end = 1;
2049
2050 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
2051 // We need to reset the values when we are working on kernel 4.15 or newer, because kernel does not create
@@ -2122,11 +2169,13 @@ static void read_listen_table()
2169 void *ebpf_socket_read_hash(void *ptr)
2170 {
2171 netdata_thread_cleanup_push(ebpf_socket_cleanup, ptr);
2172 + ebpf_module_t *em = (ebpf_module_t *)ptr;
2173
2174 heartbeat_t hb;
2175 heartbeat_init(&hb);
2176 int fd_ipv4 = socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd;
2177 int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd;
2178 + int maps_per_core = em->maps_per_core;
2179 // This thread is cancelled from another thread
2180 for (;;) {
2181 (void)heartbeat_next(&hb, USEC_PER_SEC);
@@ -2134,8 +2183,8 @@ void *ebpf_socket_read_hash(void *ptr)
2183 break;
2184
2185 pthread_mutex_lock(&nv_mutex);
2137 - ebpf_read_socket_hash_table(fd_ipv4, AF_INET);
2138 - ebpf_read_socket_hash_table(fd_ipv6, AF_INET6);
2186 + ebpf_read_socket_hash_table(fd_ipv4, AF_INET, maps_per_core);
2187 + ebpf_read_socket_hash_table(fd_ipv6, AF_INET6, maps_per_core);
2188 pthread_mutex_unlock(&nv_mutex);
2189 }
2190
@@ -2145,23 +2194,30 @@ void *ebpf_socket_read_hash(void *ptr)
2194
2195 /**
2196 * Read the hash table and store data to allocated vectors.
2197 + *
2198 + * @param maps_per_core do I need to read all cores?
2199 */
2149 -static void read_hash_global_tables()
2200 +static void read_hash_global_tables(int maps_per_core)
2201 {
2202 uint64_t idx;
2203 netdata_idx_t res[NETDATA_SOCKET_COUNTER];
2204
2205 netdata_idx_t *val = socket_hash_values;
2206 + size_t length = sizeof(netdata_idx_t);
2207 + if (maps_per_core)
2208 + length *= ebpf_nprocs;
2209 +
2210 int fd = socket_maps[NETDATA_SOCKET_GLOBAL].map_fd;
2211 for (idx = 0; idx < NETDATA_SOCKET_COUNTER; idx++) {
2212 if (!bpf_map_lookup_elem(fd, &idx, val)) {
2213 uint64_t total = 0;
2214 int i;
2160 - int end = ebpf_nprocs;
2215 + int end = (maps_per_core) ? ebpf_nprocs : 1;
2216 for (i = 0; i < end; i++)
2217 total += val[i];
2218
2219 res[idx] = total;
2220 + memset(socket_hash_values, 0, length);
2221 } else {
2222 res[idx] = 0;
2223 }
@@ -2220,9 +2276,9 @@ void ebpf_socket_fill_publish_apps(uint32_t current_pid, ebpf_bandwidth_t *eb)
2276 *
2277 * @param out the vector with the values to sum
2278 */
2223 -void ebpf_socket_bandwidth_accumulator(ebpf_bandwidth_t *out)
2279 +void ebpf_socket_bandwidth_accumulator(ebpf_bandwidth_t *out, int maps_per_core)
2280 {
2225 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
2281 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
2282 ebpf_bandwidth_t *total = &out[0];
2283 for (i = 1; i < end; i++) {
2284 ebpf_bandwidth_t *move = &out[i];
@@ -2241,13 +2297,18 @@ void ebpf_socket_bandwidth_accumulator(ebpf_bandwidth_t *out)
2297
2298 /**
2299 * Update the apps data reading information from the hash table
2300 + *
2301 + * @param maps_per_core do I need to read all cores?
2302 */
2245 -static void ebpf_socket_update_apps_data()
2303 +static void ebpf_socket_update_apps_data(int maps_per_core)
2304 {
2305 int fd = socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH].map_fd;
2306 ebpf_bandwidth_t *eb = bandwidth_vector;
2307 uint32_t key;
2308 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
2309 + size_t length = sizeof(ebpf_bandwidth_t);
2310 + if (maps_per_core)
2311 + length *= ebpf_nprocs;
2312 while (pids) {
2313 key = pids->pid;
2314
@@ -2256,10 +2317,12 @@ static void ebpf_socket_update_apps_data()
2317 continue;
2318 }
2319
2259 - ebpf_socket_bandwidth_accumulator(eb);
2320 + ebpf_socket_bandwidth_accumulator(eb, maps_per_core);
2321
2322 ebpf_socket_fill_publish_apps(key, eb);
2323
2324 + memset(eb, 0, length);
2325 +
2326 pids = pids->next;
2327 }
2328 }
@@ -2267,15 +2330,21 @@ static void ebpf_socket_update_apps_data()
2330 /**
2331 * Update cgroup
2332 *
2270 - * Update cgroup data based in
2333 + * Update cgroup data based in PIDs.
2334 + *
2335 + * @param maps_per_core do I need to read all cores?
2336 */
2272 -static void ebpf_update_socket_cgroup()
2337 +static void ebpf_update_socket_cgroup(int maps_per_core)
2338 {
2339 ebpf_cgroup_target_t *ect ;
2340
2341 ebpf_bandwidth_t *eb = bandwidth_vector;
2342 int fd = socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH].map_fd;
2343
2344 + size_t length = sizeof(ebpf_bandwidth_t);
2345 + if (maps_per_core)
2346 + length *= ebpf_nprocs;
2347 +
2348 pthread_mutex_lock(&mutex_cgroup_shm);
2349 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2350 struct pid_on_target2 *pids;
@@ -2298,7 +2367,7 @@ static void ebpf_update_socket_cgroup()
2367 publish->call_tcp_v6_connection = in->call_tcp_v6_connection;
2368 } else {
2369 if (!bpf_map_lookup_elem(fd, &pid, eb)) {
2301 - ebpf_socket_bandwidth_accumulator(eb);
2370 + ebpf_socket_bandwidth_accumulator(eb, maps_per_core);
2371
2372 memcpy(out, eb, sizeof(ebpf_bandwidth_t));
2373
@@ -2312,6 +2381,8 @@ static void ebpf_update_socket_cgroup()
2381 publish->call_close = out->close;
2382 publish->call_tcp_v4_connection = out->tcp_v4_connection;
2383 publish->call_tcp_v6_connection = out->tcp_v6_connection;
2384 +
2385 + memset(eb, 0, length);
2386 }
2387 }
2388 }
@@ -2845,6 +2916,7 @@ static void socket_collector(ebpf_module_t *em)
2916
2917 int socket_global_enabled = em->global_charts;
2918 int update_every = em->update_every;
2919 + int maps_per_core = em->maps_per_core;
2920 int counter = update_every - 1;
2921 while (!ebpf_exit_plugin) {
2922 (void)heartbeat_next(&hb, USEC_PER_SEC);
@@ -2855,15 +2927,15 @@ static void socket_collector(ebpf_module_t *em)
2927 netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
2928 if (socket_global_enabled) {
2929 read_listen_table();
2858 - read_hash_global_tables();
2930 + read_hash_global_tables(maps_per_core);
2931 }
2932
2933 pthread_mutex_lock(&collect_data_mutex);
2934 if (socket_apps_enabled)
2863 - ebpf_socket_update_apps_data();
2935 + ebpf_socket_update_apps_data(maps_per_core);
2936
2937 if (cgroups)
2866 - ebpf_update_socket_cgroup();
2938 + ebpf_update_socket_cgroup(maps_per_core);
2939
2940 if (network_connection)
2941 calculate_nv_plot();
@@ -3855,6 +3927,10 @@ void parse_table_size_options(struct config *cfg)
3927 */
3928 static int ebpf_socket_load_bpf(ebpf_module_t *em)
3929 {
3930 +#ifdef LIBBPF_MAJOR_VERSION
3931 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
3932 +#endif
3933 +
3934 int ret = 0;
3935
3936 if (em->load & EBPF_LOAD_LEGACY) {
collectors/ebpf.plugin/ebpf_softirq.c
+27 -5
@@ -16,7 +16,10 @@ static ebpf_local_maps_t softirq_maps[] = {
16 .internal_input = NETDATA_SOFTIRQ_MAX_IRQS,
17 .user_input = 0,
18 .type = NETDATA_EBPF_MAP_STATIC,
19 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
19 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
20 +#ifdef LIBBPF_MAJOR_VERSION
21 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
22 +#endif
23 },
24 /* end */
25 {
@@ -24,7 +27,10 @@ static ebpf_local_maps_t softirq_maps[] = {
27 .internal_input = 0,
28 .user_input = 0,
29 .type = NETDATA_EBPF_MAP_CONTROLLER,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED
30 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
31 +#ifdef LIBBPF_MAJOR_VERSION
32 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
33 +#endif
34 }
35 };
36
@@ -94,10 +100,21 @@ static void softirq_cleanup(void *ptr)
100 * MAIN LOOP
101 *****************************************************************/
102
97 -static void softirq_read_latency_map()
103 +/**
104 + * Read Latency Map
105 + *
106 + * Read data from kernel ring to plot for users.
107 + *
108 + * @param maps_per_core do I need to read all cores?
109 + */
110 +static void softirq_read_latency_map(int maps_per_core)
111 {
112 int fd = softirq_maps[SOFTIRQ_MAP_LATENCY].map_fd;
113 int i;
114 + size_t length = sizeof(softirq_ebpf_val_t);
115 + if (maps_per_core)
116 + length *= ebpf_nprocs;
117 +
118 for (i = 0; i < NETDATA_SOFTIRQ_MAX_IRQS; i++) {
119 int test = bpf_map_lookup_elem(fd, &i, softirq_ebpf_vals);
120 if (unlikely(test < 0)) {
@@ -106,12 +123,13 @@ static void softirq_read_latency_map()
123
124 uint64_t total_latency = 0;
125 int cpu_i;
109 - int end = ebpf_nprocs;
126 + int end = (maps_per_core) ? ebpf_nprocs : 1;
127 for (cpu_i = 0; cpu_i < end; cpu_i++) {
128 total_latency += softirq_ebpf_vals[cpu_i].latency/1000;
129 }
130
131 softirq_vals[i].latency = total_latency;
132 + memset(softirq_ebpf_vals, 0, length);
133 }
134 }
135
@@ -172,6 +190,7 @@ static void softirq_collector(ebpf_module_t *em)
190 heartbeat_init(&hb);
191 int update_every = em->update_every;
192 int counter = update_every - 1;
193 + int maps_per_core = em->maps_per_core;
194 //This will be cancelled by its parent
195 while (!ebpf_exit_plugin) {
196 (void)heartbeat_next(&hb, USEC_PER_SEC);
@@ -179,7 +198,7 @@ static void softirq_collector(ebpf_module_t *em)
198 continue;
199
200 counter = 0;
182 - softirq_read_latency_map();
201 + softirq_read_latency_map(maps_per_core);
202 pthread_mutex_lock(&lock);
203
204 // write dims now for all hitherto discovered IRQs.
@@ -212,6 +231,9 @@ void *ebpf_softirq_thread(void *ptr)
231 goto endsoftirq;
232 }
233
234 +#ifdef LIBBPF_MAJOR_VERSION
235 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
236 +#endif
237 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
238 if (!em->probe_links) {
239 goto endsoftirq;
collectors/ebpf.plugin/ebpf_swap.c
+59 -20
@@ -21,16 +21,32 @@ struct config swap_config = { .first_section = NULL,
21 static ebpf_local_maps_t swap_maps[] = {{.name = "tbl_pid_swap", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
22 .user_input = 0,
23 .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
24 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
24 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
25 +#ifdef LIBBPF_MAJOR_VERSION
26 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
27 +#endif
28 + },
29 {.name = "swap_ctrl", .internal_input = NETDATA_CONTROLLER_END,
30 .user_input = 0,
31 .type = NETDATA_EBPF_MAP_CONTROLLER,
28 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
32 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
33 +#ifdef LIBBPF_MAJOR_VERSION
34 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
35 +#endif
36 + },
37 {.name = "tbl_swap", .internal_input = NETDATA_SWAP_END,
38 .user_input = 0,
39 .type = NETDATA_EBPF_MAP_STATIC,
32 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
33 - {.name = NULL, .internal_input = 0, .user_input = 0}};
40 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
41 +#ifdef LIBBPF_MAJOR_VERSION
42 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
43 +#endif
44 + },
45 + {.name = NULL, .internal_input = 0, .user_input = 0,
46 +#ifdef LIBBPF_MAJOR_VERSION
47 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
48 +#endif
49 + }};
50
51 netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
52 {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -133,17 +149,21 @@ static void ebpf_swap_set_hash_tables(struct swap_bpf *obj)
149 }
150
151 /**
136 - * Adjust Map Size
152 + * Adjust Map
153 *
154 * Resize maps according input from users.
155 *
156 * @param obj is the main structure for bpf objects.
157 * @param em structure with configuration
158 */
143 -static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em)
159 +static void ebpf_swap_adjust_map(struct swap_bpf *obj, ebpf_module_t *em)
160 {
161 ebpf_update_map_size(obj->maps.tbl_pid_swap, &swap_maps[NETDATA_PID_SWAP_TABLE],
162 em, bpf_map__name(obj->maps.tbl_pid_swap));
163 +
164 + ebpf_update_map_type(obj->maps.tbl_pid_swap, &swap_maps[NETDATA_PID_SWAP_TABLE]);
165 + ebpf_update_map_type(obj->maps.tbl_swap, &swap_maps[NETDATA_SWAP_GLOBAL_TABLE]);
166 + ebpf_update_map_type(obj->maps.swap_ctrl, &swap_maps[NETDATA_SWAP_CONTROLLER]);
167 }
168
169 /**
@@ -182,7 +202,7 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
202 ebpf_swap_disable_trampoline(obj);
203 }
204
185 - ebpf_swap_adjust_map_size(obj, em);
205 + ebpf_swap_adjust_map(obj, em);
206
207 if (!em->apps_charts && !em->cgroup_charts)
208 ebpf_swap_disable_release_task(obj);
@@ -251,10 +271,11 @@ static void ebpf_swap_exit(void *ptr)
271 * Sum all values read from kernel and store in the first address.
272 *
273 * @param out the vector with read values.
274 + * @param maps_per_core do I need to read all cores?
275 */
255 -static void swap_apps_accumulator(netdata_publish_swap_t *out)
276 +static void swap_apps_accumulator(netdata_publish_swap_t *out, int maps_per_core)
277 {
257 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
278 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
279 netdata_publish_swap_t *total = &out[0];
280 for (i = 1; i < end; i++) {
281 netdata_publish_swap_t *w = &out[i];
@@ -286,13 +307,17 @@ static void swap_fill_pid(uint32_t current_pid, netdata_publish_swap_t *publish)
307 * Update cgroup
308 *
309 * Update cgroup data based in
310 + *
311 + * @param maps_per_core do I need to read all cores?
312 */
290 -static void ebpf_update_swap_cgroup()
313 +static void ebpf_update_swap_cgroup(int maps_per_core)
314 {
315 ebpf_cgroup_target_t *ect ;
316 netdata_publish_swap_t *cv = swap_vector;
317 int fd = swap_maps[NETDATA_PID_SWAP_TABLE].map_fd;
295 - size_t length = sizeof(netdata_publish_swap_t)*ebpf_nprocs;
318 + size_t length = sizeof(netdata_publish_swap_t);
319 + if (maps_per_core)
320 + length *= ebpf_nprocs;
321 pthread_mutex_lock(&mutex_cgroup_shm);
322 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
323 struct pid_on_target2 *pids;
@@ -306,9 +331,12 @@ static void ebpf_update_swap_cgroup()
331 } else {
332 memset(cv, 0, length);
333 if (!bpf_map_lookup_elem(fd, &pid, cv)) {
309 - swap_apps_accumulator(cv);
334 + swap_apps_accumulator(cv, maps_per_core);
335
336 memcpy(out, cv, sizeof(netdata_publish_swap_t));
337 +
338 + // We are cleaning to avoid passing data read from one process to other.
339 + memset(cv, 0, length);
340 }
341 }
342 }
@@ -320,14 +348,18 @@ static void ebpf_update_swap_cgroup()
348 * Read APPS table
349 *
350 * Read the apps table and store data inside the structure.
351 + *
352 + * @param maps_per_core do I need to read all cores?
353 */
324 -static void read_apps_table()
354 +static void read_swap_apps_table(int maps_per_core)
355 {
356 netdata_publish_swap_t *cv = swap_vector;
357 uint32_t key;
358 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
359 int fd = swap_maps[NETDATA_PID_SWAP_TABLE].map_fd;
330 - size_t length = sizeof(netdata_publish_swap_t)*ebpf_nprocs;
360 + size_t length = sizeof(netdata_publish_swap_t);
361 + if (maps_per_core)
362 + length *= ebpf_nprocs;
363 while (pids) {
364 key = pids->pid;
365
@@ -336,7 +368,7 @@ static void read_apps_table()
368 continue;
369 }
370
339 - swap_apps_accumulator(cv);
371 + swap_apps_accumulator(cv, maps_per_core);
372
373 swap_fill_pid(key, cv);
374
@@ -365,8 +397,10 @@ static void swap_send_global()
397 * Read global counter
398 *
399 * Read the table with number of calls to all functions
400 + *
401 + * @param maps_per_core do I need to read all cores?
402 */
369 -static void ebpf_swap_read_global_table()
403 +static void ebpf_swap_read_global_table(int maps_per_core)
404 {
405 netdata_idx_t *stored = swap_values;
406 netdata_idx_t *val = swap_hash_values;
@@ -376,7 +410,7 @@ static void ebpf_swap_read_global_table()
410 for (i = NETDATA_KEY_SWAP_READPAGE_CALL; i < end; i++) {
411 if (!bpf_map_lookup_elem(fd, &i, stored)) {
412 int j;
379 - int last = ebpf_nprocs;
413 + int last = (maps_per_core) ? ebpf_nprocs : 1;
414 netdata_idx_t total = 0;
415 for (j = 0; j < last; j++)
416 total += stored[j];
@@ -646,6 +680,7 @@ static void swap_collector(ebpf_module_t *em)
680 heartbeat_t hb;
681 heartbeat_init(&hb);
682 int counter = update_every - 1;
683 + int maps_per_core = em->maps_per_core;
684 while (!ebpf_exit_plugin) {
685 (void)heartbeat_next(&hb, USEC_PER_SEC);
686 if (ebpf_exit_plugin || ++counter != update_every)
@@ -653,13 +688,13 @@ static void swap_collector(ebpf_module_t *em)
688
689 counter = 0;
690 netdata_apps_integration_flags_t apps = em->apps_charts;
656 - ebpf_swap_read_global_table();
691 + ebpf_swap_read_global_table(maps_per_core);
692 pthread_mutex_lock(&collect_data_mutex);
693 if (apps)
659 - read_apps_table();
694 + read_swap_apps_table(maps_per_core);
695
696 if (cgroup)
662 - ebpf_update_swap_cgroup();
697 + ebpf_update_swap_cgroup(maps_per_core);
698
699 pthread_mutex_lock(&lock);
700
@@ -767,6 +802,10 @@ static void ebpf_create_swap_charts(int update_every)
802 */
803 static int ebpf_swap_load_bpf(ebpf_module_t *em)
804 {
805 +#ifdef LIBBPF_MAJOR_VERSION
806 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
807 +#endif
808 +
809 int ret = 0;
810 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SWAP_READPAGE_CALL].mode);
811 if (em->load & EBPF_LOAD_LEGACY) {
collectors/ebpf.plugin/ebpf_sync.c
+139 -33
@@ -10,27 +10,95 @@ static netdata_publish_syscall_t sync_counter_publish_aggregated[NETDATA_SYNC_ID
10
11 static netdata_idx_t sync_hash_values[NETDATA_SYNC_IDX_END];
12
13 -static ebpf_local_maps_t sync_maps[] = {{.name = "tbl_sync", .internal_input = NETDATA_SYNC_END,
14 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
15 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
16 - {.name = "tbl_syncfs", .internal_input = NETDATA_SYNC_END,
17 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
18 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
19 - {.name = "tbl_msync", .internal_input = NETDATA_SYNC_END,
20 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
21 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
22 - {.name = "tbl_fsync", .internal_input = NETDATA_SYNC_END,
23 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
24 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
25 - {.name = "tbl_fdatasync", .internal_input = NETDATA_SYNC_END,
26 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
28 - {.name = "tbl_syncfr", .internal_input = NETDATA_SYNC_END,
29 - .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
30 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
31 - {.name = NULL, .internal_input = 0, .user_input = 0,
32 - .type = NETDATA_EBPF_MAP_CONTROLLER,
33 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
13 +ebpf_local_maps_t sync_maps[] = {{.name = "tbl_sync", .internal_input = NETDATA_SYNC_END,
14 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
15 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
16 +#ifdef LIBBPF_MAJOR_VERSION
17 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
18 +#endif
19 + },
20 + {.name = NULL, .internal_input = 0, .user_input = 0,
21 + .type = NETDATA_EBPF_MAP_CONTROLLER,
22 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
23 +#ifdef LIBBPF_MAJOR_VERSION
24 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
25 +#endif
26 + }};
27 +
28 +ebpf_local_maps_t syncfs_maps[] = {{.name = "tbl_syncfs", .internal_input = NETDATA_SYNC_END,
29 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
30 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
31 +#ifdef LIBBPF_MAJOR_VERSION
32 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
33 +#endif
34 + },
35 + {.name = NULL, .internal_input = 0, .user_input = 0,
36 + .type = NETDATA_EBPF_MAP_CONTROLLER,
37 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
38 +#ifdef LIBBPF_MAJOR_VERSION
39 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
40 +#endif
41 + }};
42 +
43 +ebpf_local_maps_t msync_maps[] = {{.name = "tbl_msync", .internal_input = NETDATA_SYNC_END,
44 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
45 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
46 +#ifdef LIBBPF_MAJOR_VERSION
47 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
48 +#endif
49 + },
50 + {.name = NULL, .internal_input = 0, .user_input = 0,
51 + .type = NETDATA_EBPF_MAP_CONTROLLER,
52 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
53 +#ifdef LIBBPF_MAJOR_VERSION
54 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
55 +#endif
56 + }};
57 +
58 +ebpf_local_maps_t fsync_maps[] = {{.name = "tbl_fsync", .internal_input = NETDATA_SYNC_END,
59 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
60 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
61 +#ifdef LIBBPF_MAJOR_VERSION
62 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
63 +#endif
64 + },
65 + {.name = NULL, .internal_input = 0, .user_input = 0,
66 + .type = NETDATA_EBPF_MAP_CONTROLLER,
67 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
68 +#ifdef LIBBPF_MAJOR_VERSION
69 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
70 +#endif
71 + }};
72 +
73 +ebpf_local_maps_t fdatasync_maps[] = {{.name = "tbl_fdatasync", .internal_input = NETDATA_SYNC_END,
74 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
75 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
76 +#ifdef LIBBPF_MAJOR_VERSION
77 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
78 +#endif
79 + },
80 + {.name = NULL, .internal_input = 0, .user_input = 0,
81 + .type = NETDATA_EBPF_MAP_CONTROLLER,
82 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
83 +#ifdef LIBBPF_MAJOR_VERSION
84 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
85 +#endif
86 + }};
87 +
88 +ebpf_local_maps_t sync_file_range_maps[] = {{.name = "tbl_syncfr", .internal_input = NETDATA_SYNC_END,
89 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
90 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
91 +#ifdef LIBBPF_MAJOR_VERSION
92 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
93 +#endif
94 + },
95 + {.name = NULL, .internal_input = 0, .user_input = 0,
96 + .type = NETDATA_EBPF_MAP_CONTROLLER,
97 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
98 +#ifdef LIBBPF_MAJOR_VERSION
99 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
100 +#endif
101 + }};
102
103 struct config sync_config = { .first_section = NULL,
104 .last_section = NULL,
@@ -111,12 +179,12 @@ void ebpf_sync_disable_tracepoints(struct sync_bpf *obj, sync_syscalls_index_t i
179 *
180 * Set the values for maps according the value given by kernel.
181 *
114 - * @param obj is the main structure for bpf objects.
115 - * @param idx the index for the main structure
182 + * @param map the map loaded.
183 + * @param obj the main structure for bpf objects.
184 */
117 -static void ebpf_sync_set_hash_tables(struct sync_bpf *obj, sync_syscalls_index_t idx)
185 +static void ebpf_sync_set_hash_tables(ebpf_local_maps_t *map, struct sync_bpf *obj)
186 {
119 - sync_maps[idx].map_fd = bpf_map__fd(obj->maps.tbl_sync);
187 + map->map_fd = bpf_map__fd(obj->maps.tbl_sync);
188 }
189
190 /**
@@ -154,6 +222,8 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t
222 ebpf_sync_disable_tracepoints(obj, idx);
223 }
224
225 + ebpf_update_map_type(obj->maps.tbl_sync, &em->maps[NETDATA_SYNC_GLOBAL_TABLE]);
226 +
227 int ret = sync_bpf__load(obj);
228 if (!ret) {
229 if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE) {
@@ -165,7 +235,7 @@ static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t
235 }
236
237 if (!ret)
168 - ebpf_sync_set_hash_tables(obj, idx);
238 + ebpf_sync_set_hash_tables(&em->maps[NETDATA_SYNC_GLOBAL_TABLE], obj);
239 }
240
241 return ret;
@@ -264,11 +334,21 @@ static int ebpf_sync_load_legacy(ebpf_sync_syscalls_t *w, ebpf_module_t *em)
334 */
335 static int ebpf_sync_initialize_syscall(ebpf_module_t *em)
336 {
337 +#ifdef LIBBPF_MAJOR_VERSION
338 + ebpf_define_map_type(sync_maps, em->maps_per_core, running_on_kernel);
339 + ebpf_define_map_type(syncfs_maps, em->maps_per_core, running_on_kernel);
340 + ebpf_define_map_type(msync_maps, em->maps_per_core, running_on_kernel);
341 + ebpf_define_map_type(fsync_maps, em->maps_per_core, running_on_kernel);
342 + ebpf_define_map_type(fdatasync_maps, em->maps_per_core, running_on_kernel);
343 + ebpf_define_map_type(sync_file_range_maps, em->maps_per_core, running_on_kernel);
344 +#endif
345 +
346 int i;
347 const char *saved_name = em->thread_name;
348 int errors = 0;
349 for (i = 0; local_syscalls[i].syscall; i++) {
350 ebpf_sync_syscalls_t *w = &local_syscalls[i];
351 + w->sync_maps = local_syscalls[i].sync_maps;
352 if (w->enabled) {
353 if (em->load & EBPF_LOAD_LEGACY) {
354 if (ebpf_sync_load_legacy(w, em))
@@ -317,17 +397,25 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em)
397 * Read global table
398 *
399 * Read the table with number of calls for all functions
400 + *
401 + * @param maps_per_core do I need to read all cores?
402 */
321 -static void ebpf_sync_read_global_table()
403 +static void ebpf_sync_read_global_table(int maps_per_core)
404 {
323 - netdata_idx_t stored;
405 + netdata_idx_t stored[ebpf_nprocs];
406 uint32_t idx = NETDATA_SYNC_CALL;
407 int i;
408 for (i = 0; local_syscalls[i].syscall; i++) {
327 - if (local_syscalls[i].enabled) {
328 - int fd = sync_maps[i].map_fd;
409 + ebpf_sync_syscalls_t *w = &local_syscalls[i];
410 + if (w->enabled) {
411 + int fd = w->sync_maps[NETDATA_SYNC_GLOBAL_TABLE].map_fd;
412 if (!bpf_map_lookup_elem(fd, &idx, &stored)) {
330 - sync_hash_values[i] = stored;
413 + int j, end = (maps_per_core) ? ebpf_nprocs : 1;
414 + netdata_idx_t total = 0;
415 + for (j = 0; j < end ;j++ )
416 + total += stored[j];
417 +
418 + sync_hash_values[i] = total;
419 }
420 }
421 }
@@ -352,7 +440,7 @@ static void ebpf_send_sync_chart(char *id,
440
441 while (move && idx <= end) {
442 if (local_syscalls[idx].enabled)
355 - write_chart_dimension(move->name, sync_hash_values[idx]);
443 + write_chart_dimension(move->name, (long long)sync_hash_values[idx]);
444
445 move = move->next;
446 idx++;
@@ -396,13 +484,14 @@ static void sync_collector(ebpf_module_t *em)
484 heartbeat_init(&hb);
485 int update_every = em->update_every;
486 int counter = update_every - 1;
487 + int maps_per_core = em->maps_per_core;
488 while (!ebpf_exit_plugin) {
489 (void)heartbeat_next(&hb, USEC_PER_SEC);
490 if (ebpf_exit_plugin || ++counter != update_every)
491 continue;
492
493 counter = 0;
405 - ebpf_sync_read_global_table();
494 + ebpf_sync_read_global_table(maps_per_core);
495 pthread_mutex_lock(&lock);
496
497 sync_send_data();
@@ -497,6 +586,22 @@ static void ebpf_sync_parse_syscalls()
586 }
587 }
588
589 +/**
590 + * Set sync maps
591 + *
592 + * When thread is initialized the variable sync_maps is set as null,
593 + * this function fills the variable before to use.
594 + */
595 +static void ebpf_set_sync_maps()
596 +{
597 + local_syscalls[NETDATA_SYNC_SYNC_IDX].sync_maps = sync_maps;
598 + local_syscalls[NETDATA_SYNC_SYNCFS_IDX].sync_maps = syncfs_maps;
599 + local_syscalls[NETDATA_SYNC_MSYNC_IDX].sync_maps = msync_maps;
600 + local_syscalls[NETDATA_SYNC_FSYNC_IDX].sync_maps = fsync_maps;
601 + local_syscalls[NETDATA_SYNC_FDATASYNC_IDX].sync_maps = fdatasync_maps;
602 + local_syscalls[NETDATA_SYNC_SYNC_FILE_RANGE_IDX].sync_maps = sync_file_range_maps;
603 +}
604 +
605 /**
606 * Sync thread
607 *
@@ -513,6 +618,7 @@ void *ebpf_sync_thread(void *ptr)
618 ebpf_module_t *em = (ebpf_module_t *)ptr;
619 em->maps = sync_maps;
620
621 + ebpf_set_sync_maps();
622 ebpf_sync_parse_syscalls();
623
624 #ifdef LIBBPF_MAJOR_VERSION
collectors/ebpf.plugin/ebpf_vfs.c
+64 -25
@@ -17,15 +17,31 @@ netdata_publish_vfs_t *vfs_vector = NULL;
17
18 static ebpf_local_maps_t vfs_maps[] = {{.name = "tbl_vfs_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
19 .user_input = 0, .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
20 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
20 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
21 +#ifdef LIBBPF_MAJOR_VERSION
22 + .map_type = BPF_MAP_TYPE_PERCPU_HASH
23 +#endif
24 + },
25 {.name = "tbl_vfs_stats", .internal_input = NETDATA_VFS_COUNTER,
26 .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
23 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
27 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
28 +#ifdef LIBBPF_MAJOR_VERSION
29 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
30 +#endif
31 + },
32 {.name = "vfs_ctrl", .internal_input = NETDATA_CONTROLLER_END,
33 .user_input = 0,
34 .type = NETDATA_EBPF_MAP_CONTROLLER,
27 - .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
28 - {.name = NULL, .internal_input = 0, .user_input = 0}};
35 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
36 +#ifdef LIBBPF_MAJOR_VERSION
37 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
38 +#endif
39 + },
40 + {.name = NULL, .internal_input = 0, .user_input = 0,
41 +#ifdef LIBBPF_MAJOR_VERSION
42 + .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
43 +#endif
44 + }};
45
46 struct config vfs_config = { .first_section = NULL,
47 .last_section = NULL,
@@ -293,17 +309,21 @@ static int ebpf_vfs_attach_probe(struct vfs_bpf *obj)
309 }
310
311 /**
296 - * Adjust Map Size
312 + * Adjust Size
313 *
314 * Resize maps according input from users.
315 *
316 * @param obj is the main structure for bpf objects.
317 * @param em structure with configuration
318 */
303 -static void ebpf_vfs_adjust_map_size(struct vfs_bpf *obj, ebpf_module_t *em)
319 +static void ebpf_vfs_adjust_map(struct vfs_bpf *obj, ebpf_module_t *em)
320 {
321 ebpf_update_map_size(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID],
322 em, bpf_map__name(obj->maps.tbl_vfs_pid));
323 +
324 + ebpf_update_map_type(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID]);
325 + ebpf_update_map_type(obj->maps.tbl_vfs_stats, &vfs_maps[NETDATA_VFS_ALL]);
326 + ebpf_update_map_type(obj->maps.vfs_ctrl, &vfs_maps[NETDATA_VFS_CTRL]);
327 }
328
329 /**
@@ -356,7 +376,7 @@ static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *e
376 ebpf_vfs_disable_trampoline(obj);
377 }
378
359 - ebpf_vfs_adjust_map_size(obj, em);
379 + ebpf_vfs_adjust_map(obj, em);
380
381 if (!em->apps_charts && !em->cgroup_charts)
382 ebpf_vfs_disable_release_task(obj);
@@ -475,23 +495,30 @@ static void ebpf_vfs_send_data(ebpf_module_t *em)
495
496 /**
497 * Read the hash table and store data to allocated vectors.
498 + *
499 + * @param maps_per_core do I need to read all cores?
500 */
479 -static void ebpf_vfs_read_global_table()
501 +static void ebpf_vfs_read_global_table(int maps_per_core)
502 {
503 uint64_t idx;
504 netdata_idx_t res[NETDATA_VFS_COUNTER];
505
506 netdata_idx_t *val = vfs_hash_values;
507 + size_t length = sizeof(netdata_idx_t);
508 + if (maps_per_core)
509 + length *= ebpf_nprocs;
510 +
511 int fd = vfs_maps[NETDATA_VFS_ALL].map_fd;
512 for (idx = 0; idx < NETDATA_VFS_COUNTER; idx++) {
513 uint64_t total = 0;
514 if (!bpf_map_lookup_elem(fd, &idx, val)) {
515 int i;
490 - int end = ebpf_nprocs;
516 + int end = (maps_per_core) ? ebpf_nprocs : 1;
517 for (i = 0; i < end; i++)
518 total += val[i];
519 }
520 res[idx] = total;
521 + memset(val, 0, length);
522 }
523
524 vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].ncall = res[NETDATA_KEY_CALLS_VFS_UNLINK];
@@ -723,9 +750,9 @@ void ebpf_vfs_send_apps_data(ebpf_module_t *em, struct ebpf_target *root)
750 *
751 * @param out the vector with read values.
752 */
726 -static void vfs_apps_accumulator(netdata_publish_vfs_t *out)
753 +static void vfs_apps_accumulator(netdata_publish_vfs_t *out, int maps_per_core)
754 {
728 - int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
755 + int i, end = (maps_per_core) ? ebpf_nprocs : 1;
756 netdata_publish_vfs_t *total = &out[0];
757 for (i = 1; i < end; i++) {
758 netdata_publish_vfs_t *w = &out[i];
@@ -771,12 +798,15 @@ static void vfs_fill_pid(uint32_t current_pid, netdata_publish_vfs_t *publish)
798 /**
799 * Read the hash table and store data to allocated vectors.
800 */
774 -static void ebpf_vfs_read_apps()
801 +static void ebpf_vfs_read_apps(int maps_per_core)
802 {
803 struct ebpf_pid_stat *pids = ebpf_root_of_pids;
804 netdata_publish_vfs_t *vv = vfs_vector;
805 int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
779 - size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
806 + size_t length = sizeof(netdata_publish_vfs_t);
807 + if (maps_per_core)
808 + length *= ebpf_nprocs;
809 +
810 while (pids) {
811 uint32_t key = pids->pid;
812
@@ -785,7 +815,7 @@ static void ebpf_vfs_read_apps()
815 continue;
816 }
817
788 - vfs_apps_accumulator(vv);
818 + vfs_apps_accumulator(vv, maps_per_core);
819
820 vfs_fill_pid(key, vv);
821
@@ -799,14 +829,18 @@ static void ebpf_vfs_read_apps()
829 /**
830 * Update cgroup
831 *
802 - * Update cgroup data based in
832 + * Update cgroup data based in PID.
833 + *
834 + * @param maps_per_core do I need to read all cores?
835 */
804 -static void read_update_vfs_cgroup()
836 +static void read_update_vfs_cgroup(int maps_per_core)
837 {
838 ebpf_cgroup_target_t *ect ;
839 netdata_publish_vfs_t *vv = vfs_vector;
840 int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
809 - size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
841 + size_t length = sizeof(netdata_publish_vfs_t);
842 + if (maps_per_core)
843 + length *= ebpf_nprocs;
844
845 pthread_mutex_lock(&mutex_cgroup_shm);
846 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
@@ -821,7 +855,7 @@ static void read_update_vfs_cgroup()
855 } else {
856 memset(vv, 0, length);
857 if (!bpf_map_lookup_elem(fd, &pid, vv)) {
824 - vfs_apps_accumulator(vv);
858 + vfs_apps_accumulator(vv, maps_per_core);
859
860 memcpy(out, vv, sizeof(netdata_publish_vfs_t));
861 }
@@ -1458,6 +1492,7 @@ static void vfs_collector(ebpf_module_t *em)
1492 heartbeat_init(&hb);
1493 int update_every = em->update_every;
1494 int counter = update_every - 1;
1495 + int maps_per_core = em->maps_per_core;
1496 while (!ebpf_exit_plugin) {
1497 (void)heartbeat_next(&hb, USEC_PER_SEC);
1498 if (ebpf_exit_plugin || ++counter != update_every)
@@ -1465,21 +1500,21 @@ static void vfs_collector(ebpf_module_t *em)
1500
1501 counter = 0;
1502 netdata_apps_integration_flags_t apps = em->apps_charts;
1468 - ebpf_vfs_read_global_table();
1503 + ebpf_vfs_read_global_table(maps_per_core);
1504 pthread_mutex_lock(&collect_data_mutex);
1505 if (apps)
1471 - ebpf_vfs_read_apps();
1506 + ebpf_vfs_read_apps(maps_per_core);
1507 +
1508 + if (cgroups)
1509 + read_update_vfs_cgroup(maps_per_core);
1510 +
1511 + pthread_mutex_lock(&lock);
1512
1513 #ifdef NETDATA_DEV_MODE
1514 if (ebpf_aral_vfs_pid)
1515 ebpf_send_data_aral_chart(ebpf_aral_vfs_pid, em);
1516 #endif
1517
1478 - if (cgroups)
1479 - read_update_vfs_cgroup();
1480 -
1481 - pthread_mutex_lock(&lock);
1482 -
1518 ebpf_vfs_send_data(em);
1519 fflush(stdout);
1520
@@ -1843,6 +1878,10 @@ static void ebpf_vfs_allocate_global_vectors(int apps)
1878 */
1879 static int ebpf_vfs_load_bpf(ebpf_module_t *em)
1880 {
1881 +#ifdef LIBBPF_MAJOR_VERSION
1882 + ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
1883 +#endif
1884 +
1885 int ret = 0;
1886 ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_EBPF_VFS_WRITE].mode);
1887 if (em->load & EBPF_LOAD_LEGACY) {
libnetdata/ebpf/ebpf.c
+101 -16
@@ -453,6 +453,11 @@ void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
453 else if (em->load & EBPF_LOAD_CORE)
454 report->core++;
455
456 + if (em->maps_per_core)
457 + report->hash_percpu++;
458 + else
459 + report->hash_unique++;
460 +
461 ebpf_stats_targets(report, em->targets);
462 }
463
@@ -596,15 +601,70 @@ void ebpf_update_map_size(struct bpf_map *map, ebpf_local_maps_t *lmap, ebpf_mod
601 #endif
602 }
603
604 +#ifdef LIBBPF_MAJOR_VERSION
605 +/**
606 + * Update map type
607 + *
608 + * Update map type with information given.
609 + *
610 + * @param map the map we want to modify
611 + * @param w a structure with user input
612 + */
613 +void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w)
614 +{
615 + if (bpf_map__set_type(map, w->map_type)) {
616 + error("Cannot modify map type for %s", w->name);
617 + }
618 +}
619 +
620 +/**
621 + * Define map type
622 + *
623 + * This PR defines the type used by hash tables according user input.
624 + *
625 + * @param maps the list of maps used with a hash table.
626 + * @param maps_per_core define if map type according user specification.
627 + * @param kver kernel version host is running.
628 + */
629 +void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver)
630 +{
631 + if (!maps)
632 + return;
633 +
634 + // Before kernel 4.06 there was not percpu hash tables
635 + if (kver < NETDATA_EBPF_KERNEL_4_06)
636 + maps_per_core = CONFIG_BOOLEAN_NO;
637 +
638 + int i = 0;
639 + while (maps[i].name) {
640 + ebpf_local_maps_t *map = &maps[i];
641 + // maps_per_core is a boolean value in configuration files.
642 + if (maps_per_core) {
643 + if (map->map_type == BPF_MAP_TYPE_HASH)
644 + map->map_type = BPF_MAP_TYPE_PERCPU_HASH;
645 + else if (map->map_type == BPF_MAP_TYPE_ARRAY)
646 + map->map_type = BPF_MAP_TYPE_PERCPU_ARRAY;
647 + } else {
648 + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH)
649 + map->map_type = BPF_MAP_TYPE_HASH;
650 + else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
651 + map->map_type = BPF_MAP_TYPE_ARRAY;
652 + }
653 +
654 + i++;
655 + }
656 +}
657 +#endif
658 +
659 /**
600 - * Update Legacy map sizes
660 + * Update Legacy map
661 *
602 - * Update map size for eBPF legacy code.
662 + * Update map for eBPF legacy code.
663 *
664 * @param program the structure with values read from binary.
665 * @param em the structure with information about how the module/thread is working.
666 */
607 -static void ebpf_update_legacy_map_sizes(struct bpf_object *program, ebpf_module_t *em)
667 +static void ebpf_update_legacy_map(struct bpf_object *program, ebpf_module_t *em)
668 {
669 struct bpf_map *map;
670 ebpf_local_maps_t *maps = em->maps;
@@ -614,13 +674,19 @@ static void ebpf_update_legacy_map_sizes(struct bpf_object *program, ebpf_module
674 bpf_map__for_each(map, program)
675 {
676 const char *map_name = bpf_map__name(map);
617 - int i = 0; ;
677 + int i = 0;
678 while (maps[i].name) {
679 ebpf_local_maps_t *w = &maps[i];
620 - if (w->type & NETDATA_EBPF_MAP_RESIZABLE) {
621 - if (!strcmp(w->name, map_name)) {
680 +
681 + if (!strcmp(w->name, map_name)) {
682 + // Modify size
683 + if (w->type & NETDATA_EBPF_MAP_RESIZABLE) {
684 ebpf_update_map_size(map, w, em, map_name);
685 }
686 +
687 +#ifdef LIBBPF_MAJOR_VERSION
688 + ebpf_update_map_type(map, w);
689 +#endif
690 }
691
692 i++;
@@ -796,7 +862,7 @@ struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, int kv
862 return NULL;
863 }
864
799 - ebpf_update_legacy_map_sizes(*obj, em);
865 + ebpf_update_legacy_map(*obj, em);
866
867 if (bpf_object__load(*obj)) {
868 error("ERROR: loading BPF object file failed %s\n", lpath);
@@ -1156,8 +1222,8 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
1222 {
1223 char default_value[EBPF_MAX_MODE_LENGTH + 1];
1224 ebpf_select_mode_string(default_value, EBPF_MAX_MODE_LENGTH, modules->mode);
1159 - char *value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value);
1160 - modules->mode = ebpf_select_mode(value);
1225 + char *load_mode = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_LOAD_MODE, default_value);
1226 + modules->mode = ebpf_select_mode(load_mode);
1227
1228 modules->update_every = (int)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION,
1229 EBPF_CFG_UPDATE_EVERY, modules->update_every);
@@ -1171,19 +1237,38 @@ void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_m
1237 modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
1238 modules->pid_map_size);
1239
1174 - value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
1175 - value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
1176 - netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(value);
1240 + char *value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
1241 + char *type_format = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
1242 + netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(type_format);
1243 load = ebpf_select_load_mode(btf_file, load, kver, is_rh);
1244 modules->load = origin | load;
1245
1180 - value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CORE_ATTACH, EBPF_CFG_ATTACH_TRAMPOLINE);
1181 - netdata_ebpf_program_loaded_t fill_lm = ebpf_convert_core_type(value, modules->mode);
1246 + char *core_attach = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CORE_ATTACH, EBPF_CFG_ATTACH_TRAMPOLINE);
1247 + netdata_ebpf_program_loaded_t fill_lm = ebpf_convert_core_type(core_attach, modules->mode);
1248 ebpf_update_target_with_conf(modules, fill_lm);
1249
1250 value = ebpf_convert_collect_pid_to_string(modules->apps_level);
1185 - value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_COLLECT_PID, value);
1186 - modules->apps_level = ebpf_convert_string_to_apps_level(value);
1251 + char *collect_pid = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_COLLECT_PID, value);
1252 + modules->apps_level = ebpf_convert_string_to_apps_level(collect_pid);
1253 +
1254 + modules->maps_per_core = appconfig_get_boolean(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_MAPS_PER_CORE,
1255 + modules->maps_per_core);
1256 + if (kver < NETDATA_EBPF_KERNEL_4_06)
1257 + modules->maps_per_core = CONFIG_BOOLEAN_NO;
1258 +
1259 +#ifdef NETDATA_DEV_MODE
1260 + info("The thread %s was configured with: mode = %s; update every = %d; apps = %s; cgroup = %s; ebpf type format = %s; ebpf co-re tracing = %s; collect pid = %s; maps per core = %s",
1261 + modules->thread_name,
1262 + load_mode,
1263 + modules->update_every,
1264 + (modules->apps_charts)?"enabled":"disabled",
1265 + (modules->cgroup_charts)?"enabled":"disabled",
1266 + type_format,
1267 + core_attach,
1268 + collect_pid,
1269 + (modules->maps_per_core)?"enabled":"disabled"
1270 + );
1271 +#endif
1272 }
1273
1274 /**
libnetdata/ebpf/ebpf.h
+14
@@ -40,6 +40,8 @@
40
41 #define EBPF_CFG_PROGRAM_PATH "btf path"
42
43 +#define EBPF_CFG_MAPS_PER_CORE "maps per core"
44 +
45 #define EBPF_CFG_UPDATE_EVERY "update every"
46 #define EBPF_CFG_UPDATE_APPS_EVERY_DEFAULT 10
47 #define EBPF_CFG_PID_SIZE "pid table size"
@@ -77,6 +79,7 @@
79 *
80 */
81 enum netdata_ebpf_kernel_versions {
82 + NETDATA_EBPF_KERNEL_4_06 = 263680, // 264960 = 4 * 65536 + 6 * 256
83 NETDATA_EBPF_KERNEL_4_11 = 264960, // 264960 = 4 * 65536 + 15 * 256
84 NETDATA_EBPF_KERNEL_4_14 = 265728, // 264960 = 4 * 65536 + 14 * 256
85 NETDATA_EBPF_KERNEL_4_15 = 265984, // 265984 = 4 * 65536 + 15 * 256
@@ -196,6 +199,9 @@ typedef struct ebpf_local_maps {
199 uint32_t user_input;
200 uint32_t type;
201 int map_fd;
202 +#ifdef LIBBPF_MAJOR_VERSION
203 + enum bpf_map_type map_type;
204 +#endif
205 } ebpf_local_maps_t;
206
207 typedef struct ebpf_specify_name {
@@ -243,6 +249,9 @@ typedef struct ebpf_plugin_stats {
249 uint64_t memlock_kern; // The same information reported by bpftool, but it is not accurated
250 // https://lore.kernel.org/linux-mm/20230112155326.26902-5-laoar.shao@gmail.com/T/
251 uint32_t hash_tables; // Number of hash tables used on the system.
252 +
253 + uint32_t hash_percpu; // Number of threads running per cpu maps
254 + uint32_t hash_unique; // Number of threads running an unique map for all cores.
255 } ebpf_plugin_stats_t;
256
257 typedef enum ebpf_stats_action {
@@ -296,6 +305,7 @@ typedef struct ebpf_module {
305 // charts
306 char memory_usage[NETDATA_EBPF_CHART_MEM_LENGTH];
307 char memory_allocations[NETDATA_EBPF_CHART_MEM_LENGTH];
308 + int maps_per_core;
309 } ebpf_module_t;
310
311 int ebpf_get_kernel_version();
@@ -348,6 +358,7 @@ typedef struct ebpf_filesystem_partitions {
358
359 ebpf_addresses_t addresses;
360 uint64_t kernels;
361 + ebpf_local_maps_t *fs_maps;
362 } ebpf_filesystem_partitions_t;
363
364 typedef struct ebpf_sync_syscalls {
@@ -365,6 +376,7 @@ typedef struct ebpf_sync_syscalls {
376 #else
377 void *sync_obj;
378 #endif
379 + ebpf_local_maps_t *sync_maps;
380 } ebpf_sync_syscalls_t;
381
382 void ebpf_histogram_dimension_cleanup(char **ptr, size_t length);
@@ -391,6 +403,8 @@ void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file);
403 struct btf *ebpf_parse_btf_file(const char *filename);
404 struct btf *ebpf_load_btf_file(char *path, char *filename);
405 int ebpf_is_function_inside_btf(struct btf *file, char *function);
406 +void ebpf_update_map_type(struct bpf_map *map, ebpf_local_maps_t *w);
407 +void ebpf_define_map_type(ebpf_local_maps_t *maps, int maps_per_core, int kver);
408 #endif
409
410 void ebpf_update_kernel_memory_with_vector(ebpf_plugin_stats_t *report, ebpf_local_maps_t *maps);