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);