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 */