summaryrefslogtreecommitdiffstats
path: root/collectors/ebpf.plugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--collectors/ebpf.plugin/README.md39
-rw-r--r--collectors/ebpf.plugin/ebpf.c98
-rw-r--r--collectors/ebpf.plugin/ebpf.d.conf12
-rw-r--r--collectors/ebpf.plugin/ebpf.h3
-rw-r--r--collectors/ebpf.plugin/ebpf_cachestat.c139
-rw-r--r--collectors/ebpf.plugin/ebpf_cachestat.h6
-rw-r--r--collectors/ebpf.plugin/ebpf_dcstat.c78
-rw-r--r--collectors/ebpf.plugin/ebpf_dcstat.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_disk.c76
-rw-r--r--collectors/ebpf.plugin/ebpf_disk.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_fd.c145
-rw-r--r--collectors/ebpf.plugin/ebpf_fd.h13
-rw-r--r--collectors/ebpf.plugin/ebpf_filesystem.c75
-rw-r--r--collectors/ebpf.plugin/ebpf_filesystem.h1
-rw-r--r--collectors/ebpf.plugin/ebpf_hardirq.c77
-rw-r--r--collectors/ebpf.plugin/ebpf_hardirq.h1
-rw-r--r--collectors/ebpf.plugin/ebpf_mdflush.c84
-rw-r--r--collectors/ebpf.plugin/ebpf_mdflush.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_mount.c85
-rw-r--r--collectors/ebpf.plugin/ebpf_mount.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_oomkill.c11
-rw-r--r--collectors/ebpf.plugin/ebpf_oomkill.h1
-rw-r--r--collectors/ebpf.plugin/ebpf_process.c72
-rw-r--r--collectors/ebpf.plugin/ebpf_process.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_shm.c82
-rw-r--r--collectors/ebpf.plugin/ebpf_shm.h2
-rw-r--r--collectors/ebpf.plugin/ebpf_socket.c247
-rw-r--r--collectors/ebpf.plugin/ebpf_socket.h3
-rw-r--r--collectors/ebpf.plugin/ebpf_softirq.c79
-rw-r--r--collectors/ebpf.plugin/ebpf_softirq.h1
-rw-r--r--collectors/ebpf.plugin/ebpf_swap.c79
-rw-r--r--collectors/ebpf.plugin/ebpf_sync.c81
-rw-r--r--collectors/ebpf.plugin/ebpf_vfs.c81
-rw-r--r--collectors/ebpf.plugin/ebpf_vfs.h2
34 files changed, 474 insertions, 1209 deletions
diff --git a/collectors/ebpf.plugin/README.md b/collectors/ebpf.plugin/README.md
index 7762ed34..deedf4d7 100644
--- a/collectors/ebpf.plugin/README.md
+++ b/collectors/ebpf.plugin/README.md
@@ -1,9 +1,11 @@
<!--
-title: "eBPF monitoring with Netdata"
-description: "Use Netdata's extended Berkeley Packet Filter (eBPF) collector to monitor kernel-level metrics about your
-complex applications with per-second granularity."
-custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/ebpf.plugin/README.md
-sidebar_label: "eBPF"
+title: "Kernel traces/metrics (eBPF) monitoring with Netdata"
+description: "Use Netdata's extended Berkeley Packet Filter (eBPF) collector to monitor kernel-level metrics about yourcomplex applications with per-second granularity."
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/collectors/ebpf.plugin/README.md"
+sidebar_label: "Kernel traces/metrics (eBPF)"
+learn_status: "Published"
+learn_topic_type: "References"
+learn_rel_path: "References/Collectors references/System metrics"
-->
# eBPF monitoring with Netdata
@@ -13,7 +15,7 @@ The Netdata Agent provides many [eBPF](https://ebpf.io/what-is-ebpf/) programs t
> ❗ eBPF monitoring only works on Linux systems and with specific Linux kernels, including all kernels newer than `4.11.0`, and all kernels on CentOS 7.6 or later. For kernels older than `4.11.0`, improved support is in active development.
This document provides comprehensive details about the `ebpf.plugin`.
-For hands-on configuration and troubleshooting tips see our [tutorial on troubleshooting apps with eBPF metrics](/docs/guides/troubleshoot/monitor-debug-applications-ebpf.md).
+For hands-on configuration and troubleshooting tips see our [tutorial on troubleshooting apps with eBPF metrics](https://github.com/netdata/netdata/blob/master/docs/guides/troubleshoot/monitor-debug-applications-ebpf.md).
<figure>
<img src="https://user-images.githubusercontent.com/1153921/74746434-ad6a1e00-5222-11ea-858a-a7882617ae02.png" alt="An example of VFS charts, made possible by the eBPF collector plugin" />
@@ -42,12 +44,12 @@ If your Agent is v1.22 or older, you may to enable the collector yourself.
To enable or disable the entire eBPF collector:
-1. Navigate to the [Netdata config directory](/docs/configure/nodes.md#the-netdata-config-directory).
+1. Navigate to the [Netdata config directory](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#the-netdata-config-directory).
```bash
cd /etc/netdata
```
-2. Use the [`edit-config`](/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit `netdata.conf`.
+2. Use the [`edit-config`](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit `netdata.conf`.
```bash
./edit-config netdata.conf
@@ -67,11 +69,11 @@ You can configure the eBPF collector's behavior to fine-tune which metrics you r
To edit the `ebpf.d.conf`:
-1. Navigate to the [Netdata config directory](/docs/configure/nodes.md#the-netdata-config-directory).
+1. Navigate to the [Netdata config directory](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#the-netdata-config-directory).
```bash
cd /etc/netdata
```
-2. Use the [`edit-config`](/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit [`ebpf.d.conf`](https://github.com/netdata/netdata/blob/master/collectors/ebpf.plugin/ebpf.d.conf).
+2. Use the [`edit-config`](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit [`ebpf.d.conf`](https://github.com/netdata/netdata/blob/master/collectors/ebpf.plugin/ebpf.d.conf).
```bash
./edit-config ebpf.d.conf
@@ -103,11 +105,10 @@ accepts the following values:
#### Integration with `apps.plugin`
The eBPF collector also creates charts for each running application through an integration with the
-[`apps.plugin`](/collectors/apps.plugin/README.md). This integration helps you understand how specific applications
+[`apps.plugin`](https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/README.md). This integration helps you understand how specific applications
interact with the Linux kernel.
-If you want to _disable_ the integration with `apps.plugin` along with the above charts, change the setting `apps` to
-`no`.
+If you want to enable `apps.plugin` integration, change the "apps" setting to "yes".
```conf
[global]
@@ -122,7 +123,7 @@ it runs.
#### Integration with `cgroups.plugin`
The eBPF collector also creates charts for each cgroup through an integration with the
-[`cgroups.plugin`](/collectors/cgroups.plugin/README.md). This integration helps you understand how a specific cgroup
+[`cgroups.plugin`](https://github.com/netdata/netdata/blob/master/collectors/cgroups.plugin/README.md). This integration helps you understand how a specific cgroup
interacts with the Linux kernel.
The integration with `cgroups.plugin` is disabled by default to avoid creating overhead on your system. If you want to
@@ -244,7 +245,7 @@ The eBPF collector enables and runs the following eBPF programs by default:
You can also enable the following eBPF programs:
- `cachestat`: Netdata's eBPF data collector creates charts about the memory page cache. When the integration with
- [`apps.plugin`](/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
+ [`apps.plugin`](https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/README.md) is enabled, this collector creates charts for the whole host _and_
for each application.
- `dcstat` : This eBPF program creates charts that show information about file access using directory cache. It appends
`kprobes` for `lookup_fast()` and `d_lookup()` to identify if files are inside directory cache, outside and files are
@@ -261,11 +262,11 @@ You can configure each thread of the eBPF data collector. This allows you to ove
To configure an eBPF thread:
-1. Navigate to the [Netdata config directory](/docs/configure/nodes.md#the-netdata-config-directory).
+1. Navigate to the [Netdata config directory](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#the-netdata-config-directory).
```bash
cd /etc/netdata
```
-2. Use the [`edit-config`](/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit a thread configuration file. The following configuration files are available:
+2. Use the [`edit-config`](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) script to edit a thread configuration file. The following configuration files are available:
- `network.conf`: Configuration for the [`network` thread](#network-configuration). This config file overwrites the global options and also
lets you specify which network the eBPF collector monitors.
@@ -304,7 +305,7 @@ You can configure the information shown on `outbound` and `inbound` charts with
When you define a `ports` setting, Netdata will collect network metrics for that specific port. For example, if you
write `ports = 19999`, Netdata will collect only connections for itself. The `hostnames` setting accepts
-[simple patterns](/libnetdata/simple_pattern/README.md). The `ports`, and `ips` settings accept negation (`!`) to deny
+[simple patterns](https://github.com/netdata/netdata/blob/master/libnetdata/simple_pattern/README.md). The `ports`, and `ips` settings accept negation (`!`) to deny
specific values or asterisk alone to define all values.
In the above example, Netdata will collect metrics for all ports between 1 and 443, with the exception of 53 (domain)
@@ -881,7 +882,7 @@ significantly increases kernel memory usage by several hundred MB.
If your node is experiencing high memory usage and there is no obvious culprit to be found in the `apps.mem` chart,
consider testing for high kernel memory usage by [disabling eBPF monitoring](#configuring-ebpfplugin). Next,
-[restart Netdata](/docs/configure/start-stop-restart.md) with `sudo systemctl restart netdata` to see if system memory
+[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
usage (see the `system.ram` chart) has dropped significantly.
Beginning with `v1.31`, kernel memory usage is configurable via the [`pid table size` setting](#ebpf-load-mode)
diff --git a/collectors/ebpf.plugin/ebpf.c b/collectors/ebpf.plugin/ebpf.c
index 00b53a57..67fe477c 100644
--- a/collectors/ebpf.plugin/ebpf.c
+++ b/collectors/ebpf.plugin/ebpf.c
@@ -483,6 +483,16 @@ static void ebpf_exit()
if (unlink(filename))
error("Cannot remove PID file %s", filename);
+#ifdef NETDATA_INTERNAL_CHECKS
+ error("Good bye world! I was PID %d", main_thread_id);
+#endif
+ printf("DISABLE\n");
+
+ if (shm_ebpf_cgroup.header) {
+ munmap(shm_ebpf_cgroup.header, shm_ebpf_cgroup.header->body_length);
+ shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME);
+ }
+
exit(0);
}
@@ -534,7 +544,7 @@ static void ebpf_stop_threads(int sig)
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_exit_plugin = 1;
- usec_t max = 3 * USEC_PER_SEC, step = 100000;
+ usec_t max = USEC_PER_SEC, step = 100000;
while (i && max) {
max -= step;
sleep_usec(step);
@@ -548,32 +558,35 @@ static void ebpf_stop_threads(int sig)
pthread_mutex_unlock(&ebpf_exit_cleanup);
}
- //Unload threads(except sync and filesystem)
- pthread_mutex_lock(&ebpf_exit_cleanup);
- for (i = 0; ebpf_threads[i].name != NULL; i++) {
- if (ebpf_threads[i].enabled == NETDATA_THREAD_EBPF_STOPPED && i != EBPF_MODULE_FILESYSTEM_IDX &&
- i != EBPF_MODULE_SYNC_IDX)
- ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links);
- }
- pthread_mutex_unlock(&ebpf_exit_cleanup);
+ if (!i) {
+ //Unload threads(except sync and filesystem)
+ pthread_mutex_lock(&ebpf_exit_cleanup);
+ for (i = 0; ebpf_threads[i].name != NULL; i++) {
+ if (ebpf_threads[i].enabled == NETDATA_THREAD_EBPF_STOPPED && i != EBPF_MODULE_FILESYSTEM_IDX &&
+ i != EBPF_MODULE_SYNC_IDX)
+ ebpf_unload_legacy_code(ebpf_modules[i].objects, ebpf_modules[i].probe_links);
+ }
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
- //Unload filesystem
- pthread_mutex_lock(&ebpf_exit_cleanup);
- if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
- for (i = 0; localfs[i].filesystem != NULL; i++) {
- ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links);
+ //Unload filesystem
+ pthread_mutex_lock(&ebpf_exit_cleanup);
+ if (ebpf_threads[EBPF_MODULE_FILESYSTEM_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
+ for (i = 0; localfs[i].filesystem != NULL; i++) {
+ ebpf_unload_legacy_code(localfs[i].objects, localfs[i].probe_links);
+ }
}
- }
- pthread_mutex_unlock(&ebpf_exit_cleanup);
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
- //Unload Sync
- pthread_mutex_lock(&ebpf_exit_cleanup);
- if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
- for (i = 0; local_syscalls[i].syscall != NULL; i++) {
- ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links);
+ //Unload Sync
+ pthread_mutex_lock(&ebpf_exit_cleanup);
+ if (ebpf_threads[EBPF_MODULE_SYNC_IDX].enabled == NETDATA_THREAD_EBPF_STOPPED) {
+ for (i = 0; local_syscalls[i].syscall != NULL; i++) {
+ ebpf_unload_legacy_code(local_syscalls[i].objects, local_syscalls[i].probe_links);
+ }
}
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
+
}
- pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_exit();
}
@@ -1317,7 +1330,7 @@ static void read_local_addresses()
}
}
- fill_ip_list((family == AF_INET)?&network_viewer_opt.ipv4_local_ip:&network_viewer_opt.ipv6_local_ip,
+ ebpf_fill_ip_list((family == AF_INET)?&network_viewer_opt.ipv4_local_ip:&network_viewer_opt.ipv6_local_ip,
w,
"selector");
}
@@ -1520,13 +1533,8 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION,
ebpf_modules[EBPF_MODULE_SOCKET_IDX].config_name,
CONFIG_BOOLEAN_NO);
-
if (enabled) {
ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps, *disable_cgroups);
- // Read network viewer section if network viewer is enabled
- // This is kept here to keep backward compatibility
- parse_network_viewer_section(&collector_config);
- parse_service_name_section(&collector_config);
started++;
}
@@ -1536,7 +1544,17 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
if (!enabled)
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "network connections",
CONFIG_BOOLEAN_NO);
- ebpf_modules[EBPF_MODULE_SOCKET_IDX].optional = (int)enabled;
+ network_viewer_opt.enabled = enabled;
+ if (enabled) {
+ if (!ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled)
+ ebpf_enable_chart(EBPF_MODULE_SOCKET_IDX, *disable_apps, *disable_cgroups);
+
+ // Read network viewer section if network viewer is enabled
+ // This is kept here to keep backward compatibility
+ parse_network_viewer_section(&collector_config);
+ parse_service_name_section(&collector_config);
+ started++;
+ }
enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "cachestat",
CONFIG_BOOLEAN_NO);
@@ -1642,8 +1660,10 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups,
ebpf_enable_all_charts(*disable_apps, *disable_cgroups);
// Read network viewer section
// This is kept here to keep backward compatibility
- parse_network_viewer_section(&collector_config);
- parse_service_name_section(&collector_config);
+ if (network_viewer_opt.enabled) {
+ parse_network_viewer_section(&collector_config);
+ parse_service_name_section(&collector_config);
+ }
}
}
@@ -2158,6 +2178,7 @@ static void ebpf_manage_pid(pid_t pid)
*/
int main(int argc, char **argv)
{
+ stderror = stderr;
clocks_init();
main_thread_id = gettid();
@@ -2237,13 +2258,26 @@ int main(int argc, char **argv)
}
}
- usec_t step = EBPF_DEFAULT_UPDATE_EVERY * USEC_PER_SEC;
+ usec_t step = USEC_PER_SEC;
+ int counter = NETDATA_EBPF_CGROUP_UPDATE - 1;
heartbeat_t hb;
heartbeat_init(&hb);
//Plugin will be killed when it receives a signal
while (!ebpf_exit_plugin) {
(void)heartbeat_next(&hb, step);
+
+ // We are using a small heartbeat time to wake up thread,
+ // but we should not update so frequently the shared memory data
+ if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) {
+ counter = 0;
+ if (!shm_ebpf_cgroup.header)
+ ebpf_map_cgroup_shared_memory();
+
+ ebpf_parse_cgroup_shm_data();
+ }
}
+ ebpf_stop_threads(0);
+
return 0;
}
diff --git a/collectors/ebpf.plugin/ebpf.d.conf b/collectors/ebpf.plugin/ebpf.d.conf
index cf5c740f..112df275 100644
--- a/collectors/ebpf.plugin/ebpf.d.conf
+++ b/collectors/ebpf.plugin/ebpf.d.conf
@@ -17,7 +17,7 @@
#
[global]
ebpf load mode = entry
- apps = yes
+ apps = no
cgroups = no
update every = 5
pid table size = 32768
@@ -50,7 +50,7 @@
# When plugin detects that system has support to BTF, it enables integration with apps.plugin.
#
[ebpf programs]
- cachestat = no
+ cachestat = yes
dcstat = no
disk = no
fd = yes
@@ -60,10 +60,10 @@
mount = yes
oomkill = yes
process = yes
- shm = no
- socket = yes
+ shm = yes
+ socket = no
softirq = yes
sync = yes
- swap = no
- vfs = yes
+ swap = yes
+ vfs = no
network connections = no
diff --git a/collectors/ebpf.plugin/ebpf.h b/collectors/ebpf.plugin/ebpf.h
index 28b04ce4..16e62498 100644
--- a/collectors/ebpf.plugin/ebpf.h
+++ b/collectors/ebpf.plugin/ebpf.h
@@ -123,6 +123,9 @@ enum ebpf_threads_status {
#endif
#endif
+// Messages
+#define NETDATA_EBPF_DEFAULT_FNT_NOT_FOUND "Cannot find the necessary functions to monitor"
+
// Chart definitions
#define NETDATA_EBPF_FAMILY "ebpf"
#define NETDATA_EBPF_IP_FAMILY "ip"
diff --git a/collectors/ebpf.plugin/ebpf_cachestat.c b/collectors/ebpf.plugin/ebpf_cachestat.c
index 4c410647..b21cc610 100644
--- a/collectors/ebpf.plugin/ebpf_cachestat.c
+++ b/collectors/ebpf.plugin/ebpf_cachestat.c
@@ -15,15 +15,6 @@ netdata_cachestat_pid_t *cachestat_vector = NULL;
static netdata_idx_t cachestat_hash_values[NETDATA_CACHESTAT_END];
static netdata_idx_t *cachestat_values = NULL;
-struct netdata_static_thread cachestat_threads = {.name = "CACHESTAT KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL};
-
ebpf_local_maps_t cachestat_maps[] = {{.name = "cstat_global", .internal_input = NETDATA_CACHESTAT_END,
.user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
@@ -51,6 +42,9 @@ netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru",
{.name = "mark_buffer_dirty", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
+static char *account_page[NETDATA_CACHESTAT_ACCOUNT_DIRTY_END] ={ "account_page_dirtied",
+ "__set_page_dirty", "__folio_mark_dirty" };
+
#ifdef LIBBPF_MAJOR_VERSION
#include "includes/cachestat.skel.h" // BTF code
@@ -83,10 +77,12 @@ static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj)
*/
static void ebpf_cachestat_disable_specific_probe(struct cachestat_bpf *obj)
{
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
+ if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_FOLIO_DIRTY])) {
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
- } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
+ } else if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY])) {
bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
} else {
@@ -122,10 +118,12 @@ static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj)
*/
static void ebpf_cachestat_disable_specific_trampoline(struct cachestat_bpf *obj)
{
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
+ if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_FOLIO_DIRTY])) {
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
- } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
+ } else if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY])) {
bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
} else {
@@ -149,10 +147,12 @@ static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj)
bpf_program__set_attach_target(obj->progs.netdata_mark_page_accessed_fentry, 0,
cachestat_targets[NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED].name);
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
+ if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_FOLIO_DIRTY])) {
bpf_program__set_attach_target(obj->progs.netdata_folio_mark_dirty_fentry, 0,
cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
- } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
+ } else if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY])) {
bpf_program__set_attach_target(obj->progs.netdata_set_page_dirty_fentry, 0,
cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
} else {
@@ -192,12 +192,14 @@ static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
if (ret)
return -1;
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
+ if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_FOLIO_DIRTY])) {
obj->links.netdata_folio_mark_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_folio_mark_dirty_kprobe,
false,
cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
ret = libbpf_get_error(obj->links.netdata_folio_mark_dirty_kprobe);
- } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
+ } else if (!strcmp(cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name,
+ account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY])) {
obj->links.netdata_set_page_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_set_page_dirty_kprobe,
false,
cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
@@ -278,7 +280,7 @@ static void ebpf_cachestat_disable_release_task(struct cachestat_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf_module_t *em)
{
@@ -331,18 +333,13 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
static void ebpf_cachestat_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_cleanup_publish_syscall(cachestat_counter_publish_aggregated);
freez(cachestat_vector);
freez(cachestat_values);
- freez(cachestat_threads.thread);
#ifdef LIBBPF_MAJOR_VERSION
if (bpf_obj)
@@ -363,20 +360,7 @@ static void ebpf_cachestat_free(ebpf_module_t *em)
static void ebpf_cachestat_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*cachestat_threads.thread);
- ebpf_cachestat_free(em);
-}
-/**
- * Cachestat cleanup
- *
- * Clean up allocated addresses.
- *
- * @param ptr thread data.
- */
-static void ebpf_cachestat_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_cachestat_free(em);
}
@@ -656,7 +640,7 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_cachestat_read_global_table()
{
uint32_t idx;
netdata_idx_t *val = cachestat_hash_values;
@@ -677,35 +661,6 @@ static void read_global_table()
}
/**
- * Socket read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_cachestat_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_cachestat_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_LATENCY_CACHESTAT_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Send global
*
* Send global charts to Netdata
@@ -1106,26 +1061,23 @@ void ebpf_cachestat_send_cgroup_data(int update_every)
*/
static void cachestat_collector(ebpf_module_t *em)
{
- cachestat_threads.thread = callocz(1, sizeof(netdata_thread_t));
- cachestat_threads.start_routine = ebpf_cachestat_read_hash;
-
- netdata_thread_create(cachestat_threads.thread, cachestat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_cachestat_read_hash, em);
-
netdata_publish_cachestat_t publish;
memset(&publish, 0, sizeof(publish));
int cgroups = em->cgroup_charts;
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
//This will be cancelled by its parent
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_cachestat_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps)
read_apps_table();
@@ -1237,16 +1189,28 @@ static void ebpf_cachestat_allocate_global_vectors(int apps)
* Update Internal value
*
* Update values used during runtime.
+ *
+ * @return It returns 0 when one of the functions is present and -1 otherwise.
*/
-static void ebpf_cachestat_set_internal_value()
+static int ebpf_cachestat_set_internal_value()
{
- static char *account_page[] = { "account_page_dirtied", "__set_page_dirty", "__folio_mark_dirty" };
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16)
- cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_FOLIO_DIRTY];
- else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15)
- cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY];
- else
- cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY];
+ ebpf_addresses_t address = {.function = NULL, .hash = 0, .addr = 0};
+ int i;
+ for (i = 0; i < NETDATA_CACHESTAT_ACCOUNT_DIRTY_END ; i++) {
+ address.function = account_page[i];
+ ebpf_load_addresses(&address, -1);
+ if (address.addr)
+ break;
+ }
+
+ if (!address.addr) {
+ error("%s cachestat.", NETDATA_EBPF_DEFAULT_FNT_NOT_FOUND);
+ return -1;
+ }
+
+ cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = address.function;
+
+ return 0;
}
/*
@@ -1300,7 +1264,10 @@ void *ebpf_cachestat_thread(void *ptr)
ebpf_update_pid_table(&cachestat_maps[NETDATA_CACHESTAT_PID_STATS], em);
- ebpf_cachestat_set_internal_value();
+ if (ebpf_cachestat_set_internal_value()) {
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
+ goto endcachestat;
+ }
#ifdef LIBBPF_MAJOR_VERSION
ebpf_adjust_thread_load(em, default_btf);
diff --git a/collectors/ebpf.plugin/ebpf_cachestat.h b/collectors/ebpf.plugin/ebpf_cachestat.h
index 07f0745d..15b06511 100644
--- a/collectors/ebpf.plugin/ebpf_cachestat.h
+++ b/collectors/ebpf.plugin/ebpf_cachestat.h
@@ -19,8 +19,6 @@
#define EBPF_CACHESTAT_DIMENSION_HITS "hits/s"
#define EBPF_CACHESTAT_DIMENSION_MISSES "misses/s"
-#define NETDATA_LATENCY_CACHESTAT_SLEEP_MS 600000ULL
-
// configuration file
#define NETDATA_CACHESTAT_CONFIG_FILE "cachestat.conf"
@@ -48,7 +46,9 @@ enum cachestat_counters {
enum cachestat_account_dirty_pages {
NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY,
NETDATA_CACHESTAT_SET_PAGE_DIRTY,
- NETDATA_CACHESTAT_FOLIO_DIRTY
+ NETDATA_CACHESTAT_FOLIO_DIRTY,
+
+ NETDATA_CACHESTAT_ACCOUNT_DIRTY_END
};
enum cachestat_indexes {
diff --git a/collectors/ebpf.plugin/ebpf_dcstat.c b/collectors/ebpf.plugin/ebpf_dcstat.c
index 71169e15..75e83214 100644
--- a/collectors/ebpf.plugin/ebpf_dcstat.c
+++ b/collectors/ebpf.plugin/ebpf_dcstat.c
@@ -19,15 +19,6 @@ struct config dcstat_config = { .first_section = NULL,
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
-struct netdata_static_thread dcstat_threads = {"DCSTAT KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL};
-
ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
.user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
@@ -216,7 +207,7 @@ static void ebpf_dc_disable_release_task(struct dc_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
{
@@ -303,16 +294,11 @@ void ebpf_dcstat_clean_names()
static void ebpf_dcstat_free(ebpf_module_t *em )
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
freez(dcstat_vector);
freez(dcstat_values);
- freez(dcstat_threads.thread);
ebpf_cleanup_publish_syscall(dcstat_counter_publish_aggregated);
@@ -338,18 +324,6 @@ static void ebpf_dcstat_free(ebpf_module_t *em )
static void ebpf_dcstat_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*dcstat_threads.thread);
- ebpf_dcstat_free(em);
-}
-
-/**
- * Clean up the main thread.
- *
- * @param ptr thread data.
- */
-static void ebpf_dcstat_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_dcstat_free(em);
}
@@ -538,7 +512,7 @@ static void ebpf_update_dc_cgroup()
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_dc_read_global_table()
{
uint32_t idx;
netdata_idx_t *val = dcstat_hash_values;
@@ -559,35 +533,6 @@ static void read_global_table()
}
/**
- * DCstat read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_dcstat_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_dcstat_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_LATENCY_DCSTAT_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Cachestat sum PIDs
*
* Sum values for all PIDs associated to a group
@@ -1034,25 +979,22 @@ void ebpf_dc_send_cgroup_data(int update_every)
*/
static void dcstat_collector(ebpf_module_t *em)
{
- dcstat_threads.thread = mallocz(sizeof(netdata_thread_t));
- dcstat_threads.start_routine = ebpf_dcstat_read_hash;
-
- netdata_thread_create(dcstat_threads.thread, dcstat_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_dcstat_read_hash, em);
-
netdata_publish_dcstat_t publish;
memset(&publish, 0, sizeof(publish));
int cgroups = em->cgroup_charts;
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_dc_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps)
read_apps_table();
diff --git a/collectors/ebpf.plugin/ebpf_dcstat.h b/collectors/ebpf.plugin/ebpf_dcstat.h
index d8687f96..201fc8a0 100644
--- a/collectors/ebpf.plugin/ebpf_dcstat.h
+++ b/collectors/ebpf.plugin/ebpf_dcstat.h
@@ -28,8 +28,6 @@
#define NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT "services.dc_not_cache"
#define NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT "services.dc_not_found"
-#define NETDATA_LATENCY_DCSTAT_SLEEP_MS 700000ULL
-
enum directory_cache_indexes {
NETDATA_DCSTAT_IDX_RATIO,
NETDATA_DCSTAT_IDX_REFERENCE,
diff --git a/collectors/ebpf.plugin/ebpf_disk.c b/collectors/ebpf.plugin/ebpf_disk.c
index a27bd81e..5e7e2599 100644
--- a/collectors/ebpf.plugin/ebpf_disk.c
+++ b/collectors/ebpf.plugin/ebpf_disk.c
@@ -33,16 +33,6 @@ static netdata_syscall_stat_t disk_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
static netdata_publish_syscall_t disk_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
static netdata_idx_t *disk_hash_values = NULL;
-static struct netdata_static_thread disk_threads = {
- .name = "DISK KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
ebpf_publish_disk_t *plot_disks = NULL;
pthread_mutex_t plot_mutex;
@@ -439,11 +429,7 @@ static void ebpf_cleanup_disk_list()
static void ebpf_disk_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_disk_disable_tracepoints();
@@ -452,7 +438,6 @@ static void ebpf_disk_free(ebpf_module_t *em)
ebpf_histogram_dimension_cleanup(dimensions, NETDATA_EBPF_HIST_MAX_BINS);
freez(disk_hash_values);
- freez(disk_threads.thread);
pthread_mutex_destroy(&plot_mutex);
ebpf_cleanup_plot_disks();
@@ -473,20 +458,6 @@ static void ebpf_disk_free(ebpf_module_t *em)
static void ebpf_disk_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*disk_threads.thread);
- ebpf_disk_free(em);
-}
-
-/**
- * Disk Cleanup
- *
- * Clean up allocated memory.
- *
- * @param ptr thread data.
- */
-static void ebpf_disk_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_disk_free(em);
}
@@ -592,35 +563,6 @@ static void read_hard_disk_tables(int table)
}
/**
- * Disk read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_disk_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_disk_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_LATENCY_DISK_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Obsolete Hard Disk charts
*
* Make Hard disk charts and fill chart name
@@ -743,21 +685,19 @@ static void ebpf_latency_send_hd_data(int update_every)
static void disk_collector(ebpf_module_t *em)
{
disk_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
- disk_threads.thread = mallocz(sizeof(netdata_thread_t));
- disk_threads.start_routine = ebpf_disk_read_hash;
-
- netdata_thread_create(disk_threads.thread, disk_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_disk_read_hash, em);
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ read_hard_disk_tables(disk_maps[NETDATA_DISK_READ].map_fd);
pthread_mutex_lock(&lock);
ebpf_remove_pointer_from_plot_disk(em);
ebpf_latency_send_hd_data(update_every);
diff --git a/collectors/ebpf.plugin/ebpf_disk.h b/collectors/ebpf.plugin/ebpf_disk.h
index c14b887f..c606d659 100644
--- a/collectors/ebpf.plugin/ebpf_disk.h
+++ b/collectors/ebpf.plugin/ebpf_disk.h
@@ -11,8 +11,6 @@
#define NETDATA_EBPF_PROC_PARTITIONS "/proc/partitions"
-#define NETDATA_LATENCY_DISK_SLEEP_MS 650000ULL
-
// Process configuration name
#define NETDATA_DISK_CONFIG_FILE "disk.conf"
diff --git a/collectors/ebpf.plugin/ebpf_fd.c b/collectors/ebpf.plugin/ebpf_fd.c
index 30b7f22c..79537066 100644
--- a/collectors/ebpf.plugin/ebpf_fd.c
+++ b/collectors/ebpf.plugin/ebpf_fd.c
@@ -6,6 +6,9 @@
static char *fd_dimension_names[NETDATA_FD_SYSCALL_END] = { "open", "close" };
static char *fd_id_names[NETDATA_FD_SYSCALL_END] = { "do_sys_open", "__close_fd" };
+static char *close_targets[NETDATA_EBPF_MAX_FD_TARGETS] = {"close_fd", "__close_fd"};
+static char *open_targets[NETDATA_EBPF_MAX_FD_TARGETS] = {"do_sys_openat2", "do_sys_open"};
+
static netdata_syscall_stat_t fd_aggregated_data[NETDATA_FD_SYSCALL_END];
static netdata_publish_syscall_t fd_publish_aggregated[NETDATA_FD_SYSCALL_END];
@@ -29,15 +32,6 @@ struct config fd_config = { .first_section = NULL, .last_section = NULL, .mutex
.index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
-struct netdata_static_thread fd_thread = {"FD KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL};
-
static netdata_idx_t fd_hash_values[NETDATA_FD_COUNTER];
static netdata_idx_t *fd_values = NULL;
@@ -65,7 +59,7 @@ static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false);
bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false);
bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
+ if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
@@ -85,7 +79,7 @@ static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
*/
static inline void ebpf_disable_specific_probes(struct fd_bpf *obj)
{
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
+ if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
} else {
@@ -121,7 +115,7 @@ static inline void ebpf_disable_trampoline(struct fd_bpf *obj)
*/
static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj)
{
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
+ if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
} else {
@@ -143,7 +137,7 @@ static void ebpf_set_trampoline_target(struct fd_bpf *obj)
bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
+ if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
bpf_program__set_attach_target(
obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
@@ -185,7 +179,7 @@ static int ebpf_fd_attach_probe(struct fd_bpf *obj)
if (ret)
return -1;
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
+ if (!strcmp(fd_targets[NETDATA_FD_SYSCALL_CLOSE].name, close_targets[NETDATA_FD_CLOSE_FD])) {
obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true,
fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe);
@@ -217,24 +211,50 @@ static int ebpf_fd_attach_probe(struct fd_bpf *obj)
}
/**
- * Set target values
+ * FD Fill Address
*
- * Set pointers used to laod data.
+ * Fill address value used to load probes/trampoline.
*/
-static void ebpf_fd_set_target_values()
+static inline void ebpf_fd_fill_address(ebpf_addresses_t *address, char **targets)
{
- static char *close_targets[] = {"close_fd", "__close_fd"};
- static char *open_targets[] = {"do_sys_openat2", "do_sys_open"};
- if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
- fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[0];
- fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[0];
- } else {
- fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[1];
- fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[1];
+ int i;
+ for (i = 0; i < NETDATA_EBPF_MAX_FD_TARGETS; i++) {
+ address->function = targets[i];
+ ebpf_load_addresses(address, -1);
+ if (address->addr)
+ break;
}
}
/**
+ * Set target values
+ *
+ * Set pointers used to load data.
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+static int ebpf_fd_set_target_values()
+{
+ ebpf_addresses_t address = {.function = NULL, .hash = 0, .addr = 0};
+ ebpf_fd_fill_address(&address, close_targets);
+
+ if (!address.addr)
+ return -1;
+
+ fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = address.function;
+
+ address.addr = 0;
+ ebpf_fd_fill_address(&address, open_targets);
+
+ if (!address.addr)
+ return -1;
+
+ fd_targets[NETDATA_FD_SYSCALL_OPEN].name = address.function;
+
+ return 0;
+}
+
+/**
* Set hash tables
*
* Set the values for maps according the value given by kernel.
@@ -283,14 +303,18 @@ static void ebpf_fd_disable_release_task(struct fd_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
{
netdata_ebpf_targets_t *mt = em->targets;
netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode;
- ebpf_fd_set_target_values();
+ if (ebpf_fd_set_target_values()) {
+ error("%s file descriptor.", NETDATA_EBPF_DEFAULT_FNT_NOT_FOUND);
+ return -1;
+ }
+
if (test == EBPF_LOAD_TRAMPOLINE) {
ebpf_fd_disable_probes(obj);
ebpf_disable_specific_trampoline(obj);
@@ -340,15 +364,10 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
static void ebpf_fd_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_cleanup_publish_syscall(fd_publish_aggregated);
- freez(fd_thread.thread);
freez(fd_values);
freez(fd_vector);
@@ -372,18 +391,6 @@ static void ebpf_fd_free(ebpf_module_t *em)
static void ebpf_fd_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*fd_thread.thread);
- ebpf_fd_free(em);
-}
-
-/**
- * Clean up the main thread.
- *
- * @param ptr thread data.
- */
-static void ebpf_fd_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_fd_free(em);
}
@@ -420,7 +427,7 @@ static void ebpf_fd_send_data(ebpf_module_t *em)
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_fd_read_global_table()
{
uint32_t idx;
netdata_idx_t *val = fd_hash_values;
@@ -441,34 +448,6 @@ static void read_global_table()
}
/**
- * File descriptor read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_fd_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_fd_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- usec_t step = NETDATA_FD_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Apps Accumulator
*
* Sum all values read from kernel and store in the first address.
@@ -942,22 +921,20 @@ static void ebpf_fd_send_cgroup_data(ebpf_module_t *em)
*/
static void fd_collector(ebpf_module_t *em)
{
- fd_thread.thread = mallocz(sizeof(netdata_thread_t));
- fd_thread.start_routine = ebpf_fd_read_hash;
-
- netdata_thread_create(fd_thread.thread, fd_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_fd_read_hash, em);
-
int cgroups = em->cgroup_charts;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_fd_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps)
read_apps_table();
diff --git a/collectors/ebpf.plugin/ebpf_fd.h b/collectors/ebpf.plugin/ebpf_fd.h
index 914a34b9..e6545d79 100644
--- a/collectors/ebpf.plugin/ebpf_fd.h
+++ b/collectors/ebpf.plugin/ebpf_fd.h
@@ -6,8 +6,6 @@
// Module name
#define NETDATA_EBPF_MODULE_NAME_FD "filedescriptor"
-#define NETDATA_FD_SLEEP_MS 850000ULL
-
// Menu group
#define NETDATA_FILE_GROUP "file_access"
@@ -36,9 +34,6 @@
#define NETDATA_SYSTEMD_FD_CLOSE_ERR_CONTEXT "services.fd_close_error"
typedef struct netdata_fd_stat {
- uint64_t pid_tgid; // Unique identifier
- uint32_t pid; // Process ID
-
uint32_t open_call; // Open syscalls (open and openat)
uint32_t close_call; // Close syscall (close)
@@ -74,6 +69,14 @@ enum fd_syscalls {
NETDATA_FD_SYSCALL_END
};
+enum fd_close_syscall {
+ NETDATA_FD_CLOSE_FD,
+ NETDATA_FD___CLOSE_FD,
+
+ NETDATA_FD_CLOSE_END
+};
+
+#define NETDATA_EBPF_MAX_FD_TARGETS 2
void *ebpf_fd_thread(void *ptr);
void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr);
diff --git a/collectors/ebpf.plugin/ebpf_filesystem.c b/collectors/ebpf.plugin/ebpf_filesystem.c
index 7dbec741..5250ed8a 100644
--- a/collectors/ebpf.plugin/ebpf_filesystem.c
+++ b/collectors/ebpf.plugin/ebpf_filesystem.c
@@ -30,17 +30,6 @@ static ebpf_local_maps_t fs_maps[] = {{.name = "tbl_ext4", .internal_input = NET
.type = NETDATA_EBPF_MAP_CONTROLLER,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
-struct netdata_static_thread filesystem_threads = {
- .name = "EBPF FS READ",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_EBPF_HIST_MAX_BINS];
static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_EBPF_HIST_MAX_BINS];
@@ -337,14 +326,9 @@ void ebpf_filesystem_cleanup_ebpf_data()
static void ebpf_filesystem_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
- freez(filesystem_threads.thread);
ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
ebpf_filesystem_cleanup_ebpf_data();
@@ -367,20 +351,6 @@ static void ebpf_filesystem_free(ebpf_module_t *em)
static void ebpf_filesystem_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*filesystem_threads.thread);
- ebpf_filesystem_free(em);
-}
-
-/**
- * File system cleanup
- *
- * Clean up allocated thread.
- *
- * @param ptr thread data.
- */
-static void ebpf_filesystem_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_filesystem_free(em);
}
@@ -483,30 +453,16 @@ static void read_filesystem_tables()
*
* @return It always returns NULL.
*/
-void *ebpf_filesystem_read_hash(void *ptr)
+void ebpf_filesystem_read_hash(ebpf_module_t *em)
{
- netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_every;
- int update_every = em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
+ ebpf_obsolete_fs_charts(em->update_every);
- (void) ebpf_update_partitions(em);
- ebpf_obsolete_fs_charts(update_every);
+ (void) ebpf_update_partitions(em);
- // No more partitions, it is not necessary to read tables
- if (em->optional)
- continue;
-
- read_filesystem_tables();
- }
+ if (em->optional)
+ return;
- netdata_thread_cleanup_pop(1);
- return NULL;
+ read_filesystem_tables();
}
/**
@@ -543,21 +499,18 @@ static void ebpf_histogram_send_data()
*/
static void filesystem_collector(ebpf_module_t *em)
{
- filesystem_threads.thread = mallocz(sizeof(netdata_thread_t));
- filesystem_threads.start_routine = ebpf_filesystem_read_hash;
-
- netdata_thread_create(filesystem_threads.thread, filesystem_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT, ebpf_filesystem_read_hash, em);
-
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ ebpf_filesystem_read_hash(em);
pthread_mutex_lock(&lock);
ebpf_create_fs_charts(update_every);
diff --git a/collectors/ebpf.plugin/ebpf_filesystem.h b/collectors/ebpf.plugin/ebpf_filesystem.h
index 0d558df7..cf19b253 100644
--- a/collectors/ebpf.plugin/ebpf_filesystem.h
+++ b/collectors/ebpf.plugin/ebpf_filesystem.h
@@ -11,7 +11,6 @@
#define NETDATA_FS_MAX_DIST_NAME 64UL
#define NETDATA_FILESYSTEM_CONFIG_NAME "filesystem"
-#define NETDATA_FILESYSTEM_READ_SLEEP_MS 600000ULL
// Process configuration name
#define NETDATA_FILESYSTEM_CONFIG_FILE "filesystem.conf"
diff --git a/collectors/ebpf.plugin/ebpf_hardirq.c b/collectors/ebpf.plugin/ebpf_hardirq.c
index b07dd24c..20c4b9d0 100644
--- a/collectors/ebpf.plugin/ebpf_hardirq.c
+++ b/collectors/ebpf.plugin/ebpf_hardirq.c
@@ -135,17 +135,6 @@ static hardirq_ebpf_val_t *hardirq_ebpf_vals = NULL;
// tmp store for static hard IRQ values we get from a per-CPU eBPF map.
static hardirq_ebpf_static_val_t *hardirq_ebpf_static_vals = NULL;
-static struct netdata_static_thread hardirq_threads = {
- .name = "HARDIRQ KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
/**
* Hardirq Free
*
@@ -156,21 +145,18 @@ static struct netdata_static_thread hardirq_threads = {
static void ebpf_hardirq_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
- freez(hardirq_threads.thread);
for (int i = 0; hardirq_tracepoints[i].class != NULL; i++) {
ebpf_disable_tracepoint(&hardirq_tracepoints[i]);
}
freez(hardirq_ebpf_vals);
freez(hardirq_ebpf_static_vals);
+ pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
}
/**
@@ -183,20 +169,6 @@ static void ebpf_hardirq_free(ebpf_module_t *em)
static void hardirq_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*hardirq_threads.thread);
- ebpf_hardirq_free(em);
-}
-
-/**
- * Hardirq clean up
- *
- * Clean up allocated memory.
- *
- * @param ptr thread data.
- */
-static void hardirq_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_hardirq_free(em);
}
@@ -331,24 +303,10 @@ static void hardirq_read_latency_static_map(int mapfd)
/**
* Read eBPF maps for hard IRQ.
*/
-static void *hardirq_reader(void *ptr)
+static void hardirq_reader()
{
- netdata_thread_cleanup_push(hardirq_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_HARDIRQ_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd);
- hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd);
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
+ hardirq_read_latency_map(hardirq_maps[HARDIRQ_MAP_LATENCY].map_fd);
+ hardirq_read_latency_static_map(hardirq_maps[HARDIRQ_MAP_LATENCY_STATIC].map_fd);
}
static void hardirq_create_charts(int update_every)
@@ -428,17 +386,6 @@ static void hardirq_collector(ebpf_module_t *em)
avl_init_lock(&hardirq_pub, hardirq_val_cmp);
- // create reader thread.
- hardirq_threads.thread = mallocz(sizeof(netdata_thread_t));
- hardirq_threads.start_routine = hardirq_reader;
- netdata_thread_create(
- hardirq_threads.thread,
- hardirq_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT,
- hardirq_reader,
- em
- );
-
// create chart and static dims.
pthread_mutex_lock(&lock);
hardirq_create_charts(em->update_every);
@@ -449,13 +396,17 @@ static void hardirq_collector(ebpf_module_t *em)
// loop and read from published data until ebpf plugin is closed.
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
//This will be cancelled by its parent
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ hardirq_reader();
pthread_mutex_lock(&lock);
// write dims now for all hitherto discovered IRQs.
diff --git a/collectors/ebpf.plugin/ebpf_hardirq.h b/collectors/ebpf.plugin/ebpf_hardirq.h
index 381da57d..fe38b1bb 100644
--- a/collectors/ebpf.plugin/ebpf_hardirq.h
+++ b/collectors/ebpf.plugin/ebpf_hardirq.h
@@ -47,7 +47,6 @@ typedef struct hardirq_ebpf_static_val {
*****************************************************************/
#define NETDATA_EBPF_MODULE_NAME_HARDIRQ "hardirq"
-#define NETDATA_HARDIRQ_SLEEP_MS 650000ULL
#define NETDATA_HARDIRQ_CONFIG_FILE "hardirq.conf"
typedef struct hardirq_val {
diff --git a/collectors/ebpf.plugin/ebpf_mdflush.c b/collectors/ebpf.plugin/ebpf_mdflush.c
index dc805da2..1a5a7731 100644
--- a/collectors/ebpf.plugin/ebpf_mdflush.c
+++ b/collectors/ebpf.plugin/ebpf_mdflush.c
@@ -35,17 +35,6 @@ static avl_tree_lock mdflush_pub;
// tmp store for mdflush values we get from a per-CPU eBPF map.
static mdflush_ebpf_val_t *mdflush_ebpf_vals = NULL;
-static struct netdata_static_thread mdflush_threads = {
- .name = "MDFLUSH KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
/**
* MDflush Free
*
@@ -55,18 +44,10 @@ static struct netdata_static_thread mdflush_threads = {
*/
static void ebpf_mdflush_free(ebpf_module_t *em)
{
- pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
- pthread_mutex_unlock(&ebpf_exit_cleanup);
-
freez(mdflush_ebpf_vals);
- freez(mdflush_threads.thread);
-
+ pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
}
/**
@@ -83,20 +64,6 @@ static void mdflush_exit(void *ptr)
}
/**
- * CLeanup
- *
- * Clean allocated memory.
- *
- * @param ptr thread data.
- */
-static void mdflush_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*mdflush_threads.thread);
- ebpf_mdflush_free(em);
-}
-
-/**
* Compare mdflush values.
*
* @param a `netdata_mdflush_t *`.
@@ -188,28 +155,6 @@ static void mdflush_read_count_map()
}
}
-/**
- * Read eBPF maps for mdflush.
- */
-static void *mdflush_reader(void *ptr)
-{
- netdata_thread_cleanup_push(mdflush_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_MDFLUSH_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- mdflush_read_count_map();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
static void mdflush_create_charts(int update_every)
{
ebpf_create_chart(
@@ -256,34 +201,27 @@ static void mdflush_collector(ebpf_module_t *em)
{
mdflush_ebpf_vals = callocz(ebpf_nprocs, sizeof(mdflush_ebpf_val_t));
+ int update_every = em->update_every;
avl_init_lock(&mdflush_pub, mdflush_val_cmp);
- // create reader thread.
- mdflush_threads.thread = mallocz(sizeof(netdata_thread_t));
- mdflush_threads.start_routine = mdflush_reader;
- netdata_thread_create(
- mdflush_threads.thread,
- mdflush_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT,
- mdflush_reader,
- em
- );
-
// create chart and static dims.
pthread_mutex_lock(&lock);
- mdflush_create_charts(em->update_every);
+ mdflush_create_charts(update_every);
ebpf_update_stats(&plugin_statistics, em);
pthread_mutex_unlock(&lock);
// loop and read from published data until ebpf plugin is closed.
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+
+ counter = 0;
+ mdflush_read_count_map();
// write dims now for all hitherto discovered devices.
write_begin_chart("mdstat", "mdstat_flush");
avl_traverse_lock(&mdflush_pub, mdflush_write_dims, NULL);
diff --git a/collectors/ebpf.plugin/ebpf_mdflush.h b/collectors/ebpf.plugin/ebpf_mdflush.h
index b04eefd2..4913ad01 100644
--- a/collectors/ebpf.plugin/ebpf_mdflush.h
+++ b/collectors/ebpf.plugin/ebpf_mdflush.h
@@ -6,8 +6,6 @@
// Module name
#define NETDATA_EBPF_MODULE_NAME_MDFLUSH "mdflush"
-#define NETDATA_MDFLUSH_SLEEP_MS 850000ULL
-
// charts
#define NETDATA_MDFLUSH_GLOBAL_CHART "mdflush"
diff --git a/collectors/ebpf.plugin/ebpf_mount.c b/collectors/ebpf.plugin/ebpf_mount.c
index ec1f07a6..e06010b5 100644
--- a/collectors/ebpf.plugin/ebpf_mount.c
+++ b/collectors/ebpf.plugin/ebpf_mount.c
@@ -22,17 +22,6 @@ static netdata_idx_t *mount_values = NULL;
static netdata_idx_t mount_hash_values[NETDATA_MOUNT_END];
-struct netdata_static_thread mount_thread = {
- .name = "MOUNT KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
netdata_ebpf_targets_t mount_targets[] = { {.name = "mount", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "umount", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
@@ -187,7 +176,7 @@ static void ebpf_mount_set_hash_tables(struct mount_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_t *em)
{
@@ -239,14 +228,9 @@ static inline int ebpf_mount_load_and_attach(struct mount_bpf *obj, ebpf_module_
static void ebpf_mount_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
- freez(mount_thread.thread);
freez(mount_values);
#ifdef LIBBPF_MAJOR_VERSION
@@ -269,20 +253,6 @@ static void ebpf_mount_free(ebpf_module_t *em)
static void ebpf_mount_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*mount_thread.thread);
- ebpf_mount_free(em);
-}
-
-/**
- * Mount cleanup
- *
- * Clean up allocated memory.
- *
- * @param ptr thread data.
- */
-static void ebpf_mount_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_mount_free(em);
}
@@ -297,7 +267,7 @@ static void ebpf_mount_cleanup(void *ptr)
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_mount_read_global_table()
{
uint32_t idx;
netdata_idx_t *val = mount_hash_values;
@@ -318,36 +288,6 @@ static void read_global_table()
}
/**
- * Mount read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_mount_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_mount_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_every;
- //This will be cancelled by its parent
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Send data to Netdata calling auxiliary functions.
*/
static void ebpf_mount_send_data()
@@ -371,23 +311,20 @@ static void ebpf_mount_send_data()
*/
static void mount_collector(ebpf_module_t *em)
{
- mount_thread.thread = mallocz(sizeof(netdata_thread_t));
- mount_thread.start_routine = ebpf_mount_read_hash;
- memset(mount_hash_values, 0, sizeof(mount_hash_values));
-
mount_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
-
- netdata_thread_create(mount_thread.thread, mount_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_mount_read_hash, em);
+ memset(mount_hash_values, 0, sizeof(mount_hash_values));
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ ebpf_mount_read_global_table();
pthread_mutex_lock(&lock);
ebpf_mount_send_data();
diff --git a/collectors/ebpf.plugin/ebpf_mount.h b/collectors/ebpf.plugin/ebpf_mount.h
index 5a8d11a5..11b21f83 100644
--- a/collectors/ebpf.plugin/ebpf_mount.h
+++ b/collectors/ebpf.plugin/ebpf_mount.h
@@ -8,8 +8,6 @@
#define NETDATA_EBPF_MOUNT_SYSCALL 2
-#define NETDATA_LATENCY_MOUNT_SLEEP_MS 700000ULL
-
#define NETDATA_EBPF_MOUNT_CALLS "call"
#define NETDATA_EBPF_MOUNT_ERRORS "error"
#define NETDATA_EBPF_MOUNT_FAMILY "mount (eBPF)"
diff --git a/collectors/ebpf.plugin/ebpf_oomkill.c b/collectors/ebpf.plugin/ebpf_oomkill.c
index d93e4159..82420d54 100644
--- a/collectors/ebpf.plugin/ebpf_oomkill.c
+++ b/collectors/ebpf.plugin/ebpf_oomkill.c
@@ -46,7 +46,9 @@ static netdata_publish_syscall_t oomkill_publish_aggregated = {.name = "oomkill"
static void oomkill_cleanup(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
+ pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
}
static void oomkill_write_data(int32_t *keys, uint32_t total)
@@ -294,12 +296,13 @@ static void oomkill_collector(ebpf_module_t *em)
// loop and read until ebpf plugin is closed.
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (!ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
pthread_mutex_lock(&collect_data_mutex);
pthread_mutex_lock(&lock);
diff --git a/collectors/ebpf.plugin/ebpf_oomkill.h b/collectors/ebpf.plugin/ebpf_oomkill.h
index 78608638..f921f9d8 100644
--- a/collectors/ebpf.plugin/ebpf_oomkill.h
+++ b/collectors/ebpf.plugin/ebpf_oomkill.h
@@ -17,7 +17,6 @@ typedef uint8_t oomkill_ebpf_val_t;
*****************************************************************/
#define NETDATA_EBPF_MODULE_NAME_OOMKILL "oomkill"
-#define NETDATA_OOMKILL_SLEEP_MS 650000ULL
#define NETDATA_OOMKILL_CONFIG_FILE "oomkill.conf"
#define NETDATA_OOMKILL_CHART "oomkills"
diff --git a/collectors/ebpf.plugin/ebpf_process.c b/collectors/ebpf.plugin/ebpf_process.c
index 682577da..9a191d39 100644
--- a/collectors/ebpf.plugin/ebpf_process.c
+++ b/collectors/ebpf.plugin/ebpf_process.c
@@ -57,17 +57,6 @@ struct config process_config = { .first_section = NULL,
static char *threads_stat[NETDATA_EBPF_THREAD_STAT_END] = {"total", "running"};
static char *load_event_stat[NETDATA_EBPF_LOAD_STAT_END] = {"legacy", "co-re"};
-static struct netdata_static_thread cgroup_thread = {
- .name = "EBPF CGROUP",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
/*****************************************************************
*
* PROCESS DATA AND SEND TO NETDATA
@@ -327,55 +316,6 @@ static void ebpf_process_update_apps_data()
}
/**
- * Cgroup Exit
- *
- * Function used with netdata_thread_clean_push
- *
- * @param ptr unused argument
- */
-static void ebpf_cgroup_exit(void *ptr)
-{
- UNUSED(ptr);
-}
-
-/**
- * Cgroup update shm
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data from shared memory.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_cgroup_update_shm(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_cgroup_exit, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- usec_t step = 3 * USEC_PER_SEC;
- int counter = NETDATA_EBPF_CGROUP_UPDATE - 1;
- //This will be cancelled by its parent
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- // We are using a small heartbeat time to wake up thread,
- // but we should not update so frequently the shared memory data
- if (++counter >= NETDATA_EBPF_CGROUP_UPDATE) {
- counter = 0;
- if (!shm_ebpf_cgroup.header)
- ebpf_map_cgroup_shared_memory();
-
- ebpf_parse_cgroup_shm_data();
- }
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Update cgroup
*
* Update cgroup data based in
@@ -745,7 +685,6 @@ static void ebpf_process_exit(void *ptr)
pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
pthread_mutex_unlock(&ebpf_exit_cleanup);
- pthread_cancel(*cgroup_thread.thread);
}
/*****************************************************************
@@ -1104,13 +1043,6 @@ void ebpf_send_statistic_data()
*/
static void process_collector(ebpf_module_t *em)
{
- // Start cgroup integration before other threads
- cgroup_thread.thread = mallocz(sizeof(netdata_thread_t));
- cgroup_thread.start_routine = ebpf_cgroup_update_shm;
-
- netdata_thread_create(cgroup_thread.thread, cgroup_thread.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_cgroup_update_shm, NULL);
-
heartbeat_t hb;
heartbeat_init(&hb);
int publish_global = em->global_charts;
@@ -1152,7 +1084,7 @@ static void process_collector(ebpf_module_t *em)
ebpf_process_update_apps_data();
}
- if (cgroups) {
+ if (cgroups && shm_ebpf_cgroup.header) {
ebpf_update_process_cgroup();
}
}
@@ -1169,7 +1101,7 @@ static void process_collector(ebpf_module_t *em)
ebpf_process_send_apps_data(apps_groups_root_target, em);
}
- if (cgroups) {
+ if (cgroups && shm_ebpf_cgroup.header) {
ebpf_process_send_cgroup_data(em);
}
}
diff --git a/collectors/ebpf.plugin/ebpf_process.h b/collectors/ebpf.plugin/ebpf_process.h
index 43df34d4..6fded16f 100644
--- a/collectors/ebpf.plugin/ebpf_process.h
+++ b/collectors/ebpf.plugin/ebpf_process.h
@@ -39,7 +39,7 @@
#define NETDATA_SYSTEMD_PROCESS_EXIT_CONTEXT "services.task_exit"
#define NETDATA_SYSTEMD_PROCESS_ERROR_CONTEXT "services.task_error"
-#define NETDATA_EBPF_CGROUP_UPDATE 10
+#define NETDATA_EBPF_CGROUP_UPDATE 30
// Statistical information
enum netdata_ebpf_thread_stats{
diff --git a/collectors/ebpf.plugin/ebpf_shm.c b/collectors/ebpf.plugin/ebpf_shm.c
index f81287d8..4057eff7 100644
--- a/collectors/ebpf.plugin/ebpf_shm.c
+++ b/collectors/ebpf.plugin/ebpf_shm.c
@@ -34,17 +34,6 @@ static ebpf_local_maps_t shm_maps[] = {{.name = "tbl_pid_shm", .internal_input =
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = NULL, .internal_input = 0, .user_input = 0}};
-struct netdata_static_thread shm_threads = {
- .name = "SHM KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
netdata_ebpf_targets_t shm_targets[] = { {.name = "shmget", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "shmat", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "shmdt", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -246,7 +235,7 @@ static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *em)
{
@@ -299,11 +288,7 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
static void ebpf_shm_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_cleanup_publish_syscall(shm_publish_aggregated);
@@ -316,7 +301,9 @@ static void ebpf_shm_free(ebpf_module_t *em)
shm_bpf__destroy(bpf_obj);
#endif
+ pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
+ pthread_mutex_unlock(&ebpf_exit_cleanup);
}
/**
@@ -329,20 +316,6 @@ static void ebpf_shm_free(ebpf_module_t *em)
static void ebpf_shm_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*shm_threads.thread);
- ebpf_shm_free(em);
-}
-
-/**
- * SHM Cleanup
- *
- * Clean up allocated memory.
- *
- * @param ptr thread data.
- */
-static void ebpf_shm_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_shm_free(em);
}
@@ -491,7 +464,7 @@ static void shm_send_global()
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_shm_read_global_table()
{
netdata_idx_t *stored = shm_values;
netdata_idx_t *val = shm_hash_values;
@@ -512,30 +485,6 @@ static void read_global_table()
}
/**
- * Shared memory reader thread.
- *
- * @param ptr It is a NULL value for this thread.
- * @return It always returns NULL.
- */
-void *ebpf_shm_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_shm_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- usec_t step = NETDATA_SHM_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Sum values for all targets.
*/
static void ebpf_shm_sum_pids(netdata_publish_shm_t *shm, struct pid_on_target *root)
@@ -894,28 +843,19 @@ void ebpf_shm_send_cgroup_data(int update_every)
*/
static void shm_collector(ebpf_module_t *em)
{
- shm_threads.thread = mallocz(sizeof(netdata_thread_t));
- shm_threads.start_routine = ebpf_shm_read_hash;
-
- netdata_thread_create(
- shm_threads.thread,
- shm_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_shm_read_hash,
- em
- );
-
int cgroups = em->cgroup_charts;
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_shm_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps) {
read_apps_table();
diff --git a/collectors/ebpf.plugin/ebpf_shm.h b/collectors/ebpf.plugin/ebpf_shm.h
index 4e068819..b06a4a5d 100644
--- a/collectors/ebpf.plugin/ebpf_shm.h
+++ b/collectors/ebpf.plugin/ebpf_shm.h
@@ -6,8 +6,6 @@
// Module name
#define NETDATA_EBPF_MODULE_NAME_SHM "shm"
-#define NETDATA_SHM_SLEEP_MS 850000ULL
-
// charts
#define NETDATA_SHM_GLOBAL_CHART "shared_memory_calls"
#define NETDATA_SHMGET_CHART "shmget_call"
diff --git a/collectors/ebpf.plugin/ebpf_socket.c b/collectors/ebpf.plugin/ebpf_socket.c
index 3a023e4a..1954be71 100644
--- a/collectors/ebpf.plugin/ebpf_socket.c
+++ b/collectors/ebpf.plugin/ebpf_socket.c
@@ -62,8 +62,6 @@ ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
static ebpf_bandwidth_t *bandwidth_vector = NULL;
pthread_mutex_t nv_mutex;
-int wait_to_plot = 0;
-
netdata_vector_plot_t inbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
netdata_vector_plot_t outbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
netdata_socket_t *socket_values;
@@ -389,7 +387,7 @@ static void ebpf_socket_adjust_map_size(struct socket_bpf *obj, ebpf_module_t *e
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_module_t *em)
{
@@ -459,6 +457,9 @@ static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
*/
static void clean_allocated_socket_plot()
{
+ if (!network_viewer_opt.enabled)
+ return;
+
uint32_t i;
uint32_t end = inbound_vectors.last;
netdata_socket_plot_t *plot = inbound_vectors.plot;
@@ -647,7 +648,8 @@ static void ebpf_socket_free(ebpf_module_t *em )
static void ebpf_socket_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*socket_threads.thread);
+ if (socket_threads.thread)
+ netdata_thread_cancel(*socket_threads.thread);
ebpf_socket_free(em);
}
@@ -724,7 +726,7 @@ static void ebpf_update_global_publish(
*/
static inline void update_nv_plot_data(netdata_plot_values_t *plot, netdata_socket_t *sock)
{
- if (sock->ct > plot->last_time) {
+ if (sock->ct != plot->last_time) {
plot->last_time = sock->ct;
plot->plot_recv_packets = sock->recv_packets;
plot->plot_sent_packets = sock->sent_packets;
@@ -747,6 +749,7 @@ static inline void update_nv_plot_data(netdata_plot_values_t *plot, netdata_sock
*/
static inline void calculate_nv_plot()
{
+ pthread_mutex_lock(&nv_mutex);
uint32_t i;
uint32_t end = inbound_vectors.next;
for (i = 0; i < end; i++) {
@@ -764,9 +767,12 @@ static inline void calculate_nv_plot()
}
outbound_vectors.max_plot = end;
+ /*
// The 'Other' dimension is always calculated for the chart to have at least one dimension
update_nv_plot_data(&outbound_vectors.plot[outbound_vectors.last].plot,
&outbound_vectors.plot[outbound_vectors.last].sock);
+ */
+ pthread_mutex_unlock(&nv_mutex);
}
/**
@@ -1441,17 +1447,17 @@ static void ebpf_socket_create_nv_charts(netdata_vector_plot_t *ptr, int update_
*
* @return It returns 1 if the IP is inside the range and 0 otherwise
*/
-static int is_specific_ip_inside_range(union netdata_ip_t *cmp, int family)
+static int ebpf_is_specific_ip_inside_range(union netdata_ip_t *cmp, int family)
{
if (!network_viewer_opt.excluded_ips && !network_viewer_opt.included_ips)
return 1;
- uint32_t ipv4_test = ntohl(cmp->addr32[0]);
+ uint32_t ipv4_test = htonl(cmp->addr32[0]);
ebpf_network_viewer_ip_list_t *move = network_viewer_opt.excluded_ips;
while (move) {
if (family == AF_INET) {
- if (ntohl(move->first.addr32[0]) <= ipv4_test &&
- ipv4_test <= ntohl(move->last.addr32[0]) )
+ if (move->first.addr32[0] <= ipv4_test &&
+ ipv4_test <= move->last.addr32[0])
return 0;
} else {
if (memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
@@ -1464,12 +1470,13 @@ static int is_specific_ip_inside_range(union netdata_ip_t *cmp, int family)
move = network_viewer_opt.included_ips;
while (move) {
- if (family == AF_INET) {
- if (ntohl(move->first.addr32[0]) <= ipv4_test &&
- ntohl(move->last.addr32[0]) >= ipv4_test)
+ if (family == AF_INET && move->ver == AF_INET) {
+ if (move->first.addr32[0] <= ipv4_test &&
+ move->last.addr32[0] >= ipv4_test)
return 1;
} else {
- if (memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
+ if (move->ver == AF_INET6 &&
+ memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
memcmp(move->last.addr8, cmp->addr8, sizeof(union netdata_ip_t)) >= 0) {
return 1;
}
@@ -1565,7 +1572,7 @@ int is_socket_allowed(netdata_socket_idx_t *key, int family)
if (!is_port_inside_range(key->dport))
return 0;
- return is_specific_ip_inside_range(&key->daddr, family);
+ return ebpf_is_specific_ip_inside_range(&key->daddr, family);
}
/**
@@ -1580,38 +1587,26 @@ int is_socket_allowed(netdata_socket_idx_t *key, int family)
*
* @return It returns 0 case the values are equal, 1 case a is bigger than b and -1 case a is smaller than b.
*/
-static int compare_sockets(void *a, void *b)
+static int ebpf_compare_sockets(void *a, void *b)
{
struct netdata_socket_plot *val1 = a;
struct netdata_socket_plot *val2 = b;
- int cmp;
+ int cmp = 0;
// We do not need to compare val2 family, because data inside hash table is always from the same family
if (val1->family == AF_INET) { //IPV4
- if (val1->flags & NETDATA_INBOUND_DIRECTION) {
- if (val1->index.sport == val2->index.sport)
- cmp = 0;
- else {
- cmp = (val1->index.sport > val2->index.sport)?1:-1;
- }
- } else {
+ if (network_viewer_opt.included_port || network_viewer_opt.excluded_port)
cmp = memcmp(&val1->index.dport, &val2->index.dport, sizeof(uint16_t));
- if (!cmp) {
- cmp = memcmp(&val1->index.daddr.addr32[0], &val2->index.daddr.addr32[0], sizeof(uint32_t));
- }
+
+ if (!cmp) {
+ cmp = memcmp(&val1->index.daddr.addr32[0], &val2->index.daddr.addr32[0], sizeof(uint32_t));
}
} else {
- if (val1->flags & NETDATA_INBOUND_DIRECTION) {
- if (val1->index.sport == val2->index.sport)
- cmp = 0;
- else {
- cmp = (val1->index.sport > val2->index.sport)?1:-1;
- }
- } else {
+ if (network_viewer_opt.included_port || network_viewer_opt.excluded_port)
cmp = memcmp(&val1->index.dport, &val2->index.dport, sizeof(uint16_t));
- if (!cmp) {
- cmp = memcmp(&val1->index.daddr.addr32, &val2->index.daddr.addr32, 4*sizeof(uint32_t));
- }
+
+ if (!cmp) {
+ cmp = memcmp(&val1->index.daddr.addr32, &val2->index.daddr.addr32, 4*sizeof(uint32_t));
}
}
@@ -1631,12 +1626,15 @@ static int compare_sockets(void *a, void *b)
*
* @return it returns the size of the data copied on success and -1 otherwise.
*/
-static inline int build_outbound_dimension_name(char *dimname, char *hostname, char *service_name,
- char *proto, int family)
+static inline int ebpf_build_outbound_dimension_name(char *dimname, char *hostname, char *service_name,
+ char *proto, int family)
{
- return snprintf(dimname, CONFIG_MAX_NAME - 7, (family == AF_INET)?"%s:%s:%s_":"%s:%s:[%s]_",
- service_name, proto,
- hostname);
+ if (network_viewer_opt.included_port || network_viewer_opt.excluded_port)
+ return snprintf(dimname, CONFIG_MAX_NAME - 7, (family == AF_INET)?"%s:%s:%s_":"%s:%s:[%s]_",
+ service_name, proto, hostname);
+
+ return snprintf(dimname, CONFIG_MAX_NAME - 7, (family == AF_INET)?"%s:%s_":"%s:[%s]_",
+ proto, hostname);
}
/**
@@ -1692,7 +1690,7 @@ static inline void fill_resolved_name(netdata_socket_plot_t *ptr, char *hostname
}
if (is_outbound)
- size = build_outbound_dimension_name(dimname, hostname, service_name, protocol, ptr->family);
+ size = ebpf_build_outbound_dimension_name(dimname, hostname, service_name, protocol, ptr->family);
else
size = build_inbound_dimension_name(dimname,service_name, protocol);
@@ -1850,14 +1848,12 @@ static void fill_last_nv_dimension(netdata_socket_plot_t *ptr, int is_outbound)
*/
static inline void update_socket_data(netdata_socket_t *sock, netdata_socket_t *lvalues)
{
- sock->recv_packets += lvalues->recv_packets;
- sock->sent_packets += lvalues->sent_packets;
- sock->recv_bytes += lvalues->recv_bytes;
- sock->sent_bytes += lvalues->sent_bytes;
- sock->retransmit += lvalues->retransmit;
-
- if (lvalues->ct > sock->ct)
- sock->ct = lvalues->ct;
+ sock->recv_packets = lvalues->recv_packets;
+ sock->sent_packets = lvalues->sent_packets;
+ sock->recv_bytes = lvalues->recv_bytes;
+ sock->sent_bytes = lvalues->sent_bytes;
+ sock->retransmit = lvalues->retransmit;
+ sock->ct = lvalues->ct;
}
/**
@@ -1881,7 +1877,7 @@ static void store_socket_inside_avl(netdata_vector_plot_t *out, netdata_socket_t
ret = (netdata_socket_plot_t *) avl_search_lock(&out->tree, (avl_t *)&test);
if (ret) {
- if (lvalues->ct > ret->plot.last_time) {
+ if (lvalues->ct != ret->plot.last_time) {
update_socket_data(&ret->sock, lvalues);
}
} else {
@@ -1892,7 +1888,7 @@ static void store_socket_inside_avl(netdata_vector_plot_t *out, netdata_socket_t
int resolved;
if (curr == last) {
- if (lvalues->ct > w->plot.last_time) {
+ if (lvalues->ct != w->plot.last_time) {
update_socket_data(&w->sock, lvalues);
}
return;
@@ -1977,6 +1973,9 @@ netdata_vector_plot_t * select_vector_to_store(uint32_t *direction, netdata_sock
*/
static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key, int family, int end)
{
+ if (!network_viewer_opt.enabled || !is_socket_allowed(key, family))
+ return;
+
uint64_t bsent = 0, brecv = 0, psent = 0, precv = 0;
uint16_t retransmit = 0;
int i;
@@ -1994,7 +1993,7 @@ static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key
if (!protocol)
protocol = w->protocol;
- if (w->ct > ct)
+ if (w->ct != ct)
ct = w->ct;
}
@@ -2006,11 +2005,9 @@ static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key
values[0].protocol = (!protocol)?IPPROTO_TCP:protocol;
values[0].ct = ct;
- if (is_socket_allowed(key, family)) {
- uint32_t dir;
- netdata_vector_plot_t *table = select_vector_to_store(&dir, key, protocol);
- store_socket_inside_avl(table, &values[0], key, family, dir);
- }
+ uint32_t dir;
+ netdata_vector_plot_t *table = select_vector_to_store(&dir, key, protocol);
+ store_socket_inside_avl(table, &values[0], key, family, dir);
}
/**
@@ -2018,16 +2015,13 @@ static void hash_accumulator(netdata_socket_t *values, netdata_socket_idx_t *key
*
* Read data from hash tables created on kernel ring.
*
- * @param fd the hash table with data.
- * @param family the family associated to the hash table
+ * @param fd the hash table with data.
+ * @param family the family associated to the hash table
*
* @return it returns 0 on success and -1 otherwise.
*/
-static void read_socket_hash_table(int fd, int family, int network_connection)
+static void ebpf_read_socket_hash_table(int fd, int family)
{
- if (wait_to_plot)
- return;
-
netdata_socket_idx_t key = {};
netdata_socket_idx_t next_key = {};
@@ -2046,9 +2040,7 @@ static void read_socket_hash_table(int fd, int family, int network_connection)
continue;
}
- if (network_connection) {
- hash_accumulator(values, &key, family, end);
- }
+ hash_accumulator(values, &key, family, end);
key = next_key;
}
@@ -2057,12 +2049,12 @@ static void read_socket_hash_table(int fd, int family, int network_connection)
/**
* Fill Network Viewer Port list
*
- * Fill the strcture with values read from /proc or hash table.
+ * Fill the structure with values read from /proc or hash table.
*
* @param out the structure where we will store data.
* @param value the ports we are listen to.
* @param proto the protocol used for this connection.
- * @param in the strcuture with values read form different sources.
+ * @param in the structure with values read form different sources.
*/
static inline void fill_nv_port_list(ebpf_network_viewer_port_list_t *out, uint16_t value, uint16_t proto,
netdata_passive_connection_t *in)
@@ -2081,7 +2073,7 @@ static inline void fill_nv_port_list(ebpf_network_viewer_port_list_t *out, uint1
*
* @param value the ports we are listen to.
* @param proto the protocol used with port connection.
- * @param in the strcuture with values read form different sources.
+ * @param in the structure with values read form different sources.
*/
void update_listen_table(uint16_t value, uint16_t proto, netdata_passive_connection_t *in)
{
@@ -2159,22 +2151,19 @@ static void read_listen_table()
void *ebpf_socket_read_hash(void *ptr)
{
netdata_thread_cleanup_push(ebpf_socket_cleanup, ptr);
- ebpf_module_t *em = (ebpf_module_t *)ptr;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = NETDATA_SOCKET_READ_SLEEP_MS * em->update_every;
int fd_ipv4 = socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd;
int fd_ipv6 = socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd;
- int network_connection = em->optional;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin)
+ continue;
pthread_mutex_lock(&nv_mutex);
- read_listen_table();
- read_socket_hash_table(fd_ipv4, AF_INET, network_connection);
- read_socket_hash_table(fd_ipv6, AF_INET6, network_connection);
- wait_to_plot = 1;
+ ebpf_read_socket_hash_table(fd_ipv4, AF_INET);
+ ebpf_read_socket_hash_table(fd_ipv6, AF_INET6);
pthread_mutex_unlock(&nv_mutex);
}
@@ -2863,44 +2852,50 @@ static void ebpf_socket_send_cgroup_data(int update_every)
/**
* Main loop for this collector.
*
- * @param step the number of microseconds used with heart beat
* @param em the structure with thread information
*/
-static void socket_collector(usec_t step, ebpf_module_t *em)
+static void socket_collector(ebpf_module_t *em)
{
heartbeat_t hb;
heartbeat_init(&hb);
+ uint32_t network_connection = network_viewer_opt.enabled;
- socket_threads.thread = mallocz(sizeof(netdata_thread_t));
- socket_threads.start_routine = ebpf_socket_read_hash;
+ if (network_connection) {
+ socket_threads.thread = mallocz(sizeof(netdata_thread_t));
+ socket_threads.start_routine = ebpf_socket_read_hash;
- netdata_thread_create(socket_threads.thread, socket_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT, ebpf_socket_read_hash, em);
+ netdata_thread_create(socket_threads.thread, socket_threads.name,
+ NETDATA_THREAD_OPTION_DEFAULT, ebpf_socket_read_hash, em);
+ }
int cgroups = em->cgroup_charts;
if (cgroups)
ebpf_socket_update_cgroup_algorithm();
int socket_global_enabled = em->global_charts;
- int network_connection = em->optional;
int update_every = em->update_every;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
- pthread_mutex_lock(&collect_data_mutex);
- if (socket_global_enabled)
+ if (socket_global_enabled) {
+ read_listen_table();
read_hash_global_tables();
+ }
+ pthread_mutex_lock(&collect_data_mutex);
if (socket_apps_enabled)
ebpf_socket_update_apps_data();
if (cgroups)
ebpf_update_socket_cgroup();
- calculate_nv_plot();
+ if (network_connection)
+ calculate_nv_plot();
pthread_mutex_lock(&lock);
if (socket_global_enabled)
@@ -2925,7 +2920,6 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
ebpf_socket_create_nv_charts(&outbound_vectors, update_every);
fflush(stdout);
ebpf_socket_send_nv_data(&outbound_vectors);
- wait_to_plot = 0;
pthread_mutex_unlock(&nv_mutex);
}
@@ -2959,8 +2953,10 @@ static void ebpf_socket_allocate_global_vectors(int apps)
bandwidth_vector = callocz((size_t)ebpf_nprocs, sizeof(ebpf_bandwidth_t));
socket_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_socket_t));
- inbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
- outbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
+ if (network_viewer_opt.enabled) {
+ inbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
+ outbound_vectors.plot = callocz(network_viewer_opt.max_dim, sizeof(netdata_socket_plot_t));
+ }
}
/**
@@ -3219,12 +3215,11 @@ static void get_ipv6_first_addr(union netdata_ip_t *out, union netdata_ip_t *in,
*
* @return It returns 1 if the IP is inside the range and 0 otherwise
*/
-static int is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rlast,
- union netdata_ip_t *cmpfirst, union netdata_ip_t *cmplast, int family)
+static int ebpf_is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rlast,
+ union netdata_ip_t *cmpfirst, union netdata_ip_t *cmplast, int family)
{
if (family == AF_INET) {
- if (ntohl(rfirst->addr32[0]) <= ntohl(cmpfirst->addr32[0]) &&
- ntohl(rlast->addr32[0]) >= ntohl(cmplast->addr32[0]))
+ if ((rfirst->addr32[0] <= cmpfirst->addr32[0]) && (rlast->addr32[0] >= cmplast->addr32[0]))
return 1;
} else {
if (memcmp(rfirst->addr8, cmpfirst->addr8, sizeof(union netdata_ip_t)) <= 0 &&
@@ -3241,16 +3236,22 @@ static int is_ip_inside_range(union netdata_ip_t *rfirst, union netdata_ip_t *rl
*
* @param out a pointer to the link list.
* @param in the structure that will be linked.
+ * @param table the modified table.
*/
-void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table)
+void ebpf_fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table)
{
#ifndef NETDATA_INTERNAL_CHECKS
UNUSED(table);
#endif
+ if (in->ver == AF_INET) { // It is simpler to compare using host order
+ in->first.addr32[0] = ntohl(in->first.addr32[0]);
+ in->last.addr32[0] = ntohl(in->last.addr32[0]);
+ }
if (likely(*out)) {
ebpf_network_viewer_ip_list_t *move = *out, *store = *out;
while (move) {
- if (in->ver == move->ver && is_ip_inside_range(&move->first, &move->last, &in->first, &in->last, in->ver)) {
+ if (in->ver == move->ver &&
+ ebpf_is_ip_inside_range(&move->first, &move->last, &in->first, &in->last, in->ver)) {
info("The range/value (%s) is inside the range/value (%s) already inserted, it will be ignored.",
in->value, move->value);
freez(in->value);
@@ -3267,14 +3268,12 @@ void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_li
}
#ifdef NETDATA_INTERNAL_CHECKS
- char first[512], last[512];
+ char first[256], last[512];
if (in->ver == AF_INET) {
- if (inet_ntop(AF_INET, in->first.addr8, first, INET_ADDRSTRLEN) &&
- inet_ntop(AF_INET, in->last.addr8, last, INET_ADDRSTRLEN))
- info("Adding values %s - %s to %s IP list \"%s\" used on network viewer",
- first, last,
- (*out == network_viewer_opt.included_ips)?"included":"excluded",
- table);
+ info("Adding values %s: (%u - %u) to %s IP list \"%s\" used on network viewer",
+ in->value, in->first.addr32[0], in->last.addr32[0],
+ (*out == network_viewer_opt.included_ips)?"included":"excluded",
+ table);
} else {
if (inet_ntop(AF_INET6, in->first.addr8, first, INET6_ADDRSTRLEN) &&
inet_ntop(AF_INET6, in->last.addr8, last, INET6_ADDRSTRLEN))
@@ -3294,7 +3293,7 @@ void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_li
* @param out a pointer to store the link list
* @param ip the value given as parameter
*/
-static void parse_ip_list(void **out, char *ip)
+static void ebpf_parse_ip_list(void **out, char *ip)
{
ebpf_network_viewer_ip_list_t **list = (ebpf_network_viewer_ip_list_t **)out;
@@ -3442,7 +3441,7 @@ static void parse_ip_list(void **out, char *ip)
ebpf_network_viewer_ip_list_t *store;
- storethisip:
+storethisip:
store = callocz(1, sizeof(ebpf_network_viewer_ip_list_t));
store->value = ipdup;
store->hash = simple_hash(ipdup);
@@ -3450,7 +3449,7 @@ static void parse_ip_list(void **out, char *ip)
memcpy(store->first.addr8, first.addr8, sizeof(first.addr8));
memcpy(store->last.addr8, last.addr8, sizeof(last.addr8));
- fill_ip_list(list, store, "socket");
+ ebpf_fill_ip_list(list, store, "socket");
return;
cleanipdup:
@@ -3464,7 +3463,7 @@ cleanipdup:
*
* @param ptr is a pointer with the text to parse.
*/
-static void parse_ips(char *ptr)
+static void ebpf_parse_ips(char *ptr)
{
// No value
if (unlikely(!ptr))
@@ -3491,8 +3490,9 @@ static void parse_ips(char *ptr)
}
if (isascii(*ptr)) { // Parse port
- parse_ip_list((!neg)?(void **)&network_viewer_opt.included_ips:(void **)&network_viewer_opt.excluded_ips,
- ptr);
+ ebpf_parse_ip_list((!neg)?(void **)&network_viewer_opt.included_ips:
+ (void **)&network_viewer_opt.excluded_ips,
+ ptr);
}
ptr = end;
@@ -3762,7 +3762,7 @@ void parse_network_viewer_section(struct config *cfg)
value = appconfig_get(cfg, EBPF_NETWORK_VIEWER_SECTION,
"ips", "!127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 fc00::/7 !::1/128");
- parse_ips(value);
+ ebpf_parse_ips(value);
}
/**
@@ -3916,16 +3916,9 @@ void *ebpf_socket_thread(void *ptr)
{
netdata_thread_cleanup_push(ebpf_socket_exit, ptr);
- memset(&inbound_vectors.tree, 0, sizeof(avl_tree_lock));
- memset(&outbound_vectors.tree, 0, sizeof(avl_tree_lock));
- avl_init_lock(&inbound_vectors.tree, compare_sockets);
- avl_init_lock(&outbound_vectors.tree, compare_sockets);
-
ebpf_module_t *em = (ebpf_module_t *)ptr;
em->maps = socket_maps;
- parse_network_viewer_section(&socket_config);
- parse_service_name_section(&socket_config);
parse_table_size_options(&socket_config);
if (pthread_mutex_init(&nv_mutex, NULL)) {
@@ -3935,7 +3928,15 @@ void *ebpf_socket_thread(void *ptr)
}
ebpf_socket_allocate_global_vectors(em->apps_charts);
- initialize_inbound_outbound();
+
+ if (network_viewer_opt.enabled) {
+ memset(&inbound_vectors.tree, 0, sizeof(avl_tree_lock));
+ memset(&outbound_vectors.tree, 0, sizeof(avl_tree_lock));
+ avl_init_lock(&inbound_vectors.tree, ebpf_compare_sockets);
+ avl_init_lock(&outbound_vectors.tree, ebpf_compare_sockets);
+
+ initialize_inbound_outbound();
+ }
if (running_on_kernel < NETDATA_EBPF_KERNEL_5_0)
em->mode = MODE_ENTRY;
@@ -3966,7 +3967,7 @@ void *ebpf_socket_thread(void *ptr)
pthread_mutex_unlock(&lock);
- socket_collector((usec_t)(em->update_every * USEC_PER_SEC), em);
+ socket_collector(em);
endsocket:
ebpf_update_disabled_plugin_stats(em);
diff --git a/collectors/ebpf.plugin/ebpf_socket.h b/collectors/ebpf.plugin/ebpf_socket.h
index ca6b193f..63b1e107 100644
--- a/collectors/ebpf.plugin/ebpf_socket.h
+++ b/collectors/ebpf.plugin/ebpf_socket.h
@@ -244,6 +244,7 @@ typedef struct ebpf_network_viewer_hostname_list {
#define NETDATA_NV_CAP_VALUE 50L
typedef struct ebpf_network_viewer_options {
+ uint32_t enabled;
uint32_t max_dim; // Store value read from 'maximum dimensions'
uint32_t hostname_resolution_enabled;
@@ -360,7 +361,7 @@ void clean_port_structure(ebpf_network_viewer_port_list_t **clean);
extern ebpf_network_viewer_port_list_t *listen_ports;
void update_listen_table(uint16_t value, uint16_t proto, netdata_passive_connection_t *values);
void parse_network_viewer_section(struct config *cfg);
-void fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table);
+void ebpf_fill_ip_list(ebpf_network_viewer_ip_list_t **out, ebpf_network_viewer_ip_list_t *in, char *table);
void parse_service_name_section(struct config *cfg);
extern ebpf_socket_publish_apps_t **socket_bandwidth_curr;
diff --git a/collectors/ebpf.plugin/ebpf_softirq.c b/collectors/ebpf.plugin/ebpf_softirq.c
index 3b5d1592..49e9c305 100644
--- a/collectors/ebpf.plugin/ebpf_softirq.c
+++ b/collectors/ebpf.plugin/ebpf_softirq.c
@@ -54,17 +54,6 @@ static softirq_val_t softirq_vals[] = {
// tmp store for soft IRQ values we get from a per-CPU eBPF map.
static softirq_ebpf_val_t *softirq_ebpf_vals = NULL;
-static struct netdata_static_thread softirq_threads = {
- .name = "SOFTIRQ KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
/**
* Cachestat Free
*
@@ -75,40 +64,20 @@ static struct netdata_static_thread softirq_threads = {
static void ebpf_softirq_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
- freez(softirq_threads.thread);
-
for (int i = 0; softirq_tracepoints[i].class != NULL; i++) {
ebpf_disable_tracepoint(&softirq_tracepoints[i]);
}
freez(softirq_ebpf_vals);
pthread_mutex_lock(&ebpf_exit_cleanup);
- em->thread->enabled = NETDATA_MAIN_THREAD_EXITED;
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
pthread_mutex_unlock(&ebpf_exit_cleanup);
}
/**
- * Exit
- *
- * Cancel thread.
- *
- * @param ptr thread data.
- */
-static void softirq_exit(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*softirq_threads.thread);
- ebpf_softirq_free(em);
-}
-
-/**
* Cleanup
*
* Clean up allocated memory.
@@ -146,28 +115,6 @@ static void softirq_read_latency_map()
}
}
-/**
- * Read eBPF maps for soft IRQ.
- */
-static void *softirq_reader(void *ptr)
-{
- netdata_thread_cleanup_push(softirq_exit, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_SOFTIRQ_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- softirq_read_latency_map();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
static void softirq_create_charts(int update_every)
{
ebpf_create_chart(
@@ -212,17 +159,6 @@ static void softirq_collector(ebpf_module_t *em)
{
softirq_ebpf_vals = callocz(ebpf_nprocs, sizeof(softirq_ebpf_val_t));
- // create reader thread.
- softirq_threads.thread = mallocz(sizeof(netdata_thread_t));
- softirq_threads.start_routine = softirq_reader;
- netdata_thread_create(
- softirq_threads.thread,
- softirq_threads.name,
- NETDATA_THREAD_OPTION_DEFAULT,
- softirq_reader,
- em
- );
-
// create chart and static dims.
pthread_mutex_lock(&lock);
softirq_create_charts(em->update_every);
@@ -233,13 +169,16 @@ static void softirq_collector(ebpf_module_t *em)
// loop and read from published data until ebpf plugin is closed.
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
//This will be cancelled by its parent
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ softirq_read_latency_map();
pthread_mutex_lock(&lock);
// write dims now for all hitherto discovered IRQs.
diff --git a/collectors/ebpf.plugin/ebpf_softirq.h b/collectors/ebpf.plugin/ebpf_softirq.h
index 7dcddbb4..eea2a184 100644
--- a/collectors/ebpf.plugin/ebpf_softirq.h
+++ b/collectors/ebpf.plugin/ebpf_softirq.h
@@ -20,7 +20,6 @@ typedef struct softirq_ebpf_val {
*****************************************************************/
#define NETDATA_EBPF_MODULE_NAME_SOFTIRQ "softirq"
-#define NETDATA_SOFTIRQ_SLEEP_MS 650000ULL
#define NETDATA_SOFTIRQ_CONFIG_FILE "softirq.conf"
typedef struct sofirq_val {
diff --git a/collectors/ebpf.plugin/ebpf_swap.c b/collectors/ebpf.plugin/ebpf_swap.c
index 8199573a..059efb63 100644
--- a/collectors/ebpf.plugin/ebpf_swap.c
+++ b/collectors/ebpf.plugin/ebpf_swap.c
@@ -34,17 +34,6 @@ static ebpf_local_maps_t swap_maps[] = {{.name = "tbl_pid_swap", .internal_input
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
{.name = NULL, .internal_input = 0, .user_input = 0}};
-struct netdata_static_thread swap_threads = {
- .name = "SWAP KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
@@ -184,7 +173,7 @@ static void ebpf_swap_disable_release_task(struct swap_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t *em)
{
@@ -236,18 +225,13 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
static void ebpf_swap_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
ebpf_cleanup_publish_syscall(swap_publish_aggregated);
freez(swap_vector);
freez(swap_values);
- freez(swap_threads.thread);
#ifdef LIBBPF_MAJOR_VERSION
if (bpf_obj)
@@ -268,20 +252,6 @@ static void ebpf_swap_free(ebpf_module_t *em)
static void ebpf_swap_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*swap_threads.thread);
- ebpf_swap_free(em);
-}
-
-/**
- * Swap cleanup
- *
- * Clean up allocated memory.
- *
- * @param ptr thread data.
- */
-static void ebpf_swap_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_swap_free(em);
}
@@ -412,7 +382,7 @@ static void swap_send_global()
*
* Read the table with number of calls to all functions
*/
-static void read_global_table()
+static void ebpf_swap_read_global_table()
{
netdata_idx_t *stored = swap_values;
netdata_idx_t *val = swap_hash_values;
@@ -433,33 +403,6 @@ static void read_global_table()
}
/**
- * Swap read hash
- *
- * This is the thread callback.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_swap_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_swap_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- usec_t step = NETDATA_SWAP_SLEEP_MS * em->update_every;
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Sum PIDs
*
* Sum values for all targets.
@@ -714,23 +657,19 @@ void ebpf_swap_send_cgroup_data(int update_every)
*/
static void swap_collector(ebpf_module_t *em)
{
- swap_threads.thread = mallocz(sizeof(netdata_thread_t));
- swap_threads.start_routine = ebpf_swap_read_hash;
-
- netdata_thread_create(swap_threads.thread, swap_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_swap_read_hash, em);
-
int cgroup = em->cgroup_charts;
int update_every = em->update_every;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = update_every * USEC_PER_SEC;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_swap_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps)
read_apps_table();
diff --git a/collectors/ebpf.plugin/ebpf_sync.c b/collectors/ebpf.plugin/ebpf_sync.c
index 84049753..7c81c1df 100644
--- a/collectors/ebpf.plugin/ebpf_sync.c
+++ b/collectors/ebpf.plugin/ebpf_sync.c
@@ -10,17 +10,6 @@ static netdata_publish_syscall_t sync_counter_publish_aggregated[NETDATA_SYNC_ID
static netdata_idx_t sync_hash_values[NETDATA_SYNC_IDX_END];
-struct netdata_static_thread sync_threads = {
- .name = "SYNC KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
static ebpf_local_maps_t sync_maps[] = {{.name = "tbl_sync", .internal_input = NETDATA_SYNC_END,
.user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
.map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
@@ -77,7 +66,7 @@ static inline void ebpf_sync_disable_probe(struct sync_bpf *obj)
}
/**
- * Disable tramppoline
+ * Disable trampoline
*
* Disable trampoline to use another method.
*
@@ -140,7 +129,7 @@ static void ebpf_sync_set_hash_tables(struct sync_bpf *obj, sync_syscalls_index_
* @param target the syscall that we are attaching a tracer.
* @param idx the index for the main structure
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_sync_load_and_attach(struct sync_bpf *obj, ebpf_module_t *em, char *target,
sync_syscalls_index_t idx)
@@ -216,17 +205,12 @@ void ebpf_sync_cleanup_objects()
static void ebpf_sync_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
#ifdef LIBBPF_MAJOR_VERSION
ebpf_sync_cleanup_objects();
#endif
- freez(sync_threads.thread);
pthread_mutex_lock(&ebpf_exit_cleanup);
em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
@@ -243,18 +227,6 @@ static void ebpf_sync_free(ebpf_module_t *em)
static void ebpf_sync_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*sync_threads.thread);
- ebpf_sync_free(em);
-}
-
-/**
- * Clean up the main thread.
- *
- * @param ptr thread data.
- */
-static void ebpf_sync_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_sync_free(em);
}
@@ -350,7 +322,7 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em)
*
* Read the table with number of calls for all functions
*/
-static void read_global_table()
+static void ebpf_sync_read_global_table()
{
netdata_idx_t stored;
uint32_t idx = NETDATA_SYNC_CALL;
@@ -366,34 +338,6 @@ static void read_global_table()
}
/**
- * Sync read hash
- *
- * This is the thread callback.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_sync_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_sync_cleanup, ptr);
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- heartbeat_t hb;
- heartbeat_init(&hb);
- usec_t step = NETDATA_EBPF_SYNC_SLEEP_MS * em->update_every;
-
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Create Sync charts
*
* Create charts and dimensions according user input.
@@ -452,20 +396,17 @@ static void sync_send_data()
*/
static void sync_collector(ebpf_module_t *em)
{
- sync_threads.thread = mallocz(sizeof(netdata_thread_t));
- sync_threads.start_routine = ebpf_sync_read_hash;
-
- netdata_thread_create(sync_threads.thread, sync_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_sync_read_hash, em);
-
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
+ ebpf_sync_read_global_table();
pthread_mutex_lock(&lock);
sync_send_data();
diff --git a/collectors/ebpf.plugin/ebpf_vfs.c b/collectors/ebpf.plugin/ebpf_vfs.c
index ad6de4a0..b3c0ba45 100644
--- a/collectors/ebpf.plugin/ebpf_vfs.c
+++ b/collectors/ebpf.plugin/ebpf_vfs.c
@@ -34,17 +34,6 @@ struct config vfs_config = { .first_section = NULL,
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
-struct netdata_static_thread vfs_threads = {
- .name = "VFS KERNEL",
- .config_section = NULL,
- .config_name = NULL,
- .env_name = NULL,
- .enabled = 1,
- .thread = NULL,
- .init_routine = NULL,
- .start_routine = NULL
-};
-
netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = "vfs_read", .mode = EBPF_LOAD_TRAMPOLINE},
@@ -357,7 +346,7 @@ static void ebpf_vfs_disable_release_task(struct vfs_bpf *obj)
* @param obj is the main structure for bpf objects.
* @param em structure with configuration
*
- * @return it returns 0 on succes and -1 otherwise
+ * @return it returns 0 on success and -1 otherwise
*/
static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *em)
{
@@ -409,16 +398,11 @@ static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *e
static void ebpf_vfs_free(ebpf_module_t *em)
{
pthread_mutex_lock(&ebpf_exit_cleanup);
- if (em->thread->enabled == NETDATA_THREAD_EBPF_RUNNING) {
- em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
- pthread_mutex_unlock(&ebpf_exit_cleanup);
- return;
- }
+ em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
pthread_mutex_unlock(&ebpf_exit_cleanup);
freez(vfs_hash_values);
freez(vfs_vector);
- freez(vfs_threads.thread);
#ifdef LIBBPF_MAJOR_VERSION
if (bpf_obj)
@@ -440,18 +424,6 @@ static void ebpf_vfs_free(ebpf_module_t *em)
static void ebpf_vfs_exit(void *ptr)
{
ebpf_module_t *em = (ebpf_module_t *)ptr;
- netdata_thread_cancel(*vfs_threads.thread);
- ebpf_vfs_free(em);
-}
-
-/**
-* Clean up the main thread.
-*
-* @param ptr thread data.
-**/
-static void ebpf_vfs_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
ebpf_vfs_free(em);
}
@@ -518,7 +490,7 @@ static void ebpf_vfs_send_data(ebpf_module_t *em)
/**
* Read the hash table and store data to allocated vectors.
*/
-static void read_global_table()
+static void ebpf_vfs_read_global_table()
{
uint64_t idx;
netdata_idx_t res[NETDATA_VFS_COUNTER];
@@ -874,36 +846,6 @@ static void read_update_vfs_cgroup()
}
/**
- * VFS read hash
- *
- * This is the thread callback.
- * This thread is necessary, because we cannot freeze the whole plugin to read the data.
- *
- * @param ptr It is a NULL value for this thread.
- *
- * @return It always returns NULL.
- */
-void *ebpf_vfs_read_hash(void *ptr)
-{
- netdata_thread_cleanup_push(ebpf_vfs_cleanup, ptr);
- heartbeat_t hb;
- heartbeat_init(&hb);
-
- ebpf_module_t *em = (ebpf_module_t *)ptr;
-
- usec_t step = NETDATA_LATENCY_VFS_SLEEP_MS * em->update_every;
- //This will be cancelled by its parent
- while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
-
- read_global_table();
- }
-
- netdata_thread_cleanup_pop(1);
- return NULL;
-}
-
-/**
* Sum PIDs
*
* Sum values for all targets.
@@ -1525,22 +1467,19 @@ static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em)
*/
static void vfs_collector(ebpf_module_t *em)
{
- vfs_threads.thread = mallocz(sizeof(netdata_thread_t));
- vfs_threads.start_routine = ebpf_vfs_read_hash;
-
- netdata_thread_create(vfs_threads.thread, vfs_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
- ebpf_vfs_read_hash, em);
-
int cgroups = em->cgroup_charts;
heartbeat_t hb;
heartbeat_init(&hb);
- usec_t step = em->update_every * USEC_PER_SEC;
+ int update_every = em->update_every;
+ int counter = update_every - 1;
while (!ebpf_exit_plugin) {
- (void)heartbeat_next(&hb, step);
- if (ebpf_exit_plugin)
- break;
+ (void)heartbeat_next(&hb, USEC_PER_SEC);
+ if (ebpf_exit_plugin || ++counter != update_every)
+ continue;
+ counter = 0;
netdata_apps_integration_flags_t apps = em->apps_charts;
+ ebpf_vfs_read_global_table();
pthread_mutex_lock(&collect_data_mutex);
if (apps)
ebpf_vfs_read_apps();
diff --git a/collectors/ebpf.plugin/ebpf_vfs.h b/collectors/ebpf.plugin/ebpf_vfs.h
index 2e3c7cc2..d7fc2672 100644
--- a/collectors/ebpf.plugin/ebpf_vfs.h
+++ b/collectors/ebpf.plugin/ebpf_vfs.h
@@ -8,8 +8,6 @@
#define NETDATA_DIRECTORY_VFS_CONFIG_FILE "vfs.conf"
-#define NETDATA_LATENCY_VFS_SLEEP_MS 750000ULL
-
// Global chart name
#define NETDATA_VFS_FILE_CLEAN_COUNT "vfs_deleted_objects"
#define NETDATA_VFS_FILE_IO_COUNT "vfs_io"