summaryrefslogtreecommitdiffstats
path: root/src/collectors/ebpf.plugin/ebpf_apps.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/collectors/ebpf.plugin/ebpf_apps.c (renamed from collectors/ebpf.plugin/ebpf_apps.c)445
1 files changed, 60 insertions, 385 deletions
diff --git a/collectors/ebpf.plugin/ebpf_apps.c b/src/collectors/ebpf.plugin/ebpf_apps.c
index 10c452267..a17cdb33d 100644
--- a/collectors/ebpf.plugin/ebpf_apps.c
+++ b/src/collectors/ebpf.plugin/ebpf_apps.c
@@ -7,24 +7,6 @@
// ----------------------------------------------------------------------------
// ARAL vectors used to speed up processing
ARAL *ebpf_aral_apps_pid_stat = NULL;
-ARAL *ebpf_aral_process_stat = NULL;
-ARAL *ebpf_aral_socket_pid = NULL;
-ARAL *ebpf_aral_cachestat_pid = NULL;
-ARAL *ebpf_aral_dcstat_pid = NULL;
-ARAL *ebpf_aral_vfs_pid = NULL;
-ARAL *ebpf_aral_fd_pid = NULL;
-ARAL *ebpf_aral_shm_pid = NULL;
-
-// ----------------------------------------------------------------------------
-// Global vectors used with apps
-ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
-netdata_publish_cachestat_t **cachestat_pid = NULL;
-netdata_publish_dcstat_t **dcstat_pid = NULL;
-netdata_publish_swap_t **swap_pid = NULL;
-netdata_publish_vfs_t **vfs_pid = NULL;
-netdata_fd_stat_t **fd_pid = NULL;
-netdata_publish_shm_t **shm_pid = NULL;
-ebpf_process_stat_t **global_process_stats = NULL;
/**
* eBPF ARAL Init
@@ -41,8 +23,6 @@ void ebpf_aral_init(void)
ebpf_aral_apps_pid_stat = ebpf_allocate_pid_aral("ebpf_pid_stat", sizeof(struct ebpf_pid_stat));
- ebpf_aral_process_stat = ebpf_allocate_pid_aral(NETDATA_EBPF_PROC_ARAL_NAME, sizeof(ebpf_process_stat_t));
-
#ifdef NETDATA_DEV_MODE
netdata_log_info("Plugin is using ARAL with values %d", NETDATA_EBPF_ALLOC_MAX_PID);
#endif
@@ -72,266 +52,6 @@ void ebpf_pid_stat_release(struct ebpf_pid_stat *stat)
aral_freez(ebpf_aral_apps_pid_stat, stat);
}
-/*****************************************************************
- *
- * PROCESS ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF process stat get
- *
- * Get a ebpf_pid_stat entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-ebpf_process_stat_t *ebpf_process_stat_get(void)
-{
- ebpf_process_stat_t *target = aral_mallocz(ebpf_aral_process_stat);
- memset(target, 0, sizeof(ebpf_process_stat_t));
- return target;
-}
-
-/**
- * eBPF process release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_process_stat_release(ebpf_process_stat_t *stat)
-{
- aral_freez(ebpf_aral_process_stat, stat);
-}
-
-/*****************************************************************
- *
- * SOCKET ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF socket Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_socket_aral_init()
-{
- ebpf_aral_socket_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_SOCKET_ARAL_NAME, sizeof(ebpf_socket_publish_apps_t));
-}
-
-/**
- * eBPF socket get
- *
- * Get a ebpf_socket_publish_apps_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-ebpf_socket_publish_apps_t *ebpf_socket_stat_get(void)
-{
- ebpf_socket_publish_apps_t *target = aral_mallocz(ebpf_aral_socket_pid);
- memset(target, 0, sizeof(ebpf_socket_publish_apps_t));
- return target;
-}
-
-/*****************************************************************
- *
- * CACHESTAT ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF Cachestat Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_cachestat_aral_init()
-{
- ebpf_aral_cachestat_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_CACHESTAT_ARAL_NAME, sizeof(netdata_publish_cachestat_t));
-}
-
-/**
- * eBPF publish cachestat get
- *
- * Get a netdata_publish_cachestat_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-netdata_publish_cachestat_t *ebpf_publish_cachestat_get(void)
-{
- netdata_publish_cachestat_t *target = aral_mallocz(ebpf_aral_cachestat_pid);
- memset(target, 0, sizeof(netdata_publish_cachestat_t));
- return target;
-}
-
-/**
- * eBPF cachestat release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_cachestat_release(netdata_publish_cachestat_t *stat)
-{
- aral_freez(ebpf_aral_cachestat_pid, stat);
-}
-
-/*****************************************************************
- *
- * DCSTAT ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF directory cache Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_dcstat_aral_init()
-{
- ebpf_aral_dcstat_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_DCSTAT_ARAL_NAME, sizeof(netdata_publish_dcstat_t));
-}
-
-/**
- * eBPF publish dcstat get
- *
- * Get a netdata_publish_dcstat_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-netdata_publish_dcstat_t *ebpf_publish_dcstat_get(void)
-{
- netdata_publish_dcstat_t *target = aral_mallocz(ebpf_aral_dcstat_pid);
- memset(target, 0, sizeof(netdata_publish_dcstat_t));
- return target;
-}
-
-/**
- * eBPF dcstat release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_dcstat_release(netdata_publish_dcstat_t *stat)
-{
- aral_freez(ebpf_aral_dcstat_pid, stat);
-}
-
-/*****************************************************************
- *
- * VFS ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF VFS Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_vfs_aral_init()
-{
- ebpf_aral_vfs_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_VFS_ARAL_NAME, sizeof(netdata_publish_vfs_t));
-}
-
-/**
- * eBPF publish VFS get
- *
- * Get a netdata_publish_vfs_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-netdata_publish_vfs_t *ebpf_vfs_get(void)
-{
- netdata_publish_vfs_t *target = aral_mallocz(ebpf_aral_vfs_pid);
- memset(target, 0, sizeof(netdata_publish_vfs_t));
- return target;
-}
-
-/**
- * eBPF VFS release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_vfs_release(netdata_publish_vfs_t *stat)
-{
- aral_freez(ebpf_aral_vfs_pid, stat);
-}
-
-/*****************************************************************
- *
- * FD ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF file descriptor Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_fd_aral_init()
-{
- ebpf_aral_fd_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_FD_ARAL_NAME, sizeof(netdata_fd_stat_t));
-}
-
-/**
- * eBPF publish file descriptor get
- *
- * Get a netdata_fd_stat_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-netdata_fd_stat_t *ebpf_fd_stat_get(void)
-{
- netdata_fd_stat_t *target = aral_mallocz(ebpf_aral_fd_pid);
- memset(target, 0, sizeof(netdata_fd_stat_t));
- return target;
-}
-
-/**
- * eBPF file descriptor release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_fd_release(netdata_fd_stat_t *stat)
-{
- aral_freez(ebpf_aral_fd_pid, stat);
-}
-
-/*****************************************************************
- *
- * SHM ARAL FUNCTIONS
- *
- *****************************************************************/
-
-/**
- * eBPF shared memory Aral init
- *
- * Initiallize array allocator that will be used when integration with apps is enabled.
- */
-void ebpf_shm_aral_init()
-{
- ebpf_aral_shm_pid = ebpf_allocate_pid_aral(NETDATA_EBPF_SHM_ARAL_NAME, sizeof(netdata_publish_shm_t));
-}
-
-/**
- * eBPF shared memory get
- *
- * Get a netdata_publish_shm_t entry to be used with a specific PID.
- *
- * @return it returns the address on success.
- */
-netdata_publish_shm_t *ebpf_shm_stat_get(void)
-{
- netdata_publish_shm_t *target = aral_mallocz(ebpf_aral_shm_pid);
- memset(target, 0, sizeof(netdata_publish_shm_t));
- return target;
-}
-
-/**
- * eBPF shared memory release
- *
- * @param stat Release a target after usage.
- */
-void ebpf_shm_release(netdata_publish_shm_t *stat)
-{
- aral_freez(ebpf_aral_shm_pid, stat);
-}
-
// ----------------------------------------------------------------------------
// internal flags
// handled in code (automatically set)
@@ -372,24 +92,6 @@ int ebpf_read_hash_table(void *ep, int fd, uint32_t pid)
*****************************************************************/
/**
- * Am I running as Root
- *
- * Verify the user that is running the collector.
- *
- * @return It returns 1 for root and 0 otherwise.
- */
-int am_i_running_as_root()
-{
- uid_t uid = getuid(), euid = geteuid();
-
- if (uid == 0 || euid == 0) {
- return 1;
- }
-
- return 0;
-}
-
-/**
* Reset the target values
*
* @param root the pointer to the chain that will be reset.
@@ -753,14 +455,19 @@ static inline int managed_log(struct ebpf_pid_stat *p, uint32_t log, int status)
*
* Get or allocate the PID entry for the specified pid.
*
- * @param pid the pid to search the data.
+ * @param pid the pid to search the data.
+ * @param tgid the task group id
*
* @return It returns the pid entry structure
*/
-static inline struct ebpf_pid_stat *get_pid_entry(pid_t pid)
+ebpf_pid_stat_t *ebpf_get_pid_entry(pid_t pid, pid_t tgid)
{
- if (unlikely(ebpf_all_pids[pid]))
+ ebpf_pid_stat_t *ptr = ebpf_all_pids[pid];
+ if (unlikely(ptr)) {
+ if (!ptr->ppid && tgid)
+ ptr->ppid = tgid;
return ebpf_all_pids[pid];
+ }
struct ebpf_pid_stat *p = ebpf_pid_stat_get();
@@ -771,6 +478,7 @@ static inline struct ebpf_pid_stat *get_pid_entry(pid_t pid)
ebpf_root_of_pids = p;
p->pid = pid;
+ p->ppid = tgid;
ebpf_all_pids[pid] = p;
ebpf_all_pids_count++;
@@ -951,14 +659,14 @@ static inline int read_proc_pid_stat(struct ebpf_pid_stat *p, void *ptr)
*
* @return It returns 1 on success and 0 otherwise
*/
-static inline int collect_data_for_pid(pid_t pid, void *ptr)
+static inline int ebpf_collect_data_for_pid(pid_t pid, void *ptr)
{
if (unlikely(pid < 0 || pid > pid_max)) {
netdata_log_error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, 0, pid_max);
return 0;
}
- struct ebpf_pid_stat *p = get_pid_entry(pid);
+ ebpf_pid_stat_t *p = ebpf_get_pid_entry(pid, 0);
if (unlikely(!p || p->read))
return 0;
p->read = 1;
@@ -1164,7 +872,7 @@ static inline void post_aggregate_targets(struct ebpf_target *root)
*
* @param pid the PID that will be removed.
*/
-static inline void del_pid_entry(pid_t pid)
+static inline void ebpf_del_pid_entry(pid_t pid)
{
struct ebpf_pid_stat *p = ebpf_all_pids[pid];
@@ -1201,6 +909,7 @@ static inline void del_pid_entry(pid_t pid)
}
JudyLFreeArray(&pid_ptr->socket_stats.JudyLArray, PJE0);
}
+ aral_freez(ebpf_judy_pid.pid_table, pid_ptr);
JudyLDel(&ebpf_judy_pid.index.JudyLArray, p->pid, PJE0);
}
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
@@ -1240,79 +949,23 @@ int get_pid_comm(pid_t pid, size_t n, char *dest)
}
/**
- * Cleanup variable from other threads
- *
- * @param pid current pid.
- */
-void cleanup_variables_from_other_threads(uint32_t pid)
-{
- // Clean cachestat structure
- if (cachestat_pid) {
- ebpf_cachestat_release(cachestat_pid[pid]);
- cachestat_pid[pid] = NULL;
- }
-
- // Clean directory cache structure
- if (dcstat_pid) {
- ebpf_dcstat_release(dcstat_pid[pid]);
- dcstat_pid[pid] = NULL;
- }
-
- // Clean swap structure
- if (swap_pid) {
- freez(swap_pid[pid]);
- swap_pid[pid] = NULL;
- }
-
- // Clean vfs structure
- if (vfs_pid) {
- ebpf_vfs_release(vfs_pid[pid]);
- vfs_pid[pid] = NULL;
- }
-
- // Clean fd structure
- if (fd_pid) {
- ebpf_fd_release(fd_pid[pid]);
- fd_pid[pid] = NULL;
- }
-
- // Clean shm structure
- if (shm_pid) {
- ebpf_shm_release(shm_pid[pid]);
- shm_pid[pid] = NULL;
- }
-}
-
-/**
* Remove PIDs when they are not running more.
*/
-void cleanup_exited_pids()
+void ebpf_cleanup_exited_pids(int max)
{
struct ebpf_pid_stat *p = NULL;
for (p = ebpf_root_of_pids; p;) {
- if (!p->updated && (!p->keep || p->keeploops > 0)) {
+ if (p->not_updated > max) {
if (unlikely(debug_enabled && (p->keep || p->keeploops)))
debug_log(" > CLEANUP cannot keep exited process %d (%s) anymore - removing it.", p->pid, p->comm);
pid_t r = p->pid;
p = p->next;
- // Clean process structure
- if (global_process_stats) {
- ebpf_process_stat_release(global_process_stats[r]);
- global_process_stats[r] = NULL;
- }
-
- cleanup_variables_from_other_threads(r);
-
- del_pid_entry(r);
- } else {
- if (unlikely(p->keep))
- p->keeploops++;
- p->keep = 0;
- p = p->next;
+ ebpf_del_pid_entry(r);
}
+ p = p->next;
}
}
@@ -1344,7 +997,7 @@ static inline void read_proc_filesystem()
if (unlikely(endptr == de->d_name || *endptr != '\0'))
continue;
- collect_data_for_pid(pid, NULL);
+ ebpf_collect_data_for_pid(pid, NULL);
}
closedir(dir);
}
@@ -1400,6 +1053,31 @@ void ebpf_process_apps_accumulator(ebpf_process_stat_t *out, int maps_per_core)
}
/**
+ * Sum values for pid
+ *
+ * @param structure to store result.
+ * @param root the structure with all available PIDs
+ */
+void ebpf_process_sum_values_for_pids(ebpf_process_stat_t *process, struct ebpf_pid_on_target *root)
+{
+ memset(process, 0, sizeof(ebpf_process_stat_t));
+ while (root) {
+ int32_t pid = root->pid;
+ ebpf_pid_stat_t *local_pid = ebpf_get_pid_entry(pid, 0);
+ if (local_pid) {
+ ebpf_process_stat_t *in = &local_pid->process;
+ process->task_err += in->task_err;
+ process->release_call += in->release_call;
+ process->exit_call += in->exit_call;
+ process->create_thread += in->create_thread;
+ process->create_process += in->create_process;
+ }
+
+ root = root->next;
+ }
+}
+
+/**
* Collect data for all process
*
* Read data from hash table and store it in appropriate vectors.
@@ -1431,42 +1109,31 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core)
read_proc_filesystem();
- uint32_t key;
pids = ebpf_root_of_pids; // global list of all processes running
- // while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
if (tbl_pid_stats_fd != -1) {
size_t length = sizeof(ebpf_process_stat_t);
if (maps_per_core)
length *= ebpf_nprocs;
- while (pids) {
- key = pids->pid;
-
- ebpf_process_stat_t *w = global_process_stats[key];
- if (!w) {
- w = ebpf_process_stat_get();
- global_process_stats[key] = w;
- }
+ uint32_t key = 0, next_key = 0;
+ while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
+ ebpf_pid_stat_t *local_pid = ebpf_get_pid_entry(key, 0);
+ if (!local_pid)
+ goto end_process_loop;
+ ebpf_process_stat_t *w = &local_pid->process;
if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, process_stat_vector)) {
- // Clean Process structures
- ebpf_process_stat_release(w);
- global_process_stats[key] = NULL;
-
- cleanup_variables_from_other_threads(key);
-
- pids = pids->next;
- continue;
+ goto end_process_loop;
}
ebpf_process_apps_accumulator(process_stat_vector, maps_per_core);
memcpy(w, process_stat_vector, sizeof(ebpf_process_stat_t));
+end_process_loop:
memset(process_stat_vector, 0, length);
-
- pids = pids->next;
+ key = next_key;
}
}
@@ -1482,4 +1149,12 @@ void collect_data_for_all_processes(int tbl_pid_stats_fd, int maps_per_core)
aggregate_pid_on_target(pids->target, pids, NULL);
post_aggregate_targets(apps_groups_root_target);
+
+ struct ebpf_target *w;
+ for (w = apps_groups_root_target; w; w = w->next) {
+ if (unlikely(!(w->processes)))
+ continue;
+
+ ebpf_process_sum_values_for_pids(&w->process, w->root_pid);
+ }
}