master
c 3,165 lines 109 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include <sys/resource.h>
4
5 #include "ebpf.h"
6 #include "ebpf_socket.h"
7 #include "libbpf_api/ebpf_library.h"
8
9 /*****************************************************************
10 *
11 * GLOBAL VARIABLES
12 *
13 *****************************************************************/
14
15 static char *socket_dimension_names[NETDATA_MAX_SOCKET_VECTOR] = {
16 "received",
17 "sent",
18 "close",
19 "received",
20 "sent",
21 "retransmitted",
22 "connected_V4",
23 "connected_V6",
24 "connected_tcp",
25 "connected_udp"};
26 static char *socket_id_names[NETDATA_MAX_SOCKET_VECTOR] = {
27 "tcp_cleanup_rbuf",
28 "tcp_sendmsg",
29 "tcp_close",
30 "udp_recvmsg",
31 "udp_sendmsg",
32 "tcp_retransmit_skb",
33 "tcp_connect_v4",
34 "tcp_connect_v6",
35 "inet_csk_accept_tcp",
36 "inet_csk_accept_udp"};
37
38 static ebpf_local_maps_t socket_maps[] = {
39 {.name = "tbl_global_sock",
40 .internal_input = NETDATA_SOCKET_COUNTER,
41 .user_input = 0,
42 .type = NETDATA_EBPF_MAP_STATIC,
43 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
44 #ifdef LIBBPF_MAJOR_VERSION
45 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
46 #endif
47 },
48 {.name = "tbl_lports",
49 .internal_input = NETDATA_SOCKET_COUNTER,
50 .user_input = 0,
51 .type = NETDATA_EBPF_MAP_STATIC,
52 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
53 #ifdef LIBBPF_MAJOR_VERSION
54 .map_type = BPF_MAP_TYPE_PERCPU_HASH
55 #endif
56 },
57 {.name = "tbl_nd_socket",
58 .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED,
59 .user_input = NETDATA_MAXIMUM_CONNECTIONS_ALLOWED,
60 .type = NETDATA_EBPF_MAP_STATIC,
61 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
62 #ifdef LIBBPF_MAJOR_VERSION
63 .map_type = BPF_MAP_TYPE_PERCPU_HASH
64 #endif
65 },
66 {.name = "tbl_nv_udp",
67 .internal_input = NETDATA_COMPILED_UDP_CONNECTIONS_ALLOWED,
68 .user_input = NETDATA_MAXIMUM_UDP_CONNECTIONS_ALLOWED,
69 .type = NETDATA_EBPF_MAP_STATIC,
70 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
71 #ifdef LIBBPF_MAJOR_VERSION
72 .map_type = BPF_MAP_TYPE_PERCPU_HASH
73 #endif
74 },
75 {.name = "socket_ctrl",
76 .internal_input = NETDATA_CONTROLLER_END,
77 .user_input = 0,
78 .type = NETDATA_EBPF_MAP_CONTROLLER,
79 .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED,
80 #ifdef LIBBPF_MAJOR_VERSION
81 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
82 #endif
83 },
84 {.name = NULL,
85 .internal_input = 0,
86 .user_input = 0,
87 #ifdef LIBBPF_MAJOR_VERSION
88 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY
89 #endif
90 }};
91
92 static netdata_idx_t *socket_hash_values = NULL;
93 static netdata_syscall_stat_t socket_aggregated_data[NETDATA_MAX_SOCKET_VECTOR];
94 static netdata_publish_syscall_t socket_publish_aggregated[NETDATA_MAX_SOCKET_VECTOR];
95
96 netdata_socket_t *socket_values;
97
98 ebpf_network_viewer_port_list_t *listen_ports = NULL;
99 ebpf_addresses_t tcp_v6_connect_address = {.function = "tcp_v6_connect", .hash = 0, .addr = 0, .type = 0};
100
101 struct config socket_config = APPCONFIG_INITIALIZER;
102
103 netdata_ebpf_targets_t socket_targets[] = {
104 {.name = "inet_csk_accept", .mode = EBPF_LOAD_PROBE},
105 {.name = "tcp_retransmit_skb", .mode = EBPF_LOAD_PROBE},
106 {.name = "tcp_cleanup_rbuf", .mode = EBPF_LOAD_PROBE},
107 {.name = "tcp_close", .mode = EBPF_LOAD_PROBE},
108 {.name = "udp_recvmsg", .mode = EBPF_LOAD_PROBE},
109 {.name = "tcp_sendmsg", .mode = EBPF_LOAD_PROBE},
110 {.name = "udp_sendmsg", .mode = EBPF_LOAD_PROBE},
111 {.name = "tcp_v4_connect", .mode = EBPF_LOAD_PROBE},
112 {.name = "tcp_v6_connect", .mode = EBPF_LOAD_PROBE},
113 {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
114
115 struct netdata_static_thread ebpf_read_socket = {
116 .name = "EBPF_READ_SOCKET",
117 .config_section = NULL,
118 .config_name = NULL,
119 .env_name = NULL,
120 .enabled = 1,
121 .thread = NULL,
122 .init_routine = NULL,
123 .start_routine = NULL};
124
125 ARAL *aral_socket_table = NULL;
126
127 #define NETDATA_MAX(a, b) ((a) > (b) ? (a) : (b))
128
129 #ifdef LIBBPF_MAJOR_VERSION
130 /**
131 * Disable Probe
132 *
133 * Disable probes to use trampoline.
134 *
135 * @param obj is the main structure for bpf objects.
136 */
137 static void ebpf_socket_disable_probes(struct socket_bpf *obj)
138 {
139 bpf_program__set_autoload(obj->progs.netdata_inet_csk_accept_kretprobe, false);
140 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_kprobe, false);
141 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_kretprobe, false);
142 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kprobe, false);
143 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kretprobe, false);
144 bpf_program__set_autoload(obj->progs.netdata_tcp_retransmit_skb_kprobe, false);
145 bpf_program__set_autoload(obj->progs.netdata_tcp_cleanup_rbuf_kprobe, false);
146 bpf_program__set_autoload(obj->progs.netdata_tcp_close_kprobe, false);
147 bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_kprobe, false);
148 bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_kretprobe, false);
149 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kretprobe, false);
150 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kprobe, false);
151 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kretprobe, false);
152 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kprobe, false);
153 }
154
155 /**
156 * Disable Trampoline
157 *
158 * Disable trampoline to use probes.
159 *
160 * @param obj is the main structure for bpf objects.
161 */
162 static void ebpf_socket_disable_trampoline(struct socket_bpf *obj)
163 {
164 bpf_program__set_autoload(obj->progs.netdata_inet_csk_accept_fexit, false);
165 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_fentry, false);
166 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_fexit, false);
167 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fentry, false);
168 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fexit, false);
169 bpf_program__set_autoload(obj->progs.netdata_tcp_retransmit_skb_fentry, false);
170 bpf_program__set_autoload(obj->progs.netdata_tcp_cleanup_rbuf_fentry, false);
171 bpf_program__set_autoload(obj->progs.netdata_tcp_close_fentry, false);
172 bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_fentry, false);
173 bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_fexit, false);
174 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fentry, false);
175 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fexit, false);
176 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fentry, false);
177 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fexit, false);
178 }
179
180 /**
181 * Set trampoline target.
182 *
183 * @param obj is the main structure for bpf objects.
184 */
185 static void ebpf_set_trampoline_target(struct socket_bpf *obj)
186 {
187 bpf_program__set_attach_target(
188 obj->progs.netdata_inet_csk_accept_fexit, 0, socket_targets[NETDATA_FCNT_INET_CSK_ACCEPT].name);
189
190 bpf_program__set_attach_target(
191 obj->progs.netdata_tcp_v4_connect_fentry, 0, socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
192
193 bpf_program__set_attach_target(
194 obj->progs.netdata_tcp_v4_connect_fexit, 0, socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
195
196 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
197 bpf_program__set_attach_target(
198 obj->progs.netdata_tcp_v6_connect_fentry, 0, socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
199
200 bpf_program__set_attach_target(
201 obj->progs.netdata_tcp_v6_connect_fexit, 0, socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
202 }
203
204 bpf_program__set_attach_target(
205 obj->progs.netdata_tcp_retransmit_skb_fentry, 0, socket_targets[NETDATA_FCNT_TCP_RETRANSMIT].name);
206
207 bpf_program__set_attach_target(
208 obj->progs.netdata_tcp_cleanup_rbuf_fentry, 0, socket_targets[NETDATA_FCNT_CLEANUP_RBUF].name);
209
210 bpf_program__set_attach_target(obj->progs.netdata_tcp_close_fentry, 0, socket_targets[NETDATA_FCNT_TCP_CLOSE].name);
211
212 bpf_program__set_attach_target(
213 obj->progs.netdata_udp_recvmsg_fentry, 0, socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
214
215 bpf_program__set_attach_target(
216 obj->progs.netdata_udp_recvmsg_fexit, 0, socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
217
218 bpf_program__set_attach_target(
219 obj->progs.netdata_tcp_sendmsg_fentry, 0, socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
220
221 bpf_program__set_attach_target(
222 obj->progs.netdata_tcp_sendmsg_fexit, 0, socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
223
224 bpf_program__set_attach_target(
225 obj->progs.netdata_udp_sendmsg_fentry, 0, socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
226
227 bpf_program__set_attach_target(
228 obj->progs.netdata_udp_sendmsg_fexit, 0, socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
229 }
230
231 /**
232 * Disable specific trampoline
233 *
234 * Disable specific trampoline to match user selection.
235 *
236 * @param obj is the main structure for bpf objects.
237 * @param sel option selected by user.
238 */
239 static inline void ebpf_socket_disable_specific_trampoline(struct socket_bpf *obj, netdata_run_mode_t sel)
240 {
241 if (sel == MODE_RETURN) {
242 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fentry, false);
243 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_fentry, false);
244 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fentry, false);
245 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fentry, false);
246 } else {
247 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fexit, false);
248 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_fexit, false);
249 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fexit, false);
250 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fexit, false);
251 }
252 }
253
254 /**
255 * Disable specific probe
256 *
257 * Disable specific probe to match user selection.
258 *
259 * @param obj is the main structure for bpf objects.
260 * @param sel option selected by user.
261 */
262 static inline void ebpf_socket_disable_specific_probe(struct socket_bpf *obj, netdata_run_mode_t sel)
263 {
264 if (sel == MODE_RETURN) {
265 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kprobe, false);
266 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_kprobe, false);
267 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kprobe, false);
268 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kprobe, false);
269 } else {
270 bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kretprobe, false);
271 bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_kretprobe, false);
272 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kretprobe, false);
273 bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kretprobe, false);
274 }
275 }
276
277 /**
278 * Attach probes
279 *
280 * Attach probes to targets.
281 *
282 * @param obj is the main structure for bpf objects.
283 * @param sel option selected by user.
284 */
285 static long ebpf_socket_attach_probes(struct socket_bpf *obj, netdata_run_mode_t sel)
286 {
287 obj->links.netdata_inet_csk_accept_kretprobe = bpf_program__attach_kprobe(
288 obj->progs.netdata_inet_csk_accept_kretprobe, true, socket_targets[NETDATA_FCNT_INET_CSK_ACCEPT].name);
289 long ret = libbpf_get_error(obj->links.netdata_inet_csk_accept_kretprobe);
290 if (ret) {
291 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_INET_CSK_ACCEPT].name);
292 return -1;
293 }
294
295 obj->links.netdata_tcp_retransmit_skb_kprobe = bpf_program__attach_kprobe(
296 obj->progs.netdata_tcp_retransmit_skb_kprobe, false, socket_targets[NETDATA_FCNT_TCP_RETRANSMIT].name);
297 ret = libbpf_get_error(obj->links.netdata_tcp_retransmit_skb_kprobe);
298 if (ret) {
299 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_TCP_RETRANSMIT].name);
300 return -1;
301 }
302
303 obj->links.netdata_tcp_cleanup_rbuf_kprobe = bpf_program__attach_kprobe(
304 obj->progs.netdata_tcp_cleanup_rbuf_kprobe, false, socket_targets[NETDATA_FCNT_CLEANUP_RBUF].name);
305 ret = libbpf_get_error(obj->links.netdata_tcp_cleanup_rbuf_kprobe);
306 if (ret) {
307 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_CLEANUP_RBUF].name);
308 return -1;
309 }
310
311 obj->links.netdata_tcp_close_kprobe = bpf_program__attach_kprobe(
312 obj->progs.netdata_tcp_close_kprobe, false, socket_targets[NETDATA_FCNT_TCP_CLOSE].name);
313 ret = libbpf_get_error(obj->links.netdata_tcp_close_kprobe);
314 if (ret) {
315 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_TCP_CLOSE].name);
316 return -1;
317 }
318
319 obj->links.netdata_udp_recvmsg_kprobe = bpf_program__attach_kprobe(
320 obj->progs.netdata_udp_recvmsg_kprobe, false, socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
321 ret = libbpf_get_error(obj->links.netdata_udp_recvmsg_kprobe);
322 if (ret) {
323 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
324 return -1;
325 }
326
327 obj->links.netdata_udp_recvmsg_kretprobe = bpf_program__attach_kprobe(
328 obj->progs.netdata_udp_recvmsg_kretprobe, true, socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
329 ret = libbpf_get_error(obj->links.netdata_udp_recvmsg_kretprobe);
330 if (ret) {
331 collector_error("Cannot attach kretprobe for %s", socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name);
332 return -1;
333 }
334
335 if (sel == MODE_RETURN) {
336 obj->links.netdata_tcp_sendmsg_kretprobe = bpf_program__attach_kprobe(
337 obj->progs.netdata_tcp_sendmsg_kretprobe, true, socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
338 ret = libbpf_get_error(obj->links.netdata_tcp_sendmsg_kretprobe);
339 if (ret) {
340 collector_error("Cannot attach kretprobe for %s", socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
341 return -1;
342 }
343
344 obj->links.netdata_udp_sendmsg_kretprobe = bpf_program__attach_kprobe(
345 obj->progs.netdata_udp_sendmsg_kretprobe, true, socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
346 ret = libbpf_get_error(obj->links.netdata_udp_sendmsg_kretprobe);
347 if (ret) {
348 collector_error("Cannot attach kretprobe for %s", socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
349 return -1;
350 }
351
352 obj->links.netdata_tcp_v4_connect_kretprobe = bpf_program__attach_kprobe(
353 obj->progs.netdata_tcp_v4_connect_kretprobe, true, socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
354 ret = libbpf_get_error(obj->links.netdata_tcp_v4_connect_kretprobe);
355 if (ret) {
356 collector_error("Cannot attach kretprobe for %s", socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
357 return -1;
358 }
359
360 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
361 obj->links.netdata_tcp_v6_connect_kretprobe = bpf_program__attach_kprobe(
362 obj->progs.netdata_tcp_v6_connect_kretprobe, true, socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
363 ret = libbpf_get_error(obj->links.netdata_tcp_v6_connect_kretprobe);
364 if (ret) {
365 collector_error("Cannot attach kretprobe for %s", socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
366 return -1;
367 }
368 }
369 } else {
370 obj->links.netdata_tcp_sendmsg_kprobe = bpf_program__attach_kprobe(
371 obj->progs.netdata_tcp_sendmsg_kprobe, false, socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
372 ret = libbpf_get_error(obj->links.netdata_tcp_sendmsg_kprobe);
373 if (ret) {
374 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_TCP_SENDMSG].name);
375 return -1;
376 }
377
378 obj->links.netdata_udp_sendmsg_kprobe = bpf_program__attach_kprobe(
379 obj->progs.netdata_udp_sendmsg_kprobe, false, socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
380 ret = libbpf_get_error(obj->links.netdata_udp_sendmsg_kprobe);
381 if (ret) {
382 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_UDP_SENDMSG].name);
383 return -1;
384 }
385
386 obj->links.netdata_tcp_v4_connect_kprobe = bpf_program__attach_kprobe(
387 obj->progs.netdata_tcp_v4_connect_kprobe, false, socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
388 ret = libbpf_get_error(obj->links.netdata_tcp_v4_connect_kprobe);
389 if (ret) {
390 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name);
391 return -1;
392 }
393
394 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
395 obj->links.netdata_tcp_v6_connect_kprobe = bpf_program__attach_kprobe(
396 obj->progs.netdata_tcp_v6_connect_kprobe, false, socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
397 ret = libbpf_get_error(obj->links.netdata_tcp_v6_connect_kprobe);
398 if (ret) {
399 collector_error("Cannot attach kprobe for %s", socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name);
400 return -1;
401 }
402 }
403 }
404
405 return 0;
406 }
407
408 /**
409 * Set hash tables
410 *
411 * Set the values for maps according the value given by kernel.
412 *
413 * @param obj is the main structure for bpf objects.
414 */
415 static void ebpf_socket_set_hash_tables(struct socket_bpf *obj)
416 {
417 socket_maps[NETDATA_SOCKET_GLOBAL].map_fd = bpf_map__fd(obj->maps.tbl_global_sock);
418 socket_maps[NETDATA_SOCKET_LPORTS].map_fd = bpf_map__fd(obj->maps.tbl_lports);
419 socket_maps[NETDATA_SOCKET_OPEN_SOCKET].map_fd = bpf_map__fd(obj->maps.tbl_nd_socket);
420 socket_maps[NETDATA_SOCKET_TABLE_UDP].map_fd = bpf_map__fd(obj->maps.tbl_nv_udp);
421 socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd = bpf_map__fd(obj->maps.socket_ctrl);
422 }
423
424 /**
425 * Adjust Map Size
426 *
427 * Resize maps according input from users.
428 *
429 * @param obj is the main structure for bpf objects.
430 * @param em structure with configuration
431 */
432 static void ebpf_socket_adjust_map(struct socket_bpf *obj, ebpf_module_t *em)
433 {
434 ebpf_update_map_size(
435 obj->maps.tbl_nd_socket, &socket_maps[NETDATA_SOCKET_OPEN_SOCKET], em, bpf_map__name(obj->maps.tbl_nd_socket));
436
437 ebpf_update_map_size(
438 obj->maps.tbl_nv_udp, &socket_maps[NETDATA_SOCKET_TABLE_UDP], em, bpf_map__name(obj->maps.tbl_nv_udp));
439
440 ebpf_update_map_type(obj->maps.tbl_nd_socket, &socket_maps[NETDATA_SOCKET_OPEN_SOCKET]);
441 ebpf_update_map_type(obj->maps.tbl_nv_udp, &socket_maps[NETDATA_SOCKET_TABLE_UDP]);
442 ebpf_update_map_type(obj->maps.socket_ctrl, &socket_maps[NETDATA_SOCKET_TABLE_CTRL]);
443 ebpf_update_map_type(obj->maps.tbl_global_sock, &socket_maps[NETDATA_SOCKET_GLOBAL]);
444 ebpf_update_map_type(obj->maps.tbl_lports, &socket_maps[NETDATA_SOCKET_LPORTS]);
445 }
446
447 /**
448 * Disable TCP V6 connect
449 */
450 static void ebpf_disable_tcp_v6_connect(struct socket_bpf *obj)
451 {
452 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kretprobe, false);
453 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kprobe, false);
454 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fexit, false);
455 bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fentry, false);
456 }
457
458 /**
459 * Load and attach
460 *
461 * Load and attach the eBPF code in kernel.
462 *
463 * @param obj is the main structure for bpf objects.
464 * @param em structure with configuration
465 *
466 * @return it returns 0 on success and -1 otherwise
467 */
468 static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_module_t *em)
469 {
470 netdata_ebpf_targets_t *mt = em->targets;
471 netdata_ebpf_program_loaded_t test = mt[NETDATA_FCNT_INET_CSK_ACCEPT].mode;
472
473 if (test == EBPF_LOAD_TRAMPOLINE) {
474 ebpf_socket_disable_probes(obj);
475
476 ebpf_set_trampoline_target(obj);
477 ebpf_socket_disable_specific_trampoline(obj, em->mode);
478 } else { // We are not using tracepoints for this thread.
479 ebpf_socket_disable_trampoline(obj);
480
481 ebpf_socket_disable_specific_probe(obj, em->mode);
482 }
483
484 ebpf_socket_adjust_map(obj, em);
485
486 if (tcp_v6_connect_address.type != 'T') {
487 ebpf_disable_tcp_v6_connect(obj);
488 }
489
490 int ret = socket_bpf__load(obj);
491 if (ret) {
492 fprintf(stderr, "failed to load BPF object: %d\n", ret);
493 return ret;
494 }
495
496 if (test == EBPF_LOAD_TRAMPOLINE) {
497 ret = socket_bpf__attach(obj);
498 } else {
499 ret = (int)ebpf_socket_attach_probes(obj, em->mode);
500 }
501
502 if (!ret) {
503 ebpf_socket_set_hash_tables(obj);
504
505 ebpf_update_controller(socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd, em);
506 }
507
508 return ret;
509 }
510 #endif
511
512 /*****************************************************************
513 *
514 * FUNCTIONS TO CLOSE THE THREAD
515 *
516 *****************************************************************/
517
518 /**
519 * Socket Free
520 *
521 * Cleanup variables after child threads to stop
522 *
523 * @param ptr thread data.
524 */
525 static void ebpf_socket_free(ebpf_module_t *em)
526 {
527 netdata_mutex_lock(&ebpf_exit_cleanup);
528 ebpf_module_enabled_set(em, NETDATA_THREAD_EBPF_STOPPED);
529 ebpf_update_stats(&plugin_statistics, em);
530 netdata_mutex_unlock(&ebpf_exit_cleanup);
531
532 netdata_mutex_lock(&lock);
533 collect_pids &= ~(1 << EBPF_MODULE_SOCKET_IDX);
534 netdata_mutex_unlock(&lock);
535 }
536
537 /**
538 * Obsolete Systemd Socket Charts
539 *
540 * Obsolete charts when systemd is enabled
541 *
542 * @param update_every value to overwrite the update frequency set by the server.
543 **/
544 static void ebpf_obsolete_systemd_socket_charts(int update_every, char *id)
545 {
546 int order = NETDATA_SOCKET_SYSTEMD_ORDER_BASE;
547 ebpf_write_chart_obsolete(
548 id,
549 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4,
550 "",
551 "Calls to tcp_v4_connection",
552 EBPF_COMMON_UNITS_CONNECTIONS,
553 NETDATA_APPS_NET_GROUP,
554 NETDATA_EBPF_CHART_TYPE_STACKED,
555 NETDATA_SERVICES_SOCKET_TCP_V4_CONN_CONTEXT,
556 order++,
557 update_every);
558
559 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
560 ebpf_write_chart_obsolete(
561 id,
562 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6,
563 "",
564 "Calls to tcp_v6_connection",
565 EBPF_COMMON_UNITS_CONNECTIONS,
566 NETDATA_APPS_NET_GROUP,
567 NETDATA_EBPF_CHART_TYPE_STACKED,
568 NETDATA_SERVICES_SOCKET_TCP_V6_CONN_CONTEXT,
569 order++,
570 update_every);
571 }
572
573 ebpf_write_chart_obsolete(
574 id,
575 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH,
576 "",
577 "Bandwidth.",
578 EBPF_COMMON_UNITS_KILOBITS,
579 NETDATA_APPS_NET_GROUP,
580 NETDATA_EBPF_CHART_TYPE_STACKED,
581 NETDATA_SERVICES_SOCKET_TCP_BANDWIDTH_CONTEXT,
582 order++,
583 update_every);
584
585 ebpf_write_chart_obsolete(
586 id,
587 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS,
588 "",
589 "Calls to tcp_cleanup_rbuf.",
590 EBPF_COMMON_UNITS_CALLS_PER_SEC,
591 NETDATA_APPS_NET_GROUP,
592 NETDATA_EBPF_CHART_TYPE_STACKED,
593 NETDATA_SERVICES_SOCKET_TCP_RECV_CONTEXT,
594 order++,
595 update_every);
596
597 ebpf_write_chart_obsolete(
598 id,
599 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS,
600 "",
601 "Calls to tcp_sendmsg.",
602 EBPF_COMMON_UNITS_CALLS_PER_SEC,
603 NETDATA_APPS_NET_GROUP,
604 NETDATA_EBPF_CHART_TYPE_STACKED,
605 NETDATA_SERVICES_SOCKET_TCP_SEND_CONTEXT,
606 order++,
607 update_every);
608
609 ebpf_write_chart_obsolete(
610 id,
611 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT,
612 "",
613 "Calls to tcp_retransmit",
614 EBPF_COMMON_UNITS_CALLS_PER_SEC,
615 NETDATA_APPS_NET_GROUP,
616 NETDATA_EBPF_CHART_TYPE_STACKED,
617 NETDATA_SERVICES_SOCKET_TCP_RETRANSMIT_CONTEXT,
618 order++,
619 update_every);
620
621 ebpf_write_chart_obsolete(
622 id,
623 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS,
624 "",
625 "Calls to udp_sendmsg",
626 EBPF_COMMON_UNITS_CALLS_PER_SEC,
627 NETDATA_APPS_NET_GROUP,
628 NETDATA_EBPF_CHART_TYPE_STACKED,
629 NETDATA_SERVICES_SOCKET_UDP_SEND_CONTEXT,
630 order++,
631 update_every);
632
633 ebpf_write_chart_obsolete(
634 id,
635 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS,
636 "",
637 "Calls to udp_recvmsg",
638 EBPF_COMMON_UNITS_CALLS_PER_SEC,
639 NETDATA_APPS_NET_GROUP,
640 NETDATA_EBPF_CHART_TYPE_STACKED,
641 NETDATA_SERVICES_SOCKET_UDP_RECV_CONTEXT,
642 order++,
643 update_every);
644 }
645
646 static void ebpf_obsolete_specific_socket_charts(char *type, int update_every);
647 /**
648 * Obsolete cgroup chart
649 *
650 * Send obsolete for all charts created before to close.
651 *
652 * @param em a pointer to `struct ebpf_module`
653 */
654 static inline void ebpf_obsolete_socket_cgroup_charts(ebpf_module_t *em)
655 {
656 netdata_mutex_lock(&mutex_cgroup_shm);
657
658 ebpf_cgroup_target_t *ect;
659 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
660 if (ect->systemd) {
661 ebpf_obsolete_systemd_socket_charts(em->update_every, ect->name);
662
663 continue;
664 }
665
666 ebpf_obsolete_specific_socket_charts(ect->name, em->update_every);
667 }
668 netdata_mutex_unlock(&mutex_cgroup_shm);
669 }
670
671 /**
672 * Create apps charts
673 *
674 * Call ebpf_create_chart to create the charts on apps submenu.
675 *
676 * @param em a pointer to the structure with the default values.
677 */
678 void ebpf_socket_obsolete_apps_charts(struct ebpf_module *em)
679 {
680 int order = NETDATA_SOCKET_APPS_ORDER_BASE;
681 struct ebpf_target *w;
682 int update_every = em->update_every;
683 netdata_mutex_lock(&collect_data_mutex);
684 for (w = apps_groups_root_target; w; w = w->next) {
685 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_SOCKET_IDX))))
686 continue;
687
688 ebpf_write_chart_obsolete(
689 NETDATA_APP_FAMILY,
690 w->clean_name,
691 "_ebpf_call_tcp_v4_connection",
692 "Calls to tcp_v4_connection.",
693 EBPF_COMMON_UNITS_CONNECTIONS,
694 NETDATA_APPS_NET_GROUP,
695 NETDATA_EBPF_CHART_TYPE_STACKED,
696 "app.ebpf_call_tcp_v4_connection",
697 order++,
698 update_every);
699
700 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
701 ebpf_write_chart_obsolete(
702 NETDATA_APP_FAMILY,
703 w->clean_name,
704 "_ebpf_call_tcp_v6_connection",
705 "Calls to tcp_v6_connection.",
706 EBPF_COMMON_UNITS_CONNECTIONS,
707 NETDATA_APPS_NET_GROUP,
708 NETDATA_EBPF_CHART_TYPE_STACKED,
709 "app.ebpf_call_tcp_v6_connection",
710 order++,
711 update_every);
712 }
713
714 ebpf_write_chart_obsolete(
715 NETDATA_APP_FAMILY,
716 w->clean_name,
717 "_ebpf_sock_bandwidth",
718 "Bandwidth.",
719 EBPF_COMMON_UNITS_KILOBITS,
720 NETDATA_APPS_NET_GROUP,
721 NETDATA_EBPF_CHART_TYPE_STACKED,
722 "app.ebpf_sock_total_bandwidth",
723 order++,
724 update_every);
725
726 ebpf_write_chart_obsolete(
727 NETDATA_APP_FAMILY,
728 w->clean_name,
729 "_ebpf_call_tcp_sendmsg",
730 "Calls to tcp_sendmsg.",
731 EBPF_COMMON_UNITS_CALLS_PER_SEC,
732 NETDATA_APPS_NET_GROUP,
733 NETDATA_EBPF_CHART_TYPE_STACKED,
734 "app.ebpf_call_tcp_sendmsg",
735 order++,
736 update_every);
737
738 ebpf_write_chart_obsolete(
739 NETDATA_APP_FAMILY,
740 w->clean_name,
741 "_ebpf_call_tcp_cleanup_rbuf",
742 "Calls to tcp_cleanup_rbuf.",
743 EBPF_COMMON_UNITS_CALLS_PER_SEC,
744 NETDATA_APPS_NET_GROUP,
745 NETDATA_EBPF_CHART_TYPE_STACKED,
746 "app.ebpf_call_tcp_cleanup_rbuf",
747 order++,
748 update_every);
749
750 ebpf_write_chart_obsolete(
751 NETDATA_APP_FAMILY,
752 w->clean_name,
753 "_ebpf_call_tcp_retransmit",
754 "Calls to tcp_retransmit.",
755 EBPF_COMMON_UNITS_CALLS_PER_SEC,
756 NETDATA_APPS_NET_GROUP,
757 NETDATA_EBPF_CHART_TYPE_STACKED,
758 "app.ebpf_call_tcp_retransmit",
759 order++,
760 update_every);
761
762 ebpf_write_chart_obsolete(
763 NETDATA_APP_FAMILY,
764 w->clean_name,
765 "_ebpf_call_udp_sendmsg",
766 "Calls to udp_sendmsg.",
767 EBPF_COMMON_UNITS_CALLS_PER_SEC,
768 NETDATA_APPS_NET_GROUP,
769 NETDATA_EBPF_CHART_TYPE_STACKED,
770 "app.ebpf_call_udp_sendmsg",
771 order++,
772 update_every);
773
774 ebpf_write_chart_obsolete(
775 NETDATA_APP_FAMILY,
776 w->clean_name,
777 "_ebpf_call_udp_recvmsg",
778 "Calls to udp_recvmsg.",
779 EBPF_COMMON_UNITS_CALLS_PER_SEC,
780 NETDATA_APPS_NET_GROUP,
781 NETDATA_EBPF_CHART_TYPE_STACKED,
782 "app.ebpf_call_udp_recvmsg",
783 order++,
784 update_every);
785
786 w->charts_created &= ~(1 << EBPF_MODULE_SOCKET_IDX);
787 }
788 netdata_mutex_unlock(&collect_data_mutex);
789 }
790
791 /**
792 * Obsolete global charts
793 *
794 * Obsolete charts created.
795 *
796 * @param em a pointer to the structure with the default values.
797 */
798 static void ebpf_socket_obsolete_global_charts(ebpf_module_t *em)
799 {
800 int order = NETDATA_SOCKET_CHART_ORDER_BASE;
801 ebpf_write_chart_obsolete(
802 NETDATA_EBPF_IP_FAMILY,
803 NETDATA_INBOUND_CONNECTIONS,
804 "",
805 "Inbound connections.",
806 EBPF_COMMON_UNITS_CONNECTIONS,
807 NETDATA_SOCKET_KERNEL_FUNCTIONS,
808 NETDATA_EBPF_CHART_TYPE_LINE,
809 "ip.inbound_conn",
810 order++,
811 em->update_every);
812
813 ebpf_write_chart_obsolete(
814 NETDATA_EBPF_IP_FAMILY,
815 NETDATA_TCP_OUTBOUND_CONNECTIONS,
816 "",
817 "TCP outbound connections.",
818 EBPF_COMMON_UNITS_CONNECTIONS,
819 NETDATA_SOCKET_KERNEL_FUNCTIONS,
820 NETDATA_EBPF_CHART_TYPE_LINE,
821 "ip.tcp_outbound_conn",
822 order++,
823 em->update_every);
824
825 ebpf_write_chart_obsolete(
826 NETDATA_EBPF_IP_FAMILY,
827 NETDATA_TCP_FUNCTION_COUNT,
828 "",
829 "Calls to internal functions",
830 EBPF_COMMON_UNITS_CALLS_PER_SEC,
831 NETDATA_SOCKET_KERNEL_FUNCTIONS,
832 NETDATA_EBPF_CHART_TYPE_LINE,
833 "ip.tcp_functions",
834 order++,
835 em->update_every);
836
837 ebpf_write_chart_obsolete(
838 NETDATA_EBPF_IP_FAMILY,
839 NETDATA_TCP_FUNCTION_BITS,
840 "",
841 "TCP bandwidth",
842 EBPF_COMMON_UNITS_KILOBITS,
843 NETDATA_SOCKET_KERNEL_FUNCTIONS,
844 NETDATA_EBPF_CHART_TYPE_LINE,
845 "ip.total_tcp_bandwidth",
846 order++,
847 em->update_every);
848
849 if (em->mode < MODE_ENTRY) {
850 ebpf_write_chart_obsolete(
851 NETDATA_EBPF_IP_FAMILY,
852 NETDATA_TCP_FUNCTION_ERROR,
853 "",
854 "TCP errors",
855 EBPF_COMMON_UNITS_CALLS_PER_SEC,
856 NETDATA_SOCKET_KERNEL_FUNCTIONS,
857 NETDATA_EBPF_CHART_TYPE_LINE,
858 "ip.tcp_error",
859 order++,
860 em->update_every);
861 }
862
863 ebpf_write_chart_obsolete(
864 NETDATA_EBPF_IP_FAMILY,
865 NETDATA_TCP_RETRANSMIT,
866 "",
867 "Packages retransmitted",
868 EBPF_COMMON_UNITS_CALLS_PER_SEC,
869 NETDATA_SOCKET_KERNEL_FUNCTIONS,
870 NETDATA_EBPF_CHART_TYPE_LINE,
871 "ip.tcp_retransmit",
872 order++,
873 em->update_every);
874
875 ebpf_write_chart_obsolete(
876 NETDATA_EBPF_IP_FAMILY,
877 NETDATA_UDP_FUNCTION_COUNT,
878 "",
879 "UDP calls",
880 EBPF_COMMON_UNITS_CALLS_PER_SEC,
881 NETDATA_SOCKET_KERNEL_FUNCTIONS,
882 NETDATA_EBPF_CHART_TYPE_LINE,
883 "ip.udp_functions",
884 order++,
885 em->update_every);
886
887 ebpf_write_chart_obsolete(
888 NETDATA_EBPF_IP_FAMILY,
889 NETDATA_UDP_FUNCTION_BITS,
890 "",
891 "UDP bandwidth",
892 EBPF_COMMON_UNITS_KILOBITS,
893 NETDATA_SOCKET_KERNEL_FUNCTIONS,
894 NETDATA_EBPF_CHART_TYPE_LINE,
895 "ip.total_udp_bandwidth",
896 order++,
897 em->update_every);
898
899 if (em->mode < MODE_ENTRY) {
900 ebpf_write_chart_obsolete(
901 NETDATA_EBPF_IP_FAMILY,
902 NETDATA_UDP_FUNCTION_ERROR,
903 "",
904 "UDP errors",
905 EBPF_COMMON_UNITS_CALLS_PER_SEC,
906 NETDATA_SOCKET_KERNEL_FUNCTIONS,
907 NETDATA_EBPF_CHART_TYPE_LINE,
908 "ip.udp_error",
909 order++,
910 em->update_every);
911 }
912
913 fflush(stdout);
914 }
915 /**
916 * Socket exit
917 *
918 * Clean up the main thread.
919 *
920 * @param ptr thread data.
921 */
922 static void ebpf_socket_exit(void *pptr)
923 {
924 ebpf_module_t *em = CLEANUP_FUNCTION_GET_PTR(pptr);
925 if (!em)
926 return;
927
928 if (ebpf_read_socket.thread) {
929 nd_thread_signal_cancel(ebpf_read_socket.thread);
930 nd_thread_join(ebpf_read_socket.thread);
931 }
932
933 // Drop this module's bits from the shared PID pool so its slots don't
934 // stay pinned if the plugin keeps running after the module stops.
935 if (integration_shm && ebpf_shm_sem_wait_or_stop(shm_mutex_ebpf_integration)) {
936 netdata_ebpf_sweep_shm_for_module_unsafe(NETDATA_EBPF_PIDS_SOCKET_IDX);
937 sem_post(shm_mutex_ebpf_integration);
938 }
939
940 if (ebpf_module_enabled_get(em) == NETDATA_THREAD_EBPF_FUNCTION_RUNNING && !ebpf_plugin_stop()) {
941 netdata_mutex_lock(&lock);
942
943 if (em->cgroup_charts) {
944 ebpf_obsolete_socket_cgroup_charts(em);
945 fflush(stdout);
946 }
947
948 if (em->apps_charts & NETDATA_EBPF_APPS_FLAG_CHART_CREATED) {
949 ebpf_socket_obsolete_apps_charts(em);
950 fflush(stdout);
951 }
952
953 ebpf_socket_obsolete_global_charts(em);
954
955 netdata_mutex_unlock(&lock);
956 }
957
958 if (!ebpf_plugin_stop() && em->functions.bpf_unload)
959 em->functions.bpf_unload(em);
960
961 ebpf_socket_free(em);
962 }
963
964 /*****************************************************************
965 *
966 * PROCESS DATA AND SEND TO NETDATA
967 *
968 *****************************************************************/
969
970 /**
971 * Update publish structure before to send data to Netdata.
972 *
973 * @param publish the first output structure with independent dimensions
974 * @param tcp structure to store IO from tcp sockets
975 * @param udp structure to store IO from udp sockets
976 * @param input the structure with the input data.
977 */
978 static void ebpf_update_global_publish(
979 netdata_publish_syscall_t *publish,
980 netdata_publish_vfs_common_t *tcp,
981 netdata_publish_vfs_common_t *udp,
982 netdata_syscall_stat_t *input)
983 {
984 netdata_publish_syscall_t *move = publish;
985 while (move) {
986 if (input->call != move->pcall) {
987 if (move->pcall) {
988 move->ncall = (input->call > move->pcall) ? input->call - move->pcall : move->pcall - input->call;
989 move->nbyte = (input->bytes > move->pbyte) ? input->bytes - move->pbyte : move->pbyte - input->bytes;
990 move->nerr = (input->ecall > move->perr) ? input->ecall - move->perr : move->perr - input->ecall;
991 } else {
992 move->ncall = 0;
993 move->nbyte = 0;
994 move->nerr = 0;
995 }
996
997 move->pcall = input->call;
998 move->pbyte = input->bytes;
999 move->perr = input->ecall;
1000 } else {
1001 move->ncall = 0;
1002 move->nbyte = 0;
1003 move->nerr = 0;
1004 }
1005
1006 input = input->next;
1007 move = move->next;
1008 }
1009
1010 tcp->write = -(long)publish[0].nbyte;
1011 tcp->read = (long)publish[1].nbyte;
1012
1013 udp->write = -(long)publish[3].nbyte;
1014 udp->read = (long)publish[4].nbyte;
1015 }
1016
1017 /**
1018 * Socket Bytes 2 bits
1019 *
1020 * Convert data read from kernel ring to bits
1021 *
1022 * @param value data read from kernel ring
1023 *
1024 * @return
1025 */
1026 static inline collected_number ebpf_socket_bytes2bits(uint64_t value)
1027 {
1028 return value * 8 / BITS_IN_A_KILOBIT;
1029 }
1030
1031 /**
1032 * Send Global Inbound connection
1033 *
1034 * Send number of connections read per protocol.
1035 */
1036 static void ebpf_socket_send_global_inbound_conn()
1037 {
1038 uint64_t udp_conn = 0;
1039 uint64_t tcp_conn = 0;
1040 ebpf_network_viewer_port_list_t *move = listen_ports;
1041 while (move) {
1042 if (move->protocol == IPPROTO_TCP)
1043 tcp_conn += move->connections;
1044 else
1045 udp_conn += move->connections;
1046
1047 move = move->next;
1048 }
1049
1050 ebpf_write_begin_chart(NETDATA_EBPF_IP_FAMILY, NETDATA_INBOUND_CONNECTIONS, "");
1051 write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_TCP].name, (long long)tcp_conn);
1052 write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_UDP].name, (long long)udp_conn);
1053 ebpf_write_end_chart();
1054 }
1055
1056 /**
1057 * Send data to Netdata calling auxiliary functions.
1058 *
1059 * @param em the structure with thread information
1060 */
1061 static void ebpf_socket_send_data(ebpf_module_t *em)
1062 {
1063 netdata_publish_vfs_common_t common_tcp;
1064 netdata_publish_vfs_common_t common_udp;
1065 ebpf_update_global_publish(socket_publish_aggregated, &common_tcp, &common_udp, socket_aggregated_data);
1066
1067 ebpf_socket_send_global_inbound_conn();
1068 write_count_chart(
1069 NETDATA_TCP_OUTBOUND_CONNECTIONS,
1070 NETDATA_EBPF_IP_FAMILY,
1071 &socket_publish_aggregated[NETDATA_IDX_TCP_CONNECTION_V4],
1072 2);
1073
1074 // We read bytes from function arguments, but bandwidth is given in bits,
1075 // so we need to multiply by 8 to convert for the final value.
1076 write_count_chart(NETDATA_TCP_FUNCTION_COUNT, NETDATA_EBPF_IP_FAMILY, socket_publish_aggregated, 3);
1077 write_io_chart(
1078 NETDATA_TCP_FUNCTION_BITS,
1079 NETDATA_EBPF_IP_FAMILY,
1080 socket_id_names[0],
1081 ebpf_socket_bytes2bits(common_tcp.read),
1082 socket_id_names[1],
1083 ebpf_socket_bytes2bits(common_tcp.write));
1084 if (em->mode < MODE_ENTRY) {
1085 write_err_chart(NETDATA_TCP_FUNCTION_ERROR, NETDATA_EBPF_IP_FAMILY, socket_publish_aggregated, 2);
1086 }
1087 write_count_chart(
1088 NETDATA_TCP_RETRANSMIT, NETDATA_EBPF_IP_FAMILY, &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT], 1);
1089
1090 write_count_chart(
1091 NETDATA_UDP_FUNCTION_COUNT, NETDATA_EBPF_IP_FAMILY, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF], 2);
1092 write_io_chart(
1093 NETDATA_UDP_FUNCTION_BITS,
1094 NETDATA_EBPF_IP_FAMILY,
1095 socket_id_names[3],
1096 ebpf_socket_bytes2bits(common_udp.read),
1097 socket_id_names[4],
1098 ebpf_socket_bytes2bits(common_udp.write));
1099 if (em->mode < MODE_ENTRY) {
1100 write_err_chart(
1101 NETDATA_UDP_FUNCTION_ERROR, NETDATA_EBPF_IP_FAMILY, &socket_publish_aggregated[NETDATA_UDP_START], 2);
1102 }
1103 }
1104
1105 /**
1106 * Send data to Netdata calling auxiliary functions.
1107 */
1108 void ebpf_socket_send_apps_data()
1109 {
1110 struct ebpf_target *w;
1111 netdata_mutex_lock(&collect_data_mutex);
1112 for (w = apps_groups_root_target; w; w = w->next) {
1113 if (ebpf_plugin_stop())
1114 break;
1115
1116 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_SOCKET_IDX))))
1117 continue;
1118
1119 ebpf_socket_publish_apps_t *values = &w->socket;
1120 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_tcp_v4_connection");
1121 write_chart_dimension("connections", (collected_number)values->call_tcp_v4_connection);
1122 ebpf_write_end_chart();
1123
1124 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
1125 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_call_tcp_v6_connection");
1126 write_chart_dimension("connections", (collected_number)values->call_tcp_v6_connection);
1127 ebpf_write_end_chart();
1128 }
1129
1130 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_sock_bandwidth");
1131 // We multiply by 0.008, because we read bytes, but we display bits
1132 write_chart_dimension("received", ebpf_socket_bytes2bits(values->bytes_received));
1133 write_chart_dimension("sent", ebpf_socket_bytes2bits(values->bytes_sent));
1134 ebpf_write_end_chart();
1135
1136 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_tcp_sendmsg");
1137 write_chart_dimension("calls", (collected_number)values->call_tcp_sent);
1138 ebpf_write_end_chart();
1139
1140 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_tcp_cleanup_rbuf");
1141 write_chart_dimension("calls", (collected_number)values->call_tcp_received);
1142 ebpf_write_end_chart();
1143
1144 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_tcp_retransmit");
1145 write_chart_dimension("calls", (collected_number)values->retransmit);
1146 ebpf_write_end_chart();
1147
1148 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_udp_sendmsg");
1149 write_chart_dimension("calls", (collected_number)values->call_udp_sent);
1150 ebpf_write_end_chart();
1151
1152 ebpf_write_begin_chart(NETDATA_APP_FAMILY, w->clean_name, "_ebpf_call_udp_recvmsg");
1153 write_chart_dimension("calls", (collected_number)values->call_udp_received);
1154 ebpf_write_end_chart();
1155 }
1156 netdata_mutex_unlock(&collect_data_mutex);
1157 }
1158
1159 /*****************************************************************
1160 *
1161 * FUNCTIONS TO CREATE CHARTS
1162 *
1163 *****************************************************************/
1164
1165 /**
1166 * Create global charts
1167 *
1168 * Call ebpf_create_chart to create the charts for the collector.
1169 *
1170 * @param em a pointer to the structure with the default values.
1171 */
1172 static void ebpf_socket_create_global_charts(ebpf_module_t *em)
1173 {
1174 int order = NETDATA_SOCKET_CHART_ORDER_BASE;
1175 ebpf_create_chart(
1176 NETDATA_EBPF_IP_FAMILY,
1177 NETDATA_INBOUND_CONNECTIONS,
1178 "Inbound connections.",
1179 EBPF_COMMON_UNITS_CONNECTIONS,
1180 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1181 "ip.inbound_conn",
1182 NETDATA_EBPF_CHART_TYPE_LINE,
1183 order++,
1184 ebpf_create_global_dimension,
1185 &socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_TCP],
1186 2,
1187 em->update_every,
1188 NETDATA_EBPF_MODULE_NAME_SOCKET);
1189
1190 ebpf_create_chart(
1191 NETDATA_EBPF_IP_FAMILY,
1192 NETDATA_TCP_OUTBOUND_CONNECTIONS,
1193 "TCP outbound connections.",
1194 EBPF_COMMON_UNITS_CONNECTIONS,
1195 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1196 "ip.tcp_outbound_conn",
1197 NETDATA_EBPF_CHART_TYPE_LINE,
1198 order++,
1199 ebpf_create_global_dimension,
1200 &socket_publish_aggregated[NETDATA_IDX_TCP_CONNECTION_V4],
1201 2,
1202 em->update_every,
1203 NETDATA_EBPF_MODULE_NAME_SOCKET);
1204
1205 ebpf_create_chart(
1206 NETDATA_EBPF_IP_FAMILY,
1207 NETDATA_TCP_FUNCTION_COUNT,
1208 "Calls to internal functions",
1209 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1210 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1211 "ip.tcp_functions",
1212 NETDATA_EBPF_CHART_TYPE_LINE,
1213 order++,
1214 ebpf_create_global_dimension,
1215 socket_publish_aggregated,
1216 3,
1217 em->update_every,
1218 NETDATA_EBPF_MODULE_NAME_SOCKET);
1219
1220 ebpf_create_chart(
1221 NETDATA_EBPF_IP_FAMILY,
1222 NETDATA_TCP_FUNCTION_BITS,
1223 "TCP bandwidth",
1224 EBPF_COMMON_UNITS_KILOBITS,
1225 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1226 "ip.total_tcp_bandwidth",
1227 NETDATA_EBPF_CHART_TYPE_LINE,
1228 order++,
1229 ebpf_create_global_dimension,
1230 socket_publish_aggregated,
1231 2,
1232 em->update_every,
1233 NETDATA_EBPF_MODULE_NAME_SOCKET);
1234
1235 if (em->mode < MODE_ENTRY) {
1236 ebpf_create_chart(
1237 NETDATA_EBPF_IP_FAMILY,
1238 NETDATA_TCP_FUNCTION_ERROR,
1239 "TCP errors",
1240 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1241 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1242 "ip.tcp_error",
1243 NETDATA_EBPF_CHART_TYPE_LINE,
1244 order++,
1245 ebpf_create_global_dimension,
1246 socket_publish_aggregated,
1247 2,
1248 em->update_every,
1249 NETDATA_EBPF_MODULE_NAME_SOCKET);
1250 }
1251
1252 ebpf_create_chart(
1253 NETDATA_EBPF_IP_FAMILY,
1254 NETDATA_TCP_RETRANSMIT,
1255 "Packages retransmitted",
1256 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1257 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1258 "ip.tcp_retransmit",
1259 NETDATA_EBPF_CHART_TYPE_LINE,
1260 order++,
1261 ebpf_create_global_dimension,
1262 &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT],
1263 1,
1264 em->update_every,
1265 NETDATA_EBPF_MODULE_NAME_SOCKET);
1266
1267 ebpf_create_chart(
1268 NETDATA_EBPF_IP_FAMILY,
1269 NETDATA_UDP_FUNCTION_COUNT,
1270 "UDP calls",
1271 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1272 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1273 "ip.udp_functions",
1274 NETDATA_EBPF_CHART_TYPE_LINE,
1275 order++,
1276 ebpf_create_global_dimension,
1277 &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
1278 2,
1279 em->update_every,
1280 NETDATA_EBPF_MODULE_NAME_SOCKET);
1281
1282 ebpf_create_chart(
1283 NETDATA_EBPF_IP_FAMILY,
1284 NETDATA_UDP_FUNCTION_BITS,
1285 "UDP bandwidth",
1286 EBPF_COMMON_UNITS_KILOBITS,
1287 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1288 "ip.total_udp_bandwidth",
1289 NETDATA_EBPF_CHART_TYPE_LINE,
1290 order++,
1291 ebpf_create_global_dimension,
1292 &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
1293 2,
1294 em->update_every,
1295 NETDATA_EBPF_MODULE_NAME_SOCKET);
1296
1297 if (em->mode < MODE_ENTRY) {
1298 ebpf_create_chart(
1299 NETDATA_EBPF_IP_FAMILY,
1300 NETDATA_UDP_FUNCTION_ERROR,
1301 "UDP errors",
1302 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1303 NETDATA_SOCKET_KERNEL_FUNCTIONS,
1304 "ip.udp_error",
1305 NETDATA_EBPF_CHART_TYPE_LINE,
1306 order++,
1307 ebpf_create_global_dimension,
1308 &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF],
1309 2,
1310 em->update_every,
1311 NETDATA_EBPF_MODULE_NAME_SOCKET);
1312 }
1313
1314 fflush(stdout);
1315 }
1316
1317 /**
1318 * Create apps charts
1319 *
1320 * Call ebpf_create_chart to create the charts on apps submenu.
1321 *
1322 * @param em a pointer to the structure with the default values.
1323 * @param ptr a pointer for targets
1324 */
1325 void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr)
1326 {
1327 struct ebpf_target *root = ptr;
1328 struct ebpf_target *w;
1329 int order = NETDATA_SOCKET_APPS_ORDER_BASE;
1330 int update_every = em->update_every;
1331 for (w = root; w; w = w->next) {
1332 if (ebpf_plugin_stop())
1333 break;
1334
1335 if (unlikely(!w->exposed))
1336 continue;
1337
1338 ebpf_write_chart_cmd(
1339 NETDATA_APP_FAMILY,
1340 w->clean_name,
1341 "_ebpf_call_tcp_v4_connection",
1342 "Calls to tcp_v4_connection.",
1343 EBPF_COMMON_UNITS_CONNECTIONS,
1344 NETDATA_APPS_NET_GROUP,
1345 NETDATA_EBPF_CHART_TYPE_STACKED,
1346 "app.ebpf_call_tcp_v4_connection",
1347 order++,
1348 update_every,
1349 NETDATA_EBPF_MODULE_NAME_SOCKET);
1350 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1351 ebpf_commit_label();
1352 fprintf(stdout, "DIMENSION connections '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1353
1354 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
1355 ebpf_write_chart_cmd(
1356 NETDATA_APP_FAMILY,
1357 w->clean_name,
1358 "_ebpf_call_tcp_v6_connection",
1359 "Calls to tcp_v6_connection.",
1360 EBPF_COMMON_UNITS_CONNECTIONS,
1361 NETDATA_APPS_NET_GROUP,
1362 NETDATA_EBPF_CHART_TYPE_STACKED,
1363 "app.ebpf_call_tcp_v6_connection",
1364 order++,
1365 update_every,
1366 NETDATA_EBPF_MODULE_NAME_SOCKET);
1367 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1368 ebpf_commit_label();
1369 fprintf(stdout, "DIMENSION connections '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1370 }
1371
1372 ebpf_write_chart_cmd(
1373 NETDATA_APP_FAMILY,
1374 w->clean_name,
1375 "_ebpf_sock_bandwidth",
1376 "Bandwidth.",
1377 EBPF_COMMON_UNITS_KILOBITS,
1378 NETDATA_APPS_NET_GROUP,
1379 NETDATA_EBPF_CHART_TYPE_STACKED,
1380 "app.ebpf_sock_total_bandwidth",
1381 order++,
1382 update_every,
1383 NETDATA_EBPF_MODULE_NAME_SOCKET);
1384 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1385 ebpf_commit_label();
1386 fprintf(stdout, "DIMENSION received '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1387 fprintf(stdout, "DIMENSION sent '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1388
1389 ebpf_write_chart_cmd(
1390 NETDATA_APP_FAMILY,
1391 w->clean_name,
1392 "_ebpf_call_tcp_sendmsg",
1393 "Calls to tcp_sendmsg.",
1394 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1395 NETDATA_APPS_NET_GROUP,
1396 NETDATA_EBPF_CHART_TYPE_STACKED,
1397 "app.ebpf_call_tcp_sendmsg",
1398 order++,
1399 update_every,
1400 NETDATA_EBPF_MODULE_NAME_SOCKET);
1401 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1402 ebpf_commit_label();
1403 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1404
1405 ebpf_write_chart_cmd(
1406 NETDATA_APP_FAMILY,
1407 w->clean_name,
1408 "_ebpf_call_tcp_cleanup_rbuf",
1409 "Calls to tcp_cleanup_rbuf.",
1410 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1411 NETDATA_APPS_NET_GROUP,
1412 NETDATA_EBPF_CHART_TYPE_STACKED,
1413 "app.ebpf_call_tcp_cleanup_rbuf",
1414 order++,
1415 update_every,
1416 NETDATA_EBPF_MODULE_NAME_SOCKET);
1417 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1418 ebpf_commit_label();
1419 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1420
1421 ebpf_write_chart_cmd(
1422 NETDATA_APP_FAMILY,
1423 w->clean_name,
1424 "_ebpf_call_tcp_retransmit",
1425 "Calls to tcp_retransmit.",
1426 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1427 NETDATA_APPS_NET_GROUP,
1428 NETDATA_EBPF_CHART_TYPE_STACKED,
1429 "app.ebpf_call_tcp_retransmit",
1430 order++,
1431 update_every,
1432 NETDATA_EBPF_MODULE_NAME_SOCKET);
1433 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1434 ebpf_commit_label();
1435 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1436
1437 ebpf_write_chart_cmd(
1438 NETDATA_APP_FAMILY,
1439 w->clean_name,
1440 "_ebpf_call_udp_sendmsg",
1441 "Calls to udp_sendmsg.",
1442 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1443 NETDATA_APPS_NET_GROUP,
1444 NETDATA_EBPF_CHART_TYPE_STACKED,
1445 "app.ebpf_call_udp_sendmsg",
1446 order++,
1447 update_every,
1448 NETDATA_EBPF_MODULE_NAME_SOCKET);
1449 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1450 ebpf_commit_label();
1451 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1452
1453 ebpf_write_chart_cmd(
1454 NETDATA_APP_FAMILY,
1455 w->clean_name,
1456 "_ebpf_call_udp_recvmsg",
1457 "Calls to udp_recvmsg.",
1458 EBPF_COMMON_UNITS_CALLS_PER_SEC,
1459 NETDATA_APPS_NET_GROUP,
1460 NETDATA_EBPF_CHART_TYPE_STACKED,
1461 "app.ebpf_call_udp_recvmsg",
1462 order,
1463 update_every,
1464 NETDATA_EBPF_MODULE_NAME_SOCKET);
1465 ebpf_create_chart_labels("app_group", w->name, RRDLABEL_SRC_AUTO);
1466 ebpf_commit_label();
1467 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
1468
1469 w->charts_created |= 1 << EBPF_MODULE_SOCKET_IDX;
1470 }
1471 em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
1472 }
1473
1474 /*****************************************************************
1475 *
1476 * READ INFORMATION FROM KERNEL RING
1477 *
1478 *****************************************************************/
1479
1480 /**
1481 * Is specific ip inside the range
1482 *
1483 * Check if the ip is inside a IP range previously defined
1484 *
1485 * @param cmp the IP to compare
1486 * @param family the IP family
1487 *
1488 * @return It returns 1 if the IP is inside the range and 0 otherwise
1489 */
1490 static int ebpf_is_specific_ip_inside_range(union netdata_ip_t *cmp, int family)
1491 {
1492 if (!network_viewer_opt.excluded_ips && !network_viewer_opt.included_ips)
1493 return 1;
1494
1495 uint32_t ipv4_test = htonl(cmp->addr32[0]);
1496 ebpf_network_viewer_ip_list_t *move = network_viewer_opt.excluded_ips;
1497 while (move) {
1498 if (family == AF_INET) {
1499 if (move->first.addr32[0] <= ipv4_test && ipv4_test <= move->last.addr32[0])
1500 return 0;
1501 } else {
1502 if (memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
1503 memcmp(move->last.addr8, cmp->addr8, sizeof(union netdata_ip_t)) >= 0) {
1504 return 0;
1505 }
1506 }
1507 move = move->next;
1508 }
1509
1510 move = network_viewer_opt.included_ips;
1511 while (move) {
1512 if (family == AF_INET && move->ver == AF_INET) {
1513 if (move->first.addr32[0] <= ipv4_test && move->last.addr32[0] >= ipv4_test)
1514 return 1;
1515 } else {
1516 if (move->ver == AF_INET6 && memcmp(move->first.addr8, cmp->addr8, sizeof(union netdata_ip_t)) <= 0 &&
1517 memcmp(move->last.addr8, cmp->addr8, sizeof(union netdata_ip_t)) >= 0) {
1518 return 1;
1519 }
1520 }
1521 move = move->next;
1522 }
1523
1524 return 0;
1525 }
1526
1527 /**
1528 * Is port inside range
1529 *
1530 * Verify if the cmp port is inside the range [first, last].
1531 * This function expects only the last parameter as big endian.
1532 *
1533 * @param cmp the value to compare
1534 *
1535 * @return It returns 1 when cmp is inside and 0 otherwise.
1536 */
1537 static int ebpf_is_port_inside_range(uint16_t cmp)
1538 {
1539 // We do not have restrictions for ports.
1540 if (!network_viewer_opt.excluded_port && !network_viewer_opt.included_port)
1541 return 1;
1542
1543 // Test if port is excluded
1544 ebpf_network_viewer_port_list_t *move = network_viewer_opt.excluded_port;
1545 while (move) {
1546 if (move->cmp_first <= cmp && cmp <= move->cmp_last)
1547 return 0;
1548
1549 move = move->next;
1550 }
1551
1552 // Test if the port is inside allowed range
1553 move = network_viewer_opt.included_port;
1554 while (move) {
1555 if (move->cmp_first <= cmp && cmp <= move->cmp_last)
1556 return 1;
1557
1558 move = move->next;
1559 }
1560
1561 return 0;
1562 }
1563
1564 /**
1565 * Hostname matches pattern
1566 *
1567 * @param cmp the value to compare
1568 *
1569 * @return It returns 1 when the value matches and zero otherwise.
1570 */
1571 int hostname_matches_pattern(char *cmp)
1572 {
1573 if (!network_viewer_opt.included_hostnames && !network_viewer_opt.excluded_hostnames)
1574 return 1;
1575
1576 ebpf_network_viewer_hostname_list_t *move = network_viewer_opt.excluded_hostnames;
1577 while (move) {
1578 if (simple_pattern_matches(move->value_pattern, cmp))
1579 return 0;
1580
1581 move = move->next;
1582 }
1583
1584 move = network_viewer_opt.included_hostnames;
1585 while (move) {
1586 if (simple_pattern_matches(move->value_pattern, cmp))
1587 return 1;
1588
1589 move = move->next;
1590 }
1591
1592 return 0;
1593 }
1594
1595 /**
1596 * Is socket allowed?
1597 *
1598 * Compare destination addresses and destination ports to define next steps
1599 *
1600 * @param key the socket read from kernel ring
1601 * @param data the socket data used also used to refuse some sockets.
1602 *
1603 * @return It returns 1 if this socket is inside the ranges and 0 otherwise.
1604 */
1605 int ebpf_is_socket_allowed(netdata_socket_idx_t *key, netdata_socket_t *data)
1606 {
1607 int ret = 0;
1608 // If family is not AF_UNSPEC and it is different of specified
1609 if (network_viewer_opt.family && network_viewer_opt.family != data->family)
1610 goto endsocketallowed;
1611
1612 if (!ebpf_is_port_inside_range(key->dport))
1613 goto endsocketallowed;
1614
1615 ret = ebpf_is_specific_ip_inside_range(&key->daddr, data->family);
1616
1617 endsocketallowed:
1618 return ret;
1619 }
1620
1621 /**
1622 * Hash accumulator
1623 *
1624 * @param values the values used to calculate the data.
1625 * @param family the connection family
1626 * @param end the values size.
1627 */
1628 static void ebpf_hash_socket_accumulator(netdata_socket_t *values, int end)
1629 {
1630 int i;
1631 uint8_t protocol = values[0].protocol;
1632 uint64_t ct = values[0].current_timestamp;
1633 uint64_t ft = values[0].first_timestamp;
1634 uint16_t family = AF_UNSPEC;
1635 uint32_t external_origin = values[0].external_origin;
1636 for (i = 1; i < end; i++) {
1637 if (ebpf_plugin_stop())
1638 break;
1639
1640 netdata_socket_t *w = &values[i];
1641
1642 values[0].tcp.call_tcp_sent += w->tcp.call_tcp_sent;
1643 values[0].tcp.call_tcp_received += w->tcp.call_tcp_received;
1644 values[0].tcp.tcp_bytes_received += w->tcp.tcp_bytes_received;
1645 values[0].tcp.tcp_bytes_sent += w->tcp.tcp_bytes_sent;
1646 values[0].tcp.close += w->tcp.close;
1647 values[0].tcp.retransmit += w->tcp.retransmit;
1648 values[0].tcp.ipv4_connect += w->tcp.ipv4_connect;
1649 values[0].tcp.ipv6_connect += w->tcp.ipv6_connect;
1650
1651 if (!protocol)
1652 protocol = w->protocol;
1653
1654 if (family == AF_UNSPEC)
1655 family = w->family;
1656
1657 if (w->current_timestamp > ct)
1658 ct = w->current_timestamp;
1659
1660 if (!ft)
1661 ft = w->first_timestamp;
1662
1663 if (w->external_origin)
1664 external_origin = NETDATA_EBPF_SRC_IP_ORIGIN_EXTERNAL;
1665 }
1666
1667 values[0].protocol = (!protocol) ? IPPROTO_TCP : protocol;
1668 values[0].current_timestamp = ct;
1669 values[0].first_timestamp = ft;
1670 values[0].external_origin = external_origin;
1671 }
1672
1673 /**
1674 * Translate socket
1675 *
1676 * Convert socket address to string
1677 *
1678 * @param dst structure where we will store
1679 * @param key the socket address
1680 */
1681 static void ebpf_socket_translate(netdata_socket_plus_t *dst, netdata_socket_idx_t *key)
1682 {
1683 uint32_t resolve = network_viewer_opt.service_resolution_enabled;
1684 char service[NI_MAXSERV];
1685 int ret;
1686 if (dst->data.family == AF_INET) {
1687 struct sockaddr_in ipv4_addr = {};
1688 ipv4_addr.sin_port = 0;
1689 ipv4_addr.sin_addr.s_addr = key->saddr.addr32[0];
1690 ipv4_addr.sin_family = AF_INET;
1691 if (resolve) {
1692 // NI_NAMEREQD : It is too slow
1693 ret = getnameinfo(
1694 (struct sockaddr *)&ipv4_addr,
1695 sizeof(ipv4_addr),
1696 dst->socket_string.src_ip,
1697 INET6_ADDRSTRLEN,
1698 service,
1699 NI_MAXSERV,
1700 NI_NUMERICHOST | NI_NUMERICSERV);
1701 if (ret) {
1702 collector_error("Cannot resolve name: %s", gai_strerror(ret));
1703 resolve = 0;
1704 } else {
1705 ipv4_addr.sin_addr.s_addr = key->daddr.addr32[0];
1706
1707 ipv4_addr.sin_port = key->dport;
1708 ret = getnameinfo(
1709 (struct sockaddr *)&ipv4_addr,
1710 sizeof(ipv4_addr),
1711 dst->socket_string.dst_ip,
1712 INET6_ADDRSTRLEN,
1713 dst->socket_string.dst_port,
1714 NI_MAXSERV,
1715 NI_NUMERICHOST);
1716 if (ret) {
1717 collector_error("Cannot resolve name: %s", gai_strerror(ret));
1718 resolve = 0;
1719 }
1720 }
1721 }
1722
1723 // When resolution fail, we should use addresses
1724 if (!resolve) {
1725 ipv4_addr.sin_addr.s_addr = key->saddr.addr32[0];
1726
1727 if (!inet_ntop(AF_INET, &ipv4_addr.sin_addr, dst->socket_string.src_ip, INET6_ADDRSTRLEN))
1728 netdata_log_info("Cannot convert IP %u .", ipv4_addr.sin_addr.s_addr);
1729
1730 ipv4_addr.sin_addr.s_addr = key->daddr.addr32[0];
1731
1732 if (!inet_ntop(AF_INET, &ipv4_addr.sin_addr, dst->socket_string.dst_ip, INET6_ADDRSTRLEN))
1733 netdata_log_info("Cannot convert IP %u .", ipv4_addr.sin_addr.s_addr);
1734 snprintfz(dst->socket_string.dst_port, NI_MAXSERV, "%u", ntohs(key->dport));
1735 }
1736 } else {
1737 struct sockaddr_in6 ipv6_addr = {};
1738 memcpy(&ipv6_addr.sin6_addr, key->saddr.addr8, sizeof(key->saddr.addr8));
1739 ipv6_addr.sin6_family = AF_INET6;
1740 if (resolve) {
1741 ret = getnameinfo(
1742 (struct sockaddr *)&ipv6_addr,
1743 sizeof(ipv6_addr),
1744 dst->socket_string.src_ip,
1745 INET6_ADDRSTRLEN,
1746 service,
1747 NI_MAXSERV,
1748 NI_NUMERICHOST | NI_NUMERICSERV);
1749 if (ret) {
1750 collector_error("Cannot resolve name: %s", gai_strerror(ret));
1751 resolve = 0;
1752 } else {
1753 memcpy(&ipv6_addr.sin6_addr, key->daddr.addr8, sizeof(key->daddr.addr8));
1754 ret = getnameinfo(
1755 (struct sockaddr *)&ipv6_addr,
1756 sizeof(ipv6_addr),
1757 dst->socket_string.dst_ip,
1758 INET6_ADDRSTRLEN,
1759 dst->socket_string.dst_port,
1760 NI_MAXSERV,
1761 NI_NUMERICHOST);
1762 if (ret) {
1763 collector_error("Cannot resolve name: %s", gai_strerror(ret));
1764 resolve = 0;
1765 }
1766 }
1767 }
1768
1769 if (!resolve) {
1770 memcpy(&ipv6_addr.sin6_addr, key->saddr.addr8, sizeof(key->saddr.addr8));
1771 if (!inet_ntop(AF_INET6, &ipv6_addr.sin6_addr, dst->socket_string.src_ip, INET6_ADDRSTRLEN))
1772 netdata_log_info("Cannot convert IPv6 Address.");
1773
1774 memcpy(&ipv6_addr.sin6_addr, key->daddr.addr8, sizeof(key->daddr.addr8));
1775 if (!inet_ntop(AF_INET6, &ipv6_addr.sin6_addr, dst->socket_string.dst_ip, INET6_ADDRSTRLEN))
1776 netdata_log_info("Cannot convert IPv6 Address.");
1777 snprintfz(dst->socket_string.dst_port, NI_MAXSERV, "%u", ntohs(key->dport));
1778 }
1779 }
1780 dst->pid = key->pid;
1781
1782 if (!strcmp(dst->socket_string.dst_port, "0"))
1783 snprintfz(dst->socket_string.dst_port, NI_MAXSERV, "%u", ntohs(key->dport));
1784 #ifdef NETDATA_DEV_MODE
1785 collector_info(
1786 "New socket: { ORIGIN IP: %s, ORIGIN : %u, DST IP:%s, DST PORT: %s, PID: %u, PROTO: %d, FAMILY: %d}",
1787 dst->socket_string.src_ip,
1788 dst->data.external_origin,
1789 dst->socket_string.dst_ip,
1790 dst->socket_string.dst_port,
1791 dst->pid,
1792 dst->data.protocol,
1793 dst->data.family);
1794 #endif
1795 }
1796
1797 /**
1798 * Update array vectors
1799 *
1800 * Read data from hash table and update vectors.
1801 *
1802 * @param em the structure with configuration
1803 */
1804 static void ebpf_update_array_vectors(ebpf_module_t *em)
1805 {
1806 netdata_socket_idx_t key = {};
1807 netdata_socket_idx_t next_key = {};
1808
1809 int maps_per_core = em->maps_per_core;
1810 int fd = em->maps[NETDATA_SOCKET_OPEN_SOCKET].map_fd;
1811
1812 netdata_socket_t *values = socket_values;
1813 size_t length = sizeof(netdata_socket_t);
1814 int ret, end;
1815 if (maps_per_core) {
1816 length *= ebpf_nprocs;
1817 end = ebpf_nprocs;
1818 } else
1819 end = 1;
1820
1821 // We need to reset the values when we are working on kernel 4.15 or newer, because kernel does not create
1822 // values for specific processor unless it is used to store data. As result of this behavior one the next socket
1823 // can have values from the previous one.
1824 memset(values, 0, length);
1825 time_t update_time = time(NULL);
1826 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
1827 if (ebpf_plugin_stop())
1828 break;
1829
1830 ret = bpf_map_lookup_elem(fd, &key, values);
1831 bool deleted = true;
1832 if (ret < 0) {
1833 goto end_socket_loop;
1834 }
1835
1836 if (key.pid > (uint32_t)pid_max) {
1837 goto end_socket_loop;
1838 }
1839
1840 ebpf_hash_socket_accumulator(values, end);
1841
1842 // Discard non-bind sockets
1843 if (!key.daddr.addr64[0] && !key.daddr.addr64[1] && !key.saddr.addr64[0] && !key.saddr.addr64[1]) {
1844 bpf_map_delete_elem(fd, &key);
1845 goto end_socket_loop;
1846 }
1847
1848 // When socket is not allowed, we do not append it to table, but we are still keeping it to accumulate data.
1849 if (!ebpf_is_socket_allowed(&key, values)) {
1850 goto end_socket_loop;
1851 }
1852
1853 // Get PID structure
1854 rw_spinlock_write_lock(&ebpf_judy_pid.index.rw_spinlock);
1855 PPvoid_t judy_array = &ebpf_judy_pid.index.JudyLArray;
1856 netdata_ebpf_judy_pid_stats_t *pid_ptr = ebpf_get_pid_from_judy_unsafe(judy_array, key.pid);
1857 if (!pid_ptr) {
1858 goto end_socket_loop;
1859 }
1860
1861 // Get Socket structure
1862 rw_spinlock_write_lock(&pid_ptr->socket_stats.rw_spinlock);
1863 netdata_socket_plus_t **socket_pptr = (netdata_socket_plus_t **)ebpf_judy_insert_unsafe(
1864 &pid_ptr->socket_stats.JudyLArray, values[0].first_timestamp);
1865 netdata_socket_plus_t *socket_ptr = *socket_pptr;
1866 bool translate = false;
1867 if (likely(*socket_pptr == NULL)) {
1868 *socket_pptr = aral_mallocz(aral_socket_table);
1869
1870 socket_ptr = *socket_pptr;
1871
1872 translate = true;
1873 }
1874 uint64_t prev_period = socket_ptr->data.current_timestamp;
1875 memcpy(&socket_ptr->data, &values[0], sizeof(netdata_socket_t));
1876 if (translate) {
1877 ebpf_socket_translate(socket_ptr, &key);
1878 deleted = false;
1879 } else { // Check socket was updated
1880 deleted = false;
1881 if (prev_period) {
1882 if (values[0].current_timestamp > prev_period) // Socket updated
1883 socket_ptr->last_update = update_time;
1884 else if ((update_time - socket_ptr->last_update) > em->update_every) {
1885 // Socket was not updated since last read
1886 deleted = true;
1887 JudyLDel(&pid_ptr->socket_stats.JudyLArray, values[0].first_timestamp, PJE0);
1888 aral_freez(aral_socket_table, socket_ptr);
1889 }
1890 } else // First time
1891 socket_ptr->last_update = update_time;
1892 }
1893
1894 rw_spinlock_write_unlock(&pid_ptr->socket_stats.rw_spinlock);
1895 rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
1896
1897 end_socket_loop:; // the empty statement is here to allow code to be compiled by old compilers
1898 netdata_ebpf_pid_stats_t *local_pid =
1899 netdata_ebpf_get_shm_pointer_unsafe(key.pid, NETDATA_EBPF_PIDS_SOCKET_IDX);
1900 if (local_pid) {
1901 ebpf_socket_publish_apps_t *curr = &local_pid->socket;
1902
1903 if (!deleted)
1904 ebpf_socket_fill_publish_apps(curr, values);
1905 else {
1906 netdata_ebpf_reset_shm_pointer_unsafe(fd, key.pid, NETDATA_EBPF_PIDS_SOCKET_IDX);
1907 memset(curr, 0, sizeof(*curr));
1908 }
1909 }
1910 // The socket map is keyed by a tuple (not by pid), so the generic
1911 // reset_shm_pointer_unsafe() deliberately skips bpf_map_delete_elem()
1912 // for SOCKET_IDX. Delete the stale socket here regardless of whether
1913 // we had a shm slot, otherwise a full shm pool would strand dead
1914 // socket entries in the kernel map and we'd re-iterate them forever.
1915 if (deleted)
1916 bpf_map_delete_elem(fd, &key);
1917 memset(values, 0, length);
1918 memcpy(&key, &next_key, sizeof(key));
1919 }
1920 }
1921 /**
1922 * Resume apps data
1923 */
1924 void ebpf_socket_resume_apps_data()
1925 {
1926 struct ebpf_target *w;
1927
1928 netdata_mutex_lock(&collect_data_mutex);
1929 for (w = apps_groups_root_target; w; w = w->next) {
1930 if (ebpf_plugin_stop())
1931 break;
1932
1933 if (unlikely(!(w->charts_created & (1 << EBPF_MODULE_SOCKET_IDX))))
1934 continue;
1935
1936 struct ebpf_pid_on_target *move = w->root_pid;
1937
1938 ebpf_socket_publish_apps_t *values = &w->socket;
1939 memset(&w->socket, 0, sizeof(ebpf_socket_publish_apps_t));
1940 for (; move; move = move->next) {
1941 uint32_t pid = move->pid;
1942 netdata_ebpf_pid_stats_t *local_pid = netdata_ebpf_lookup_shm_pointer_unsafe(pid);
1943 if (!local_pid || !(local_pid->threads & (1U << (NETDATA_EBPF_PIDS_SOCKET_IDX << 1))))
1944 continue;
1945
1946 ebpf_socket_publish_apps_t *ws = &local_pid->socket;
1947
1948 values->call_tcp_v4_connection = ws->call_tcp_v4_connection;
1949 values->call_tcp_v6_connection = ws->call_tcp_v6_connection;
1950 values->bytes_sent = ws->bytes_sent;
1951 values->bytes_received = ws->bytes_received;
1952 values->call_tcp_sent = ws->call_tcp_sent;
1953 values->call_tcp_received = ws->call_tcp_received;
1954 values->retransmit = ws->retransmit;
1955 values->call_udp_sent = ws->call_udp_sent;
1956 values->call_udp_received = ws->call_udp_received;
1957 }
1958 }
1959 netdata_mutex_unlock(&collect_data_mutex);
1960 }
1961
1962 /**
1963 * Update cgroup
1964 *
1965 * Update cgroup data based in PIDs.
1966 */
1967 static void ebpf_update_socket_cgroup()
1968 {
1969 ebpf_cgroup_target_t *ect;
1970
1971 netdata_mutex_lock(&mutex_cgroup_shm);
1972 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
1973 if (ebpf_plugin_stop())
1974 break;
1975
1976 struct pid_on_target2 *pids;
1977 for (pids = ect->pids; pids; pids = pids->next) {
1978 uint32_t pid = pids->pid;
1979 ebpf_socket_publish_apps_t *publish = &ect->publish_socket;
1980 netdata_ebpf_pid_stats_t *local_pid = netdata_ebpf_lookup_shm_pointer_unsafe(pid);
1981 if (!local_pid || !(local_pid->threads & (1U << (NETDATA_EBPF_PIDS_SOCKET_IDX << 1))))
1982 continue;
1983
1984 ebpf_socket_publish_apps_t *in = &local_pid->socket;
1985
1986 publish->bytes_sent = in->bytes_sent;
1987 publish->bytes_received = in->bytes_received;
1988 publish->call_tcp_sent = in->call_tcp_sent;
1989 publish->call_tcp_received = in->call_tcp_received;
1990 publish->retransmit = in->retransmit;
1991 publish->call_udp_sent = in->call_udp_sent;
1992 publish->call_udp_received = in->call_udp_received;
1993 publish->call_close = in->call_close;
1994 publish->call_tcp_v4_connection = in->call_tcp_v4_connection;
1995 publish->call_tcp_v6_connection = in->call_tcp_v6_connection;
1996 }
1997 }
1998 netdata_mutex_unlock(&mutex_cgroup_shm);
1999 }
2000
2001 /**
2002 * Socket thread
2003 *
2004 * Thread used to generate socket charts.
2005 *
2006 * @param ptr a pointer to `struct ebpf_module`
2007 *
2008 * @return It always return NULL
2009 */
2010 void ebpf_read_socket_thread(void *ptr)
2011 {
2012 ebpf_module_t *em = (ebpf_module_t *)ptr;
2013
2014 ebpf_update_array_vectors(em);
2015
2016 int update_every = em->update_every;
2017 int counter = update_every - 1;
2018 int collect_pid = (em->apps_charts || em->cgroup_charts);
2019 if (!collect_pid)
2020 return;
2021
2022 uint32_t running_time = 0;
2023 uint32_t lifetime = em->lifetime;
2024 int cgroups = em->cgroup_charts;
2025 heartbeat_t hb;
2026 heartbeat_init(&hb, USEC_PER_SEC);
2027 while (!ebpf_plugin_stop() && running_time < lifetime) {
2028 if (ebpf_plugin_stop())
2029 break;
2030
2031 heartbeat_next(&hb);
2032 if (ebpf_plugin_stop())
2033 break;
2034
2035 if (++counter != update_every)
2036 continue;
2037
2038 if (!ebpf_shm_sem_wait_or_stop(shm_mutex_ebpf_integration)) {
2039 if (errno != ECANCELED)
2040 netdata_log_error("SOCKET: Failed to wait on semaphore.");
2041 break;
2042 }
2043 ebpf_update_array_vectors(em);
2044 ebpf_socket_resume_apps_data();
2045 if (ebpf_plugin_stop()) {
2046 if (sem_post(shm_mutex_ebpf_integration))
2047 netdata_log_error("SOCKET: Failed to post semaphore.");
2048 break;
2049 }
2050
2051 if (cgroups && ebpf_cgroup_integration_active_get())
2052 ebpf_update_socket_cgroup();
2053
2054 if (sem_post(shm_mutex_ebpf_integration)) {
2055 netdata_log_error("SOCKET: Failed to post semaphore.");
2056 break;
2057 }
2058
2059 counter = 0;
2060
2061 if (ebpf_plugin_stop())
2062 break;
2063 }
2064 }
2065
2066 /**
2067 * Fill Network Viewer Port list
2068 *
2069 * Fill the structure with values read from /proc or hash table.
2070 *
2071 * @param out the structure where we will store data.
2072 * @param value the ports we are listen to.
2073 * @param proto the protocol used for this connection.
2074 * @param in the structure with values read form different sources.
2075 */
2076 static inline void
2077 fill_nv_port_list(ebpf_network_viewer_port_list_t *out, uint16_t value, uint16_t proto, netdata_passive_connection_t *in)
2078 {
2079 out->first = value;
2080 out->protocol = proto;
2081 out->pid = in->pid;
2082 out->tgid = in->tgid;
2083 out->connections = in->counter;
2084 }
2085
2086 /**
2087 * Update listen table
2088 *
2089 * Update link list when it is necessary.
2090 *
2091 * @param value the ports we are listen to.
2092 * @param proto the protocol used with port connection.
2093 * @param in the structure with values read form different sources.
2094 */
2095 void update_listen_table(uint16_t value, uint16_t proto, netdata_passive_connection_t *in)
2096 {
2097 ebpf_network_viewer_port_list_t *w;
2098 if (likely(listen_ports)) {
2099 ebpf_network_viewer_port_list_t *move = listen_ports, *store = listen_ports;
2100 while (move) {
2101 if (move->protocol == proto && move->first == value) {
2102 move->pid = in->pid;
2103 move->tgid = in->tgid;
2104 move->connections = in->counter;
2105 return;
2106 }
2107
2108 store = move;
2109 move = move->next;
2110 }
2111
2112 w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
2113 store->next = w;
2114 } else {
2115 w = callocz(1, sizeof(ebpf_network_viewer_port_list_t));
2116
2117 listen_ports = w;
2118 }
2119 fill_nv_port_list(w, value, proto, in);
2120
2121 #ifdef NETDATA_INTERNAL_CHECKS
2122 netdata_log_info("The network viewer is monitoring inbound connections for port %u", ntohs(value));
2123 #endif
2124 }
2125
2126 /**
2127 * Read listen table
2128 *
2129 * Read the table with all ports that we are listen on host.
2130 */
2131 static void read_listen_table()
2132 {
2133 netdata_passive_connection_idx_t key = {};
2134 netdata_passive_connection_idx_t next_key = {};
2135
2136 int fd = socket_maps[NETDATA_SOCKET_LPORTS].map_fd;
2137 netdata_passive_connection_t value = {};
2138 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
2139 if (ebpf_plugin_stop())
2140 break;
2141
2142 int ret = bpf_map_lookup_elem(fd, &key, &value);
2143 if (ret < 0) {
2144 key = next_key;
2145 continue;
2146 }
2147
2148 // The correct protocol must come from kernel
2149 update_listen_table(key.port, key.protocol, &value);
2150
2151 key = next_key;
2152 memset(&value, 0, sizeof(value));
2153 }
2154
2155 if (next_key.port && value.pid) {
2156 // The correct protocol must come from kernel
2157 update_listen_table(next_key.port, next_key.protocol, &value);
2158 }
2159 }
2160
2161 /**
2162 * Read the hash table and store data to allocated vectors.
2163 *
2164 * @param stats vector used to read data from control table.
2165 * @param maps_per_core do I need to read all cores?
2166 */
2167 static void ebpf_socket_read_hash_global_tables(netdata_idx_t *stats, int maps_per_core)
2168 {
2169 netdata_idx_t res[NETDATA_SOCKET_COUNTER];
2170 ebpf_read_global_table_stats(
2171 res,
2172 socket_hash_values,
2173 socket_maps[NETDATA_SOCKET_GLOBAL].map_fd,
2174 maps_per_core,
2175 NETDATA_KEY_CALLS_TCP_SENDMSG,
2176 NETDATA_SOCKET_COUNTER);
2177
2178 ebpf_read_global_table_stats(
2179 stats,
2180 socket_hash_values,
2181 socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd,
2182 maps_per_core,
2183 NETDATA_CONTROLLER_PID_TABLE_ADD,
2184 NETDATA_CONTROLLER_END);
2185
2186 socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].call = res[NETDATA_KEY_CALLS_TCP_SENDMSG];
2187 socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].call = res[NETDATA_KEY_CALLS_TCP_CLEANUP_RBUF];
2188 socket_aggregated_data[NETDATA_IDX_TCP_CLOSE].call = res[NETDATA_KEY_CALLS_TCP_CLOSE];
2189 socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].call = res[NETDATA_KEY_CALLS_UDP_RECVMSG];
2190 socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].call = res[NETDATA_KEY_CALLS_UDP_SENDMSG];
2191 socket_aggregated_data[NETDATA_IDX_TCP_RETRANSMIT].call = res[NETDATA_KEY_TCP_RETRANSMIT];
2192 socket_aggregated_data[NETDATA_IDX_TCP_CONNECTION_V4].call = res[NETDATA_KEY_CALLS_TCP_CONNECT_IPV4];
2193 socket_aggregated_data[NETDATA_IDX_TCP_CONNECTION_V6].call = res[NETDATA_KEY_CALLS_TCP_CONNECT_IPV6];
2194
2195 socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_TCP_SENDMSG];
2196 socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].ecall = res[NETDATA_KEY_ERROR_TCP_CLEANUP_RBUF];
2197 socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].ecall = res[NETDATA_KEY_ERROR_UDP_RECVMSG];
2198 socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].ecall = res[NETDATA_KEY_ERROR_UDP_SENDMSG];
2199 socket_aggregated_data[NETDATA_IDX_TCP_CONNECTION_V4].ecall = res[NETDATA_KEY_ERROR_TCP_CONNECT_IPV4];
2200 socket_aggregated_data[NETDATA_IDX_TCP_CONNECTION_V6].ecall = res[NETDATA_KEY_ERROR_TCP_CONNECT_IPV6];
2201
2202 socket_aggregated_data[NETDATA_IDX_TCP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_TCP_SENDMSG];
2203 socket_aggregated_data[NETDATA_IDX_TCP_CLEANUP_RBUF].bytes = res[NETDATA_KEY_BYTES_TCP_CLEANUP_RBUF];
2204 socket_aggregated_data[NETDATA_IDX_UDP_RECVBUF].bytes = res[NETDATA_KEY_BYTES_UDP_RECVMSG];
2205 socket_aggregated_data[NETDATA_IDX_UDP_SENDMSG].bytes = res[NETDATA_KEY_BYTES_UDP_SENDMSG];
2206 }
2207
2208 /**
2209 * Fill publish apps when necessary.
2210 *
2211 * @param current_pid the PID that I am updating
2212 * @param ns the structure with data read from memory.
2213 */
2214 void ebpf_socket_fill_publish_apps(ebpf_socket_publish_apps_t *curr, netdata_socket_t *ns)
2215 {
2216 curr->bytes_sent = ns->tcp.tcp_bytes_sent;
2217 curr->bytes_received = ns->tcp.tcp_bytes_received;
2218 curr->call_tcp_sent = ns->tcp.call_tcp_sent;
2219 curr->call_tcp_received = ns->tcp.call_tcp_received;
2220 curr->retransmit = ns->tcp.retransmit;
2221 curr->call_close = ns->tcp.close;
2222 curr->call_tcp_v4_connection = ns->tcp.ipv4_connect;
2223 curr->call_tcp_v6_connection = ns->tcp.ipv6_connect;
2224
2225 curr->call_udp_sent = ns->udp.call_udp_sent;
2226 curr->call_udp_received = ns->udp.call_udp_received;
2227 }
2228
2229 /**
2230 * Sum PIDs
2231 *
2232 * Sum values for all targets.
2233 *
2234 * @param fd structure used to store data
2235 * @param pids input data
2236 */
2237 static void ebpf_socket_sum_cgroup_pids(ebpf_socket_publish_apps_t *socket, struct pid_on_target2 *pids)
2238 {
2239 ebpf_socket_publish_apps_t accumulator;
2240 memset(&accumulator, 0, sizeof(accumulator));
2241
2242 while (pids) {
2243 netdata_socket_t *w = &pids->socket;
2244
2245 accumulator.bytes_received += w->tcp.tcp_bytes_received;
2246 accumulator.bytes_sent += w->tcp.tcp_bytes_sent;
2247 accumulator.call_tcp_received += w->tcp.call_tcp_received;
2248 accumulator.call_tcp_sent += w->tcp.call_tcp_sent;
2249 accumulator.retransmit += w->tcp.retransmit;
2250 accumulator.call_close += w->tcp.close;
2251 accumulator.call_tcp_v4_connection += w->tcp.ipv4_connect;
2252 accumulator.call_tcp_v6_connection += w->tcp.ipv6_connect;
2253 accumulator.call_udp_received += w->udp.call_udp_received;
2254 accumulator.call_udp_sent += w->udp.call_udp_sent;
2255
2256 pids = pids->next;
2257 }
2258
2259 socket->bytes_sent = NETDATA_MAX(accumulator.bytes_sent, socket->bytes_sent);
2260 socket->bytes_received = NETDATA_MAX(accumulator.bytes_received, socket->bytes_received);
2261 socket->call_tcp_sent = NETDATA_MAX(accumulator.call_tcp_sent, socket->call_tcp_sent);
2262 socket->call_tcp_received = NETDATA_MAX(accumulator.call_tcp_received, socket->call_tcp_received);
2263 socket->retransmit = NETDATA_MAX(accumulator.retransmit, socket->retransmit);
2264 socket->call_udp_sent = NETDATA_MAX(accumulator.call_udp_sent, socket->call_udp_sent);
2265 socket->call_udp_received = NETDATA_MAX(accumulator.call_udp_received, socket->call_udp_received);
2266 socket->call_close = NETDATA_MAX(accumulator.call_close, socket->call_close);
2267 socket->call_tcp_v4_connection = NETDATA_MAX(accumulator.call_tcp_v4_connection, socket->call_tcp_v4_connection);
2268 socket->call_tcp_v6_connection = NETDATA_MAX(accumulator.call_tcp_v6_connection, socket->call_tcp_v6_connection);
2269 }
2270
2271 /**
2272 * Create specific socket charts
2273 *
2274 * Create charts for cgroup/application.
2275 *
2276 * @param type the chart type.
2277 * @param update_every value to overwrite the update frequency set by the server.
2278 */
2279 static void ebpf_create_specific_socket_charts(char *type, int update_every)
2280 {
2281 int order_basis = NETDATA_SOCKET_CGROUP_ORDER_BASE;
2282 char *label = (!strncmp(type, "cgroup_", 7)) ? &type[7] : type;
2283 ebpf_write_chart_cmd(
2284 type,
2285 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4,
2286 "",
2287 "Calls to tcp_v4_connection",
2288 EBPF_COMMON_UNITS_CONNECTIONS,
2289 NETDATA_CGROUP_NET_GROUP,
2290 NETDATA_EBPF_CHART_TYPE_LINE,
2291 NETDATA_CGROUP_TCP_V4_CONN_CONTEXT,
2292 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2293 update_every,
2294 NETDATA_EBPF_MODULE_NAME_SOCKET);
2295 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2296 ebpf_commit_label();
2297 fprintf(stdout, "DIMENSION connections '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2298
2299 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
2300 ebpf_write_chart_cmd(
2301 type,
2302 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6,
2303 "",
2304 "Calls to tcp_v6_connection",
2305 EBPF_COMMON_UNITS_CONNECTIONS,
2306 NETDATA_CGROUP_NET_GROUP,
2307 NETDATA_EBPF_CHART_TYPE_LINE,
2308 NETDATA_CGROUP_TCP_V6_CONN_CONTEXT,
2309 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2310 update_every,
2311 NETDATA_EBPF_MODULE_NAME_SOCKET);
2312 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2313 ebpf_commit_label();
2314 fprintf(stdout, "DIMENSION connections '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2315 }
2316
2317 ebpf_write_chart_cmd(
2318 type,
2319 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH,
2320 "",
2321 "Bandwidth.",
2322 EBPF_COMMON_UNITS_KILOBITS,
2323 NETDATA_CGROUP_NET_GROUP,
2324 NETDATA_EBPF_CHART_TYPE_LINE,
2325 NETDATA_CGROUP_SOCKET_TCP_BANDWIDTH_CONTEXT,
2326 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2327 update_every,
2328 NETDATA_EBPF_MODULE_NAME_SOCKET);
2329 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2330 ebpf_commit_label();
2331 fprintf(stdout, "DIMENSION received '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2332 fprintf(stdout, "DIMENSION sent '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2333
2334 ebpf_write_chart_cmd(
2335 type,
2336 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS,
2337 "",
2338 "Calls to tcp_cleanup_rbuf.",
2339 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2340 NETDATA_CGROUP_NET_GROUP,
2341 NETDATA_EBPF_CHART_TYPE_LINE,
2342 NETDATA_CGROUP_SOCKET_TCP_RECV_CONTEXT,
2343 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2344 update_every,
2345 NETDATA_EBPF_MODULE_NAME_SOCKET);
2346 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2347 ebpf_commit_label();
2348 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2349
2350 ebpf_write_chart_cmd(
2351 type,
2352 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS,
2353 "",
2354 "Calls to tcp_sendmsg.",
2355 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2356 NETDATA_CGROUP_NET_GROUP,
2357 NETDATA_EBPF_CHART_TYPE_LINE,
2358 NETDATA_CGROUP_SOCKET_TCP_SEND_CONTEXT,
2359 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2360 update_every,
2361 NETDATA_EBPF_MODULE_NAME_SOCKET);
2362 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2363 ebpf_commit_label();
2364 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2365
2366 ebpf_write_chart_cmd(
2367 type,
2368 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT,
2369 "",
2370 "Calls to tcp_retransmit.",
2371 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2372 NETDATA_CGROUP_NET_GROUP,
2373 NETDATA_EBPF_CHART_TYPE_LINE,
2374 NETDATA_CGROUP_SOCKET_TCP_RETRANSMIT_CONTEXT,
2375 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2376 update_every,
2377 NETDATA_EBPF_MODULE_NAME_SOCKET);
2378 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2379 ebpf_commit_label();
2380 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2381
2382 ebpf_write_chart_cmd(
2383 type,
2384 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS,
2385 "",
2386 "Calls to udp_sendmsg.",
2387 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2388 NETDATA_CGROUP_NET_GROUP,
2389 NETDATA_EBPF_CHART_TYPE_LINE,
2390 NETDATA_CGROUP_SOCKET_UDP_SEND_CONTEXT,
2391 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2392 update_every,
2393 NETDATA_EBPF_MODULE_NAME_SOCKET);
2394 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2395 ebpf_commit_label();
2396 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2397
2398 ebpf_write_chart_cmd(
2399 type,
2400 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS,
2401 "",
2402 "Calls to udp_recvmsg.",
2403 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2404 NETDATA_CGROUP_NET_GROUP,
2405 NETDATA_EBPF_CHART_TYPE_LINE,
2406 NETDATA_CGROUP_SOCKET_UDP_RECV_CONTEXT,
2407 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2408 update_every,
2409 NETDATA_EBPF_MODULE_NAME_SOCKET);
2410 ebpf_create_chart_labels("cgroup_name", label, RRDLABEL_SRC_AUTO);
2411 ebpf_commit_label();
2412 fprintf(stdout, "DIMENSION calls '' %s 1 1\n", ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX]);
2413 }
2414
2415 /**
2416 * Obsolete specific socket charts
2417 *
2418 * Obsolete charts for cgroup/application.
2419 *
2420 * @param type the chart type.
2421 * @param update_every value to overwrite the update frequency set by the server.
2422 */
2423 static void ebpf_obsolete_specific_socket_charts(char *type, int update_every)
2424 {
2425 int order_basis = NETDATA_SOCKET_CGROUP_ORDER_BASE;
2426 ebpf_write_chart_obsolete(
2427 type,
2428 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4,
2429 "",
2430 "Calls to tcp_v4_connection",
2431 EBPF_COMMON_UNITS_CONNECTIONS,
2432 NETDATA_APPS_NET_GROUP,
2433 NETDATA_EBPF_CHART_TYPE_LINE,
2434 NETDATA_CGROUP_TCP_V4_CONN_CONTEXT,
2435 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2436 update_every);
2437
2438 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
2439 ebpf_write_chart_obsolete(
2440 type,
2441 NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6,
2442 "",
2443 "Calls to tcp_v6_connection",
2444 EBPF_COMMON_UNITS_CONNECTIONS,
2445 NETDATA_APPS_NET_GROUP,
2446 NETDATA_EBPF_CHART_TYPE_LINE,
2447 NETDATA_CGROUP_TCP_V6_CONN_CONTEXT,
2448 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2449 update_every);
2450 }
2451
2452 ebpf_write_chart_obsolete(
2453 type,
2454 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH,
2455 "",
2456 "Bandwidth.",
2457 EBPF_COMMON_UNITS_KILOBITS,
2458 NETDATA_APPS_NET_GROUP,
2459 NETDATA_EBPF_CHART_TYPE_LINE,
2460 NETDATA_CGROUP_SOCKET_TCP_BANDWIDTH_CONTEXT,
2461 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2462 update_every);
2463
2464 ebpf_write_chart_obsolete(
2465 type,
2466 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS,
2467 "",
2468 "Calls to tcp_cleanup_rbuf.",
2469 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2470 NETDATA_APPS_NET_GROUP,
2471 NETDATA_EBPF_CHART_TYPE_LINE,
2472 NETDATA_CGROUP_SOCKET_TCP_RECV_CONTEXT,
2473 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2474 update_every);
2475
2476 ebpf_write_chart_obsolete(
2477 type,
2478 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS,
2479 "",
2480 "Calls to tcp_sendmsg.",
2481 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2482 NETDATA_APPS_NET_GROUP,
2483 NETDATA_EBPF_CHART_TYPE_LINE,
2484 NETDATA_CGROUP_SOCKET_TCP_SEND_CONTEXT,
2485 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2486 update_every);
2487
2488 ebpf_write_chart_obsolete(
2489 type,
2490 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT,
2491 "",
2492 "Calls to tcp_retransmit.",
2493 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2494 NETDATA_APPS_NET_GROUP,
2495 NETDATA_EBPF_CHART_TYPE_LINE,
2496 NETDATA_CGROUP_SOCKET_TCP_RETRANSMIT_CONTEXT,
2497 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2498 update_every);
2499
2500 ebpf_write_chart_obsolete(
2501 type,
2502 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS,
2503 "",
2504 "Calls to udp_sendmsg.",
2505 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2506 NETDATA_APPS_NET_GROUP,
2507 NETDATA_EBPF_CHART_TYPE_LINE,
2508 NETDATA_CGROUP_SOCKET_UDP_SEND_CONTEXT,
2509 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2510 update_every);
2511
2512 ebpf_write_chart_obsolete(
2513 type,
2514 NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS,
2515 "",
2516 "Calls to udp_recvmsg.",
2517 EBPF_COMMON_UNITS_CALLS_PER_SEC,
2518 NETDATA_APPS_NET_GROUP,
2519 NETDATA_EBPF_CHART_TYPE_LINE,
2520 NETDATA_CGROUP_SOCKET_UDP_RECV_CONTEXT,
2521 NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + order_basis++,
2522 update_every);
2523 }
2524
2525 /*
2526 * Send Specific Swap data
2527 *
2528 * Send data for specific cgroup/apps.
2529 *
2530 * @param type chart type
2531 * @param values structure with values that will be sent to netdata
2532 */
2533 static void ebpf_send_specific_socket_data(char *type, ebpf_socket_publish_apps_t *values)
2534 {
2535 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4, "");
2536 write_chart_dimension("connections", (long long)values->call_tcp_v4_connection);
2537 ebpf_write_end_chart();
2538
2539 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
2540 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6, "");
2541 write_chart_dimension("connections", (long long)values->call_tcp_v6_connection);
2542 ebpf_write_end_chart();
2543 }
2544
2545 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH, "");
2546 write_chart_dimension("received", (long long)ebpf_socket_bytes2bits(values->bytes_received));
2547 write_chart_dimension("sent", (long long)ebpf_socket_bytes2bits(values->bytes_sent));
2548 ebpf_write_end_chart();
2549
2550 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS, "");
2551 write_chart_dimension("calls", (long long)values->call_tcp_received);
2552 ebpf_write_end_chart();
2553
2554 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS, "");
2555 write_chart_dimension("calls", (long long)values->call_tcp_sent);
2556 ebpf_write_end_chart();
2557
2558 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT, "");
2559 write_chart_dimension("calls", (long long)values->retransmit);
2560 ebpf_write_end_chart();
2561
2562 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS, "");
2563 write_chart_dimension("calls", (long long)values->call_udp_sent);
2564 ebpf_write_end_chart();
2565
2566 ebpf_write_begin_chart(type, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS, "");
2567 write_chart_dimension("calls", (long long)values->call_udp_received);
2568 ebpf_write_end_chart();
2569 }
2570
2571 /**
2572 * Create Systemd Socket Charts
2573 *
2574 * Create charts when systemd is enabled
2575 *
2576 * @param update_every value to overwrite the update frequency set by the server.
2577 **/
2578 static void ebpf_create_systemd_socket_charts(int update_every)
2579 {
2580 static ebpf_systemd_args_t data_tcp_v4 = {
2581 .title = "Calls to tcp_v4_connection",
2582 .units = EBPF_COMMON_UNITS_CONNECTIONS,
2583 .family = NETDATA_APPS_NET_GROUP,
2584 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2585 .order = 20080,
2586 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2587 .context = NETDATA_SERVICES_SOCKET_TCP_V4_CONN_CONTEXT,
2588 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2589 .update_every = 0,
2590 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4,
2591 .dimension = "connections"};
2592
2593 static ebpf_systemd_args_t data_tcp_v6 = {
2594 .title = "Calls to tcp_v6_connection",
2595 .units = EBPF_COMMON_UNITS_CONNECTIONS,
2596 .family = NETDATA_APPS_NET_GROUP,
2597 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2598 .order = 20081,
2599 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2600 .context = NETDATA_SERVICES_SOCKET_TCP_V6_CONN_CONTEXT,
2601 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2602 .update_every = 0,
2603 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6,
2604 .dimension = "connections"};
2605
2606 static ebpf_systemd_args_t data_bandwidth = {
2607 .title = "Bandwidth.",
2608 .units = EBPF_COMMON_UNITS_KILOBITS,
2609 .family = NETDATA_APPS_NET_GROUP,
2610 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2611 .order = 20082,
2612 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2613 .context = NETDATA_SERVICES_SOCKET_TCP_BANDWIDTH_CONTEXT,
2614 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2615 .update_every = 0,
2616 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH,
2617 .dimension = "received,sent"};
2618
2619 static ebpf_systemd_args_t data_tcp_cleanup = {
2620 .title = "Calls to tcp_cleanup_rbuf.",
2621 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2622 .family = NETDATA_APPS_NET_GROUP,
2623 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2624 .order = 20084,
2625 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2626 .context = NETDATA_SERVICES_SOCKET_TCP_RECV_CONTEXT,
2627 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2628 .update_every = 0,
2629 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS,
2630 .dimension = "calls"};
2631
2632 static ebpf_systemd_args_t data_tcp_sendmsg = {
2633 .title = "Calls to tcp_sendmsg.",
2634 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2635 .family = NETDATA_APPS_NET_GROUP,
2636 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2637 .order = 20085,
2638 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2639 .context = NETDATA_SERVICES_SOCKET_TCP_SEND_CONTEXT,
2640 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2641 .update_every = 0,
2642 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS,
2643 .dimension = "calls"};
2644
2645 static ebpf_systemd_args_t data_tcp_retransmit = {
2646 .title = "Calls to tcp_retransmit",
2647 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2648 .family = NETDATA_APPS_NET_GROUP,
2649 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2650 .order = 20086,
2651 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2652 .context = NETDATA_SERVICES_SOCKET_TCP_RETRANSMIT_CONTEXT,
2653 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2654 .update_every = 0,
2655 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT,
2656 .dimension = "calls"};
2657
2658 static ebpf_systemd_args_t data_udp_send = {
2659 .title = "Calls to udp_sendmsg",
2660 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2661 .family = NETDATA_APPS_NET_GROUP,
2662 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2663 .order = 20087,
2664 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2665 .context = NETDATA_SERVICES_SOCKET_UDP_SEND_CONTEXT,
2666 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2667 .update_every = 0,
2668 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS,
2669 .dimension = "calls"};
2670
2671 static ebpf_systemd_args_t data_udp_recv = {
2672 .title = "Calls to udp_recvmsg",
2673 .units = EBPF_COMMON_UNITS_CALLS_PER_SEC,
2674 .family = NETDATA_APPS_NET_GROUP,
2675 .charttype = NETDATA_EBPF_CHART_TYPE_STACKED,
2676 .order = 20088,
2677 .algorithm = EBPF_CHART_ALGORITHM_INCREMENTAL,
2678 .context = NETDATA_SERVICES_SOCKET_UDP_RECV_CONTEXT,
2679 .module = NETDATA_EBPF_MODULE_NAME_SOCKET,
2680 .update_every = 0,
2681 .suffix = NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS,
2682 .dimension = "calls"};
2683
2684 if (!data_tcp_v4.update_every)
2685 data_tcp_v4.update_every = data_tcp_v6.update_every = data_bandwidth.update_every =
2686 data_tcp_cleanup.update_every = data_tcp_sendmsg.update_every = data_tcp_retransmit.update_every =
2687 data_udp_send.update_every = data_udp_recv.update_every = update_every;
2688
2689 ebpf_cgroup_target_t *w;
2690 for (w = ebpf_cgroup_pids; w; w = w->next) {
2691 if (ebpf_plugin_stop())
2692 break;
2693
2694 if (unlikely(!w->systemd || w->flags & NETDATA_EBPF_SERVICES_HAS_SOCKET_CHART))
2695 continue;
2696
2697 data_tcp_v4.id = data_tcp_v6.id = data_bandwidth.id = data_tcp_cleanup.id = data_tcp_sendmsg.id =
2698 data_tcp_retransmit.id = data_udp_send.id = data_udp_recv.id = w->name;
2699
2700 ebpf_create_charts_on_systemd(&data_tcp_v4);
2701 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
2702 ebpf_create_charts_on_systemd(&data_tcp_v6);
2703 }
2704
2705 ebpf_create_charts_on_systemd(&data_bandwidth);
2706
2707 ebpf_create_charts_on_systemd(&data_tcp_cleanup);
2708
2709 ebpf_create_charts_on_systemd(&data_tcp_sendmsg);
2710
2711 ebpf_create_charts_on_systemd(&data_tcp_retransmit);
2712
2713 ebpf_create_charts_on_systemd(&data_udp_recv);
2714
2715 ebpf_create_charts_on_systemd(&data_udp_send);
2716
2717 w->flags |= NETDATA_EBPF_SERVICES_HAS_SOCKET_CHART;
2718 }
2719 }
2720
2721 /**
2722 * Send Systemd charts
2723 *
2724 * Send collected data to Netdata.
2725 */
2726 static void ebpf_send_systemd_socket_charts()
2727 {
2728 ebpf_cgroup_target_t *ect;
2729 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2730 if (ebpf_plugin_stop())
2731 break;
2732
2733 if (unlikely(!(ect->flags & NETDATA_EBPF_SERVICES_HAS_SOCKET_CHART))) {
2734 continue;
2735 }
2736
2737 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V4, "");
2738 write_chart_dimension("connections", (long long)ect->publish_socket.call_tcp_v4_connection);
2739 ebpf_write_end_chart();
2740
2741 if (tcp_v6_connect_address.type == TCP_V6_CONNECT_TYPE) {
2742 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_CONNECTION_TCP_V6, "");
2743 write_chart_dimension("connections", (long long)ect->publish_socket.call_tcp_v6_connection);
2744 ebpf_write_end_chart();
2745 }
2746
2747 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH, "");
2748 write_chart_dimension("received", (long long)ect->publish_socket.bytes_received);
2749 write_chart_dimension("sent", (long long)ect->publish_socket.bytes_sent);
2750 ebpf_write_end_chart();
2751
2752 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_SEND_CALLS, "");
2753 write_chart_dimension("calls", (long long)ect->publish_socket.call_tcp_sent);
2754 ebpf_write_end_chart();
2755
2756 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RECV_CALLS, "");
2757 write_chart_dimension("calls", (long long)ect->publish_socket.call_tcp_received);
2758 ebpf_write_end_chart();
2759
2760 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_TCP_RETRANSMIT, "");
2761 write_chart_dimension("calls", (long long)ect->publish_socket.retransmit);
2762 ebpf_write_end_chart();
2763
2764 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_SEND_CALLS, "");
2765 write_chart_dimension("calls", (long long)ect->publish_socket.call_udp_sent);
2766 ebpf_write_end_chart();
2767
2768 ebpf_write_begin_chart(ect->name, NETDATA_SOCK_ID_OR_SUFFIX_BANDWIDTH_UDP_RECV_CALLS, "");
2769 write_chart_dimension("calls", (long long)ect->publish_socket.call_udp_received);
2770 ebpf_write_end_chart();
2771 }
2772 }
2773
2774 /**
2775 * Update Cgroup algorithm
2776 *
2777 * Change algorithm from absolute to incremental
2778 */
2779 void ebpf_socket_update_cgroup_algorithm()
2780 {
2781 int i;
2782 for (i = 0; i < NETDATA_MAX_SOCKET_VECTOR; i++) {
2783 netdata_publish_syscall_t *ptr = &socket_publish_aggregated[i];
2784 ptr->algorithm = ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX];
2785 }
2786 }
2787
2788 /**
2789 * Send data to Netdata calling auxiliary functions.
2790 *
2791 * @param update_every value to overwrite the update frequency set by the server.
2792 */
2793 static void ebpf_socket_send_cgroup_data(int update_every)
2794 {
2795 netdata_mutex_lock(&mutex_cgroup_shm);
2796 ebpf_cgroup_target_t *ect;
2797 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2798 ebpf_socket_sum_cgroup_pids(&ect->publish_socket, ect->pids);
2799 }
2800
2801 if (ebpf_plugin_stop()) {
2802 netdata_mutex_unlock(&mutex_cgroup_shm);
2803 return;
2804 }
2805
2806 if (ebpf_cgroup_systemd_enabled_get()) {
2807 if (ebpf_send_cgroup_chart_get()) {
2808 ebpf_create_systemd_socket_charts(update_every);
2809 }
2810 ebpf_send_systemd_socket_charts();
2811 }
2812
2813 for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
2814 if (ebpf_plugin_stop())
2815 break;
2816
2817 if (ect->systemd)
2818 continue;
2819
2820 if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART)) {
2821 ebpf_create_specific_socket_charts(ect->name, update_every);
2822 ect->flags |= NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART;
2823 }
2824
2825 if (ect->flags & NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART && ect->updated) {
2826 ebpf_send_specific_socket_data(ect->name, &ect->publish_socket);
2827 } else {
2828 ebpf_obsolete_specific_socket_charts(ect->name, update_every);
2829 ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_SOCKET_CHART;
2830 }
2831 }
2832
2833 netdata_mutex_unlock(&mutex_cgroup_shm);
2834 }
2835
2836 /*****************************************************************
2837 *
2838 * FUNCTIONS WITH THE MAIN LOOP
2839 *
2840 *****************************************************************/
2841
2842 /**
2843 * Main loop for this collector.
2844 *
2845 * @param em the structure with thread information
2846 */
2847 static void socket_collector(ebpf_module_t *em)
2848 {
2849 int cgroups = em->cgroup_charts;
2850 if (cgroups)
2851 ebpf_socket_update_cgroup_algorithm();
2852
2853 int socket_global_enabled = em->global_charts;
2854 int update_every = em->update_every;
2855 int maps_per_core = em->maps_per_core;
2856 int counter = update_every - 1;
2857 uint32_t running_time = 0;
2858 uint32_t lifetime = em->lifetime;
2859 netdata_idx_t *stats = em->hash_table_stats;
2860 memset(stats, 0, sizeof(em->hash_table_stats));
2861 heartbeat_t hb;
2862 heartbeat_init(&hb, USEC_PER_SEC);
2863 while (!ebpf_plugin_stop() && running_time < lifetime) {
2864 if (ebpf_plugin_stop())
2865 break;
2866
2867 heartbeat_next(&hb);
2868 if (ebpf_plugin_stop())
2869 break;
2870
2871 if (++counter != update_every)
2872 continue;
2873
2874 counter = 0;
2875 netdata_apps_integration_flags_t socket_apps_enabled = em->apps_charts;
2876 if (socket_global_enabled) {
2877 read_listen_table();
2878 ebpf_socket_read_hash_global_tables(stats, maps_per_core);
2879 }
2880
2881 if (ebpf_plugin_stop())
2882 break;
2883
2884 netdata_mutex_lock(&lock);
2885 if (socket_global_enabled)
2886 ebpf_socket_send_data(em);
2887
2888 if (socket_apps_enabled & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
2889 ebpf_socket_send_apps_data();
2890
2891 if (ebpf_plugin_stop()) {
2892 netdata_mutex_unlock(&lock);
2893 break;
2894 }
2895
2896 if (cgroups && ebpf_cgroup_integration_active_get())
2897 ebpf_socket_send_cgroup_data(update_every);
2898
2899 fflush(stdout);
2900
2901 netdata_mutex_unlock(&lock);
2902
2903 if (ebpf_plugin_stop())
2904 break;
2905
2906 netdata_mutex_lock(&ebpf_exit_cleanup);
2907 running_time += update_every;
2908 em->running_time = running_time;
2909 netdata_mutex_unlock(&ebpf_exit_cleanup);
2910 }
2911 }
2912
2913 /*****************************************************************
2914 *
2915 * FUNCTIONS TO START THREAD
2916 *
2917 *****************************************************************/
2918
2919 /**
2920 * Initialize vectors used with this thread.
2921 *
2922 * We are not testing the return, because callocz does this and shutdown the software
2923 * case it was not possible to allocate.
2924 */
2925 static void ebpf_socket_initialize_global_vectors()
2926 {
2927 memset(socket_aggregated_data, 0, NETDATA_MAX_SOCKET_VECTOR * sizeof(netdata_syscall_stat_t));
2928 memset(socket_publish_aggregated, 0, NETDATA_MAX_SOCKET_VECTOR * sizeof(netdata_publish_syscall_t));
2929 socket_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
2930
2931 aral_socket_table = ebpf_allocate_pid_aral(NETDATA_EBPF_SOCKET_ARAL_TABLE_NAME, sizeof(netdata_socket_plus_t));
2932
2933 socket_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_socket_t));
2934
2935 ebpf_load_addresses(&tcp_v6_connect_address, -1);
2936 }
2937
2938 /*****************************************************************
2939 *
2940 * EBPF SOCKET THREAD
2941 *
2942 *****************************************************************/
2943
2944 /**
2945 * Link dimension name
2946 *
2947 * Link user specified names inside a link list.
2948 *
2949 * @param port the port number associated to the dimension name.
2950 * @param hash the calculated hash for the dimension name.
2951 * @param name the dimension name.
2952 */
2953 static void ebpf_link_dimension_name(const char *port, uint32_t hash, const char *value)
2954 {
2955 int port_val = str2i(port);
2956 if (port_val < NETDATA_MINIMUM_PORT_VALUE || port_val > NETDATA_MAXIMUM_PORT_VALUE) {
2957 netdata_log_error("The dimension given (%s = %s) has an invalid value and it will be ignored.", port, value);
2958 return;
2959 }
2960
2961 ebpf_network_viewer_dim_name_t *w;
2962 w = callocz(1, sizeof(ebpf_network_viewer_dim_name_t));
2963
2964 w->name = strdupz(value);
2965 w->hash = hash;
2966
2967 w->port = (uint16_t)htons(port_val);
2968
2969 ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
2970 if (unlikely(!names)) {
2971 network_viewer_opt.names = w;
2972 } else {
2973 for (; names->next; names = names->next) {
2974 if (names->port == w->port) {
2975 netdata_log_info("Duplicated definition for a service, the name %s will be ignored. ", names->name);
2976 freez(names->name);
2977 names->name = w->name;
2978 names->hash = w->hash;
2979 freez(w);
2980 return;
2981 }
2982 }
2983 names->next = w;
2984 }
2985
2986 #ifdef NETDATA_INTERNAL_CHECKS
2987 netdata_log_info("Adding values %s( %u) to dimension name list used on network viewer", w->name, htons(w->port));
2988 #endif
2989 }
2990
2991 /**
2992 * Parse service Name section.
2993 *
2994 * This function gets the values that will be used to overwrite dimensions.
2995 *
2996 * @param cfg the configuration structure
2997 */
2998
2999 static bool config_service_value_cb(void *data __maybe_unused, const char *name, const char *value)
3000 {
3001 ebpf_link_dimension_name(name, simple_hash(name), value);
3002 return true;
3003 }
3004
3005 void ebpf_parse_service_name_section(struct config *cfg)
3006 {
3007 inicfg_foreach_value_in_section(cfg, EBPF_SERVICE_NAME_SECTION, config_service_value_cb, NULL);
3008
3009 // Always associated the default port to Netdata
3010 ebpf_network_viewer_dim_name_t *names = network_viewer_opt.names;
3011 if (names) {
3012 uint16_t default_port = htons(19999);
3013 while (names) {
3014 if (names->port == default_port)
3015 return;
3016
3017 names = names->next;
3018 }
3019 }
3020
3021 char *port_string = getenv("NETDATA_LISTEN_PORT");
3022 if (port_string) {
3023 // if variable has an invalid value, we assume netdata is using 19999
3024 int default_port = str2i(port_string);
3025 if (default_port > 0 && default_port < 65536)
3026 ebpf_link_dimension_name(port_string, simple_hash(port_string), "Netdata");
3027 }
3028 }
3029
3030 /**
3031 * Parse table size options
3032 *
3033 * @param cfg configuration options read from user file.
3034 */
3035 void parse_table_size_options(struct config *cfg)
3036 {
3037 socket_maps[NETDATA_SOCKET_OPEN_SOCKET].user_input = (uint32_t)inicfg_get_number(
3038 cfg, EBPF_GLOBAL_SECTION, EBPF_CONFIG_SOCKET_MONITORING_SIZE, NETDATA_MAXIMUM_CONNECTIONS_ALLOWED);
3039
3040 socket_maps[NETDATA_SOCKET_TABLE_UDP].user_input = (uint32_t)inicfg_get_number(
3041 cfg, EBPF_GLOBAL_SECTION, EBPF_CONFIG_UDP_SIZE, NETDATA_MAXIMUM_UDP_CONNECTIONS_ALLOWED);
3042 }
3043
3044 /*
3045 * Load BPF
3046 *
3047 * Load BPF files.
3048 *
3049 * @param em the structure with configuration
3050 */
3051 static int ebpf_socket_load_bpf(ebpf_module_t *em)
3052 {
3053 #ifdef LIBBPF_MAJOR_VERSION
3054 ebpf_define_map_type(em->maps, em->maps_per_core, running_on_kernel);
3055 #endif
3056
3057 int ret = 0;
3058
3059 if (em->load & EBPF_LOAD_LEGACY) {
3060 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
3061 if (!em->probe_links) {
3062 ret = -1;
3063 }
3064 }
3065 #ifdef LIBBPF_MAJOR_VERSION
3066 else {
3067 socket_bpf_obj = socket_bpf__open();
3068 if (!socket_bpf_obj)
3069 ret = -1;
3070 else {
3071 ret = ebpf_socket_load_and_attach(socket_bpf_obj, em);
3072 if (ret) {
3073 socket_bpf__destroy(socket_bpf_obj);
3074 socket_bpf_obj = NULL;
3075 }
3076 }
3077 }
3078 #endif
3079
3080 if (ret) {
3081 netdata_log_error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->info.thread_name);
3082 }
3083
3084 return ret;
3085 }
3086
3087 /**
3088 * Socket thread
3089 *
3090 * Thread used to generate socket charts.
3091 *
3092 * @param ptr a pointer to `struct ebpf_module`
3093 *
3094 * @return It always return NULL
3095 */
3096 void ebpf_socket_thread(void *ptr)
3097 {
3098 ebpf_set_pid_map_fd(NETDATA_EBPF_PIDS_SOCKET_IDX, -1);
3099 ebpf_module_t *em = (ebpf_module_t *)ptr;
3100
3101 CLEANUP_FUNCTION_REGISTER(ebpf_socket_exit) cleanup_ptr = em;
3102
3103 if (!ebpf_module_thread_has_valid_state(em))
3104 goto endsocket;
3105
3106 em->maps = socket_maps;
3107
3108 rw_spinlock_write_lock(&network_viewer_opt.rw_spinlock);
3109 // It was not enabled from main config file (ebpf.d.conf)
3110 if (!network_viewer_opt.enabled)
3111 network_viewer_opt.enabled =
3112 inicfg_get_boolean(&socket_config, EBPF_NETWORK_VIEWER_SECTION, "enabled", CONFIG_BOOLEAN_YES);
3113
3114 rw_spinlock_write_unlock(&network_viewer_opt.rw_spinlock);
3115
3116 parse_table_size_options(&socket_config);
3117
3118 ebpf_socket_initialize_global_vectors();
3119
3120 if (running_on_kernel < NETDATA_EBPF_KERNEL_5_0)
3121 em->mode = MODE_ENTRY;
3122
3123 #ifdef LIBBPF_MAJOR_VERSION
3124 ebpf_adjust_thread_load(em, default_btf);
3125 #endif
3126 if (ebpf_socket_load_bpf(em)) {
3127 goto endsocket;
3128 }
3129 ebpf_mark_program_loaded();
3130
3131 int algorithms[NETDATA_MAX_SOCKET_VECTOR] = {
3132 NETDATA_EBPF_ABSOLUTE_IDX,
3133 NETDATA_EBPF_ABSOLUTE_IDX,
3134 NETDATA_EBPF_ABSOLUTE_IDX,
3135 NETDATA_EBPF_ABSOLUTE_IDX,
3136 NETDATA_EBPF_ABSOLUTE_IDX,
3137 NETDATA_EBPF_ABSOLUTE_IDX,
3138 NETDATA_EBPF_ABSOLUTE_IDX,
3139 NETDATA_EBPF_ABSOLUTE_IDX,
3140 NETDATA_EBPF_INCREMENTAL_IDX,
3141 NETDATA_EBPF_INCREMENTAL_IDX};
3142 ebpf_global_labels(
3143 socket_aggregated_data,
3144 socket_publish_aggregated,
3145 socket_dimension_names,
3146 socket_id_names,
3147 algorithms,
3148 NETDATA_MAX_SOCKET_VECTOR);
3149
3150 ebpf_read_socket.thread =
3151 nd_thread_create(ebpf_read_socket.name, NETDATA_THREAD_OPTION_DEFAULT, ebpf_read_socket_thread, em);
3152
3153 netdata_mutex_lock(&lock);
3154 ebpf_socket_create_global_charts(em);
3155
3156 ebpf_update_stats(&plugin_statistics, em);
3157 ebpf_update_kernel_memory_with_vector(&plugin_statistics, em->maps, EBPF_ACTION_STAT_ADD);
3158
3159 netdata_mutex_unlock(&lock);
3160
3161 socket_collector(em);
3162
3163 endsocket:
3164 ebpf_update_disabled_plugin_stats(em);
3165 }