@cryptotaxi247 / netdata-1 / commits / 93f94c003

ebpf memory cleanup (#10096)

Fix memory cleanup when process exit.

thiagoftsm committed Oct 28, 2020 at 13:45 UTC 93f94c003ef6d494e6beb05a1e6523f2a2cf1a00
9 files changed +220 -96
collectors/ebpf.plugin/ebpf.c
+6 -7
@@ -69,6 +69,7 @@ int running_on_kernel = 0;
69 char kernel_string[64];
70 int ebpf_nprocs;
71 static int isrh;
72 +uint32_t finalized_threads = 1;
73
74 pthread_mutex_t lock;
75 pthread_mutex_t collect_data_mutex;
@@ -115,7 +116,6 @@ ebpf_module_t ebpf_modules[] = {
116 };
117
118 // Link with apps.plugin
118 -pid_t *pid_index;
119 ebpf_process_stat_t *global_process_stat = NULL;
120
121 //Network viewer
@@ -142,6 +142,7 @@ void clean_port_structure(ebpf_network_viewer_port_list_t **clean)
142 ebpf_network_viewer_port_list_t *move = *clean;
143 while (move) {
144 ebpf_network_viewer_port_list_t *next = move->next;
145 + freez(move->value);
146 freez(move);
147
148 move = next;
@@ -181,13 +182,13 @@ static void change_events()
182 * Clean Loaded Events
183 *
184 * This function cleans the events previous loaded on Linux.
184 - */
185 void clean_loaded_events()
186 {
187 int event_pid;
188 for (event_pid = 0; ebpf_modules[event_pid].probes; event_pid++)
189 clean_kprobe_events(NULL, (int)ebpf_modules[event_pid].thread_id, ebpf_modules[event_pid].probes);
190 }
191 + */
192
193 /**
194 * Close the collector gracefully
@@ -203,11 +204,9 @@ static void ebpf_exit(int sig)
204 return;
205 }
206
206 - clean_apps_groups_target(apps_groups_root_target);
207 -
208 - freez(pid_index);
207 freez(global_process_stat);
208
209 + /*
210 int ret = fork();
211 if (ret < 0) // error
212 error("Cannot fork(), so I won't be able to clean %skprobe_events", NETDATA_DEBUGFS);
@@ -237,6 +236,7 @@ static void ebpf_exit(int sig)
236 } else { // parent
237 exit(0);
238 }
239 + */
240
241 exit(sig);
242 }
@@ -830,7 +830,6 @@ int ebpf_start_pthread_variables()
830 static void ebpf_allocate_common_vectors()
831 {
832 all_pids = callocz((size_t)pid_max, sizeof(struct pid_stat *));
833 - pid_index = callocz((size_t)pid_max, sizeof(pid_t));
833 global_process_stat = callocz((size_t)ebpf_nprocs, sizeof(ebpf_process_stat_t));
834 }
835
@@ -1969,7 +1968,7 @@ int main(int argc, char **argv)
1968 };
1969
1970 change_events();
1972 - clean_loaded_events();
1971 + //clean_loaded_events();
1972
1973 int i;
1974 for (i = 0; ebpf_threads[i].name != NULL; i++) {
collectors/ebpf.plugin/ebpf.h
+2 -21
@@ -31,12 +31,6 @@
31
32 #include "ebpf_apps.h"
33
34 -typedef enum {
35 - MODE_RETURN = 0, // This attaches kprobe when the function returns
36 - MODE_DEVMODE, // This stores log given description about the errors raised
37 - MODE_ENTRY // This attaches kprobe when the function is called
38 -} netdata_run_mode_t;
39 -
34 typedef struct netdata_syscall_stat {
35 unsigned long bytes; // total number of bytes
36 uint64_t call; // total number of calls
@@ -74,20 +68,6 @@ typedef struct netdata_error_report {
68 int err;
69 } netdata_error_report_t;
70
77 -typedef struct ebpf_module {
78 - const char *thread_name;
79 - const char *config_name;
80 - int enabled;
81 - void *(*start_routine)(void *);
82 - int update_time;
83 - int global_charts;
84 - int apps_charts;
85 - netdata_run_mode_t mode;
86 - netdata_ebpf_events_t *probes;
87 - uint32_t thread_id;
88 - int optional;
89 -} ebpf_module_t;
90 -
71 extern ebpf_module_t ebpf_modules[];
72 #define EBPF_MODULE_PROCESS_IDX 0
73 #define EBPF_MODULE_SOCKET_IDX 1
@@ -198,8 +178,8 @@ extern void write_end_chart();
178 // Common variables
179 extern char *ebpf_user_config_dir;
180 extern char *ebpf_stock_config_dir;
201 -extern pid_t *pid_index;
181 extern int debug_enabled;
182 +extern struct pid_stat *root_of_pids;
183
184 // Socket functions and variables
185 // Common functions
@@ -209,6 +189,7 @@ extern struct pid_stat *root_of_pids;
189 extern ebpf_process_stat_t *global_process_stat;
190 extern size_t all_pids_count;
191 extern int update_every;
192 +extern uint32_t finalized_threads;
193
194 #define EBPF_MAX_SYNCHRONIZATION_TIME 300
195
collectors/ebpf.plugin/ebpf_apps.c
+35 -21
@@ -1,6 +1,7 @@
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "ebpf.h"
4 +#include "ebpf_socket.h"
5 #include "ebpf_apps.h"
6
7 // ----------------------------------------------------------------------------
@@ -910,10 +911,8 @@ static inline void del_pid_entry(pid_t pid)
911
912 /**
913 * Remove PIDs when they are not running more.
913 - *
914 - * @param out is the structure where PIDs are stored.
914 */
916 -void cleanup_exited_pids(ebpf_process_stat_t **out)
915 +void cleanup_exited_pids()
916 {
917 struct pid_stat *p = NULL;
918
@@ -926,10 +925,19 @@ void cleanup_exited_pids(ebpf_process_stat_t **out)
925 p = p->next;
926 del_pid_entry(r);
927
929 - ebpf_process_stat_t *w = out[r];
930 - if (w) {
931 - freez(w);
932 - out[r] = NULL;
928 + // Clean process structure
929 + freez(global_process_stats[r]);
930 + global_process_stats[r] = NULL;
931 +
932 + freez(current_apps_data[r]);
933 + current_apps_data[r] = NULL;
934 + prev_apps_data[r] = NULL;
935 +
936 + // Clean socket structures
937 + if (socket_bandwidth_curr) {
938 + freez(socket_bandwidth_curr[r]);
939 + socket_bandwidth_curr[r] = NULL;
940 + socket_bandwidth_prev[r] = NULL;
941 }
942 } else {
943 if (unlikely(p->keep))
@@ -1007,12 +1015,9 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
1015 * Read data from hash table and store it in appropriate vectors.
1016 * It also creates the link between targets and PIDs.
1017 *
1010 - * @param out the output vector where we store data read from hash table.
1011 - * @param index the vector to store the indexes read.
1012 - * @param bpf_map_lookup_elem A pointer to the function that reads the data.
1018 * @param tbl_pid_stats_fd The mapped file descriptor for the hash table.
1019 */
1015 -void collect_data_for_all_processes(ebpf_process_stat_t **out, pid_t *index, int tbl_pid_stats_fd)
1020 +void collect_data_for_all_processes(int tbl_pid_stats_fd)
1021 {
1022 struct pid_stat *pids = root_of_pids; // global list of all processes running
1023 while (pids) {
@@ -1032,26 +1037,37 @@ void collect_data_for_all_processes(ebpf_process_stat_t **out, pid_t *index, int
1037
1038 read_proc_filesystem();
1039
1035 - int counter = 0;
1040 uint32_t key;
1041 pids = root_of_pids; // global list of all processes running
1042 // while (bpf_map_get_next_key(tbl_pid_stats_fd, &key, &next_key) == 0) {
1043 while (pids) {
1044 key = pids->pid;
1041 - ebpf_process_stat_t *w = out[key];
1045 + ebpf_process_stat_t *w = global_process_stats[key];
1046 if (!w) {
1047 w = mallocz(sizeof(ebpf_process_stat_t));
1044 - out[key] = w;
1048 + global_process_stats[key] = w;
1049 }
1050
1051 if (bpf_map_lookup_elem(tbl_pid_stats_fd, &key, w)) {
1052 + // Clean Process structures
1053 + freez(w);
1054 + global_process_stats[key] = NULL;
1055 +
1056 + freez(current_apps_data[key]);
1057 + current_apps_data[key] = NULL;
1058 + prev_apps_data[key] = NULL;
1059 +
1060 + // Clean socket structures
1061 + if (socket_bandwidth_curr) {
1062 + freez(socket_bandwidth_curr[key]);
1063 + socket_bandwidth_curr[key] = NULL;
1064 + socket_bandwidth_prev[key] = NULL;
1065 + }
1066 +
1067 pids = pids->next;
1068 continue;
1069 }
1070
1052 - index[counter] = key;
1053 - counter++;
1054 -
1071 pids = pids->next;
1072 }
1073
@@ -1062,11 +1078,9 @@ void collect_data_for_all_processes(ebpf_process_stat_t **out, pid_t *index, int
1078 apps_groups_targets_count = zero_all_targets(apps_groups_root_target);
1079
1080 // this has to be done, before the cleanup
1065 - struct pid_stat *p = NULL;
1066 -
1081 // // concentrate everything on the targets
1068 - for (p = root_of_pids; p; p = p->next)
1069 - aggregate_pid_on_target(p->target, p, NULL);
1082 + for (pids = root_of_pids; pids; pids = pids->next)
1083 + aggregate_pid_on_target(pids->target, pids, NULL);
1084
1085 post_aggregate_targets(apps_groups_root_target);
1086 }
collectors/ebpf.plugin/ebpf_apps.h
+8 -2
@@ -14,6 +14,8 @@
14 #define NETDATA_APPS_SYSCALL_GROUP "ebpf syscall"
15 #define NETDATA_APPS_NET_GROUP "ebpf net"
16
17 +#include "ebpf_process.h"
18 +
19 #define MAX_COMPARE_NAME 100
20 #define MAX_NAME 100
21
@@ -404,7 +406,7 @@ extern size_t zero_all_targets(struct target *root);
406
407 extern int am_i_running_as_root();
408
407 -extern void cleanup_exited_pids(ebpf_process_stat_t **out);
409 +extern void cleanup_exited_pids();
410
411 extern int ebpf_read_hash_table(void *ep, int fd, uint32_t pid);
412
@@ -414,6 +416,10 @@ extern size_t read_processes_statistic_using_pid_on_target(ebpf_process_stat_t *
416
417 extern size_t read_bandwidth_statistic_using_pid_on_target(ebpf_bandwidth_t **ep, int fd, struct pid_on_target *pids);
418
417 -extern void collect_data_for_all_processes(ebpf_process_stat_t **out, pid_t *index, int tbl_pid_stats_fd);
419 +extern void collect_data_for_all_processes(int tbl_pid_stats_fd);
420 +
421 +extern ebpf_process_stat_t **global_process_stats;
422 +extern ebpf_process_publish_apps_t **current_apps_data;
423 +extern ebpf_process_publish_apps_t **prev_apps_data;
424
425 #endif /* NETDATA_EBPF_APPS_H */
collectors/ebpf.plugin/ebpf_process.c
+77 -19
@@ -24,13 +24,15 @@ static netdata_publish_syscall_t *process_publish_aggregated = NULL;
24
25 static ebpf_data_t process_data;
26
27 -static ebpf_process_stat_t **local_process_stats = NULL;
28 -static ebpf_process_publish_apps_t **current_apps_data = NULL;
29 -static ebpf_process_publish_apps_t **prev_apps_data = NULL;
27 +ebpf_process_stat_t **global_process_stats = NULL;
28 +ebpf_process_publish_apps_t **current_apps_data = NULL;
29 +ebpf_process_publish_apps_t **prev_apps_data = NULL;
30
31 int process_enabled = 0;
32
33 static int *map_fd = NULL;
34 +static struct bpf_object *objects = NULL;
35 +static struct bpf_link **probe_links = NULL;
36
37 /*****************************************************************
38 *
@@ -201,11 +203,11 @@ void ebpf_process_remove_pids()
203 int pid_fd = map_fd[0];
204 while (pids) {
205 uint32_t pid = pids->pid;
204 - ebpf_process_stat_t *w = local_process_stats[pid];
206 + ebpf_process_stat_t *w = global_process_stats[pid];
207 if (w) {
208 if (w->removeme) {
209 freez(w);
208 - local_process_stats[pid] = NULL;
210 + global_process_stats[pid] = NULL;
211 bpf_map_delete_elem(pid_fd, &pid);
212 }
213 }
@@ -432,12 +434,14 @@ static void read_hash_global_tables()
434 */
435 static void ebpf_process_update_apps_data()
436 {
435 - size_t i;
436 - for (i = 0; i < all_pids_count; i++) {
437 - uint32_t current_pid = pid_index[i];
438 - ebpf_process_stat_t *ps = local_process_stats[current_pid];
439 - if (!ps)
437 + struct pid_stat *pids = root_of_pids;
438 + while (pids) {
439 + uint32_t current_pid = pids->pid;
440 + ebpf_process_stat_t *ps = global_process_stats[current_pid];
441 + if (!ps) {
442 + pids = pids->next;
443 continue;
444 + }
445
446 ebpf_process_publish_apps_t *cad = current_apps_data[current_pid];
447 ebpf_process_publish_apps_t *pad = prev_apps_data[current_pid];
@@ -477,6 +481,8 @@ static void ebpf_process_update_apps_data()
481 cad->bytes_read = (uint64_t)ps->read_bytes + (uint64_t)ps->readv_bytes;
482
483 ebpf_process_update_apps_publish(cad, pad, lstatus);
484 +
485 + pids = pids->next;
486 }
487 }
488
@@ -832,8 +838,8 @@ static void process_collector(usec_t step, ebpf_module_t *em)
838 read_hash_global_tables();
839
840 pthread_mutex_lock(&collect_data_mutex);
835 - cleanup_exited_pids(local_process_stats);
836 - collect_data_for_all_processes(local_process_stats, pid_index, pid_fd);
841 + cleanup_exited_pids();
842 + collect_data_for_all_processes(pid_fd);
843
844 ebpf_create_apps_charts(em, apps_groups_root_target);
845
@@ -866,6 +872,40 @@ static void process_collector(usec_t step, ebpf_module_t *em)
872 *
873 *****************************************************************/
874
875 +void clean_global_memory() {
876 + int pid_fd = map_fd[0];
877 + struct pid_stat *pids = root_of_pids;
878 + while (pids) {
879 + uint32_t pid = pids->pid;
880 + freez(global_process_stats[pid]);
881 +
882 + bpf_map_delete_elem(pid_fd, &pid);
883 + freez(current_apps_data[pid]);
884 +
885 + pids = pids->next;
886 + }
887 +}
888 +
889 +void clean_pid_on_target(struct pid_on_target *ptr) {
890 + while (ptr) {
891 + struct pid_on_target *next = ptr->next;
892 + freez(ptr);
893 +
894 + ptr = next;
895 + }
896 +}
897 +
898 +void clean_apps_structures(struct target *ptr) {
899 + struct target *agdt = ptr;
900 + while (agdt) {
901 + struct target *next = agdt->next;
902 + clean_pid_on_target(agdt->root_pid);
903 + freez(agdt);
904 +
905 + agdt = next;
906 + }
907 +}
908 +
909 /**
910 * Clean up the main thread.
911 *
@@ -873,17 +913,35 @@ static void process_collector(usec_t step, ebpf_module_t *em)
913 */
914 static void ebpf_process_cleanup(void *ptr)
915 {
876 - (void)ptr;
916 + UNUSED(ptr);
917 +
918 + heartbeat_t hb;
919 + heartbeat_init(&hb);
920 + uint32_t tick = 200*USEC_PER_MS;
921 + while (!finalized_threads) {
922 + usec_t dt = heartbeat_next(&hb, tick);
923 + UNUSED(dt);
924 + }
925
926 freez(process_aggregated_data);
927 freez(process_publish_aggregated);
928 freez(process_hash_values);
929
882 - freez(local_process_stats);
883 -
884 - freez(process_data.map_fd);
930 + clean_global_memory();
931 + freez(global_process_stats);
932 freez(current_apps_data);
933 freez(prev_apps_data);
934 +
935 + clean_apps_structures(apps_groups_root_target);
936 + freez(process_data.map_fd);
937 +
938 + struct bpf_program *prog;
939 + size_t i = 0 ;
940 + bpf_object__for_each_program(prog, objects) {
941 + bpf_link__destroy(probe_links[i]);
942 + i++;
943 + }
944 + bpf_object__close(objects);
945 }
946
947 /*****************************************************************
@@ -905,7 +963,7 @@ static void ebpf_process_allocate_global_vectors(size_t length)
963 process_publish_aggregated = callocz(length, sizeof(netdata_publish_syscall_t));
964 process_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
965
908 - local_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
966 + global_process_stats = callocz((size_t)pid_max, sizeof(ebpf_process_stat_t *));
967 current_apps_data = callocz((size_t)pid_max, sizeof(ebpf_process_publish_apps_t *));
968 prev_apps_data = callocz((size_t)pid_max, sizeof(ebpf_process_publish_apps_t *));
969 }
@@ -1000,8 +1058,8 @@ void *ebpf_process_thread(void *ptr)
1058 }
1059
1060 set_local_pointers();
1003 - if (ebpf_load_program(
1004 - ebpf_plugin_dir, em->thread_id, em->mode, kernel_string, em->thread_name, process_data.map_fd)) {
1061 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, process_data.map_fd);
1062 + if (!probe_links) {
1063 pthread_mutex_unlock(&lock);
1064 goto endprocess;
1065 }
collectors/ebpf.plugin/ebpf_socket.c
+49 -10
@@ -22,13 +22,14 @@ static netdata_publish_syscall_t *socket_publish_aggregated = NULL;
22
23 static ebpf_data_t socket_data;
24
25 -static ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
26 -static ebpf_socket_publish_apps_t **socket_bandwidth_prev = NULL;
25 +ebpf_socket_publish_apps_t **socket_bandwidth_curr = NULL;
26 +ebpf_socket_publish_apps_t **socket_bandwidth_prev = NULL;
27 static ebpf_bandwidth_t *bandwidth_vector = NULL;
28
29 static int socket_apps_created = 0;
30 pthread_mutex_t nv_mutex;
31 int wait_to_plot = 0;
32 +int read_thread_closed = 1;
33
34 netdata_vector_plot_t inbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
35 netdata_vector_plot_t outbound_vectors = { .plot = NULL, .next = 0, .last = 0 };
@@ -37,6 +38,8 @@ netdata_socket_t *socket_values;
38 ebpf_network_viewer_port_list_t *listen_ports = NULL;
39
40 static int *map_fd = NULL;
41 +static struct bpf_object *objects = NULL;
42 +static struct bpf_link **probe_links = NULL;
43
44 /*****************************************************************
45 *
@@ -1341,6 +1344,7 @@ void *ebpf_socket_read_hash(void *ptr)
1344 {
1345 ebpf_module_t *em = (ebpf_module_t *)ptr;
1346
1347 + read_thread_closed = 0;
1348 heartbeat_t hb;
1349 heartbeat_init(&hb);
1350 usec_t step = NETDATA_SOCKET_READ_SLEEP_MS;
@@ -1359,6 +1363,7 @@ void *ebpf_socket_read_hash(void *ptr)
1363 pthread_mutex_unlock(&nv_mutex);
1364 }
1365
1366 + read_thread_closed = 1;
1367 return NULL;
1368 }
1369
@@ -1480,6 +1485,10 @@ static void ebpf_socket_update_apps_data()
1485 *
1486 *****************************************************************/
1487
1488 +struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
1489 + NULL, NULL, 1, NULL,
1490 + NULL, ebpf_socket_read_hash };
1491 +
1492 /**
1493 * Main loop for this collector.
1494 *
@@ -1493,10 +1502,7 @@ static void socket_collector(usec_t step, ebpf_module_t *em)
1502 heartbeat_t hb;
1503 heartbeat_init(&hb);
1504
1496 - struct netdata_static_thread socket_threads = {"EBPF SOCKET READ",
1497 - NULL, NULL, 1, NULL,
1498 - NULL, ebpf_socket_read_hash };
1499 - socket_threads.thread = mallocz(sizeof(netdata_thread_t));;
1505 + socket_threads.thread = mallocz(sizeof(netdata_thread_t));
1506
1507 netdata_thread_create(socket_threads.thread, socket_threads.name,
1508 NETDATA_THREAD_OPTION_JOINABLE, ebpf_socket_read_hash, em);
@@ -1650,6 +1656,15 @@ static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
1656 }
1657 }
1658
1659 +void clean_thread_structures() {
1660 + struct pid_stat *pids = root_of_pids;
1661 + while (pids) {
1662 + freez(socket_bandwidth_curr[pids->pid]);
1663 +
1664 + pids = pids->next;
1665 + }
1666 +}
1667 +
1668 /**
1669 * Clean up the main thread.
1670 *
@@ -1657,12 +1672,23 @@ static void clean_hostnames(ebpf_network_viewer_hostname_list_t *hostnames)
1672 */
1673 static void ebpf_socket_cleanup(void *ptr)
1674 {
1660 - UNUSED(ptr);
1675 + ebpf_module_t *em = (ebpf_module_t *)ptr;
1676 + if (!em->enabled)
1677 + return;
1678 +
1679 + heartbeat_t hb;
1680 + heartbeat_init(&hb);
1681 + uint32_t tick = 200*USEC_PER_MS;
1682 + while (!read_thread_closed) {
1683 + usec_t dt = heartbeat_next(&hb, tick);
1684 + UNUSED(dt);
1685 + }
1686 +
1687 freez(socket_aggregated_data);
1688 freez(socket_publish_aggregated);
1689 freez(socket_hash_values);
1690
1665 - freez(socket_data.map_fd);
1691 + clean_thread_structures();
1692 freez(socket_bandwidth_curr);
1693 freez(socket_bandwidth_prev);
1694 freez(bandwidth_vector);
@@ -1683,6 +1709,18 @@ static void ebpf_socket_cleanup(void *ptr)
1709 clean_hostnames(network_viewer_opt.excluded_hostnames);
1710
1711 pthread_mutex_destroy(&nv_mutex);
1712 + freez(socket_data.map_fd);
1713 +
1714 + freez(socket_threads.thread);
1715 +
1716 + struct bpf_program *prog;
1717 + size_t i = 0 ;
1718 + bpf_object__for_each_program(prog, objects) {
1719 + bpf_link__destroy(probe_links[i]);
1720 + i++;
1721 + }
1722 + bpf_object__close(objects);
1723 + finalized_threads = 1;
1724 }
1725
1726 /*****************************************************************
@@ -1789,8 +1827,8 @@ void *ebpf_socket_thread(void *ptr)
1827 }
1828
1829 set_local_pointers(em);
1792 - if (ebpf_load_program(
1793 - ebpf_plugin_dir, em->thread_id, em->mode, kernel_string, em->thread_name, socket_data.map_fd)) {
1830 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, socket_data.map_fd);
1831 + if (!probe_links) {
1832 pthread_mutex_unlock(&lock);
1833 goto endsocket;
1834 }
@@ -1801,6 +1839,7 @@ void *ebpf_socket_thread(void *ptr)
1839
1840 ebpf_create_global_charts(em);
1841
1842 + finalized_threads = 0;
1843 pthread_mutex_unlock(&lock);
1844
1845 socket_collector((usec_t)(em->update_time * USEC_PER_SEC), em);
collectors/ebpf.plugin/ebpf_socket.h
+3
@@ -255,4 +255,7 @@ extern void clean_port_structure(ebpf_network_viewer_port_list_t **clean);
255 extern ebpf_network_viewer_port_list_t *listen_ports;
256 extern void update_listen_table(uint16_t value, uint8_t proto);
257
258 +extern ebpf_socket_publish_apps_t **socket_bandwidth_curr;
259 +extern ebpf_socket_publish_apps_t **socket_bandwidth_prev;
260 +
261 #endif
libnetdata/ebpf/ebpf.c
+15 -13
@@ -8,6 +8,7 @@
8
9 #include "../libnetdata.h"
10
11 +/*
12 static int clean_kprobe_event(FILE *out, char *filename, char *father_pid, netdata_ebpf_events_t *ptr)
13 {
14 int fd = open(filename, O_WRONLY | O_APPEND, 0);
@@ -56,6 +57,7 @@ int clean_kprobe_events(FILE *out, int pid, netdata_ebpf_events_t *ptr)
57
58 return 0;
59 }
60 +*/
61
62 //----------------------------------------------------------------------------------------------------------------------
63
@@ -280,40 +282,40 @@ static int select_file(char *name, const char *program, size_t length, int mode,
282 return ret;
283 }
284
283 -int ebpf_load_program(char *plugins_dir, int event_id, int mode, char *kernel_string, const char *name, int *map_fd)
285 +struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em, char *kernel_string, struct bpf_object **obj, int *map_fd)
286 {
285 - UNUSED(event_id);
286 -
287 char lpath[4096];
288 char lname[128];
289 - struct bpf_object *obj;
289 int prog_fd;
290
292 - int test = select_file(lname, name, (size_t)127, mode, kernel_string);
291 + int test = select_file(lname, em->thread_name, (size_t)127, em->mode, kernel_string);
292 if (test < 0 || test > 127)
294 - return -1;
293 + return NULL;
294
295 snprintf(lpath, 4096, "%s/%s", plugins_dir, lname);
297 - if (bpf_prog_load(lpath, BPF_PROG_TYPE_KPROBE, &obj, &prog_fd)) {
296 + if (bpf_prog_load(lpath, BPF_PROG_TYPE_KPROBE, obj, &prog_fd)) {
297 info("Cannot load program: %s", lpath);
299 - return -1;
298 + return NULL;
299 } else {
301 - info("The eBPF program %s was loaded with success.", name);
300 + info("The eBPF program %s was loaded with success.", em->thread_name);
301 }
302
303 struct bpf_map *map;
304 size_t i = 0;
306 - bpf_map__for_each(map, obj)
305 + bpf_map__for_each(map, *obj)
306 {
307 map_fd[i] = bpf_map__fd(map);
308 i++;
309 }
310
311 struct bpf_program *prog;
313 - bpf_object__for_each_program(prog, obj)
312 + struct bpf_link **links = callocz(NETDATA_MAX_PROBES , sizeof(struct bpf_link *));
313 + i = 0;
314 + bpf_object__for_each_program(prog, *obj)
315 {
315 - bpf_program__attach(prog);
316 + links[i] = bpf_program__attach(prog);
317 + i++;
318 }
319
318 - return 0;
320 + return links;
321 }
libnetdata/ebpf/ebpf.h
+25 -3
@@ -68,16 +68,38 @@ typedef struct ebpf_data {
68 int isrh;
69 } ebpf_data_t;
70
71 +typedef enum {
72 + MODE_RETURN = 0, // This attaches kprobe when the function returns
73 + MODE_DEVMODE, // This stores log given description about the errors raised
74 + MODE_ENTRY // This attaches kprobe when the function is called
75 +} netdata_run_mode_t;
76 +
77 +typedef struct ebpf_module {
78 + const char *thread_name;
79 + const char *config_name;
80 + int enabled;
81 + void *(*start_routine)(void *);
82 + int update_time;
83 + int global_charts;
84 + int apps_charts;
85 + netdata_run_mode_t mode;
86 + netdata_ebpf_events_t *probes;
87 + uint32_t thread_id;
88 + int optional;
89 +} ebpf_module_t;
90 +
91 +#define NETDATA_MAX_PROBES 64
92 +
93 extern int clean_kprobe_events(FILE *out, int pid, netdata_ebpf_events_t *ptr);
94 extern int get_kernel_version(char *out, int size);
95 extern int get_redhat_release();
96 extern int has_condition_to_run(int version);
97 extern char *ebpf_kernel_suffix(int version, int isrh);
98 extern int ebpf_update_kernel(ebpf_data_t *ef);
77 -extern int ebpf_load_program(char *plugins_dir,
78 - int event_id, int mode,
99 +extern struct bpf_link **ebpf_load_program(char *plugins_dir,
100 + ebpf_module_t *em,
101 char *kernel_string,
80 - const char *name,
102 + struct bpf_object **obj,
103 int *map_fd);
104
105 #endif /* NETDATA_EBPF_H */