eBPF socket (eBPF) (#16669)
thiagoftsm committed
Dec 27, 2023 at 14:28 UTC
28394c9236d740939ae27e23044b8751962ee268
3 files changed
+92
-473
collectors/ebpf.plugin/ebpf.c
-16
@@ -3777,11 +3777,6 @@ static void ebpf_create_statistic_charts(int update_every)
3777
NETDATA_EBPF_ORDER_STAT_THREADS,
3778
update_every,
3779
NULL);
3780
- /*
3781
-#ifdef NETDATA_DEV_MODE
3782
- EBPF_PLUGIN_FUNCTIONS(EBPF_FUNCTION_THREAD, EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
3783
-#endif
3784
- */
3780
3781
ebpf_create_thread_chart(NETDATA_EBPF_LIFE_TIME,
3782
"Time remaining for thread.",
@@ -3789,11 +3784,6 @@ static void ebpf_create_statistic_charts(int update_every)
3784
NETDATA_EBPF_ORDER_STAT_LIFE_TIME,
3785
update_every,
3786
NULL);
3792
- /*
3793
-#ifdef NETDATA_DEV_MODE
3794
- EBPF_PLUGIN_FUNCTIONS(EBPF_FUNCTION_THREAD, EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
3795
-#endif
3796
- */
3787
3788
int i,j;
3789
char name[256];
@@ -3811,9 +3801,6 @@ static void ebpf_create_statistic_charts(int update_every)
3801
j++,
3802
update_every,
3803
em);
3814
-#ifdef NETDATA_DEV_MODE
3815
- EBPF_PLUGIN_FUNCTIONS(em->functions.fcnt_name, em->functions.fcnt_desc);
3816
-#endif
3804
3805
em->functions.order_thread_lifetime = j;
3806
snprintfz(name, sizeof(name) - 1, "%s_%s", NETDATA_EBPF_LIFE_TIME, em->info.thread_name);
@@ -3824,9 +3811,6 @@ static void ebpf_create_statistic_charts(int update_every)
3811
j++,
3812
update_every,
3813
em);
3827
-#ifdef NETDATA_DEV_MODE
3828
- EBPF_PLUGIN_FUNCTIONS(em->functions.fcnt_name, em->functions.fcnt_desc);
3829
-#endif
3814
}
3815
3816
ebpf_create_statistic_load_chart(update_every);
collectors/ebpf.plugin/ebpf_functions.c
+89
-440
@@ -37,66 +37,6 @@ static int ebpf_function_start_thread(ebpf_module_t *em, int period)
37
return netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, em);
38
}
39
40
-/*****************************************************************
41
- * EBPF SELECT MODULE
42
- *****************************************************************/
43
-
44
-/**
45
- * Select Module
46
- *
47
- * @param thread_name name of the thread we are looking for.
48
- *
49
- * @return it returns a pointer for the module that has thread_name on success or NULL otherwise.
50
-ebpf_module_t *ebpf_functions_select_module(const char *thread_name) {
51
- int i;
52
- for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
53
- if (strcmp(ebpf_modules[i].info.thread_name, thread_name) == 0) {
54
- return &ebpf_modules[i];
55
- }
56
- }
57
-
58
- return NULL;
59
-}
60
- */
61
-
62
-/*****************************************************************
63
- * EBPF HELP FUNCTIONS
64
- *****************************************************************/
65
-
66
-/**
67
- * Thread Help
68
- *
69
- * Shows help with all options accepted by thread function.
70
- *
71
- * @param transaction the transaction id that Netdata sent for this function execution
72
-static void ebpf_function_thread_manipulation_help(const char *transaction) {
73
- BUFFER *wb = buffer_create(0, NULL);
74
- buffer_sprintf(wb, "%s",
75
- "ebpf.plugin / thread\n"
76
- "\n"
77
- "Function `thread` allows user to control eBPF threads.\n"
78
- "\n"
79
- "The following filters are supported:\n"
80
- "\n"
81
- " thread:NAME\n"
82
- " Shows information for the thread NAME. Names are listed inside `ebpf.d.conf`.\n"
83
- "\n"
84
- " enable:NAME:PERIOD\n"
85
- " Enable a specific thread named `NAME` to run a specific PERIOD in seconds. When PERIOD is not\n"
86
- " specified plugin will use the default 300 seconds\n"
87
- "\n"
88
- " disable:NAME\n"
89
- " Disable a sp.\n"
90
- "\n"
91
- "Filters can be combined. Each filter can be given only one time.\n"
92
- );
93
-
94
- pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "text/plain", now_realtime_sec() + 3600, wb);
95
-
96
- buffer_free(wb);
97
-}
98
-*/
99
-
40
/*****************************************************************
41
* EBPF ERROR FUNCTIONS
42
*****************************************************************/
@@ -110,269 +50,10 @@ static void ebpf_function_thread_manipulation_help(const char *transaction) {
50
* @param code the error code to show with the message.
51
* @param msg the error message
52
*/
113
-static void ebpf_function_error(const char *transaction, int code, const char *msg) {
53
+static inline void ebpf_function_error(const char *transaction, int code, const char *msg) {
54
pluginsd_function_json_error_to_stdout(transaction, code, msg);
55
}
56
117
-/*****************************************************************
118
- * EBPF THREAD FUNCTION
119
- *****************************************************************/
120
-
121
-/**
122
- * Function: thread
123
- *
124
- * Enable a specific thread.
125
- *
126
- * @param transaction the transaction id that Netdata sent for this function execution
127
- * @param function function name and arguments given to thread.
128
- * @param line_buffer buffer used to parse args
129
- * @param line_max Number of arguments given
130
- * @param timeout The function timeout
131
- * @param em The structure with thread information
132
-static void ebpf_function_thread_manipulation(const char *transaction,
133
- char *function __maybe_unused,
134
- char *line_buffer __maybe_unused,
135
- int line_max __maybe_unused,
136
- int timeout __maybe_unused,
137
- ebpf_module_t *em)
138
-{
139
- char *words[PLUGINSD_MAX_WORDS] = { NULL };
140
- char message[512];
141
- uint32_t show_specific_thread = 0;
142
- size_t num_words = quoted_strings_splitter_pluginsd(function, words, PLUGINSD_MAX_WORDS);
143
- for(int i = 1; i < PLUGINSD_MAX_WORDS ;i++) {
144
- const char *keyword = get_word(words, num_words, i);
145
- if (!keyword)
146
- break;
147
-
148
- ebpf_module_t *lem;
149
- if(strncmp(keyword, EBPF_THREADS_ENABLE_CATEGORY, sizeof(EBPF_THREADS_ENABLE_CATEGORY) -1) == 0) {
150
- char thread_name[128];
151
- int period = -1;
152
- const char *name = &keyword[sizeof(EBPF_THREADS_ENABLE_CATEGORY) - 1];
153
- char *separator = strchr(name, ':');
154
- if (separator) {
155
- strncpyz(thread_name, name, separator - name);
156
- period = str2i(++separator);
157
- } else {
158
- strncpyz(thread_name, name, strlen(name));
159
- }
160
-
161
- lem = ebpf_functions_select_module(thread_name);
162
- if (!lem) {
163
- snprintfz(message, sizeof(message) - 1, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
164
- ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
165
- return;
166
- }
167
-
168
- pthread_mutex_lock(&ebpf_exit_cleanup);
169
- if (lem->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
170
- // Load configuration again
171
- ebpf_update_module(lem, default_btf, running_on_kernel, isrh);
172
-
173
- if (ebpf_function_start_thread(lem, period)) {
174
- ebpf_function_error(transaction,
175
- HTTP_RESP_INTERNAL_SERVER_ERROR,
176
- "Cannot start thread.");
177
- return;
178
- }
179
- } else {
180
- lem->running_time = 0;
181
- if (period > 0) // user is modifying period to run
182
- lem->lifetime = period;
183
-#ifdef NETDATA_INTERNAL_CHECKS
184
- netdata_log_info("Thread %s had lifetime updated for %d", thread_name, period);
185
-#endif
186
- }
187
- pthread_mutex_unlock(&ebpf_exit_cleanup);
188
- } else if(strncmp(keyword, EBPF_THREADS_DISABLE_CATEGORY, sizeof(EBPF_THREADS_DISABLE_CATEGORY) -1) == 0) {
189
- const char *name = &keyword[sizeof(EBPF_THREADS_DISABLE_CATEGORY) - 1];
190
- lem = ebpf_functions_select_module(name);
191
- if (!lem) {
192
- snprintfz(message, sizeof(message) - 1, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
193
- ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
194
- return;
195
- }
196
-
197
- pthread_mutex_lock(&ebpf_exit_cleanup);
198
- if (lem->enabled < NETDATA_THREAD_EBPF_STOPPING && lem->thread->thread) {
199
- lem->lifetime = 0;
200
- lem->running_time = lem->update_every;
201
- netdata_thread_cancel(*lem->thread->thread);
202
- }
203
- pthread_mutex_unlock(&ebpf_exit_cleanup);
204
- } else if(strncmp(keyword, EBPF_THREADS_SELECT_THREAD, sizeof(EBPF_THREADS_SELECT_THREAD) -1) == 0) {
205
- const char *name = &keyword[sizeof(EBPF_THREADS_SELECT_THREAD) - 1];
206
- lem = ebpf_functions_select_module(name);
207
- if (!lem) {
208
- snprintfz(message, sizeof(message) - 1, "%s%s", EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND, name);
209
- ebpf_function_error(transaction, HTTP_RESP_NOT_FOUND, message);
210
- return;
211
- }
212
-
213
- show_specific_thread |= 1<<lem->thread_id;
214
- } else if(strncmp(keyword, "help", 4) == 0) {
215
- ebpf_function_thread_manipulation_help(transaction);
216
- return;
217
- }
218
- }
219
-
220
- time_t expires = now_realtime_sec() + em->update_every;
221
-
222
- BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX, NULL);
223
- buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS);
224
- buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
225
- buffer_json_member_add_string(wb, "type", "table");
226
- buffer_json_member_add_time_t(wb, "update_every", em->update_every);
227
- buffer_json_member_add_string(wb, "help", EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION);
228
-
229
- // Collect data
230
- buffer_json_member_add_array(wb, "data");
231
- int i;
232
- for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
233
- if (show_specific_thread && !(show_specific_thread & 1<<i))
234
- continue;
235
-
236
- ebpf_module_t *wem = &ebpf_modules[i];
237
- buffer_json_add_array_item_array(wb);
238
-
239
- // IMPORTANT!
240
- // THE ORDER SHOULD BE THE SAME WITH THE FIELDS!
241
-
242
- // thread name
243
- buffer_json_add_array_item_string(wb, wem->info.thread_name);
244
-
245
- // description
246
- buffer_json_add_array_item_string(wb, wem->info.thread_description);
247
- // Either it is not running or received a disabled signal and it is stopping.
248
- if (wem->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING ||
249
- (!wem->lifetime && (int)wem->running_time == wem->update_every)) {
250
- // status
251
- buffer_json_add_array_item_string(wb, EBPF_THREAD_STATUS_STOPPED);
252
-
253
- // Time remaining
254
- buffer_json_add_array_item_uint64(wb, 0);
255
-
256
- // action
257
- buffer_json_add_array_item_string(wb, "NULL");
258
- } else {
259
- // status
260
- buffer_json_add_array_item_string(wb, EBPF_THREAD_STATUS_RUNNING);
261
-
262
- // Time remaining
263
- buffer_json_add_array_item_uint64(wb, (wem->lifetime) ? (wem->lifetime - wem->running_time) : 0);
264
-
265
- // action
266
- buffer_json_add_array_item_string(wb, "Enabled/Disabled");
267
- }
268
-
269
- buffer_json_array_close(wb);
270
- }
271
-
272
- buffer_json_array_close(wb); // data
273
-
274
- buffer_json_member_add_object(wb, "columns");
275
- {
276
- int fields_id = 0;
277
-
278
- // IMPORTANT!
279
- // THE ORDER SHOULD BE THE SAME WITH THE VALUES!
280
- buffer_rrdf_table_add_field(wb, fields_id++, "Thread", "Thread Name", RRDF_FIELD_TYPE_STRING,
281
- RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
282
- RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
283
- RRDF_FIELD_FILTER_MULTISELECT,
284
- RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY | RRDF_FIELD_OPTS_UNIQUE_KEY, NULL);
285
-
286
- buffer_rrdf_table_add_field(wb, fields_id++, "Description", "Thread Desc", RRDF_FIELD_TYPE_STRING,
287
- RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
288
- RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
289
- RRDF_FIELD_FILTER_MULTISELECT,
290
- RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
291
-
292
- buffer_rrdf_table_add_field(wb, fields_id++, "Status", "Thread Status", RRDF_FIELD_TYPE_STRING,
293
- RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
294
- RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
295
- RRDF_FIELD_FILTER_MULTISELECT,
296
- RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
297
-
298
- buffer_rrdf_table_add_field(wb, fields_id++, "Time", "Time Remaining", RRDF_FIELD_TYPE_INTEGER,
299
- RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL,
300
- NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
301
- RRDF_FIELD_FILTER_MULTISELECT,
302
- RRDF_FIELD_OPTS_NONE, NULL);
303
-
304
- buffer_rrdf_table_add_field(wb, fields_id++, "Action", "Thread Action", RRDF_FIELD_TYPE_STRING,
305
- RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
306
- RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
307
- RRDF_FIELD_FILTER_MULTISELECT,
308
- RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
309
- }
310
- buffer_json_object_close(wb); // columns
311
-
312
- buffer_json_member_add_string(wb, "default_sort_column", "Thread");
313
-
314
- buffer_json_member_add_object(wb, "charts");
315
- {
316
- // Threads
317
- buffer_json_member_add_object(wb, "eBPFThreads");
318
- {
319
- buffer_json_member_add_string(wb, "name", "Threads");
320
- buffer_json_member_add_string(wb, "type", "line");
321
- buffer_json_member_add_array(wb, "columns");
322
- {
323
- buffer_json_add_array_item_string(wb, "Threads");
324
- }
325
- buffer_json_array_close(wb);
326
- }
327
- buffer_json_object_close(wb);
328
-
329
- // Life Time
330
- buffer_json_member_add_object(wb, "eBPFLifeTime");
331
- {
332
- buffer_json_member_add_string(wb, "name", "LifeTime");
333
- buffer_json_member_add_string(wb, "type", "line");
334
- buffer_json_member_add_array(wb, "columns");
335
- {
336
- buffer_json_add_array_item_string(wb, "Threads");
337
- buffer_json_add_array_item_string(wb, "Time");
338
- }
339
- buffer_json_array_close(wb);
340
- }
341
- buffer_json_object_close(wb);
342
- }
343
- buffer_json_object_close(wb); // charts
344
-
345
- // Do we use only on fields that can be groupped?
346
- buffer_json_member_add_object(wb, "group_by");
347
- {
348
- // group by Status
349
- buffer_json_member_add_object(wb, "Status");
350
- {
351
- buffer_json_member_add_string(wb, "name", "Thread status");
352
- buffer_json_member_add_array(wb, "columns");
353
- {
354
- buffer_json_add_array_item_string(wb, "Status");
355
- }
356
- buffer_json_array_close(wb);
357
- }
358
- buffer_json_object_close(wb);
359
- }
360
- buffer_json_object_close(wb); // group_by
361
-
362
- buffer_json_member_add_time_t(wb, "expires", expires);
363
- buffer_json_finalize(wb);
364
-
365
- // Lock necessary to avoid race condition
366
- pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires, wb);
367
-
368
- buffer_free(wb);
369
-}
370
- */
371
-
372
-/*****************************************************************
373
- * EBPF SOCKET FUNCTION
374
- *****************************************************************/
375
-
57
/**
58
* Thread Help
59
*
@@ -380,46 +61,18 @@ static void ebpf_function_thread_manipulation(const char *transaction,
61
*
62
* @param transaction the transaction id that Netdata sent for this function execution
63
*/
383
-static void ebpf_function_socket_help(const char *transaction) {
64
+static inline void ebpf_function_help(const char *transaction, const char *message) {
65
pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "text/plain", now_realtime_sec() + 3600);
385
- fprintf(stdout, "%s",
386
- "ebpf.plugin / socket\n"
387
- "\n"
388
- "Function `socket` display information for all open sockets during ebpf.plugin runtime.\n"
389
- "During thread runtime the plugin is always collecting data, but when an option is modified, the plugin\n"
390
- "resets completely the previous table and can show a clean data for the first request before to bring the\n"
391
- "modified request.\n"
392
- "\n"
393
- "The following filters are supported:\n"
394
- "\n"
395
- " family:FAMILY\n"
396
- " Shows information for the FAMILY specified. Option accepts IPV4, IPV6 and all, that is the default.\n"
397
- "\n"
398
- " period:PERIOD\n"
399
- " Enable socket to run a specific PERIOD in seconds. When PERIOD is not\n"
400
- " specified plugin will use the default 300 seconds\n"
401
- "\n"
402
- " resolve:BOOL\n"
403
- " Resolve service name, default value is YES.\n"
404
- "\n"
405
- " range:CIDR\n"
406
- " Show sockets that have only a specific destination. Default all addresses.\n"
407
- "\n"
408
- " port:range\n"
409
- " Show sockets that have only a specific destination.\n"
410
- "\n"
411
- " reset\n"
412
- " Send a reset to collector. When a collector receives this command, it uses everything defined in configuration file.\n"
413
- "\n"
414
- " interfaces\n"
415
- " When the collector receives this command, it read all available interfaces on host.\n"
416
- "\n"
417
- "Filters can be combined. Each filter can be given only one time. Default all ports\n"
418
- );
66
+ fprintf(stdout, "%s", message);
67
pluginsd_function_result_end_to_stdout();
68
fflush(stdout);
69
}
70
71
+/*****************************************************************
72
+ * EBPF SOCKET FUNCTION
73
+ *****************************************************************/
74
+
75
+
76
/**
77
* Fill Fake socket
78
*
@@ -651,8 +304,42 @@ static void ebpf_function_socket_manipulation(const char *transaction,
304
rw_spinlock_write_lock(&ebpf_judy_pid.index.rw_spinlock);
305
network_viewer_opt.enabled = CONFIG_BOOLEAN_YES;
306
uint32_t previous;
654
-
655
- for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) {
307
+ static const char *socket_help = {
308
+ "ebpf.plugin / socket\n"
309
+ "\n"
310
+ "Function `socket` display information for all open sockets during ebpf.plugin runtime.\n"
311
+ "During thread runtime the plugin is always collecting data, but when an option is modified, the plugin\n"
312
+ "resets completely the previous table and can show a clean data for the first request before to bring the\n"
313
+ "modified request.\n"
314
+ "\n"
315
+ "The following filters are supported:\n"
316
+ "\n"
317
+ " family:FAMILY\n"
318
+ " Shows information for the FAMILY specified. Option accepts IPV4, IPV6 and all, that is the default.\n"
319
+ "\n"
320
+ " period:PERIOD\n"
321
+ " Enable socket to run a specific PERIOD in seconds. When PERIOD is not\n"
322
+ " specified plugin will use the default 300 seconds\n"
323
+ "\n"
324
+ " resolve:BOOL\n"
325
+ " Resolve service name, default value is YES.\n"
326
+ "\n"
327
+ " range:CIDR\n"
328
+ " Show sockets that have only a specific destination. Default all addresses.\n"
329
+ "\n"
330
+ " port:range\n"
331
+ " Show sockets that have only a specific destination.\n"
332
+ "\n"
333
+ " reset\n"
334
+ " Send a reset to collector. When a collector receives this command, it uses everything defined in configuration file.\n"
335
+ "\n"
336
+ " interfaces\n"
337
+ " When the collector receives this command, it read all available interfaces on host.\n"
338
+ "\n"
339
+ "Filters can be combined. Each filter can be given only one time. Default all ports\n"
340
+ };
341
+
342
+for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) {
343
const char *keyword = get_word(words, num_words, i);
344
if (!keyword)
345
break;
@@ -735,20 +422,20 @@ static void ebpf_function_socket_manipulation(const char *transaction,
422
ebpf_read_local_addresses_unsafe();
423
rw_spinlock_write_unlock(&network_viewer_opt.rw_spinlock);
424
} else if (strncmp(keyword, "help", 4) == 0) {
738
- ebpf_function_socket_help(transaction);
425
+ ebpf_function_help(transaction, socket_help);
426
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
427
return;
428
}
429
}
430
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
431
745
- pthread_mutex_lock(&ebpf_exit_cleanup);
432
if (em->enabled > NETDATA_THREAD_EBPF_FUNCTION_RUNNING) {
433
// Cleanup when we already had a thread running
434
rw_spinlock_write_lock(&ebpf_judy_pid.index.rw_spinlock);
435
ebpf_socket_clean_judy_array_unsafe();
436
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
437
438
+ pthread_mutex_lock(&ebpf_exit_cleanup);
439
if (ebpf_function_start_thread(em, period)) {
440
ebpf_function_error(transaction,
441
HTTP_RESP_INTERNAL_SERVER_ERROR,
@@ -757,16 +444,14 @@ static void ebpf_function_socket_manipulation(const char *transaction,
444
return;
445
}
446
} else {
760
- if (period < 0 && em->lifetime < EBPF_NON_FUNCTION_LIFE_TIME) {
761
- em->lifetime = EBPF_NON_FUNCTION_LIFE_TIME;
762
- }
447
+ pthread_mutex_lock(&ebpf_exit_cleanup);
448
+ if (period < 0)
449
+ em->lifetime = (em->enabled != NETDATA_THREAD_EBPF_FUNCTION_RUNNING) ? EBPF_NON_FUNCTION_LIFE_TIME : EBPF_DEFAULT_LIFETIME;
450
}
451
pthread_mutex_unlock(&ebpf_exit_cleanup);
452
766
- time_t expires = now_realtime_sec() + em->update_every;
767
-
453
BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX, NULL);
769
- buffer_json_initialize(wb, "\"", "\"", 0, true, false);
454
+ buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS);
455
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
456
buffer_json_member_add_string(wb, "type", "table");
457
buffer_json_member_add_time_t(wb, "update_every", em->update_every);
@@ -790,7 +475,7 @@ static void ebpf_function_socket_manipulation(const char *transaction,
475
RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY,
476
NULL);
477
793
- buffer_rrdf_table_add_field(wb, fields_id++, "Process Name", "Process Name", RRDF_FIELD_TYPE_STRING,
478
+ buffer_rrdf_table_add_field(wb, fields_id++, "PName", "Process Name", RRDF_FIELD_TYPE_STRING,
479
RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
480
RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
481
RRDF_FIELD_FILTER_MULTISELECT,
@@ -835,14 +520,14 @@ static void ebpf_function_socket_manipulation(const char *transaction,
520
RRDF_FIELD_FILTER_MULTISELECT,
521
RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
522
838
- buffer_rrdf_table_add_field(wb, fields_id++, "Incoming Bandwidth", "Bytes received.", RRDF_FIELD_TYPE_INTEGER,
523
+ buffer_rrdf_table_add_field(wb, fields_id++, "IncomingBandwidth", "Bytes received.", RRDF_FIELD_TYPE_INTEGER,
524
RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
525
RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
526
RRDF_FIELD_FILTER_MULTISELECT,
527
RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY,
528
NULL);
529
845
- buffer_rrdf_table_add_field(wb, fields_id++, "Outgoing Bandwidth", "Bytes sent.", RRDF_FIELD_TYPE_INTEGER,
530
+ buffer_rrdf_table_add_field(wb, fields_id++, "OutgoingBandwidth", "Bytes sent.", RRDF_FIELD_TYPE_INTEGER,
531
RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
532
RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
533
RRDF_FIELD_FILTER_MULTISELECT,
@@ -858,97 +543,49 @@ static void ebpf_function_socket_manipulation(const char *transaction,
543
}
544
buffer_json_object_close(wb); // columns
545
546
+ buffer_json_member_add_string(wb, "default_sort_column", "IncomingBandwidth");
547
+
548
buffer_json_member_add_object(wb, "charts");
549
{
863
- // OutBound Connections
864
- buffer_json_member_add_object(wb, "IPInboundConn");
550
+ buffer_json_member_add_object(wb, "IncomingConnections");
551
{
552
buffer_json_member_add_string(wb, "name", "TCP Inbound Connection");
867
- buffer_json_member_add_string(wb, "type", "line");
868
- buffer_json_member_add_array(wb, "columns");
869
- {
870
- buffer_json_add_array_item_string(wb, "connected_tcp");
871
- buffer_json_add_array_item_string(wb, "connected_udp");
872
- }
873
- buffer_json_array_close(wb);
874
- }
875
- buffer_json_object_close(wb);
876
-
877
- // OutBound Connections
878
- buffer_json_member_add_object(wb, "IPTCPOutboundConn");
879
- {
880
- buffer_json_member_add_string(wb, "name", "TCP Outbound Connection");
881
- buffer_json_member_add_string(wb, "type", "line");
882
- buffer_json_member_add_array(wb, "columns");
883
- {
884
- buffer_json_add_array_item_string(wb, "connected_V4");
885
- buffer_json_add_array_item_string(wb, "connected_V6");
886
- }
887
- buffer_json_array_close(wb);
888
- }
889
- buffer_json_object_close(wb);
890
-
891
- // TCP Functions
892
- buffer_json_member_add_object(wb, "TCPFunctions");
893
- {
894
- buffer_json_member_add_string(wb, "name", "TCPFunctions");
895
- buffer_json_member_add_string(wb, "type", "line");
896
- buffer_json_member_add_array(wb, "columns");
897
- {
898
- buffer_json_add_array_item_string(wb, "received");
899
- buffer_json_add_array_item_string(wb, "sent");
900
- buffer_json_add_array_item_string(wb, "close");
901
- }
902
- buffer_json_array_close(wb);
903
- }
904
- buffer_json_object_close(wb);
905
-
906
- // TCP Bandwidth
907
- buffer_json_member_add_object(wb, "TCPBandwidth");
908
- {
909
- buffer_json_member_add_string(wb, "name", "TCPBandwidth");
910
- buffer_json_member_add_string(wb, "type", "line");
911
- buffer_json_member_add_array(wb, "columns");
912
- {
913
- buffer_json_add_array_item_string(wb, "received");
914
- buffer_json_add_array_item_string(wb, "sent");
915
- }
916
- buffer_json_array_close(wb);
917
- }
918
- buffer_json_object_close(wb);
919
-
920
- // UDP Functions
921
- buffer_json_member_add_object(wb, "UDPFunctions");
922
- {
923
- buffer_json_member_add_string(wb, "name", "UDPFunctions");
924
- buffer_json_member_add_string(wb, "type", "line");
553
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
554
buffer_json_member_add_array(wb, "columns");
555
{
927
- buffer_json_add_array_item_string(wb, "received");
928
- buffer_json_add_array_item_string(wb, "sent");
556
+ buffer_json_add_array_item_string(wb, "IncomingBandwidth");
557
}
558
buffer_json_array_close(wb);
559
}
560
buffer_json_object_close(wb);
561
934
- // UDP Bandwidth
935
- buffer_json_member_add_object(wb, "UDPBandwidth");
562
+ buffer_json_member_add_object(wb, "OutgoingConnections");
563
{
937
- buffer_json_member_add_string(wb, "name", "UDPBandwidth");
938
- buffer_json_member_add_string(wb, "type", "line");
564
+ buffer_json_member_add_string(wb, "name", "TCP Outgoing Connection");
565
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
566
buffer_json_member_add_array(wb, "columns");
567
{
941
- buffer_json_add_array_item_string(wb, "received");
942
- buffer_json_add_array_item_string(wb, "sent");
568
+ buffer_json_add_array_item_string(wb, "OutgoingBandwidth");
569
}
570
buffer_json_array_close(wb);
571
}
572
buffer_json_object_close(wb);
947
-
573
}
574
buffer_json_object_close(wb); // charts
575
951
- buffer_json_member_add_string(wb, "default_sort_column", "PID");
576
+ buffer_json_member_add_array(wb, "default_charts");
577
+ {
578
+ buffer_json_add_array_item_array(wb);
579
+ buffer_json_add_array_item_string(wb, "IncomingConnections");
580
+ buffer_json_add_array_item_string(wb, "PName");
581
+ buffer_json_array_close(wb);
582
+
583
+ buffer_json_add_array_item_array(wb);
584
+ buffer_json_add_array_item_string(wb, "OutgoingConnections");
585
+ buffer_json_add_array_item_string(wb, "PName");
586
+ buffer_json_array_close(wb);
587
+ }
588
+ buffer_json_array_close(wb);
589
590
// Do we use only on fields that can be groupped?
591
buffer_json_member_add_object(wb, "group_by");
@@ -966,12 +603,12 @@ static void ebpf_function_socket_manipulation(const char *transaction,
603
buffer_json_object_close(wb);
604
605
// group by Process Name
969
- buffer_json_member_add_object(wb, "Process Name");
606
+ buffer_json_member_add_object(wb, "PName");
607
{
608
buffer_json_member_add_string(wb, "name", "Process Name");
609
buffer_json_member_add_array(wb, "columns");
610
{
974
- buffer_json_add_array_item_string(wb, "Process Name");
611
+ buffer_json_add_array_item_string(wb, "PName");
612
}
613
buffer_json_array_close(wb);
614
}
@@ -1039,6 +676,7 @@ static void ebpf_function_socket_manipulation(const char *transaction,
676
}
677
buffer_json_object_close(wb); // group_by
678
679
+ time_t expires = now_realtime_sec() + em->update_every;
680
buffer_json_member_add_time_t(wb, "expires", expires);
681
buffer_json_finalize(wb);
682
@@ -1078,6 +716,17 @@ void *ebpf_function_thread(void *ptr)
716
ebpf_function_socket_manipulation,
717
PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT);
718
719
+ pthread_mutex_lock(&lock);
720
+ int i;
721
+ for (i = 0; i < EBPF_MODULE_FUNCTION_IDX; i++) {
722
+ ebpf_module_t *em = &ebpf_modules[i];
723
+ if (!em->functions.fnct_routine)
724
+ continue;
725
+
726
+ EBPF_PLUGIN_FUNCTIONS(em->functions.fcnt_name, em->functions.fcnt_desc, em->update_every);
727
+ }
728
+ pthread_mutex_unlock(&lock);
729
+
730
heartbeat_t hb;
731
heartbeat_init(&hb);
732
while(!ebpf_plugin_exit) {
collectors/ebpf.plugin/ebpf_functions.h
+3
-17
@@ -3,33 +3,19 @@
3
#ifndef NETDATA_EBPF_FUNCTIONS_H
4
#define NETDATA_EBPF_FUNCTIONS_H 1
5
6
-#ifdef NETDATA_DEV_MODE
6
// Common
8
-static inline void EBPF_PLUGIN_FUNCTIONS(const char *NAME, const char *DESC) {
9
- fprintf(stdout, "%s \"%s\" 10 \"%s\" \"top\" \"any\" %d\n",
10
- PLUGINSD_KEYWORD_FUNCTION, NAME, DESC, RRDFUNCTIONS_PRIORITY_DEFAULT);
7
+static inline void EBPF_PLUGIN_FUNCTIONS(const char *NAME, const char *DESC, int update_every) {
8
+ fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" \"members\" %d\n",
9
+ NAME, update_every, DESC, RRDFUNCTIONS_PRIORITY_DEFAULT);
10
}
12
-#endif
11
12
// configuration file & description
13
#define NETDATA_DIRECTORY_FUNCTIONS_CONFIG_FILE "functions.conf"
14
#define NETDATA_EBPF_FUNCTIONS_MODULE_DESC "Show information about current function status."
15
16
// function list
19
-#define EBPF_FUNCTION_THREAD "ebpf_thread"
17
#define EBPF_FUNCTION_SOCKET "ebpf_socket"
18
22
-// thread constants
23
-#define EBPF_PLUGIN_THREAD_FUNCTION_DESCRIPTION "Detailed information about eBPF threads."
24
-#define EBPF_PLUGIN_THREAD_FUNCTION_ERROR_THREAD_NOT_FOUND "ebpf.plugin does not have thread named "
25
-
26
-#define EBPF_THREADS_SELECT_THREAD "thread:"
27
-#define EBPF_THREADS_ENABLE_CATEGORY "enable:"
28
-#define EBPF_THREADS_DISABLE_CATEGORY "disable:"
29
-
30
-#define EBPF_THREAD_STATUS_RUNNING "running"
31
-#define EBPF_THREAD_STATUS_STOPPED "stopped"
32
-
19
// socket constants
20
#define EBPF_PLUGIN_SOCKET_FUNCTION_DESCRIPTION "Detailed information about open sockets."
21
#define EBPF_FUNCTION_SOCKET_FAMILY "family:"