@cryptotaxi247 / netdata-1 / commits / 28394c923

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:"