summaryrefslogtreecommitdiffstats
path: root/collectors/ebpf.plugin/ebpf.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/ebpf.plugin/ebpf.c')
-rw-r--r--collectors/ebpf.plugin/ebpf.c1306
1 files changed, 448 insertions, 858 deletions
diff --git a/collectors/ebpf.plugin/ebpf.c b/collectors/ebpf.plugin/ebpf.c
index 3648ad54c2..8ef20b03fc 100644
--- a/collectors/ebpf.plugin/ebpf.c
+++ b/collectors/ebpf.plugin/ebpf.c
@@ -35,409 +35,154 @@ void netdata_cleanup_and_exit(int ret) {
}
// ----------------------------------------------------------------------
-//Netdata eBPF library
-void *libnetdata = NULL;
-int (*load_bpf_file)(char *, int) = NULL;
-int (*set_bpf_perf_event)(int, int);
-int (*perf_event_unmap)(struct perf_event_mmap_page *, size_t);
-int (*perf_event_mmap_header)(int, struct perf_event_mmap_page **, int);
-void (*netdata_perf_loop_multi)(int *, struct perf_event_mmap_page **, int, int *, int (*nsb)(void *, int), int);
-int *map_fd = NULL;
-
-//Perf event variables
-static int pmu_fd[NETDATA_MAX_PROCESSOR];
-static struct perf_event_mmap_page *headers[NETDATA_MAX_PROCESSOR];
-int page_cnt = 8;
-
-//Libbpf (It is necessary to have at least kernel 4.10)
-int (*bpf_map_lookup_elem)(int, const void *, void *);
-
-static char *plugin_dir = PLUGINS_DIR;
-static char *user_config_dir = CONFIG_DIR;
-static char *stock_config_dir = LIBCONFIG_DIR;
-static char *netdata_configured_log_dir = LOG_DIR;
-
-FILE *developer_log = NULL;
-
-//Global vectors
-netdata_syscall_stat_t *aggregated_data = NULL;
-netdata_publish_syscall_t *publish_aggregated = NULL;
+char *ebpf_plugin_dir = PLUGINS_DIR;
+static char *ebpf_user_config_dir = CONFIG_DIR;
+static char *ebpf_stock_config_dir = LIBCONFIG_DIR;
+static char *ebpf_configured_log_dir = LOG_DIR;
static int update_every = 1;
static int thread_finished = 0;
-static int close_plugin = 0;
-static netdata_run_mode_t mode = MODE_ENTRY;
-static int debug_log = 0;
-static int use_stdout = 0;
-struct config collector_config;
-static int mykernel = 0;
-static char kernel_string[64];
-static int nprocs;
+int close_ebpf_plugin = 0;
+struct config collector_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
+ .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
+ .rwlock = AVL_LOCK_INITIALIZER } };
+
+int running_on_kernel = 0;
+char kernel_string[64];
+int ebpf_nprocs;
static int isrh;
netdata_idx_t *hash_values;
pthread_mutex_t lock;
-static struct ebpf_module {
- const char *thread_name;
- int enabled;
- void (*start_routine) (void *);
- int update_time;
- int global_charts;
- int apps_charts;
- netdata_run_mode_t mode;
-} ebpf_modules[] = {
- { .thread_name = "process", .enabled = 0, .start_routine = NULL, .update_time = 1, .global_charts = 1, .apps_charts = 1, .mode = MODE_ENTRY },
- { .thread_name = "network_viewer", .enabled = 0, .start_routine = NULL, .update_time = 1, .global_charts = 1, .apps_charts = 1, .mode = MODE_ENTRY },
- { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1, .global_charts = 0, .apps_charts = 1, .mode = MODE_ENTRY },
+netdata_ebpf_events_t process_probes[] = {
+ { .type = 'r', .name = "vfs_write" },
+ { .type = 'r', .name = "vfs_writev" },
+ { .type = 'r', .name = "vfs_read" },
+ { .type = 'r', .name = "vfs_readv" },
+ { .type = 'r', .name = "do_sys_open" },
+ { .type = 'r', .name = "vfs_unlink" },
+ { .type = 'p', .name = "do_exit" },
+ { .type = 'p', .name = "release_task" },
+ { .type = 'r', .name = "_do_fork" },
+ { .type = 'r', .name = "__close_fd" },
+ { .type = 'r', .name = "__x64_sys_clone" },
+ { .type = 0, .name = NULL }
};
-static char *dimension_names[NETDATA_MAX_MONITOR_VECTOR] = { "open", "close", "delete", "read", "write", "process", "task", "process", "thread" };
-static char *id_names[NETDATA_MAX_MONITOR_VECTOR] = { "do_sys_open", "__close_fd", "vfs_unlink", "vfs_read", "vfs_write", "do_exit", "release_task", "_do_fork", "sys_clone" };
-static char *status[] = { "process", "zombie" };
-
-int event_pid = 0;
-netdata_ebpf_events_t collector_events[] = {
- { .type = 'r', .name = "vfs_write" },
- { .type = 'r', .name = "vfs_writev" },
- { .type = 'r', .name = "vfs_read" },
- { .type = 'r', .name = "vfs_readv" },
- { .type = 'r', .name = "do_sys_open" },
- { .type = 'r', .name = "vfs_unlink" },
- { .type = 'p', .name = "do_exit" },
- { .type = 'p', .name = "release_task" },
- { .type = 'r', .name = "_do_fork" },
- { .type = 'r', .name = "__close_fd" },
- { .type = 'r', .name = "__x64_sys_clone" },
- { .type = 0, .name = NULL }
+netdata_ebpf_events_t socket_probes[] = {
+ { .type = 'r', .name = "tcp_sendmsg" },
+ { .type = 'p', .name = "tcp_cleanup_rbuf" },
+ { .type = 'p', .name = "tcp_close" },
+ { .type = 'p', .name = "udp_recvmsg" },
+ { .type = 'r', .name = "udp_recvmsg" },
+ { .type = 'r', .name = "udp_sendmsg" },
+ { .type = 'p', .name = "do_exit" },
+ { .type = 0, .name = NULL }
};
-void open_developer_log() {
- char filename[FILENAME_MAX+1];
- int tot = sprintf(filename, "%s/%s", netdata_configured_log_dir, NETDATA_DEVELOPER_LOG_FILE);
-
- if(tot > 0)
- developer_log = fopen(filename, "a");
-}
-
-static int unmap_memory() {
- int i;
- int size = (int)sysconf(_SC_PAGESIZE)*(page_cnt + 1);
- for ( i = 0 ; i < nprocs ; i++ ) {
- if (perf_event_unmap(headers[i], size) < 0) {
- fprintf(stderr,"[EBPF PROCESS] CANNOT unmap headers.\n");
- return -1;
- }
-
- close(pmu_fd[i]);
- }
-
- return 0;
-}
+ebpf_module_t ebpf_modules[] = {
+ { .thread_name = "process", .config_name = "process", .enabled = 0, .start_routine = ebpf_process_thread,
+ .update_time = 1, .global_charts = 1, .apps_charts = 1, .mode = MODE_ENTRY, .probes = process_probes },
+ { .thread_name = "socket", .config_name = "network viewer", .enabled = 0, .start_routine = ebpf_socket_thread,
+ .update_time = 1, .global_charts = 1, .apps_charts = 1, .mode = MODE_ENTRY, .probes = socket_probes },
+ { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
+ .global_charts = 0, .apps_charts = 1, .mode = MODE_ENTRY, .probes = NULL },
+};
-static void int_exit(int sig)
+/**
+ * Close the collector gracefully
+ *
+ * @param sig is the signal number used to close the collector
+ */
+static void ebpf_exit(int sig)
{
- close_plugin = 1;
+ int event_pid;
+ close_ebpf_plugin = 1;
//When both threads were not finished case I try to go in front this address, the collector will crash
if (!thread_finished) {
return;
}
- if (aggregated_data) {
- free(aggregated_data);
- aggregated_data = NULL;
- }
-
- if (publish_aggregated) {
- free(publish_aggregated);
- publish_aggregated = NULL;
- }
-
- if(mode == MODE_DEVMODE && debug_log) {
- unmap_memory();
- }
-
- if (libnetdata) {
- dlclose(libnetdata);
- libnetdata = NULL;
- }
-
- if (developer_log) {
- fclose(developer_log);
- developer_log = NULL;
- }
-
- if (hash_values) {
- freez(hash_values);
- }
-
- if (event_pid) {
- int ret = fork();
- if (ret < 0) //error
- error("[EBPF PROCESS] Cannot fork(), so I won't be able to clean %skprobe_events", NETDATA_DEBUGFS);
- else if (!ret) { //child
- int i;
- for ( i=getdtablesize(); i>=0; --i)
- close(i);
-
- int fd = open("/dev/null",O_RDWR, 0);
- if (fd != -1) {
- dup2 (fd, STDIN_FILENO);
- dup2 (fd, STDOUT_FILENO);
- dup2 (fd, STDERR_FILENO);
- }
-
- if (fd > 2)
- close (fd);
-
- int sid = setsid();
- if(sid >= 0) {
- sleep(1);
- if(debug_log) {
- open_developer_log();
- }
- debug(D_EXIT, "Wait for father %d die", event_pid);
- clean_kprobe_events(developer_log, event_pid, collector_events);
- } else {
- error("Cannot become session id leader, so I won't try to clean kprobe_events.\n");
- }
- } else { //parent
- exit(0);
- }
-
- if (developer_log) {
- fclose(developer_log);
- developer_log = NULL;
+ event_pid = getpid();
+ int ret = fork();
+ if (ret < 0) //error
+ error("Cannot fork(), so I won't be able to clean %skprobe_events", NETDATA_DEBUGFS);
+ else if (!ret) { //child
+ int i;
+ for ( i=getdtablesize(); i>=0; --i)
+ close(i);
+
+ int fd = open("/dev/null",O_RDWR, 0);
+ if (fd != -1) {
+ dup2 (fd, STDIN_FILENO);
+ dup2 (fd, STDOUT_FILENO);
+ dup2 (fd, STDERR_FILENO);
}
- }
-
- exit(sig);
-}
-
-static inline void netdata_write_chart_cmd(char *type
- , char *id
- , char *axis
- , char *web
- , int order)
-{
- printf("CHART %s.%s '' '' '%s' '%s' '' line %d 1 ''\n"
- , type
- , id
- , axis
- , web
- , order);
-}
-
-static void netdata_write_global_dimension(char *d, char *n)
-{
- printf("DIMENSION %s %s absolute 1 1\n", d, n);
-}
-
-static void netdata_create_global_dimension(void *ptr, int end)
-{
- netdata_publish_syscall_t *move = ptr;
-
- int i = 0;
- while (move && i < end) {
- netdata_write_global_dimension(move->name, move->dimension);
-
- move = move->next;
- i++;
- }
-}
-static inline void netdata_create_chart(char *family
- , char *name
- , char *axis
- , char *web
- , int order
- , void (*ncd)(void *, int)
- , void *move
- , int end)
-{
- netdata_write_chart_cmd(family, name, axis, web, order);
- ncd(move, end);
-}
-
-static void netdata_create_io_chart(char *family, char *name, char *axis, char *web, int order) {
- printf("CHART %s.%s '' '' '%s' '%s' '' line %d 1 ''\n"
- , family
- , name
- , axis
- , web
- , order);
-
- printf("DIMENSION %s %s absolute 1 1\n", id_names[3], NETDATA_VFS_DIM_OUT_FILE_BYTES);
- printf("DIMENSION %s %s absolute 1 1\n", id_names[4], NETDATA_VFS_DIM_IN_FILE_BYTES);
-}
-
-static void netdata_process_status_chart(char *family, char *name, char *axis, char *web, int order) {
- printf("CHART %s.%s '' '' '%s' '%s' '' line %d 1 ''\n"
- , family
- , name
- , axis
- , web
- , order);
-
- printf("DIMENSION %s '' absolute 1 1\n", status[0]);
- printf("DIMENSION %s '' absolute 1 1\n", status[1]);
-}
-
-static void netdata_global_charts_create() {
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_FILE_OPEN_CLOSE_COUNT
- , "Calls"
- , NETDATA_FILE_GROUP
- , 970
- , netdata_create_global_dimension
- , publish_aggregated
- , 2);
-
- if(mode < MODE_ENTRY) {
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_FILE_OPEN_ERR_COUNT
- , "Calls"
- , NETDATA_FILE_GROUP
- , 971
- , netdata_create_global_dimension
- , publish_aggregated
- , 2);
- }
+ if (fd > 2)
+ close (fd);
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_VFS_FILE_CLEAN_COUNT
- , "Calls"
- , NETDATA_VFS_GROUP
- , 972
- , netdata_create_global_dimension
- , &publish_aggregated[NETDATA_DEL_START]
- , 1);
-
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_VFS_FILE_IO_COUNT
- , "Calls"
- , NETDATA_VFS_GROUP
- , 973
- , netdata_create_global_dimension
- , &publish_aggregated[NETDATA_IN_START_BYTE]
- , 2);
-
- if(mode < MODE_ENTRY) {
- netdata_create_io_chart(NETDATA_EBPF_FAMILY
- , NETDATA_VFS_IO_FILE_BYTES
- , "bytes/s"
- , NETDATA_VFS_GROUP
- , 974);
-
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_VFS_FILE_ERR_COUNT
- , "Calls"
- , NETDATA_VFS_GROUP
- , 975
- , netdata_create_global_dimension
- , &publish_aggregated[2]
- , NETDATA_VFS_ERRORS);
+ int sid = setsid();
+ if(sid >= 0) {
+ sleep(1);
+ debug(D_EXIT, "Wait for father %d die", event_pid);
- }
-
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_PROCESS_SYSCALL
- , "Calls"
- , NETDATA_PROCESS_GROUP
- , 976
- , netdata_create_global_dimension
- , &publish_aggregated[NETDATA_PROCESS_START]
- , 2);
-
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_EXIT_SYSCALL
- , "Calls"
- , NETDATA_PROCESS_GROUP
- , 977
- , netdata_create_global_dimension
- , &publish_aggregated[NETDATA_EXIT_START]
- , 2);
-
- netdata_process_status_chart(NETDATA_EBPF_FAMILY
- , NETDATA_PROCESS_STATUS_NAME
- , "Total"
- , NETDATA_PROCESS_GROUP
- , 978);
-
- if(mode < MODE_ENTRY) {
- netdata_create_chart(NETDATA_EBPF_FAMILY
- , NETDATA_PROCESS_ERROR_NAME
- , "Calls"
- , NETDATA_PROCESS_GROUP
- , 979
- , netdata_create_global_dimension
- , &publish_aggregated[NETDATA_PROCESS_START]
- , 2);
- }
-
-}
-
-
-static void netdata_create_charts() {
- netdata_global_charts_create();
-}
-
-static void netdata_update_publish(netdata_publish_syscall_t *publish
- , netdata_publish_vfs_common_t *pvc
- , netdata_syscall_stat_t *input) {
-
- netdata_publish_syscall_t *move = publish;
- while(move) {
- if(input->call != move->pcall) {
- //This condition happens to avoid initial values with dimensions higher than normal values.
- if(move->pcall) {
- move->ncall = (input->call > move->pcall)?input->call - move->pcall: move->pcall - input->call;
- move->nbyte = (input->bytes > move->pbyte)?input->bytes - move->pbyte: move->pbyte - input->bytes;
- move->nerr = (input->ecall > move->nerr)?input->ecall - move->perr: move->perr - input->ecall;
- } else {
- move->ncall = 0;
- move->nbyte = 0;
- move->nerr = 0;
- }
-
- move->pcall = input->call;
- move->pbyte = input->bytes;
- move->perr = input->ecall;
+ for (event_pid = 0; ebpf_modules[event_pid].probes; event_pid++)
+ clean_kprobe_events(NULL, (int)ebpf_modules[event_pid].thread_id, ebpf_modules[event_pid].probes);
} else {
- move->ncall = 0;
- move->nbyte = 0;
- move->nerr = 0;
+ error("Cannot become session id leader, so I won't try to clean kprobe_events.\n");
}
-
- input = input->next;
- move = move->next;
+ } else { //parent
+ exit(0);
}
- pvc->write = -((long)publish[2].nbyte);
- pvc->read = (long)publish[3].nbyte;
-
- pvc->running = (long)publish[7].ncall - (long)publish[8].ncall;
- publish[6].ncall = -publish[6].ncall; // release
- pvc->zombie = (long)publish[5].ncall + (long)publish[6].ncall;
+ exit(sig);
}
-static inline void write_begin_chart(char *family, char *name)
+/*****************************************************************
+ *
+ * FUNCTIONS TO CREATE CHARTS
+ *
+ *****************************************************************/
+
+/**
+ * Write begin command on standard output
+ *
+ * @param family the chart family name
+ * @param name the chart name
+ */
+void write_begin_chart(char *family, char *name)
{
int ret = printf( "BEGIN %s.%s\n"
- , family
- , name);
+ , family
+ , name);
(void)ret;
}
-static inline void write_chart_dimension(char *dim, long long value)
+/**
+ * Write set command on standard output
+ *
+ * @param dim the dimension name
+ * @param value the value for the dimension
+ */
+void write_chart_dimension(char *dim, long long value)
{
int ret = printf("SET %s = %lld\n", dim, value);
(void)ret;
}
-static void write_global_count_chart(char *name, char *family, netdata_publish_syscall_t *move, int end) {
+/**
+ * Call the necessary functions to create a chart.
+ *
+ * @param name the chart name
+ * @param family the chart family
+ * @param move the pointer with the values that will be published
+ * @param end the number of values that will be written on standard output
+ */
+void write_count_chart(char *name, char *family, netdata_publish_syscall_t *move, int end) {
write_begin_chart(family, name);
int i = 0;
@@ -451,7 +196,15 @@ static void write_global_count_chart(char *name, char *family, netdata_publish_s
printf("END\n");
}
-static void write_global_err_chart(char *name, char *family, netdata_publish_syscall_t *move, int end) {
+/**
+ * Call the necessary functions to create a chart.
+ *
+ * @param name the chart name
+ * @param family the chart family
+ * @param move the pointer with the values that will be published
+ * @param end the number of values that will be written on standard output
+ */
+void write_err_chart(char *name, char *family, netdata_publish_syscall_t *move, int end) {
write_begin_chart(family, name);
int i = 0;
@@ -465,176 +218,129 @@ static void write_global_err_chart(char *name, char *family, netdata_publish_sys
printf("END\n");
}
-static void write_io_chart(char *family, netdata_publish_vfs_common_t *pvc) {
- write_begin_chart(family, NETDATA_VFS_IO_FILE_BYTES);
-
- write_chart_dimension(id_names[3], (long long) pvc->write);
- write_chart_dimension(id_names[4], (long long) pvc->read);
-
- printf("END\n");
-}
-static void write_status_chart(char *family, netdata_publish_vfs_common_t *pvc) {
- write_begin_chart(family, NETDATA_PROCESS_STATUS_NAME);
+/**
+ * Call the necessary functions to create a chart.
+ *
+ * @param family the chart family
+ * @param move the pointer with the values that will be published
+ */
+void write_io_chart(char *chart, char *family, char *dwrite, char *dread, netdata_publish_vfs_common_t *pvc) {
+ write_begin_chart(family, chart);
- write_chart_dimension(status[0], (long long) pvc->running);
- write_chart_dimension(status[1], (long long) pvc->zombie);
+ write_chart_dimension(dwrite, (long long) pvc->write);
+ write_chart_dimension(dread, (long long) pvc->read);
printf("END\n");
}
-static void netdata_publish_data() {
- netdata_publish_vfs_common_t pvc;
- netdata_update_publish(publish_aggregated, &pvc, aggregated_data);
-
- write_global_count_chart(NETDATA_FILE_OPEN_CLOSE_COUNT, NETDATA_EBPF_FAMILY, publish_aggregated, 2);
- write_global_count_chart(NETDATA_VFS_FILE_CLEAN_COUNT, NETDATA_EBPF_FAMILY, &publish_aggregated[NETDATA_DEL_START], 1);
- write_global_count_chart(NETDATA_VFS_FILE_IO_COUNT, NETDATA_EBPF_FAMILY, &publish_aggregated[NETDATA_IN_START_BYTE], 2);
- write_global_count_chart(NETDATA_EXIT_SYSCALL, NETDATA_EBPF_FAMILY, &publish_aggregated[NETDATA_EXIT_START], 2);
- write_global_count_chart(NETDATA_PROCESS_SYSCALL, NETDATA_EBPF_FAMILY, &publish_aggregated[NETDATA_PROCESS_START], 2);
-
- write_status_chart(NETDATA_EBPF_FAMILY, &pvc);
- if(mode < MODE_ENTRY) {
- write_global_err_chart(NETDATA_FILE_OPEN_ERR_COUNT, NETDATA_EBPF_FAMILY, publish_aggregated, 2);
- write_global_err_chart(NETDATA_VFS_FILE_ERR_COUNT, NETDATA_EBPF_FAMILY, &publish_aggregated[2], NETDATA_VFS_ERRORS);
- write_global_err_chart(NETDATA_PROCESS_ERROR_NAME, NETDATA_EBPF_FAMILY, &publish_aggregated[NETDATA_PROCESS_START], 2);
-
- write_io_chart(NETDATA_EBPF_FAMILY, &pvc);
- }
-}
-
-void *process_publisher(void *ptr)
+/**
+ * Write chart cmd on standard output
+ *
+ * @param type the chart type
+ * @param id the chart id
+ * @param axis the axis label
+ * @param web the group name used to attach the chart on dashaboard
+ * @param order the chart order
+ */
+void ebpf_write_chart_cmd(char *type
+ , char *id
+ , char *axis
+ , char *web
+ , int order)
{
- (void)ptr;
- netdata_create_charts();
-
- usec_t step = update_every * USEC_PER_SEC;
- heartbeat_t hb;
- heartbeat_init(&hb);
- while(!close_plugin) {
- usec_t dt = heartbeat_next(&hb, step);
- (void)dt;
-
- pthread_mutex_lock(&lock);
- netdata_publish_data();
- pthread_mutex_unlock(&lock);
-
- fflush(stdout);
- }
-
- return NULL;
-}
-
-static void move_from_kernel2user_global() {
- uint64_t idx;
- netdata_idx_t res[NETDATA_GLOBAL_VECTOR];
-
- netdata_idx_t *val = hash_values;
- for (idx = 0; idx < NETDATA_GLOBAL_VECTOR; idx++) {
- if(!bpf_map_lookup_elem(map_fd[1], &idx, val)) {
- uint64_t total = 0;
- int i;
- int end = (mykernel < NETDATA_KERNEL_V4_15)?1:nprocs;
- for (i = 0; i < end; i++)
- total += val[i];
-
- res[idx] = total;
- } else {
- res[idx] = 0;
- }
- }
-
- aggregated_data[0].call = res[NETDATA_KEY_CALLS_DO_SYS_OPEN];
- aggregated_data[1].call = res[NETDATA_KEY_CALLS_CLOSE_FD];
- aggregated_data[2].call = res[NETDATA_KEY_CALLS_VFS_UNLINK];
- aggregated_data[3].call = res[NETDATA_KEY_CALLS_VFS_READ] + res[NETDATA_KEY_CALLS_VFS_READV];
- aggregated_data[4].call = res[NETDATA_KEY_CALLS_VFS_WRITE] + res[NETDATA_KEY_CALLS_VFS_WRITEV];
- aggregated_data[5].call = res[NETDATA_KEY_CALLS_DO_EXIT];
- aggregated_data[6].call = res[NETDATA_KEY_CALLS_RELEASE_TASK];
- aggregated_data[7].call = res[NETDATA_KEY_CALLS_DO_FORK];
- aggregated_data[8].call = res[NETDATA_KEY_CALLS_SYS_CLONE];
-
- aggregated_data[0].ecall = res[NETDATA_KEY_ERROR_DO_SYS_OPEN];
- aggregated_data[1].ecall = res[NETDATA_KEY_ERROR_CLOSE_FD];
- aggregated_data[2].ecall = res[NETDATA_KEY_ERROR_VFS_UNLINK];
- aggregated_data[3].ecall = res[NETDATA_KEY_ERROR_VFS_READ] + res[NETDATA_KEY_ERROR_VFS_READV];
- aggregated_data[4].ecall = res[NETDATA_KEY_ERROR_VFS_WRITE] + res[NETDATA_KEY_ERROR_VFS_WRITEV];
- aggregated_data[7].ecall = res[NETDATA_KEY_ERROR_DO_FORK];
- aggregated_data[8].ecall = res[NETDATA_KEY_ERROR_SYS_CLONE];
-
- aggregated_data[2].bytes = (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITE] + (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITEV];
- aggregated_data[3].bytes = (uint64_t)res[NETDATA_KEY_BYTES_VFS_READ] + (uint64_t)res[NETDATA_KEY_BYTES_VFS_READV];
-}
-
-static void move_from_kernel2user()
+ printf("CHART %s.%s '' '' '%s' '%s' '' line %d 1 ''\n"
+ , type
+ , id
+ , axis
+ , web
+ , order);
+}
+
+/**
+ * Write the dimension command on standard output
+ *
+ * @param n the dimension name
+ * @param d the dimension information
+ */
+void ebpf_write_global_dimension(char *n, char *d)
{
- move_from_kernel2user_global();
+ printf("DIMENSION %s %s absolute 1 1\n", n, d);
}
-void *process_collector(void *ptr)
+/**
+ * Call ebpf_write_global_dimension to create the dimensions for a specific chart
+ *
+ * @param ptr a pointer to a structure of the type netdata_publish_syscall_t
+ * @param end the number of dimensions for the structure ptr
+ */
+void ebpf_create_global_dimension(void *ptr, int end)
{
- (void)ptr;
-
- usec_t step = 778879ULL;
- heartbeat_t hb;
- heartbeat_init(&hb);
- while(!close_plugin) {
- usec_t dt = heartbeat_next(&hb, step);
- (void)dt;
-
- pthread_mutex_lock(&lock);
- move_from_kernel2user();
- pthread_mutex_unlock(&lock);
- }
-
- return NULL;
-}
-
-static int netdata_store_bpf(void *data, int size) {
- (void)size;
-
- if (close_plugin)
- return 0;
-
- if(!debug_log)
- return -2; //LIBBPF_PERF_EVENT_CONT;
+ netdata_publish_syscall_t *move = ptr;
- netdata_error_report_t *e = data;
- fprintf(developer_log
- ,"%llu %s %u: %s, %d\n"
- , now_realtime_usec() ,e->comm, e->pid, dimension_names[e->type], e->err);
- fflush(developer_log);
+ int i = 0;
+ while (move && i < end) {
+ ebpf_write_global_dimension(move->name, move->dimension);
- return -2; //LIBBPF_PERF_EVENT_CONT;
+ move = move->next;
+ i++;
+ }
}
-void *process_log(void *ptr)
+/**
+ * Call write_chart_cmd to create the charts
+ *
+ * @param family the chart family
+ * @param name the chart name
+ * @param axis the axis label
+ * @param web the group name used to attach the chart on dashaboard
+ * @param order the order number of the specified chart
+ * @param ncd a pointer to a function called to create dimensions
+ * @param move a pointer for a structure that has the dimensions
+ * @param end number of dimensions for the chart created
+ */
+void ebpf_create_chart(char *family
+ , char *name
+ , char *axis
+ , char *web
+ , int order
+ , void (*ncd)(void *, int)
+ , void *move
+ , int end)
{
- (void) ptr;
-
- if (mode == MODE_DEVMODE && debug_log) {
- netdata_perf_loop_multi(pmu_fd, headers, nprocs, &close_plugin, netdata_store_bpf, page_cnt);
- }
+ ebpf_write_chart_cmd(family, name, axis, web, order);
- return NULL;
+ ncd(move, end);
}
-void set_global_labels() {
+/*****************************************************************
+ *
+ * FUNCTIONS TO DEFINE OPTIONS
+ *
+ *****************************************************************/
+
+/**
+ * Define labels used to generate charts
+ *
+ * @param is structure with information about number of calls made for a function.
+ * @param pio structure used to generate charts.
+ * @param dim a pointer for the dimensions name
+ * @param name a pointer for the tensor with the name of the functions.
+ * @param end the number of elements in the previous 4 arguments.
+ */
+void ebpf_global_labels(netdata_syscall_stat_t *is, netdata_publish_syscall_t *pio, char **dim, char **name, int end) {
int i;
- netdata_syscall_stat_t *is = aggregated_data;
netdata_syscall_stat_t *prev = NULL;
-
- netdata_publish_syscall_t *pio = publish_aggregated;
netdata_publish_syscall_t *publish_prev = NULL;
- for (i = 0; i < NETDATA_MAX_MONITOR_VECTOR; i++) {
+ for (i = 0; i < end; i++) {
if(prev) {
prev->next = &is[i];
}
prev = &is[i];
- pio[i].dimension = dimension_names[i];
- pio[i].name = id_names[i];
+ pio[i].dimension = dim[i];
+ pio[i].name = name[i];
if(publish_prev) {
publish_prev->next = &pio[i];
}
@@ -642,294 +348,37 @@ void set_global_labels() {
}
}
-int allocate_global_vectors() {
- aggregated_data = callocz(NETDATA_MAX_MONITOR_VECTOR, sizeof(netdata_syscall_stat_t));
- if(!aggregated_data) {
- return -1;
- }
-
- publish_aggregated = callocz(NETDATA_MAX_MONITOR_VECTOR, sizeof(netdata_publish_syscall_t));
- if(!publish_aggregated) {
- return -1;
- }
-
- hash_values = callocz(nprocs, sizeof(netdata_idx_t));
- if(!hash_values) {
- return -1;
- }
-
- return 0;
-}
-
-static void build_complete_path(char *out, size_t length,char *path, char *filename) {
- if(path){
- snprintf(out, length, "%s/%s", path, filename);
- } else {
- snprintf(out, length, "%s", filename);
- }
-}
-
-static int map_memory() {
- int i;
- for (i = 0; i < nprocs; i++) {
- pmu_fd[i] = set_bpf_perf_event(i, 2);
-
- if (perf_event_mmap_header(pmu_fd[i], &headers[i], page_cnt) < 0) {
- return -1;
- }
- }
- return 0;
-}
-
-static int ebpf_load_libraries()
-{
- char *err = NULL;
- char lpath[4096];
- char netdatasl[128];
- char *libbase = { "libnetdata_ebpf.so" };
-
- snprintf(netdatasl, 127, "%s.%s", libbase, kernel_string);
- build_complete_path(lpath, 4096, plugin_dir, netdatasl);
- libnetdata = dlopen(lpath, RTLD_LAZY);
- if (!libnetdata) {
- info("[EBPF_PROCESS] Cannot load library %s for the current kernel.", lpath);
-
- //Update kernel
- char *library = ebpf_library_suffix(mykernel, (isrh < 0)?0:1);
- size_t length = strlen(library);
- strncpyz(kernel_string, library, length);
- kernel_string[length] = '\0';
-
- //Try to load the default version
- snprintf(netdatasl, 127, "%s.%s", libbase, kernel_string);
- build_complete_path(lpath, 4096, plugin_dir, netdatasl);
- libnetdata = dlopen(lpath, RTLD_LAZY);
- if (!libnetdata) {
- error("[EBPF_PROCESS] Cannot load %s default library.", lpath);
- return -1;
- } else {
- info("[EBPF_PROCESS] Default shared library %s loaded with success.", lpath);
- }
- } else {
- info("[EBPF_PROCESS] Current shared library %s loaded with success.", lpath);
- }
-
- load_bpf_file = dlsym(libnetdata, "load_bpf_file");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find load_bpf_file: %s", err);
- return -1;
- }
-
- map_fd = dlsym(libnetdata, "map_fd");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find map_fd: %s", err);
- return -1;
- }
-
- bpf_map_lookup_elem = dlsym(libnetdata, "bpf_map_lookup_elem");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find bpf_map_lookup_elem: %s", err);
- return -1;
- }
-
- if(mode == 1) {
- set_bpf_perf_event = dlsym(libnetdata, "set_bpf_perf_event");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find set_bpf_perf_event: %s", err);
- return -1;
- }
-
- perf_event_unmap = dlsym(libnetdata, "perf_event_unmap");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find perf_event_unmap: %s", err);
- return -1;
- }
-
- perf_event_mmap_header = dlsym(libnetdata, "perf_event_mmap_header");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find perf_event_mmap_header: %s", err);
- return -1;
- }
-
- if(mode == MODE_DEVMODE) {
- set_bpf_perf_event = dlsym(libnetdata, "set_bpf_perf_event");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find set_bpf_perf_event: %s", err);
- return -1;
- }
-
- perf_event_unmap = dlsym(libnetdata, "perf_event_unmap");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find perf_event_unmap: %s", err);
- return -1;
- }
-
- perf_event_mmap_header = dlsym(libnetdata, "perf_event_mmap_header");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find perf_event_mmap_header: %s", err);
- return -1;
- }
-
- netdata_perf_loop_multi = dlsym(libnetdata, "netdata_perf_loop_multi");
- if ((err = dlerror()) != NULL) {
- error("[EBPF_PROCESS] Cannot find netdata_perf_loop_multi: %s", err);
- return -1;
- }
- }
- }
-
- return 0;
-}
-
-int select_file(char *name, int length) {
- int ret = -1;
- if (!mode)
- ret = snprintf(name, (size_t)length, "rnetdata_ebpf_process.%s.o", kernel_string);
- else if(mode == 1)
- ret = snprintf(name, (size_t)length, "dnetdata_ebpf_process.%s.o", kernel_string);
- else if(mode == 2)
- ret = snprintf(name, (size_t)length, "pnetdata_ebpf_process.%s.o", kernel_string);
-
- return ret;
-}
-
-int process_load_ebpf()
-{
- char lpath[4096];
- char name[128];
-
- int test = select_file(name, 127);
- if (test < 0 || test > 127)
- return -1;
-
- build_complete_path(lpath, 4096, plugin_dir, name);
- event_pid = getpid();
- if (load_bpf_file(lpath, event_pid)) {
- error("[EBPF_PROCESS] Cannot load program: %s", lpath);
- return -1;
- } else {
- info("[EBPF PROCESS]: The eBPF program %s was loaded with success.", name);
- }
-
- return 0;
-}
-
-void set_global_variables() {
- //Get environment variables
- plugin_dir = getenv("NETDATA_PLUGINS_DIR");
- if(!plugin_dir)
- plugin_dir = PLUGINS_DIR;
-
- user_config_dir = getenv("NETDATA_USER_CONFIG_DIR");
- if(!user_config_dir)
- user_config_dir = CONFIG_DIR;
-
- stock_config_dir = getenv("NETDATA_STOCK_CONFIG_DIR");
- if(!stock_config_dir)
- stock_config_dir = LIBCONFIG_DIR;
-
- netdata_configured_log_dir = getenv("NETDATA_LOG_DIR");
- if(!netdata_configured_log_dir)
- netdata_configured_log_dir = LOG_DIR;
-
- page_cnt *= (int)sysconf(_SC_NPROCESSORS_ONLN);
-
- nprocs = (int)sysconf(_SC_NPROCESSORS_ONLN);
- if (nprocs > NETDATA_MAX_PROCESSOR) {
- nprocs = NETDATA_MAX_PROCESSOR;
- }
-
- isrh = get_redhat_release();
-}
-
-static void change_collector_event() {
- int i;
- if (mykernel < NETDATA_KERNEL_V5_3)
- collector_events[10].name = NULL;
-