summaryrefslogtreecommitdiffstats
path: root/collectors/ebpf.plugin/ebpf_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'collectors/ebpf.plugin/ebpf_socket.c')
-rw-r--r--collectors/ebpf.plugin/ebpf_socket.c562
1 files changed, 273 insertions, 289 deletions
diff --git a/collectors/ebpf.plugin/ebpf_socket.c b/collectors/ebpf.plugin/ebpf_socket.c
index 7b2d4a5b..ba63934d 100644
--- a/collectors/ebpf.plugin/ebpf_socket.c
+++ b/collectors/ebpf.plugin/ebpf_socket.c
@@ -61,10 +61,8 @@ static netdata_publish_syscall_t socket_publish_aggregated[NETDATA_MAX_SOCKET_VE
ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
static ebpf_bandwidth_t *bandwidth_vector = NULL;
-static int socket_apps_created = 0;
pthread_mutex_t nv_mutex;
int wait_to_plot = 0;
-int read_thread_closed = 1;
netdata_vector_plot_t inbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
netdata_vector_plot_t outbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
@@ -72,9 +70,6 @@ netdata_socket_t *socket_values;
ebpf_network_viewer_port_list_t *listen_ports = NULL;
-static struct bpf_object *objects = NULL;
-static struct bpf_link **probe_links = NULL;
-
struct config socket_config = { .first_section = NULL,
.last_section = NULL,
.mutex = NETDATA_MUTEX_INITIALIZER,
@@ -92,6 +87,11 @@ netdata_ebpf_targets_t socket_targets[] = { {.name = "inet_csk_accept", .mode =
{.name = "tcp_v6_connect", .mode = EBPF_LOAD_TRAMPOLINE},
{.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
+struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
+ NULL, NULL, 1, NULL,
+ NULL, NULL };
+static enum ebpf_threads_status ebpf_socket_exited = NETDATA_THREAD_EBPF_RUNNING;
+
#ifdef LIBBPF_MAJOR_VERSION
#include "includes/socket.skel.h" // BTF code
@@ -424,6 +424,225 @@ static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_modul
return ret;
}
#endif
+
+/*****************************************************************
+ *
+ * FUNCTIONS TO CLOSE THE THREAD
+ *
+ *****************************************************************/
+
+/**
+ * Clean internal socket plot
+ *
+ * Clean all structures allocated with strdupz.
+ *
+ * @param ptr the pointer with addresses to clean.
+ */
+static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
+{
+ freez(ptr->dimension_recv);
+ freez(ptr->dimension_sent);
+ freez(ptr->resolved_name);
+ freez(ptr->dimension_retransmit);
+}
+
+/**
+ * Clean socket plot
+ *
+ * Clean the allocated data for inbound and outbound vectors.
+ */
+static void clean_allocated_socket_plot()
+{
+ uint32_t i;
+ uint32_t end = inbound_vectors.last;
+ netdata_socket_plot_t *plot = inbound_vectors.plot;
+ for (i = 0; i < end; i++) {
+ clean_internal_socket_plot(&plot[i]);
+ }
+
+ clean_internal_socket_plot(&plot[inbound_vectors.last]);
+
+ end = outbound_vectors.last;
+ plot = outbound_vectors.plot;
+ for (i = 0; i < end; i++) {
+ clean_internal_socket_plot(&plot[i]);
+ }
+ clean_internal_socket_plot(&plot[outbound_vectors.last]);
+}
+
+/**
+ * Clean network ports allocated during initialization.
+ *
+ * @param ptr a pointer to the link list.
+ */
+static void clean_network_ports(ebpf_network_viewer_port_list_t *ptr)
+{
+ if (unlikely(!ptr))
+ return;
+
+ while (ptr) {
+ ebpf_network_viewer_port_list_t *next = ptr->next;
+ freez(ptr->value);
+ freez(ptr);
+ ptr = next;
+ }
+}
+
+/**
+ * Clean service names
+ *
+ * Clean the allocated link list that stores names.
+ *
+ * @param names the link list.
+ */
+static void clean_service_names(ebpf_network_viewer_dim_name_t *names)
+{
+ if (unlikely(!names))
+ return;
+
+ while (names) {
+ ebpf_network_viewer_dim_name_t *next = names->next;
+ freez(names->name);
+ freez(names);
+ names = next;
+ }
+}
+
+/**
+ * Clean hostnames
+ *
+ * @param hostnames the hostnames to clean
+ */
+static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
+{
+ if (unlikely(!hostnames))
+ return;
+
+ while (hostnames) {
+ ebpf_network_viewer_hostname_list_t *next = hostnames->next;
+ freez(hostnames->value);
+ simple_pattern_free(hostnames->value_pattern);
+ freez(hostnames);
+ hostnames = next;
+ }
+}
+
+/**
+ * Cleanup publish syscall
+ *
+ * @param nps list of structures to clean
+ */
+void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
+{
+ while (nps) {
+ freez(nps->algorithm);
+ nps = nps->next;
+ }
+}
+
+/**
+ * Clean port Structure
+ *
+ * Clean the allocated list.
+ *
+ * @param clean the list that will be cleaned
+ */
+void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
+{
+ ebpf_network_viewer_port_list_t *move = *clean;
+ while (move) {
+ ebpf_network_viewer_port_list_t *next = move->next;
+ freez(move->value);
+ freez(move);
+
+ move = next;
+ }
+ *clean = NULL;
+}
+
+/**
+ * Clean IP structure
+ *
+ * Clean the allocated list.
+ *
+ * @param clean the list that will be cleaned
+ */
+static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
+{
+ ebpf_network_viewer_ip_list_t *move = *clean;
+ while (move) {
+ ebpf_network_viewer_ip_list_t *next = move->next;
+ freez(move->value);
+ freez(move);
+
+ move = next;
+ }
+ *clean = NULL;
+}
+
+/**
+ * Socket exit
+ *
+ * Clean up the main thread.
+ *
+ * @param ptr thread data.
+ */
+static void ebpf_socket_exit(void *ptr)
+{
+ ebpf_module_t *em = (ebpf_module_t *)ptr;
+ if (!em->enabled) {
+ em->enabled = NETDATA_MAIN_THREAD_EXITED;
+ return;
+ }
+
+ ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPING;
+}
+
+/**
+ * Socket cleanup
+ *
+ * Clean up allocated addresses.
+ *
+ * @param ptr thread data.
+ */
+void ebpf_socket_cleanup(void *ptr)
+{
+ ebpf_module_t *em = (ebpf_module_t *)ptr;
+ if (ebpf_socket_exited != NETDATA_THREAD_EBPF_STOPPED)
+ return;
+
+ ebpf_cleanup_publish_syscall(socket_publish_aggregated);
+ freez(socket_hash_values);
+
+ freez(bandwidth_vector);
+
+ freez(socket_values);
+ clean_allocated_socket_plot();
+ freez(inbound_vectors.plot);
+ freez(outbound_vectors.plot);
+
+ clean_port_structure(&listen_ports);
+
+ ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled = 0;
+
+ clean_network_ports(network_viewer_opt.included_port);
+ clean_network_ports(network_viewer_opt.excluded_port);
+ clean_service_names(network_viewer_opt.names);
+ clean_hostnames(network_viewer_opt.included_hostnames);
+ clean_hostnames(network_viewer_opt.excluded_hostnames);
+
+ pthread_mutex_destroy(&nv_mutex);
+
+ freez(socket_threads.thread);
+
+#ifdef LIBBPF_MAJOR_VERSION
+ if (bpf_obj)
+ socket_bpf__destroy(bpf_obj);
+#endif
+ socket_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
+ em->enabled = NETDATA_MAIN_THREAD_EXITED;
+}
+
/*****************************************************************
*
* PROCESS DATA AND SEND TO NETDATA
@@ -737,8 +956,6 @@ long long ebpf_socket_sum_values_for_pids(struct pid_on_target *root, size_t off
void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root)
{
UNUSED(em);
- if (!socket_apps_created)
- return;
struct target *w;
collected_number value;
@@ -1052,7 +1269,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET);
- socket_apps_created = 1;
+ em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
}
/**
@@ -1814,15 +2031,6 @@ static void read_socket_hash_table(int fd, int family, int network_connection)
key = next_key;
}
-
- test = bpf_map_lookup_elem(fd, &next_key, values);
- if (test < 0) {
- return;
- }
-
- if (network_connection) {
- hash_accumulator(values, &next_key, family, end);
- }
}
/**
@@ -1929,18 +2137,20 @@ 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;
- read_thread_closed = 0;
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 (!close_ebpf_plugin) {
+ while (ebpf_socket_exited == NETDATA_THREAD_EBPF_RUNNING) {
usec_t dt = heartbeat_next(&hb, step);
(void)dt;
+ if (ebpf_socket_exited == NETDATA_THREAD_EBPF_STOPPING)
+ break;
pthread_mutex_lock(&nv_mutex);
read_listen_table();
@@ -1950,7 +2160,9 @@ void *ebpf_socket_read_hash(void *ptr)
pthread_mutex_unlock(&nv_mutex);
}
- read_thread_closed = 1;
+ ebpf_socket_exited = NETDATA_THREAD_EBPF_STOPPED;
+
+ netdata_thread_cleanup_pop(1);
return NULL;
}
@@ -2502,7 +2714,7 @@ static int ebpf_send_systemd_socket_charts()
for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
if (unlikely(ect->systemd) && unlikely(ect->updated)) {
write_chart_dimension(ect->name, (long long)ect->publish_socket.call_tcp_v4_connection);
- } else
+ } else if (unlikely(ect->systemd))
ret = 0;
}
write_end_chart();
@@ -2643,10 +2855,6 @@ static void ebpf_socket_send_cgroup_data(int update_every)
*
*****************************************************************/
-struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
- NULL, NULL, 1, NULL,
- NULL, ebpf_socket_read_hash };
-
/**
* Main loop for this collector.
*
@@ -2655,297 +2863,74 @@ struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
*/
static void socket_collector(usec_t step, ebpf_module_t *em)
{
- UNUSED(step);
heartbeat_t hb;
heartbeat_init(&hb);
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_JOINABLE, ebpf_socket_read_hash, em);
+ NETDATA_THREAD_OPTION_DEFAULT, ebpf_socket_read_hash, em);
int cgroups = em->cgroup_charts;
if (cgroups)
ebpf_socket_update_cgroup_algorithm();
- int socket_apps_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].apps_charts;
- int socket_global_enabled = ebpf_modules[EBPF_MODULE_SOCKET_IDX].global_charts;
+ int socket_global_enabled = em->global_charts;
int network_connection = em->optional;
int update_every = em->update_every;
- int counter = update_every - 1;
- while (!close_ebpf_plugin) {
+ while (!ebpf_exit_plugin) {
+ (void)heartbeat_next(&hb, step);
+ if (ebpf_exit_plugin)
+ break;
+
+ netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
pthread_mutex_lock(&collect_data_mutex);
- pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
+ if (socket_global_enabled)
+ read_hash_global_tables();
- if (++counter == update_every) {
- counter = 0;
- if (socket_global_enabled)
- read_hash_global_tables();
+ if (socket_apps_enabled)
+ ebpf_socket_update_apps_data();
- if (socket_apps_enabled)
- ebpf_socket_update_apps_data();
+ if (cgroups)
+ ebpf_update_socket_cgroup();
- if (cgroups)
- ebpf_update_socket_cgroup();
+ calculate_nv_plot();
- calculate_nv_plot();
+ pthread_mutex_lock(&lock);
+ if (socket_global_enabled)
+ ebpf_socket_send_data(em);
- pthread_mutex_lock(&lock);
- if (socket_global_enabled)
- ebpf_socket_send_data(em);
+ if (socket_apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
+ ebpf_socket_send_apps_data(em, apps_groups_root_target);
- if (socket_apps_enabled)
- ebpf_socket_send_apps_data(em, apps_groups_root_target);
+ if (cgroups)
+ ebpf_socket_send_cgroup_data(update_every);
- if (cgroups)
- ebpf_socket_send_cgroup_data(update_every);
+ fflush(stdout);
+ if (network_connection) {
+ // We are calling fflush many times, because when we have a lot of dimensions
+ // we began to have not expected outputs and Netdata closed the plugin.
+ pthread_mutex_lock(&nv_mutex);
+ ebpf_socket_create_nv_charts(&inbound_vectors, update_every);
fflush(stdout);
+ ebpf_socket_send_nv_data(&inbound_vectors);
- if (network_connection) {
- // We are calling fflush many times, because when we have a lot of dimensions
- // we began to have not expected outputs and Netdata closed the plugin.
- pthread_mutex_lock(&nv_mutex);
- ebpf_socket_create_nv_charts(&inbound_vectors, update_every);
- fflush(stdout);
- ebpf_socket_send_nv_data(&inbound_vectors);
-
- 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);
+ 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);
- }
- pthread_mutex_unlock(&lock);
}
-
+ pthread_mutex_unlock(&lock);
pthread_mutex_unlock(&collect_data_mutex);
}
}
/*****************************************************************
*
- * FUNCTIONS TO CLOSE THE THREAD
- *
- *****************************************************************/
-
-
-/**
- * Clean internal socket plot
- *
- * Clean all structures allocated with strdupz.
- *
- * @param ptr the pointer with addresses to clean.
- */
-static inline void clean_internal_socket_plot(netdata_socket_plot_t *ptr)
-{
- freez(ptr->dimension_recv);
- freez(ptr->dimension_sent);
- freez(ptr->resolved_name);
- freez(ptr->dimension_retransmit);
-}
-
-/**
- * Clean socket plot
- *
- * Clean the allocated data for inbound and outbound vectors.
- */
-static void clean_allocated_socket_plot()
-{
- uint32_t i;
- uint32_t end = inbound_vectors.last;
- netdata_socket_plot_t *plot = inbound_vectors.plot;
- for (i = 0; i < end; i++) {
- clean_internal_socket_plot(&plot[i]);
- }
-
- clean_internal_socket_plot(&plot[inbound_vectors.last]);
-
- end = outbound_vectors.last;
- plot = outbound_vectors.plot;
- for (i = 0; i < end; i++) {
- clean_internal_socket_plot(&plot[i]);
- }
- clean_internal_socket_plot(&plot[outbound_vectors.last]);
-}
-
-/**
- * Clean network ports allocated during initialization.
- *
- * @param ptr a pointer to the link list.
- */
-static void clean_network_ports(ebpf_network_viewer_port_list_t *ptr)
-{
- if (unlikely(!ptr))
- return;
-
- while (ptr) {
- ebpf_network_viewer_port_list_t *next = ptr->next;
- freez(ptr->value);
- freez(ptr);
- ptr = next;
- }
-}
-
-/**
- * Clean service names
- *
- * Clean the allocated link list that stores names.
- *
- * @param names the link list.
- */
-static void clean_service_names(ebpf_network_viewer_dim_name_t *names)
-{
- if (unlikely(!names))
- return;
-
- while (names) {
- ebpf_network_viewer_dim_name_t *next = names->next;
- freez(names->name);
- freez(names);
- names = next;
- }
-}
-
-/**
- * Clean hostnames
- *
- * @param hostnames the hostnames to clean
- */
-static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
-{
- if (unlikely(!hostnames))
- return;
-
- while (hostnames) {
- ebpf_network_viewer_hostname_list_t *next = hostnames->next;
- freez(hostnames->value);
- simple_pattern_free(hostnames->value_pattern);
- freez(hostnames);
- hostnames = next;
- }
-}
-
-void clean_socket_apps_structures() {
- struct pid_stat *pids = root_of_pids;
- while (pids) {
- freez(socket_bandwidth_curr[pids->pid]);
-
- pids = pids->next;
- }
-}
-
-/**
- * Cleanup publish syscall
- *
- * @param nps list of structures to clean
- */
-void ebpf_cleanup_publish_syscall(netdata_publish_syscall_t *nps)
-{
- while (nps) {
- freez(nps->algorithm);
- nps = nps->next;
- }
-}
-
-/**
- * Clean port Structure
- *
- * Clean the allocated list.
- *
- * @param clean the list that will be cleaned
- */
-void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
-{
- ebpf_network_viewer_port_list_t *move = *clean;
- while (move) {
- ebpf_network_viewer_port_list_t *next = move->next;
- freez(move->value);
- freez(move);
-
- move = next;
- }
- *clean = NULL;
-}
-
-/**
- * Clean IP structure
- *
- * Clean the allocated list.
- *
- * @param clean the list that will be cleaned
- */
-static void clean_ip_structure(ebpf_network_viewer_ip_list_t **clean)
-{
- ebpf_network_viewer_ip_list_t *move = *clean;
- while (move) {
- ebpf_network_viewer_ip_list_t *next = move->next;
- freez(move->value);
- freez(move);
-
- move = next;
- }
- *clean = NULL;
-}
-
-/**
- * Clean up the main thread.
- *
- * @param ptr thread data.
- */
-static void ebpf_socket_cleanup(void *ptr)
-{
- ebpf_module_t *em = (ebpf_module_t *)ptr;
- if (!em->enabled)
- return;
-
- heartbeat_t hb;
- heartbeat_init(&hb);
- uint32_t tick = 2*USEC_PER_MS;
- while (!read_thread_closed) {
- usec_t dt = heartbeat_next(&hb, tick);
- UNUSED(dt);
- }
-
- ebpf_cleanup_publish_syscall(socket_publish_aggregated);
- freez(socket_hash_values);
-
- freez(bandwidth_vector);
-
- freez(socket_values);
- clean_allocated_socket_plot();
- freez(inbound_vectors.plot);
- freez(outbound_vectors.plot);
-
- clean_port_structure(&listen_ports);
-
- ebpf_modules[EBPF_MODULE_SOCKET_IDX].enabled = 0;
-
- clean_network_ports(network_viewer_opt.included_port);
- clean_network_ports(network_viewer_opt.excluded_port);
- clean_service_names(network_viewer_opt.names);
- clean_hostnames(network_viewer_opt.included_hostnames);
- clean_hostnames(network_viewer_opt.excluded_hostnames);
-
- pthread_mutex_destroy(&nv_mutex);
-
- freez(socket_threads.thread);
-
- if (probe_links) {
- struct bpf_program *prog;
- size_t i = 0 ;
- bpf_object__for_each_program(prog, objects) {
- bpf_link__destroy(probe_links[i]);
- i++;
- }
- bpf_object__close(objects);
- }
- finalized_threads = 1;
-}
-
-/*****************************************************************
- *
* FUNCTIONS TO START THREAD
*
*****************************************************************/
@@ -3891,8 +3876,8 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
int ret = 0;
if (em->load == EBPF_LOAD_LEGACY) {
- probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
- if (!probe_links) {
+ em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
+ if (!em->probe_links) {
ret = -1;
}
}
@@ -3924,7 +3909,7 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
*/
void *ebpf_socket_thread(void *ptr)
{
- netdata_thread_cleanup_push(ebpf_socket_cleanup, 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));
@@ -3946,7 +3931,6 @@ void *ebpf_socket_thread(void *ptr)
error("Cannot initialize local mutex");
goto endsocket;
}
- pthread_mutex_lock(&lock);
ebpf_socket_allocate_global_vectors(em->apps_charts);
initialize_inbound_outbound();
@@ -3973,11 +3957,11 @@ void *ebpf_socket_thread(void *ptr)
socket_aggregated_data, socket_publish_aggregated, socket_dimension_names, socket_id_names,
algorithms, NETDATA_MAX_SOCKET_VECTOR);
+ pthread_mutex_lock(&lock);
ebpf_create_global_charts(em);
ebpf_update_stats(&plugin_statistics, em);
- finalized_threads = 0;
pthread_mutex_unlock(&lock);
socket_collector((usec_t)(em->update_every * USEC_PER_SEC), em);