diff options
Diffstat (limited to 'collectors/ebpf.plugin/ebpf_cgroup.c')
-rw-r--r-- | collectors/ebpf.plugin/ebpf_cgroup.c | 392 |
1 files changed, 0 insertions, 392 deletions
diff --git a/collectors/ebpf.plugin/ebpf_cgroup.c b/collectors/ebpf.plugin/ebpf_cgroup.c deleted file mode 100644 index 1aadfbaf..00000000 --- a/collectors/ebpf.plugin/ebpf_cgroup.c +++ /dev/null @@ -1,392 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include <sys/resource.h> - -#include "ebpf.h" -#include "ebpf_cgroup.h" - -ebpf_cgroup_target_t *ebpf_cgroup_pids = NULL; -static void *ebpf_mapped_memory = NULL; -int send_cgroup_chart = 0; - -// -------------------------------------------------------------------------------------------------------------------- -// Map shared memory - -/** - * Map Shared Memory locally - * - * Map the shared memory for current process - * - * @param fd file descriptor returned after shm_open was called. - * @param length length of the shared memory - * - * @return It returns a pointer to the region mapped on success and MAP_FAILED otherwise. - */ -static inline void *ebpf_cgroup_map_shm_locally(int fd, size_t length) -{ - void *value; - - value = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (!value) { - netdata_log_error("Cannot map shared memory used between eBPF and cgroup, integration between processes won't happen"); - close(shm_fd_ebpf_cgroup); - shm_fd_ebpf_cgroup = -1; - shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME); - } - - return value; -} - -/** - * Unmap Shared Memory - * - * Unmap shared memory used to integrate eBPF and cgroup plugin - */ -void ebpf_unmap_cgroup_shared_memory() -{ - munmap(ebpf_mapped_memory, shm_ebpf_cgroup.header->body_length); -} - -/** - * Map cgroup shared memory - * - * Map cgroup shared memory from cgroup to plugin - */ -void ebpf_map_cgroup_shared_memory() -{ - static int limit_try = 0; - static time_t next_try = 0; - - if (shm_ebpf_cgroup.header || limit_try > NETDATA_EBPF_CGROUP_MAX_TRIES) - return; - - time_t curr_time = time(NULL); - if (curr_time < next_try) - return; - - limit_try++; - next_try = curr_time + NETDATA_EBPF_CGROUP_NEXT_TRY_SEC; - - if (shm_fd_ebpf_cgroup < 0) { - shm_fd_ebpf_cgroup = shm_open(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME, O_RDWR, 0660); - if (shm_fd_ebpf_cgroup < 0) { - if (limit_try == NETDATA_EBPF_CGROUP_MAX_TRIES) - netdata_log_error("Shared memory was not initialized, integration between processes won't happen."); - - return; - } - } - - // Map only header - void *mapped = (netdata_ebpf_cgroup_shm_header_t *) ebpf_cgroup_map_shm_locally(shm_fd_ebpf_cgroup, - sizeof(netdata_ebpf_cgroup_shm_header_t)); - if (unlikely(mapped == SEM_FAILED)) { - return; - } - netdata_ebpf_cgroup_shm_header_t *header = mapped; - - size_t length = header->body_length; - - munmap(header, sizeof(netdata_ebpf_cgroup_shm_header_t)); - - if (length <= ((sizeof(netdata_ebpf_cgroup_shm_header_t) + sizeof(netdata_ebpf_cgroup_shm_body_t)))) { - return; - } - - ebpf_mapped_memory = (void *)ebpf_cgroup_map_shm_locally(shm_fd_ebpf_cgroup, length); - if (unlikely(ebpf_mapped_memory == MAP_FAILED)) { - return; - } - shm_ebpf_cgroup.header = ebpf_mapped_memory; - shm_ebpf_cgroup.body = ebpf_mapped_memory + sizeof(netdata_ebpf_cgroup_shm_header_t); - - shm_sem_ebpf_cgroup = sem_open(NETDATA_NAMED_SEMAPHORE_EBPF_CGROUP_NAME, O_CREAT, 0660, 1); - - if (shm_sem_ebpf_cgroup == SEM_FAILED) { - netdata_log_error("Cannot create semaphore, integration between eBPF and cgroup won't happen"); - limit_try = NETDATA_EBPF_CGROUP_MAX_TRIES + 1; - munmap(ebpf_mapped_memory, length); - shm_ebpf_cgroup.header = NULL; - shm_ebpf_cgroup.body = NULL; - close(shm_fd_ebpf_cgroup); - shm_fd_ebpf_cgroup = -1; - shm_unlink(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME); - } -} - -// -------------------------------------------------------------------------------------------------------------------- -// Close and Cleanup - -/** - * Clean Specific cgroup pid - * - * Clean all PIDs associated with cgroup. - * - * @param pt structure pid on target that will have your PRs removed - */ -static inline void ebpf_clean_specific_cgroup_pids(struct pid_on_target2 *pt) -{ - while (pt) { - struct pid_on_target2 *next_pid = pt->next; - - freez(pt); - pt = next_pid; - } -} - -/** - * Remove Cgroup Update Target Update List - * - * Remove from cgroup target and update the link list - */ -static void ebpf_remove_cgroup_target_update_list() -{ - ebpf_cgroup_target_t *next, *ect = ebpf_cgroup_pids; - ebpf_cgroup_target_t *prev = ebpf_cgroup_pids; - while (ect) { - next = ect->next; - if (!ect->updated) { - if (ect == ebpf_cgroup_pids) { - ebpf_cgroup_pids = next; - prev = next; - } else { - prev->next = next; - } - - ebpf_clean_specific_cgroup_pids(ect->pids); - freez(ect); - } else { - prev = ect; - } - - ect = next; - } -} - -// -------------------------------------------------------------------------------------------------------------------- -// Fill variables - -/** - * Set Target Data - * - * Set local variable values according shared memory information. - * - * @param out local output variable. - * @param ptr input from shared memory. - */ -static inline void ebpf_cgroup_set_target_data(ebpf_cgroup_target_t *out, netdata_ebpf_cgroup_shm_body_t *ptr) -{ - out->hash = ptr->hash; - snprintfz(out->name, 255, "%s", ptr->name); - out->systemd = ptr->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE; - out->updated = 1; -} - -/** - * Find or create - * - * Find the structure inside the link list or allocate and link when it is not present. - * - * @param ptr Input from shared memory. - * - * @return It returns a pointer for the structure associated with the input. - */ -static ebpf_cgroup_target_t * ebpf_cgroup_find_or_create(netdata_ebpf_cgroup_shm_body_t *ptr) -{ - ebpf_cgroup_target_t *ect, *prev; - for (ect = ebpf_cgroup_pids, prev = ebpf_cgroup_pids; ect; prev = ect, ect = ect->next) { - if (ect->hash == ptr->hash && !strcmp(ect->name, ptr->name)) { - ect->updated = 1; - return ect; - } - } - - ebpf_cgroup_target_t *new_ect = callocz(1, sizeof(ebpf_cgroup_target_t)); - - ebpf_cgroup_set_target_data(new_ect, ptr); - if (!ebpf_cgroup_pids) { - ebpf_cgroup_pids = new_ect; - } else { - prev->next = new_ect; - } - - return new_ect; -} - -/** - * Update pid link list - * - * Update PIDs list associated with specific cgroup. - * - * @param ect cgroup structure where pids will be stored - * @param path file with PIDs associated to cgroup. - */ -static void ebpf_update_pid_link_list(ebpf_cgroup_target_t *ect, char *path) -{ - procfile *ff = procfile_open_no_log(path, " \t:", PROCFILE_FLAG_DEFAULT); - if (!ff) - return; - - ff = procfile_readall(ff); - if (!ff) - return; - - size_t lines = procfile_lines(ff), l; - for (l = 0; l < lines ;l++) { - int pid = (int)str2l(procfile_lineword(ff, l, 0)); - if (pid) { - struct pid_on_target2 *pt, *prev; - for (pt = ect->pids, prev = ect->pids; pt; prev = pt, pt = pt->next) { - if (pt->pid == pid) - break; - } - - if (!pt) { - struct pid_on_target2 *w = callocz(1, sizeof(struct pid_on_target2)); - w->pid = pid; - if (!ect->pids) - ect->pids = w; - else - prev->next = w; - } - } - } - - procfile_close(ff); -} - -/** - * Set remove var - * - * Set variable remove. If this variable is not reset, the structure will be removed from link list. - */ -void ebpf_reset_updated_var() - { - ebpf_cgroup_target_t *ect; - for (ect = ebpf_cgroup_pids; ect; ect = ect->next) { - ect->updated = 0; - } - } - -/** - * Parse cgroup shared memory - * - * This function is responsible to copy necessary data from shared memory to local memory. - */ -void ebpf_parse_cgroup_shm_data() -{ - static int previous = 0; - if (!shm_ebpf_cgroup.header || shm_sem_ebpf_cgroup == SEM_FAILED) - return; - - sem_wait(shm_sem_ebpf_cgroup); - int i, end = shm_ebpf_cgroup.header->cgroup_root_count; - if (end <= 0) { - sem_post(shm_sem_ebpf_cgroup); - return; - } - - pthread_mutex_lock(&mutex_cgroup_shm); - ebpf_remove_cgroup_target_update_list(); - - ebpf_reset_updated_var(); - - for (i = 0; i < end; i++) { - netdata_ebpf_cgroup_shm_body_t *ptr = &shm_ebpf_cgroup.body[i]; - if (ptr->enabled) { - ebpf_cgroup_target_t *ect = ebpf_cgroup_find_or_create(ptr); - ebpf_update_pid_link_list(ect, ptr->path); - } - } - send_cgroup_chart = previous != shm_ebpf_cgroup.header->cgroup_root_count; - previous = shm_ebpf_cgroup.header->cgroup_root_count; - sem_post(shm_sem_ebpf_cgroup); - pthread_mutex_unlock(&mutex_cgroup_shm); -#ifdef NETDATA_DEV_MODE - netdata_log_info("Updating cgroup %d (Previous: %d, Current: %d)", - send_cgroup_chart, previous, shm_ebpf_cgroup.header->cgroup_root_count); -#endif - - sem_post(shm_sem_ebpf_cgroup); -} - -// -------------------------------------------------------------------------------------------------------------------- -// Create charts - -/** - * Create charts on systemd submenu - * - * @param id the chart id - * @param title the value displayed on vertical axis. - * @param units the value displayed on vertical axis. - * @param family Submenu that the chart will be attached on dashboard. - * @param charttype chart type - * @param order the chart order - * @param algorithm the algorithm used by dimension - * @param context add context for chart - * @param module chart module name, this is the eBPF thread. - * @param update_every value to overwrite the update frequency set by the server. - */ -void ebpf_create_charts_on_systemd(char *id, char *title, char *units, char *family, char *charttype, int order, - char *algorithm, char *context, char *module, int update_every) -{ - ebpf_cgroup_target_t *w; - ebpf_write_chart_cmd(NETDATA_SERVICE_FAMILY, id, "", title, units, family, charttype, context, - order, update_every, module); - - for (w = ebpf_cgroup_pids; w; w = w->next) { - if (unlikely(w->systemd) && unlikely(w->updated)) - fprintf(stdout, "DIMENSION %s '' %s 1 1\n", w->name, algorithm); - } -} - -// -------------------------------------------------------------------------------------------------------------------- -// Cgroup main thread - -/** - * CGROUP exit - * - * Clean up the main thread. - * - * @param ptr thread data. - */ -static void ebpf_cgroup_exit(void *ptr) -{ - UNUSED(ptr); -} - -/** - * Cgroup integratin - * - * Thread responsible to call functions responsible to sync data between plugins. - * - * @param ptr It is a NULL value for this thread. - * - * @return It always returns NULL. - */ -void *ebpf_cgroup_integration(void *ptr) -{ - netdata_thread_cleanup_push(ebpf_cgroup_exit, ptr); - - 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_plugin_exit) { - (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(); - else - ebpf_parse_cgroup_shm_data(); - } - } - - netdata_thread_cleanup_pop(1); - return NULL; -} |