Hash table charts (#15323)
thiagoftsm committed
Jul 20, 2023 at 19:06 UTC
b762b050afa8dc19726d5b0d395b452c0510b1eb
17 files changed
+355
-172
collectors/ebpf.plugin/ebpf.c
+165
-2
@@ -60,7 +60,7 @@ ebpf_module_t ebpf_modules[] = {
60
NETDATA_V5_14,
61
.load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL,
62
.thread = NULL, .maps_per_core = CONFIG_BOOLEAN_YES, .lifetime = EBPF_DEFAULT_LIFETIME, .running_time = 0 },
63
- { .thread_name = "socket", .config_name = "socket", .thread_description = NETDATA_EBPF_SOCKET_MODULE_DESC,
63
+ { .thread_name = "socket", .config_name = "socket", .thread_description = NETDATA_EBPF_SOCKET_MODULE_DESC,
64
.enabled = 0, .start_routine = ebpf_socket_thread,
65
.update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
66
.apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -1229,7 +1229,7 @@ void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist,
1229
*/
1230
int ebpf_statistic_create_aral_chart(char *name, ebpf_module_t *em)
1231
{
1232
- static int priority = 140100;
1232
+ static int priority = NETATA_EBPF_ORDER_STAT_ARAL_BEGIN;
1233
char *mem = { NETDATA_EBPF_STAT_DIMENSION_MEMORY };
1234
char *aral = { NETDATA_EBPF_STAT_DIMENSION_ARAL };
1235
@@ -1325,6 +1325,49 @@ void ebpf_send_data_aral_chart(ARAL *memory, ebpf_module_t *em)
1325
write_end_chart();
1326
}
1327
1328
+/*****************************************************************
1329
+ *
1330
+ * FUNCTIONS TO READ GLOBAL HASH TABLES
1331
+ *
1332
+ *****************************************************************/
1333
+
1334
+/**
1335
+ * Read Global Table Stats
1336
+ *
1337
+ * Read data from specified table (map_fd) using array allocated inside thread(values) and storing
1338
+ * them in stats vector starting from the first position.
1339
+ *
1340
+ * For PID tables is recommended to use a function to parse the specific data.
1341
+ *
1342
+ * @param stats vector used to store data
1343
+ * @param values helper to read data from hash tables.
1344
+ * @param map_fd table that has data
1345
+ * @param maps_per_core Is necessary to read data from all cores?
1346
+ * @param begin initial value to query hash table
1347
+ * @param end last value that will not be used.
1348
+ */
1349
+void ebpf_read_global_table_stats(netdata_idx_t *stats,
1350
+ netdata_idx_t *values,
1351
+ int map_fd,
1352
+ int maps_per_core,
1353
+ uint32_t begin,
1354
+ uint32_t end)
1355
+{
1356
+ uint32_t idx, order;
1357
+
1358
+ for (idx = begin, order = 0; idx < end; idx++, order++) {
1359
+ if (!bpf_map_lookup_elem(map_fd, &idx, values)) {
1360
+ int i;
1361
+ int before = (maps_per_core) ? ebpf_nprocs: 1;
1362
+ netdata_idx_t total = 0;
1363
+ for (i = 0; i < before; i++)
1364
+ total += values[i];
1365
+
1366
+ stats[order] = total;
1367
+ }
1368
+ }
1369
+}
1370
+
1371
/*****************************************************************
1372
*
1373
* FUNCTIONS TO DEFINE OPTIONS
@@ -2453,6 +2496,47 @@ static char *memlock_stat = {"memory_locked"};
2496
static char *hash_table_stat = {"hash_table"};
2497
static char *hash_table_core[NETDATA_EBPF_LOAD_STAT_END] = {"per_core", "unique"};
2498
2499
+/**
2500
+ * Send Hash Table PID data
2501
+ *
2502
+ * Send all information associated with a specific pid table.
2503
+ *
2504
+ * @param chart chart id
2505
+ * @param idx index position in hash_table_stats
2506
+ */
2507
+static inline void ebpf_send_hash_table_pid_data(char *chart, uint32_t idx)
2508
+{
2509
+ int i;
2510
+ write_begin_chart(NETDATA_MONITORING_FAMILY, chart);
2511
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2512
+ ebpf_module_t *wem = &ebpf_modules[i];
2513
+ if (wem->apps_routine)
2514
+ write_chart_dimension((char *)wem->thread_name,
2515
+ (wem->enabled < NETDATA_THREAD_EBPF_STOPPING) ?
2516
+ wem->hash_table_stats[idx]:
2517
+ 0);
2518
+ }
2519
+ write_end_chart();
2520
+}
2521
+
2522
+/**
2523
+ * Send Global Hash Table data
2524
+ *
2525
+ * Send all information associated with a specific pid table.
2526
+ *
2527
+ */
2528
+static inline void ebpf_send_global_hash_table_data()
2529
+{
2530
+ int i;
2531
+ write_begin_chart(NETDATA_MONITORING_FAMILY, NETDATA_EBPF_HASH_TABLES_GLOBAL_ELEMENTS);
2532
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2533
+ ebpf_module_t *wem = &ebpf_modules[i];
2534
+ write_chart_dimension((char *)wem->thread_name,
2535
+ (wem->enabled < NETDATA_THREAD_EBPF_STOPPING) ? NETDATA_CONTROLLER_END: 0);
2536
+ }
2537
+ write_end_chart();
2538
+}
2539
+
2540
/**
2541
* Send Statistic Data
2542
*
@@ -2500,6 +2584,11 @@ void ebpf_send_statistic_data()
2584
write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_PER_CORE], (long long)plugin_statistics.hash_percpu);
2585
write_chart_dimension(hash_table_core[NETDATA_EBPF_THREAD_UNIQUE], (long long)plugin_statistics.hash_unique);
2586
write_end_chart();
2587
+
2588
+ ebpf_send_global_hash_table_data();
2589
+
2590
+ ebpf_send_hash_table_pid_data(NETDATA_EBPF_HASH_TABLES_INSERT_PID_ELEMENTS, NETDATA_EBPF_GLOBAL_TABLE_PID_TABLE_ADD);
2591
+ ebpf_send_hash_table_pid_data(NETDATA_EBPF_HASH_TABLES_REMOVE_PID_ELEMENTS, NETDATA_EBPF_GLOBAL_TABLE_PID_TABLE_DEL);
2592
}
2593
2594
/**
@@ -2681,6 +2770,66 @@ static inline void ebpf_create_statistic_hash_per_core(int update_every)
2770
ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2771
}
2772
2773
+/**
2774
+ * Hash table global elements
2775
+ *
2776
+ * Write to standard output current values inside global tables.
2777
+ *
2778
+ * @param update_every time used to update charts
2779
+ */
2780
+static void ebpf_create_statistic_hash_global_elements(int update_every)
2781
+{
2782
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2783
+ NETDATA_EBPF_HASH_TABLES_GLOBAL_ELEMENTS,
2784
+ "Controllers inside global table",
2785
+ "rows",
2786
+ NETDATA_EBPF_FAMILY,
2787
+ NETDATA_EBPF_CHART_TYPE_LINE,
2788
+ NULL,
2789
+ NETDATA_EBPF_ORDER_STAT_HASH_GLOBAL_TABLE_TOTAL,
2790
+ update_every,
2791
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2792
+
2793
+ int i;
2794
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2795
+ ebpf_write_global_dimension((char *)ebpf_modules[i].thread_name,
2796
+ (char *)ebpf_modules[i].thread_name,
2797
+ ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX]);
2798
+ }
2799
+}
2800
+
2801
+/**
2802
+ * Hash table global elements
2803
+ *
2804
+ * Write to standard output current values inside global tables.
2805
+ *
2806
+ * @param update_every time used to update charts
2807
+ * @param id chart id
2808
+ * @param title chart title
2809
+ * @param order ordder chart will be shown on dashboard.
2810
+ */
2811
+static void ebpf_create_statistic_hash_pid_table(int update_every, char *id, char *title, int order)
2812
+{
2813
+ ebpf_write_chart_cmd(NETDATA_MONITORING_FAMILY,
2814
+ id,
2815
+ title,
2816
+ "rows",
2817
+ NETDATA_EBPF_FAMILY,
2818
+ NETDATA_EBPF_CHART_TYPE_LINE,
2819
+ NULL,
2820
+ order,
2821
+ update_every,
2822
+ NETDATA_EBPF_MODULE_NAME_PROCESS);
2823
+
2824
+ int i;
2825
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
2826
+ ebpf_module_t *wem = &ebpf_modules[i];
2827
+ if (wem->apps_routine)
2828
+ ebpf_write_global_dimension((char *)wem->thread_name,
2829
+ (char *)wem->thread_name,
2830
+ ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2831
+ }
2832
+}
2833
2834
/**
2835
* Create Statistics Charts
@@ -2718,6 +2867,20 @@ static void ebpf_create_statistic_charts(int update_every)
2867
ebpf_create_statistic_hash_tables(update_every);
2868
2869
ebpf_create_statistic_hash_per_core(update_every);
2870
+
2871
+ ebpf_create_statistic_hash_global_elements(update_every);
2872
+
2873
+ ebpf_create_statistic_hash_pid_table(update_every,
2874
+ NETDATA_EBPF_HASH_TABLES_INSERT_PID_ELEMENTS,
2875
+ "Elements inserted into PID table",
2876
+ NETDATA_EBPF_ORDER_STAT_HASH_PID_TABLE_ADDED);
2877
+
2878
+ ebpf_create_statistic_hash_pid_table(update_every,
2879
+ NETDATA_EBPF_HASH_TABLES_REMOVE_PID_ELEMENTS,
2880
+ "Elements removed from PID table",
2881
+ NETDATA_EBPF_ORDER_STAT_HASH_PID_TABLE_REMOVED);
2882
+
2883
+ fflush(stdout);
2884
}
2885
2886
/*****************************************************************
collectors/ebpf.plugin/ebpf.h
+6
-2
@@ -69,8 +69,6 @@ typedef struct netdata_syscall_stat {
69
struct netdata_syscall_stat *next; // Link list
70
} netdata_syscall_stat_t;
71
72
-typedef uint64_t netdata_idx_t;
73
-
72
typedef struct netdata_publish_syscall {
73
char *dimension;
74
char *name;
@@ -169,6 +167,9 @@ typedef struct ebpf_tracepoint {
167
#define NETDATA_EBPF_KERNEL_MEMORY "ebpf_kernel_memory"
168
#define NETDATA_EBPF_HASH_TABLES_LOADED "ebpf_hash_tables_count"
169
#define NETDATA_EBPF_HASH_TABLES_PER_CORE "ebpf_hash_tables_per_core"
170
+#define NETDATA_EBPF_HASH_TABLES_GLOBAL_ELEMENTS "ebpf_hash_tables_global_elements"
171
+#define NETDATA_EBPF_HASH_TABLES_INSERT_PID_ELEMENTS "ebpf_hash_tables_insert_pid_elements"
172
+#define NETDATA_EBPF_HASH_TABLES_REMOVE_PID_ELEMENTS "ebpf_hash_tables_remove_pid_elements"
173
174
// Log file
175
#define NETDATA_DEVELOPER_LOG_FILE "developer.log"
@@ -319,6 +320,9 @@ void ebpf_update_disabled_plugin_stats(ebpf_module_t *em);
320
ARAL *ebpf_allocate_pid_aral(char *name, size_t size);
321
void ebpf_unload_legacy_code(struct bpf_object *objects, struct bpf_link **probe_links);
322
323
+void ebpf_read_global_table_stats(netdata_idx_t *stats, netdata_idx_t *values, int map_fd,
324
+ int maps_per_core, uint32_t begin, uint32_t end);
325
+
326
extern ebpf_filesystem_partitions_t localfs[];
327
extern ebpf_sync_syscalls_t local_syscalls[];
328
extern int ebpf_exit_plugin;
collectors/ebpf.plugin/ebpf_cachestat.c
+18
-18
@@ -854,26 +854,24 @@ void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *ptr)
854
*
855
* Read the table with number of calls for all functions
856
*
857
+ * @param stats vector used to read data from control table.
858
* @param maps_per_core do I need to read all cores?
859
*/
859
-static void ebpf_cachestat_read_global_table(int maps_per_core)
860
+static void ebpf_cachestat_read_global_tables(netdata_idx_t *stats, int maps_per_core)
861
{
861
- uint32_t idx;
862
- netdata_idx_t *val = cachestat_hash_values;
863
- netdata_idx_t *stored = cachestat_values;
864
- int fd = cachestat_maps[NETDATA_CACHESTAT_GLOBAL_STATS].map_fd;
865
-
866
- for (idx = NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU; idx < NETDATA_CACHESTAT_END; idx++) {
867
- if (!bpf_map_lookup_elem(fd, &idx, stored)) {
868
- int i;
869
- int end = (maps_per_core) ? ebpf_nprocs: 1;
870
- netdata_idx_t total = 0;
871
- for (i = 0; i < end; i++)
872
- total += stored[i];
873
-
874
- val[idx] = total;
875
- }
876
- }
862
+ ebpf_read_global_table_stats(cachestat_hash_values,
863
+ cachestat_values,
864
+ cachestat_maps[NETDATA_CACHESTAT_GLOBAL_STATS].map_fd,
865
+ maps_per_core,
866
+ NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU,
867
+ NETDATA_CACHESTAT_END);
868
+
869
+ ebpf_read_global_table_stats(stats,
870
+ cachestat_values,
871
+ cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd,
872
+ maps_per_core,
873
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
874
+ NETDATA_CONTROLLER_END);
875
}
876
877
/**
@@ -1288,6 +1286,8 @@ static void cachestat_collector(ebpf_module_t *em)
1286
//This will be cancelled by its parent
1287
uint32_t running_time = 0;
1288
uint32_t lifetime = em->lifetime;
1289
+ netdata_idx_t *stats = em->hash_table_stats;
1290
+ memset(stats, 0, sizeof(em->hash_table_stats));
1291
while (!ebpf_exit_plugin && running_time < lifetime) {
1292
(void)heartbeat_next(&hb, USEC_PER_SEC);
1293
@@ -1296,7 +1296,7 @@ static void cachestat_collector(ebpf_module_t *em)
1296
1297
counter = 0;
1298
netdata_apps_integration_flags_t apps = em->apps_charts;
1299
- ebpf_cachestat_read_global_table(maps_per_core);
1299
+ ebpf_cachestat_read_global_tables(stats, maps_per_core);
1300
pthread_mutex_lock(&collect_data_mutex);
1301
if (apps)
1302
ebpf_read_cachestat_apps_table(maps_per_core);
collectors/ebpf.plugin/ebpf_dcstat.c
+18
-18
@@ -690,26 +690,24 @@ static void ebpf_update_dc_cgroup(int maps_per_core)
690
*
691
* Read the table with number of calls for all functions
692
*
693
+ * @param stats vector used to read data from control table.
694
* @param maps_per_core do I need to read all cores?
695
*/
695
-static void ebpf_dc_read_global_table(int maps_per_core)
696
+static void ebpf_dc_read_global_tables(netdata_idx_t *stats, int maps_per_core)
697
{
697
- uint32_t idx;
698
- netdata_idx_t *val = dcstat_hash_values;
699
- netdata_idx_t *stored = dcstat_values;
700
- int fd = dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd;
701
-
702
- for (idx = NETDATA_KEY_DC_REFERENCE; idx < NETDATA_DIRECTORY_CACHE_END; idx++) {
703
- if (!bpf_map_lookup_elem(fd, &idx, stored)) {
704
- int i;
705
- int end = (maps_per_core) ? ebpf_nprocs: 1;
706
- netdata_idx_t total = 0;
707
- for (i = 0; i < end; i++)
708
- total += stored[i];
709
-
710
- val[idx] = total;
711
- }
712
- }
698
+ ebpf_read_global_table_stats(dcstat_hash_values,
699
+ dcstat_values,
700
+ dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd,
701
+ maps_per_core,
702
+ NETDATA_KEY_DC_REFERENCE,
703
+ NETDATA_DIRECTORY_CACHE_END);
704
+
705
+ ebpf_read_global_table_stats(stats,
706
+ dcstat_values,
707
+ dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd,
708
+ maps_per_core,
709
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
710
+ NETDATA_CONTROLLER_END);
711
}
712
713
/**
@@ -1169,6 +1167,8 @@ static void dcstat_collector(ebpf_module_t *em)
1167
int maps_per_core = em->maps_per_core;
1168
uint32_t running_time = 0;
1169
uint32_t lifetime = em->lifetime;
1170
+ netdata_idx_t *stats = em->hash_table_stats;
1171
+ memset(stats, 0, sizeof(em->hash_table_stats));
1172
while (!ebpf_exit_plugin && running_time < lifetime) {
1173
(void)heartbeat_next(&hb, USEC_PER_SEC);
1174
@@ -1177,7 +1177,7 @@ static void dcstat_collector(ebpf_module_t *em)
1177
1178
counter = 0;
1179
netdata_apps_integration_flags_t apps = em->apps_charts;
1180
- ebpf_dc_read_global_table(maps_per_core);
1180
+ ebpf_dc_read_global_tables(stats, maps_per_core);
1181
pthread_mutex_lock(&collect_data_mutex);
1182
if (apps)
1183
read_dc_apps_table(maps_per_core);
collectors/ebpf.plugin/ebpf_fd.c
+19
-19
@@ -360,7 +360,7 @@ static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
360
if (!ret) {
361
ebpf_fd_set_hash_tables(obj);
362
363
- ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
363
+ ebpf_update_controller(fd_maps[NETDATA_FD_CONTROLLER].map_fd, em);
364
}
365
366
return ret;
@@ -624,26 +624,24 @@ static void ebpf_fd_send_data(ebpf_module_t *em)
624
*
625
* Read the table with number of calls for all functions
626
*
627
+ * @param stats vector used to read data from control table.
628
* @param maps_per_core do I need to read all cores?
629
*/
629
-static void ebpf_fd_read_global_table(int maps_per_core)
630
+static void ebpf_fd_read_global_tables(netdata_idx_t *stats, int maps_per_core)
631
{
631
- uint32_t idx;
632
- netdata_idx_t *val = fd_hash_values;
633
- netdata_idx_t *stored = fd_values;
634
- int fd = fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd;
635
-
636
- for (idx = NETDATA_KEY_CALLS_DO_SYS_OPEN; idx < NETDATA_FD_COUNTER; idx++) {
637
- if (!bpf_map_lookup_elem(fd, &idx, stored)) {
638
- int i;
639
- int end = (maps_per_core) ? ebpf_nprocs: 1;
640
- netdata_idx_t total = 0;
641
- for (i = 0; i < end; i++)
642
- total += stored[i];
643
-
644
- val[idx] = total;
645
- }
646
- }
632
+ ebpf_read_global_table_stats(fd_hash_values,
633
+ fd_values,
634
+ fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd,
635
+ maps_per_core,
636
+ NETDATA_KEY_CALLS_DO_SYS_OPEN,
637
+ NETDATA_FD_COUNTER);
638
+
639
+ ebpf_read_global_table_stats(stats,
640
+ fd_values,
641
+ fd_maps[NETDATA_FD_CONTROLLER].map_fd,
642
+ maps_per_core,
643
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
644
+ NETDATA_CONTROLLER_END);
645
}
646
647
/**
@@ -1136,6 +1134,8 @@ static void fd_collector(ebpf_module_t *em)
1134
int maps_per_core = em->maps_per_core;
1135
uint32_t running_time = 0;
1136
uint32_t lifetime = em->lifetime;
1137
+ netdata_idx_t *stats = em->hash_table_stats;
1138
+ memset(stats, 0, sizeof(em->hash_table_stats));
1139
while (!ebpf_exit_plugin && running_time < lifetime) {
1140
(void)heartbeat_next(&hb, USEC_PER_SEC);
1141
@@ -1144,7 +1144,7 @@ static void fd_collector(ebpf_module_t *em)
1144
1145
counter = 0;
1146
netdata_apps_integration_flags_t apps = em->apps_charts;
1147
- ebpf_fd_read_global_table(maps_per_core);
1147
+ ebpf_fd_read_global_tables(stats, maps_per_core);
1148
pthread_mutex_lock(&collect_data_mutex);
1149
if (apps)
1150
read_fd_apps_table(maps_per_core);
collectors/ebpf.plugin/ebpf_oomkill.c
+4
@@ -419,6 +419,7 @@ static void oomkill_collector(ebpf_module_t *em)
419
int counter = update_every - 1;
420
uint32_t running_time = 0;
421
uint32_t lifetime = em->lifetime;
422
+ netdata_idx_t *stats = em->hash_table_stats;
423
while (!ebpf_exit_plugin && running_time < lifetime) {
424
(void)heartbeat_next(&hb, USEC_PER_SEC);
425
if (ebpf_exit_plugin || ++counter != update_every)
@@ -432,6 +433,9 @@ static void oomkill_collector(ebpf_module_t *em)
433
continue;
434
}
435
436
+ stats[NETDATA_CONTROLLER_PID_TABLE_ADD] += (uint64_t) count;
437
+ stats[NETDATA_CONTROLLER_PID_TABLE_DEL] += (uint64_t) count;
438
+
439
pthread_mutex_lock(&collect_data_mutex);
440
pthread_mutex_lock(&lock);
441
if (cgroups) {
collectors/ebpf.plugin/ebpf_process.c
+17
-20
@@ -267,26 +267,22 @@ void ebpf_process_send_apps_data(struct ebpf_target *root, ebpf_module_t *em)
267
*
268
* @param maps_per_core do I need to read all cores?
269
*/
270
-static void ebpf_read_process_hash_global_tables(int maps_per_core)
270
+static void ebpf_read_process_hash_global_tables(netdata_idx_t *stats, int maps_per_core)
271
{
272
- uint64_t idx;
272
netdata_idx_t res[NETDATA_KEY_END_VECTOR];
274
-
275
- netdata_idx_t *val = process_hash_values;
276
- int fd = process_maps[NETDATA_PROCESS_GLOBAL_TABLE].map_fd;
277
- for (idx = 0; idx < NETDATA_KEY_END_VECTOR; idx++) {
278
- if (!bpf_map_lookup_elem(fd, &idx, val)) {
279
- uint64_t total = 0;
280
- int i;
281
- int end = (maps_per_core) ? ebpf_nprocs : 1;
282
- for (i = 0; i < end; i++)
283
- total += val[i];
284
-
285
- res[idx] = total;
286
- } else {
287
- res[idx] = 0;
288
- }
289
- }
273
+ ebpf_read_global_table_stats(res,
274
+ process_hash_values,
275
+ process_maps[NETDATA_PROCESS_GLOBAL_TABLE].map_fd,
276
+ maps_per_core,
277
+ 0,
278
+ NETDATA_KEY_END_VECTOR);
279
+
280
+ ebpf_read_global_table_stats(stats,
281
+ process_hash_values,
282
+ process_maps[NETDATA_PROCESS_CTRL_TABLE].map_fd,
283
+ maps_per_core,
284
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
285
+ NETDATA_CONTROLLER_END);
286
287
process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_EXIT].call = res[NETDATA_KEY_CALLS_DO_EXIT];
288
process_aggregated_data[NETDATA_KEY_PUBLISH_PROCESS_RELEASE_TASK].call = res[NETDATA_KEY_CALLS_RELEASE_TASK];
@@ -747,7 +743,6 @@ static void ebpf_process_exit(void *ptr)
743
ebpf_statistic_obsolete_aral_chart(em, process_disable_priority);
744
#endif
745
750
-
746
fflush(stdout);
747
pthread_mutex_unlock(&lock);
748
}
@@ -1121,6 +1116,8 @@ static void process_collector(ebpf_module_t *em)
1116
int maps_per_core = em->maps_per_core;
1117
uint32_t running_time = 0;
1118
uint32_t lifetime = em->lifetime;
1119
+ netdata_idx_t *stats = em->hash_table_stats;
1120
+ memset(stats, 0, sizeof(em->hash_table_stats));
1121
while (!ebpf_exit_plugin && running_time < lifetime) {
1122
usec_t dt = heartbeat_next(&hb, USEC_PER_SEC);
1123
(void)dt;
@@ -1130,7 +1127,7 @@ static void process_collector(ebpf_module_t *em)
1127
if (++counter == update_every) {
1128
counter = 0;
1129
1133
- ebpf_read_process_hash_global_tables(maps_per_core);
1130
+ ebpf_read_process_hash_global_tables(stats, maps_per_core);
1131
1132
netdata_apps_integration_flags_t apps_enabled = em->apps_charts;
1133
pthread_mutex_lock(&collect_data_mutex);
collectors/ebpf.plugin/ebpf_process.h
+5
-1
@@ -48,7 +48,11 @@ enum netdata_ebpf_stats_order {
48
NETDATA_EBPF_ORDER_STAT_LOAD_METHOD,
49
NETDATA_EBPF_ORDER_STAT_KERNEL_MEMORY,
50
NETDATA_EBPF_ORDER_STAT_HASH_TABLES,
51
- NETDATA_EBPF_ORDER_STAT_HASH_CORE
51
+ NETDATA_EBPF_ORDER_STAT_HASH_CORE,
52
+ NETDATA_EBPF_ORDER_STAT_HASH_GLOBAL_TABLE_TOTAL,
53
+ NETDATA_EBPF_ORDER_STAT_HASH_PID_TABLE_ADDED,
54
+ NETDATA_EBPF_ORDER_STAT_HASH_PID_TABLE_REMOVED,
55
+ NETATA_EBPF_ORDER_STAT_ARAL_BEGIN
56
};
57
58
enum netdata_ebpf_load_mode_stats{
collectors/ebpf.plugin/ebpf_shm.c
+18
-22
@@ -646,30 +646,24 @@ static void shm_send_global()
646
*
647
* Read the table with number of calls for all functions
648
*
649
+ * @param stats vector used to read data from control table.
650
* @param maps_per_core do I need to read all cores?
651
*/
651
-static void ebpf_shm_read_global_table(int maps_per_core)
652
+static void ebpf_shm_read_global_table(netdata_idx_t *stats, int maps_per_core)
653
{
653
- netdata_idx_t *stored = shm_values;
654
- netdata_idx_t *val = shm_hash_values;
655
- int fd = shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd;
656
- size_t length = sizeof(netdata_idx_t);
657
- if (maps_per_core)
658
- length *= ebpf_nprocs;
659
-
660
- uint32_t i, end = NETDATA_SHM_END;
661
- for (i = NETDATA_KEY_SHMGET_CALL; i < end; i++) {
662
- if (!bpf_map_lookup_elem(fd, &i, stored)) {
663
- int j;
664
- int last = (maps_per_core) ? ebpf_nprocs : 1;
665
- netdata_idx_t total = 0;
666
- for (j = 0; j < last; j++)
667
- total += stored[j];
668
-
669
- val[i] = total;
670
- memset(stored, 0 , length);
671
- }
672
- }
654
+ ebpf_read_global_table_stats(shm_hash_values,
655
+ shm_values,
656
+ shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd,
657
+ maps_per_core,
658
+ NETDATA_KEY_SHMGET_CALL,
659
+ NETDATA_SHM_END);
660
+
661
+ ebpf_read_global_table_stats(stats,
662
+ shm_values,
663
+ shm_maps[NETDATA_SHM_CONTROLLER].map_fd,
664
+ maps_per_core,
665
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
666
+ NETDATA_CONTROLLER_END);
667
}
668
669
/**
@@ -1039,6 +1033,8 @@ static void shm_collector(ebpf_module_t *em)
1033
int maps_per_core = em->maps_per_core;
1034
uint32_t running_time = 0;
1035
uint32_t lifetime = em->lifetime;
1036
+ netdata_idx_t *stats = em->hash_table_stats;
1037
+ memset(stats, 0, sizeof(em->hash_table_stats));
1038
while (!ebpf_exit_plugin && running_time < lifetime) {
1039
(void)heartbeat_next(&hb, USEC_PER_SEC);
1040
if (ebpf_exit_plugin || ++counter != update_every)
@@ -1046,7 +1042,7 @@ static void shm_collector(ebpf_module_t *em)
1042
1043
counter = 0;
1044
netdata_apps_integration_flags_t apps = em->apps_charts;
1049
- ebpf_shm_read_global_table(maps_per_core);
1045
+ ebpf_shm_read_global_table(stats, maps_per_core);
1046
pthread_mutex_lock(&collect_data_mutex);
1047
if (apps) {
1048
read_shm_apps_table(maps_per_core);
collectors/ebpf.plugin/ebpf_socket.c
+18
-24
@@ -2205,33 +2205,25 @@ void *ebpf_socket_read_hash(void *ptr)
2205
/**
2206
* Read the hash table and store data to allocated vectors.
2207
*
2208
+ * @param stats vector used to read data from control table.
2209
* @param maps_per_core do I need to read all cores?
2210
*/
2210
-static void read_hash_global_tables(int maps_per_core)
2211
+static void ebpf_socket_read_hash_global_tables(netdata_idx_t *stats, int maps_per_core)
2212
{
2212
- uint64_t idx;
2213
netdata_idx_t res[NETDATA_SOCKET_COUNTER];
2214
-
2215
- netdata_idx_t *val = socket_hash_values;
2216
- size_t length = sizeof(netdata_idx_t);
2217
- if (maps_per_core)
2218
- length *= ebpf_nprocs;
2219
-
2220
- int fd = socket_maps[NETDATA_SOCKET_GLOBAL].map_fd;
2221
- for (idx = 0; idx < NETDATA_SOCKET_COUNTER; idx++) {
2222
- if (!bpf_map_lookup_elem(fd, &idx, val)) {
2223
- uint64_t total = 0;
2224
- int i;
2225
- int end = (maps_per_core) ? ebpf_nprocs : 1;
2226
- for (i = 0; i < end; i++)
2227
- total += val[i];
2228
-
2229
- res[idx] = total;
2230
- memset(socket_hash_values, 0, length);
2231
- } else {
2232
- res[idx] = 0;
2233
- }
2234
- }
2214
+ ebpf_read_global_table_stats(res,
2215
+ socket_hash_values,
2216
+ socket_maps[NETDATA_SOCKET_GLOBAL].map_fd,
2217
+ maps_per_core,
2218
+ NETDATA_KEY_CALLS_TCP_SENDMSG,
2219
+ NETDATA_SOCKET_COUNTER);
2220
+
2221
+ ebpf_read_global_table_stats(stats,
2222
+ socket_hash_values,
2223
+ socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd,
2224
+ maps_per_core,
2225
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
2226
+ NETDATA_CONTROLLER_END);
2227
2228
socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].call = res[NETDATA_KEY_CALLS_TCP_SENDMSG];
2229
socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].call = res[NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF];
@@ -2930,6 +2922,8 @@ static void socket_collector(ebpf_module_t *em)
2922
int counter = update_every - 1;
2923
uint32_t running_time = 0;
2924
uint32_t lifetime = em->lifetime;
2925
+ netdata_idx_t *stats = em->hash_table_stats;
2926
+ memset(stats, 0, sizeof(em->hash_table_stats));
2927
while (!ebpf_exit_plugin && running_time < lifetime) {
2928
(void)heartbeat_next(&hb, USEC_PER_SEC);
2929
if (ebpf_exit_plugin || ++counter != update_every)
@@ -2939,7 +2933,7 @@ static void socket_collector(ebpf_module_t *em)
2933
netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
2934
if (socket_global_enabled) {
2935
read_listen_table();
2942
- read_hash_global_tables(maps_per_core);
2936
+ ebpf_socket_read_hash_global_tables(stats, maps_per_core);
2937
}
2938
2939
pthread_mutex_lock(&collect_data_mutex);
collectors/ebpf.plugin/ebpf_swap.c
+19
-19
@@ -519,26 +519,24 @@ static void swap_send_global()
519
*
520
* Read the table with number of calls to all functions
521
*
522
+ * @param stats vector used to read data from control table.
523
* @param maps_per_core do I need to read all cores?
524
*/
524
-static void ebpf_swap_read_global_table(int maps_per_core)
525
-{
526
- netdata_idx_t *stored = swap_values;
527
- netdata_idx_t *val = swap_hash_values;
528
- int fd = swap_maps[NETDATA_SWAP_GLOBAL_TABLE].map_fd;
529
-
530
- uint32_t i, end = NETDATA_SWAP_END;
531
- for (i = NETDATA_KEY_SWAP_READPAGE_CALL; i < end; i++) {
532
- if (!bpf_map_lookup_elem(fd, &i, stored)) {
533
- int j;
534
- int last = (maps_per_core) ? ebpf_nprocs : 1;
535
- netdata_idx_t total = 0;
536
- for (j = 0; j < last; j++)
537
- total += stored[j];
538
-
539
- val[i] = total;
540
- }
541
- }
525
+static void ebpf_swap_read_global_table(netdata_idx_t *stats, int maps_per_core)
526
+{
527
+ ebpf_read_global_table_stats(swap_hash_values,
528
+ swap_values,
529
+ swap_maps[NETDATA_SWAP_GLOBAL_TABLE].map_fd,
530
+ maps_per_core,
531
+ NETDATA_KEY_SWAP_READPAGE_CALL,
532
+ NETDATA_SWAP_END);
533
+
534
+ ebpf_read_global_table_stats(stats,
535
+ swap_values,
536
+ swap_maps[NETDATA_SWAP_CONTROLLER].map_fd,
537
+ maps_per_core,
538
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
539
+ NETDATA_CONTROLLER_END);
540
}
541
542
/**
@@ -804,6 +802,8 @@ static void swap_collector(ebpf_module_t *em)
802
int maps_per_core = em->maps_per_core;
803
uint32_t running_time = 0;
804
uint32_t lifetime = em->lifetime;
805
+ netdata_idx_t *stats = em->hash_table_stats;
806
+ memset(stats, 0, sizeof(em->hash_table_stats));
807
while (!ebpf_exit_plugin && running_time < lifetime) {
808
(void)heartbeat_next(&hb, USEC_PER_SEC);
809
if (ebpf_exit_plugin || ++counter != update_every)
@@ -811,7 +811,7 @@ static void swap_collector(ebpf_module_t *em)
811
812
counter = 0;
813
netdata_apps_integration_flags_t apps = em->apps_charts;
814
- ebpf_swap_read_global_table(maps_per_core);
814
+ ebpf_swap_read_global_table(stats, maps_per_core);
815
pthread_mutex_lock(&collect_data_mutex);
816
if (apps)
817
read_swap_apps_table(maps_per_core);
collectors/ebpf.plugin/ebpf_vfs.c
+18
-21
@@ -964,30 +964,25 @@ static void ebpf_vfs_send_data(ebpf_module_t *em)
964
/**
965
* Read the hash table and store data to allocated vectors.
966
*
967
+ * @param stats vector used to read data from control table.
968
* @param maps_per_core do I need to read all cores?
969
*/
969
-static void ebpf_vfs_read_global_table(int maps_per_core)
970
+static void ebpf_vfs_read_global_table(netdata_idx_t *stats, int maps_per_core)
971
{
971
- uint64_t idx;
972
netdata_idx_t res[NETDATA_VFS_COUNTER];
973
-
974
- netdata_idx_t *val = vfs_hash_values;
975
- size_t length = sizeof(netdata_idx_t);
976
- if (maps_per_core)
977
- length *= ebpf_nprocs;
978
-
979
- int fd = vfs_maps[NETDATA_VFS_ALL].map_fd;
980
- for (idx = 0; idx < NETDATA_VFS_COUNTER; idx++) {
981
- uint64_t total = 0;
982
- if (!bpf_map_lookup_elem(fd, &idx, val)) {
983
- int i;
984
- int end = (maps_per_core) ? ebpf_nprocs : 1;
985
- for (i = 0; i < end; i++)
986
- total += val[i];
987
- }
988
- res[idx] = total;
989
- memset(val, 0, length);
990
- }
973
+ ebpf_read_global_table_stats(res,
974
+ vfs_hash_values,
975
+ vfs_maps[NETDATA_VFS_ALL].map_fd,
976
+ maps_per_core,
977
+ NETDATA_KEY_CALLS_VFS_WRITE,
978
+ NETDATA_VFS_COUNTER);
979
+
980
+ ebpf_read_global_table_stats(stats,
981
+ vfs_hash_values,
982
+ vfs_maps[NETDATA_VFS_CTRL].map_fd,
983
+ maps_per_core,
984
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
985
+ NETDATA_CONTROLLER_END);
986
987
vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].ncall = res[NETDATA_KEY_CALLS_VFS_UNLINK];
988
vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].ncall = res[NETDATA_KEY_CALLS_VFS_READ] +
@@ -1963,6 +1958,8 @@ static void vfs_collector(ebpf_module_t *em)
1958
int maps_per_core = em->maps_per_core;
1959
uint32_t running_time = 0;
1960
uint32_t lifetime = em->lifetime;
1961
+ netdata_idx_t *stats = em->hash_table_stats;
1962
+ memset(stats, 0, sizeof(em->hash_table_stats));
1963
while (!ebpf_exit_plugin && running_time < lifetime) {
1964
(void)heartbeat_next(&hb, USEC_PER_SEC);
1965
if (ebpf_exit_plugin || ++counter != update_every)
@@ -1970,7 +1967,7 @@ static void vfs_collector(ebpf_module_t *em)
1967
1968
counter = 0;
1969
netdata_apps_integration_flags_t apps = em->apps_charts;
1973
- ebpf_vfs_read_global_table(maps_per_core);
1970
+ ebpf_vfs_read_global_table(stats, maps_per_core);
1971
pthread_mutex_lock(&collect_data_mutex);
1972
if (apps)
1973
ebpf_vfs_read_apps(maps_per_core);
libnetdata/ebpf/ebpf.h
+24
@@ -181,6 +181,17 @@ enum netdata_controller {
181
NETDATA_CONTROLLER_APPS_ENABLED,
182
NETDATA_CONTROLLER_APPS_LEVEL,
183
184
+ // These index show the number of elements
185
+ // stored inside hash tables.
186
+ //
187
+ // We have indexes to count increase and
188
+ // decrease events, because __sync_fetch_and_sub
189
+ // generates compilation errors.
190
+ NETDATA_CONTROLLER_PID_TABLE_ADD,
191
+ NETDATA_CONTROLLER_PID_TABLE_DEL,
192
+ NETDATA_CONTROLLER_TEMP_TABLE_ADD,
193
+ NETDATA_CONTROLLER_TEMP_TABLE_DEL,
194
+
195
NETDATA_CONTROLLER_END
196
};
197
@@ -278,6 +289,17 @@ enum ebpf_threads_status {
289
NETDATA_THREAD_EBPF_NOT_RUNNING // thread was never started
290
};
291
292
+enum ebpf_global_table_values {
293
+ NETDATA_EBPF_GLOBAL_TABLE_PID_TABLE_ADD, // Count elements added inside PID table
294
+ NETDATA_EBPF_GLOBAL_TABLE_PID_TABLE_DEL, // Count elements removed from PID table
295
+ NETDATA_EBPF_GLOBAL_TABLE_TEMP_TABLE_ADD, // Count elements added inside TEMP table
296
+ NETDATA_EBPF_GLOBAL_TABLE_TEMP_TABLE_DEL, // Count elements removed from TEMP table
297
+
298
+ NETDATA_EBPF_GLOBAL_TABLE_STATUS_END
299
+};
300
+
301
+typedef uint64_t netdata_idx_t;
302
+
303
typedef struct ebpf_module {
304
const char *thread_name;
305
const char *config_name;
@@ -313,6 +335,8 @@ typedef struct ebpf_module {
335
// period to run
336
uint32_t running_time; // internal usage, this is used to reset a value when a new request happens.
337
uint32_t lifetime;
338
+
339
+ netdata_idx_t hash_table_stats[NETDATA_EBPF_GLOBAL_TABLE_STATUS_END];
340
} ebpf_module_t;
341
342
#define EBPF_DEFAULT_LIFETIME 300
packaging/ebpf-co-re.checksums
+1
-1
@@ -1 +1 @@
1
-2bcbe98689efe6ee364cb3e9161ef549198d7f181845add923c6561bc8fb74d1 netdata-ebpf-co-re-glibc-v1.2.0.tar.xz
1
+2abbbaf30a73e1ed365d42324a5128470568b008528c3ff8cd98d5eb86152f03 netdata-ebpf-co-re-glibc-v1.2.1.tar.xz
packaging/ebpf-co-re.version
+1
-1
@@ -1 +1 @@
1
-v1.2.0
1
+v1.2.1
packaging/ebpf.checksums
+3
-3
@@ -1,3 +1,3 @@
1
-a7386ffca8cbe9aa24c01b0b97b2e3553c11d696752037551277f9b1f5feb100 ./netdata-kernel-collector-glibc-v1.2.0.tar.xz
2
-2b37ce6129dc61fd79e5519c150196099d363b4e57dafc55b210f64f9b40a3ec ./netdata-kernel-collector-musl-v1.2.0.tar.xz
3
-ad22f11cb545557c09955f3728ba76d9734345c0ab84927086bb0e99a9f88f80 ./netdata-kernel-collector-static-v1.2.0.tar.xz
1
+cb0cd6ef4bdb8a39c42b152d328d4822217c59e1d616d3003bc67bc53a058275 ./netdata-kernel-collector-glibc-v1.2.1.tar.xz
2
+0633ff39e8654a21ab664a289f58daca5792cfaf2ed62dcaacf7cd267eeedd40 ./netdata-kernel-collector-musl-v1.2.1.tar.xz
3
+6ce60c5ac8f45cc6a01b7ac9ea150728963d0aca1ee6dfd568b0f8b2ba67b88b ./netdata-kernel-collector-static-v1.2.1.tar.xz
packaging/ebpf.version
+1
-1
@@ -1 +1 @@
1
-v1.2.0
1
+v1.2.1