diff options
author | thiagoftsm <thiagoftsm@gmail.com> | 2022-03-29 18:21:42 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-29 18:21:42 +0000 |
commit | 68684b59f704cdd1b4190f4be8b3bce95d60da75 (patch) | |
tree | 6c9cc03a116eac1ccd388136300c4a5b5f7ee4cf /collectors | |
parent | 0746b58e7abe6a63c8c07c626eef3cb8c0217a43 (diff) |
Socket connections (eBPF) and bug fix (#12532)
Diffstat (limited to 'collectors')
-rw-r--r-- | collectors/ebpf.plugin/ebpf.c | 5 | ||||
-rw-r--r-- | collectors/ebpf.plugin/ebpf.d/network.conf | 12 | ||||
-rw-r--r-- | collectors/ebpf.plugin/ebpf.h | 1 | ||||
-rw-r--r-- | collectors/ebpf.plugin/ebpf_apps.h | 3 | ||||
-rw-r--r-- | collectors/ebpf.plugin/ebpf_socket.c | 713 | ||||
-rw-r--r-- | collectors/ebpf.plugin/ebpf_socket.h | 70 |
6 files changed, 731 insertions, 73 deletions
diff --git a/collectors/ebpf.plugin/ebpf.c b/collectors/ebpf.plugin/ebpf.c index 778c2bd96e..f73e99fdc3 100644 --- a/collectors/ebpf.plugin/ebpf.c +++ b/collectors/ebpf.plugin/ebpf.c @@ -51,7 +51,7 @@ ebpf_module_t ebpf_modules[] = { .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &socket_config, .config_file = NETDATA_NETWORK_CONFIG_FILE, .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4, - .load = EBPF_LOAD_LEGACY, .targets = NULL}, + .load = EBPF_LOAD_LEGACY, .targets = socket_targets}, { .thread_name = "cachestat", .config_name = "cachestat", .enabled = 0, .start_routine = ebpf_cachestat_thread, .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, @@ -972,6 +972,7 @@ static void read_local_ports(char *filename, uint8_t proto) return; size_t lines = procfile_lines(ff), l; + netdata_passive_connection_t values = {.counter = 0, .tgid = 0, .pid = 0}; for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); // This is header or end of file @@ -985,7 +986,7 @@ static void read_local_ports(char *filename, uint8_t proto) // Read local port uint16_t port = (uint16_t)strtol(procfile_lineword(ff, l, 2), NULL, 16); - update_listen_table(htons(port), proto); + update_listen_table(htons(port), proto, &values); } procfile_close(ff); diff --git a/collectors/ebpf.plugin/ebpf.d/network.conf b/collectors/ebpf.plugin/ebpf.d/network.conf index e692622a97..d939d8e1fd 100644 --- a/collectors/ebpf.plugin/ebpf.d/network.conf +++ b/collectors/ebpf.plugin/ebpf.d/network.conf @@ -14,6 +14,16 @@ # `ipv6 connection table size`: Maximum number of IPV6 connections monitored # `udp connection table size`: Maximum number of UDP connections monitored # +# The `ebpf type format` option accepts the following values : +# `auto` : The eBPF collector will investigate hardware and select between the two next options. +# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload. +# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms. +# +# The `ebpf co-re tracing` option accepts the following values: +# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host. +# `tracepoint`: When available, the eBPF collector will use kernel tracepoint to monitor syscall. +# `probe` : This is the same as legacy code. +# [global] # ebpf load mode = entry # apps = yes @@ -23,6 +33,8 @@ ipv4 connection table size = 16384 ipv6 connection table size = 16384 udp connection table size = 4096 + ebpf type format = auto + ebpf co-re tracing = trampoline # # Network Connection diff --git a/collectors/ebpf.plugin/ebpf.h b/collectors/ebpf.plugin/ebpf.h index 5cc8cad257..337e4f4710 100644 --- a/collectors/ebpf.plugin/ebpf.h +++ b/collectors/ebpf.plugin/ebpf.h @@ -244,6 +244,7 @@ extern void ebpf_pid_file(char *filename, size_t length); #define EBPF_COMMON_DIMENSION_PERCENTAGE "%" #define EBPF_COMMON_DIMENSION_CALL "calls/s" +#define EBPF_COMMON_DIMENSION_CONNECTIONS "connections/s" #define EBPF_COMMON_DIMENSION_BITS "kilobits/s" #define EBPF_COMMON_DIMENSION_BYTES "bytes/s" #define EBPF_COMMON_DIMENSION_DIFFERENCE "difference" diff --git a/collectors/ebpf.plugin/ebpf_apps.h b/collectors/ebpf.plugin/ebpf_apps.h index 18a32dc56e..259e642ad3 100644 --- a/collectors/ebpf.plugin/ebpf_apps.h +++ b/collectors/ebpf.plugin/ebpf_apps.h @@ -380,6 +380,9 @@ typedef struct ebpf_bandwidth { uint64_t call_udp_sent; // Number of times udp_sendmsg was called uint64_t call_udp_received; // Number of times udp_recvmsg was called uint64_t close; // Number of times tcp_close was called + uint64_t drop; // THIS IS NOT USED FOR WHILE, we are in groom section + uint32_t tcp_v4_connection; // Number of times tcp_v4_connection was called. + uint32_t tcp_v6_connection; // Number of times tcp_v6_connection was called. } ebpf_bandwidth_t; /** diff --git a/collectors/ebpf.plugin/ebpf_socket.c b/collectors/ebpf.plugin/ebpf_socket.c index a61704a96a..5579cd28c9 100644 --- a/collectors/ebpf.plugin/ebpf_socket.c +++ b/collectors/ebpf.plugin/ebpf_socket.c @@ -12,9 +12,13 @@ *****************************************************************/ static char *socket_dimension_names[NETDATA_MAX_SOCKET_VECTOR] = { "received", "sent", "close", - "received", "sent", "retransmitted" }; + "received", "sent", "retransmitted", + "connected_V4", "connected_V6", "connected_tcp", + "connected_udp"}; static char *socket_id_names[NETDATA_MAX_SOCKET_VECTOR] = { "tcp_cleanup_rbuf", "tcp_sendmsg", "tcp_close", - "udp_recvmsg", "udp_sendmsg", "tcp_retransmit_skb" }; + "udp_recvmsg", "udp_sendmsg", "tcp_retransmit_skb", + "tcp_connect_v4", "tcp_connect_v6", "inet_csk_accept_tcp", + "inet_csk_accept_udp" }; static ebpf_local_maps_t socket_maps[] = {{.name = "tbl_bandwidth", .internal_input = NETDATA_COMPILED_CONNECTIONS_ALLOWED, @@ -77,6 +81,349 @@ struct config socket_config = { .first_section = NULL, .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare }, .rwlock = AVL_LOCK_INITIALIZER } }; +netdata_ebpf_targets_t socket_targets[] = { {.name = "inet_csk_accept", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_retransmit_skb", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_cleanup_rbuf", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_close", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "udp_recvmsg", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_sendmsg", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "udp_sendmsg", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_v4_connect", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = "tcp_v6_connect", .mode = EBPF_LOAD_TRAMPOLINE}, + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}}; + +#ifdef LIBBPF_MAJOR_VERSION +#include "includes/socket.skel.h" // BTF code + +static struct socket_bpf *bpf_obj = NULL; + +/** + * Disable Probe + * + * Disable probes to use trampoline. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_socket_disable_probes(struct socket_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_inet_csk_accept_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_retransmit_skb_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_cleanup_rbuf_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_close_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_socket_release_task_kprobe, false); +} + +/** + * Disable Trampoline + * + * Disable trampoline to use probes. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_socket_disable_trampoline(struct socket_bpf *obj) +{ + bpf_program__set_autoload(obj->progs.netdata_inet_csk_accept_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_v4_connect_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_v6_connect_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_retransmit_skb_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_cleanup_rbuf_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_close_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_udp_recvmsg_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_socket_release_task_fentry, false); +} + +/** + * Set trampoline target. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_set_trampoline_target(struct socket_bpf *obj) +{ + bpf_program__set_attach_target(obj->progs.netdata_inet_csk_accept_fentry, 0, + socket_targets[NETDATA_FCNT_INET_CSK_ACCEPT].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_v4_connect_fexit, 0, + socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_v6_connect_fexit, 0, + socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_retransmit_skb_fentry, 0, + socket_targets[NETDATA_FCNT_TCP_RETRANSMIT].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_cleanup_rbuf_fentry, 0, + socket_targets[NETDATA_FCNT_CLEANUP_RBUF].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_close_fentry, 0, socket_targets[NETDATA_FCNT_TCP_CLOSE].name); + + bpf_program__set_attach_target(obj->progs.netdata_udp_recvmsg_fentry, 0, + socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_udp_recvmsg_fexit, 0, + socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_sendmsg_fentry, 0, + socket_targets[NETDATA_FCNT_TCP_SENDMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_tcp_sendmsg_fexit, 0, + socket_targets[NETDATA_FCNT_TCP_SENDMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_udp_sendmsg_fentry, 0, + socket_targets[NETDATA_FCNT_UDP_SENDMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_udp_sendmsg_fexit, 0, + socket_targets[NETDATA_FCNT_UDP_SENDMSG].name); + + bpf_program__set_attach_target(obj->progs.netdata_socket_release_task_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP); +} + + +/** + * Disable specific trampoline + * + * Disable specific trampoline to match user selection. + * + * @param obj is the main structure for bpf objects. + * @param sel option selected by user. + */ +static inline void ebpf_socket_disable_specific_trampoline(struct socket_bpf *obj, netdata_run_mode_t sel) +{ + if (sel == MODE_RETURN) { + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fentry, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fentry, false); + } else { + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_fexit, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_fexit, false); + } +} + +/** + * Disable specific trampoline + * + * Disable specific trampoline to match user selection. + * + * @param obj is the main structure for bpf objects. + * @param sel option selected by user. + */ +static inline void ebpf_socket_disable_specific_probe(struct socket_bpf *obj, netdata_run_mode_t sel) +{ + if (sel == MODE_RETURN) { + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kprobe, false); + } else { + bpf_program__set_autoload(obj->progs.netdata_tcp_sendmsg_kretprobe, false); + bpf_program__set_autoload(obj->progs.netdata_udp_sendmsg_kretprobe, false); + } +} + +/** + * Attach probes + * + * Attach probes to targets. + * + * @param obj is the main structure for bpf objects. + * @param sel option selected by user. + */ +static int ebpf_socket_attach_probes(struct socket_bpf *obj, netdata_run_mode_t sel) +{ + obj->links.netdata_inet_csk_accept_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_inet_csk_accept_kretprobe, + true, + socket_targets[NETDATA_FCNT_INET_CSK_ACCEPT].name); + int ret = libbpf_get_error(obj->links.netdata_inet_csk_accept_kretprobe); + if (ret) + return -1; + + obj->links.netdata_tcp_v4_connect_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_v4_connect_kretprobe, + true, + socket_targets[NETDATA_FCNT_TCP_V4_CONNECT].name); + ret = libbpf_get_error(obj->links.netdata_tcp_v4_connect_kretprobe); + if (ret) + return -1; + + obj->links.netdata_tcp_v6_connect_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_v6_connect_kretprobe, + true, + socket_targets[NETDATA_FCNT_TCP_V6_CONNECT].name); + ret = libbpf_get_error(obj->links.netdata_tcp_v6_connect_kretprobe); + if (ret) + return -1; + + obj->links.netdata_tcp_retransmit_skb_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_retransmit_skb_kprobe, + false, + socket_targets[NETDATA_FCNT_TCP_RETRANSMIT].name); + ret = libbpf_get_error(obj->links.netdata_tcp_retransmit_skb_kprobe); + if (ret) + return -1; + + obj->links.netdata_tcp_cleanup_rbuf_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_cleanup_rbuf_kprobe, + false, + socket_targets[NETDATA_FCNT_CLEANUP_RBUF].name); + ret = libbpf_get_error(obj->links.netdata_tcp_cleanup_rbuf_kprobe); + if (ret) + return -1; + + obj->links.netdata_tcp_close_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_close_kprobe, + false, + socket_targets[NETDATA_FCNT_TCP_CLOSE].name); + ret = libbpf_get_error(obj->links.netdata_tcp_close_kprobe); + if (ret) + return -1; + + obj->links.netdata_udp_recvmsg_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_udp_recvmsg_kprobe, + false, + socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name); + ret = libbpf_get_error(obj->links.netdata_udp_recvmsg_kprobe); + if (ret) + return -1; + + obj->links.netdata_udp_recvmsg_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_udp_recvmsg_kretprobe, + true, + socket_targets[NETDATA_FCNT_UDP_RECEVMSG].name); + ret = libbpf_get_error(obj->links.netdata_udp_recvmsg_kretprobe); + if (ret) + return -1; + + if (sel == MODE_RETURN) { + obj->links.netdata_tcp_sendmsg_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_sendmsg_kretprobe, + true, + socket_targets[NETDATA_FCNT_TCP_SENDMSG].name); + ret = libbpf_get_error(obj->links.netdata_tcp_sendmsg_kretprobe); + if (ret) + return -1; + + obj->links.netdata_udp_sendmsg_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_udp_sendmsg_kretprobe, + true, + socket_targets[NETDATA_FCNT_UDP_SENDMSG].name); + ret = libbpf_get_error(obj->links.netdata_udp_sendmsg_kretprobe); + if (ret) + return -1; + } else { + obj->links.netdata_tcp_sendmsg_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_tcp_sendmsg_kprobe, + false, + socket_targets[NETDATA_FCNT_TCP_SENDMSG].name); + ret = libbpf_get_error(obj->links.netdata_tcp_sendmsg_kprobe); + if (ret) + return -1; + + obj->links.netdata_udp_sendmsg_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_udp_sendmsg_kprobe, + false, + socket_targets[NETDATA_FCNT_UDP_SENDMSG].name); + ret = libbpf_get_error(obj->links.netdata_udp_sendmsg_kprobe); + if (ret) + return -1; + } + + obj->links.netdata_socket_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_socket_release_task_kprobe, + false, EBPF_COMMON_FNCT_CLEAN_UP); + ret = libbpf_get_error(obj->links.netdata_socket_release_task_kprobe); + if (ret) + return -1; + + return 0; +} + +/** + * Set hash tables + * + * Set the values for maps according the value given by kernel. + * + * @param obj is the main structure for bpf objects. + */ +static void ebpf_socket_set_hash_tables(struct socket_bpf *obj) +{ + socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH].map_fd = bpf_map__fd(obj->maps.tbl_bandwidth); + socket_maps[NETDATA_SOCKET_GLOBAL].map_fd = bpf_map__fd(obj->maps.tbl_global_sock); + socket_maps[NETDATA_SOCKET_LPORTS].map_fd = bpf_map__fd(obj->maps.tbl_lports); + socket_maps[NETDATA_SOCKET_TABLE_IPV4].map_fd = bpf_map__fd(obj->maps.tbl_conn_ipv4); + socket_maps[NETDATA_SOCKET_TABLE_IPV6].map_fd = bpf_map__fd(obj->maps.tbl_conn_ipv6); + socket_maps[NETDATA_SOCKET_TABLE_UDP].map_fd = bpf_map__fd(obj->maps.tbl_nv_udp); + socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd = bpf_map__fd(obj->maps.socket_ctrl); +} + +/** + * Adjust Map Size + * + * Resize maps according input from users. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + */ +static void ebpf_socket_adjust_map_size(struct socket_bpf *obj, ebpf_module_t *em) +{ + ebpf_update_map_size(obj->maps.tbl_bandwidth, &socket_maps[NETDATA_SOCKET_TABLE_BANDWIDTH], + em, bpf_map__name(obj->maps.tbl_bandwidth)); + + ebpf_update_map_size(obj->maps.tbl_conn_ipv4, &socket_maps[NETDATA_SOCKET_TABLE_IPV4], + em, bpf_map__name(obj->maps.tbl_conn_ipv4)); + + ebpf_update_map_size(obj->maps.tbl_conn_ipv6, &socket_maps[NETDATA_SOCKET_TABLE_IPV6], + em, bpf_map__name(obj->maps.tbl_conn_ipv6)); + + ebpf_update_map_size(obj->maps.tbl_nv_udp, &socket_maps[NETDATA_SOCKET_TABLE_UDP], + em, bpf_map__name(obj->maps.tbl_nv_udp)); +} + +/** + * Load and attach + * + * Load and attach the eBPF code in kernel. + * + * @param obj is the main structure for bpf objects. + * @param em structure with configuration + * + * @return it returns 0 on succes and -1 otherwise + */ +static inline int ebpf_socket_load_and_attach(struct socket_bpf *obj, ebpf_module_t *em) +{ + netdata_ebpf_targets_t *mt = em->targets; + netdata_ebpf_program_loaded_t test = mt[NETDATA_FCNT_INET_CSK_ACCEPT].mode; + + if (test == EBPF_LOAD_TRAMPOLINE) { + ebpf_socket_disable_probes(obj); + + ebpf_set_trampoline_target(obj); + ebpf_socket_disable_specific_trampoline(obj, em->mode); + } else { // We are not using tracepoints for this thread. + ebpf_socket_disable_trampoline(obj); + + ebpf_socket_disable_specific_probe(obj, em->mode); + } + + int ret = socket_bpf__load(obj); + if (ret) { + fprintf(stderr, "failed to load BPF object: %d\n", ret); + return ret; + } + + ebpf_socket_adjust_map_size(obj, em); + + if (test == EBPF_LOAD_TRAMPOLINE) { + ret = socket_bpf__attach(obj); + } else { + ret = ebpf_socket_attach_probes(obj, em->mode); + } + + if (!ret) { + ebpf_socket_set_hash_tables(obj); + + ebpf_update_controller(socket_maps[NETDATA_SOCKET_TABLE_CTRL].map_fd, em); + } + + return ret; +} +#endif /***************************************************************** * * PROCESS DATA AND SEND TO NETDATA @@ -294,6 +641,31 @@ static void ebpf_socket_send_nv_data(netdata_vector_plot_t *ptr) } /** + * Send Global Inbound connection + * + * Send number of connections read per protocol. + */ +static void ebpf_socket_send_global_inbound_conn() +{ + uint64_t udp_conn = 0; + uint64_t tcp_conn = 0; + ebpf_network_viewer_port_list_t *move = listen_ports; + while (move) { + if (move->protocol == IPPROTO_TCP) + tcp_conn += move->connections; + else + udp_conn += move->connections; + + move = move->next; + } + + write_begin_chart(NETDATA_EBPF_IP_FAMILY, NETDATA_INBOUND_CONNECTIONS); + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_TCP].name, (long long) tcp_conn); + write_chart_dimension(socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_UDP].name, (long long) udp_conn); + write_end_chart(); +} + +/** * Send data to Netdata calling auxiliary functions. * * @param em the structure with thread information @@ -304,6 +676,10 @@ static void ebpf_socket_send_data(ebpf_module_t *em) netdata_publish_vfs_common_t common_udp; ebpf_update_global_publish(socket_publish_aggregated, &common_tcp, &common_udp, socket_aggregated_data); + ebpf_socket_send_global_inbound_conn(); + write_count_chart(NETDATA_TCP_OUTBOUND_CONNECTIONS, NETDATA_EBPF_IP_FAMILY, + &socket_publish_aggregated[NETDATA_IDX_TCP_CONNECTION_V4], 2); + // We read bytes from function arguments, but bandwidth is given in bits, // so we need to multiply by 8 to convert for the final value. write_count_chart(NETDATA_TCP_FUNCTION_COUNT, NETDATA_EBPF_IP_FAMILY, socket_publish_aggregated, 3); @@ -367,6 +743,26 @@ void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root) struct target *w; collected_number value; + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_CONNECTION_TCP_V4); + for (w = root; w; w = w->next) { + if (unlikely(w->exposed && w->processes)) { + value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t, + call_tcp_v4_connection)); + write_chart_dimension(w->name, value); + } + } + write_end_chart(); + + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_CONNECTION_TCP_V6); + for (w = root; w; w = w->next) { + if (unlikely(w->exposed && w->processes)) { + value = ebpf_socket_sum_values_for_pids(w->root_pid, offsetof(ebpf_socket_publish_apps_t, + call_tcp_v6_connection)); + write_chart_dimension(w->name, value); + } + } + write_end_chart(); + write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_NET_APPS_BANDWIDTH_SENT); for (w = root; w; w = w->next) { if (unlikely(w->exposed && w->processes)) { @@ -456,6 +852,32 @@ void ebpf_socket_send_apps_data(ebpf_module_t *em, struct target *root) */ static void ebpf_create_global_charts(ebpf_module_t *em) { + int order = 21070; + ebpf_create_chart(NETDATA_EBPF_IP_FAMILY, + NETDATA_INBOUND_CONNECTIONS, + "Inbound connections.", + EBPF_COMMON_DIMENSION_CONNECTIONS, + NETDATA_SOCKET_KERNEL_FUNCTIONS, + NULL, + NETDATA_EBPF_CHART_TYPE_LINE, + order++, + ebpf_create_global_dimension, + &socket_publish_aggregated[NETDATA_IDX_INCOMING_CONNECTION_TCP], + 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); + + ebpf_create_chart(NETDATA_EBPF_IP_FAMILY, + NETDATA_TCP_OUTBOUND_CONNECTIONS, + "TCP outbound connections.", + EBPF_COMMON_DIMENSION_CONNECTIONS, + NETDATA_SOCKET_KERNEL_FUNCTIONS, + NULL, + NETDATA_EBPF_CHART_TYPE_LINE, + order++, + ebpf_create_global_dimension, + &socket_publish_aggregated[NETDATA_IDX_TCP_CONNECTION_V4], + 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); + + ebpf_create_chart(NETDATA_EBPF_IP_FAMILY, NETDATA_TCP_FUNCTION_COUNT, "Calls to internal functions", @@ -463,7 +885,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21070, + order++, ebpf_create_global_dimension, socket_publish_aggregated, 3, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -473,7 +895,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21071, + order++, ebpf_create_global_dimension, socket_publish_aggregated, 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -486,7 +908,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21072, + order++, ebpf_create_global_dimension, socket_publish_aggregated, 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -499,7 +921,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21073, + order++, ebpf_create_global_dimension, &socket_publish_aggregated[NETDATA_IDX_TCP_RETRANSMIT], 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -511,7 +933,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21074, + order++, ebpf_create_global_dimension, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF], 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -521,7 +943,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21075, + order++, ebpf_create_global_dimension, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF], 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -534,7 +956,7 @@ static void ebpf_create_global_charts(ebpf_module_t *em) NETDATA_SOCKET_KERNEL_FUNCTIONS, NULL, NETDATA_EBPF_CHART_TYPE_LINE, - 21076, + order++, ebpf_create_global_dimension, &socket_publish_aggregated[NETDATA_IDX_UDP_RECVBUF], 2, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -551,12 +973,29 @@ static void ebpf_create_global_charts(ebpf_module_t *em) */ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) { - struct target *root = ptr;; + struct target *root = ptr; + int order = 20080; + ebpf_create_charts_on_apps(NETDATA_NET_APPS_CONNECTION_TCP_V4, + "Calls to tcp_v4_connection", EBPF_COMMON_DIMENSION_CONNECTIONS, + NETDATA_APPS_NET_GROUP, + NETDATA_EBPF_CHART_TYPE_STACKED, + order++, + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], + root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); + + ebpf_create_charts_on_apps(NETDATA_NET_APPS_CONNECTION_TCP_V6, + "Calls to tcp_v6_connection", EBPF_COMMON_DIMENSION_CONNECTIONS, + NETDATA_APPS_NET_GROUP, + NETDATA_EBPF_CHART_TYPE_STACKED, + order++, + ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], + root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); + ebpf_create_charts_on_apps(NETDATA_NET_APPS_BANDWIDTH_SENT, "Bytes sent", EBPF_COMMON_DIMENSION_BITS, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20080, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -564,7 +1003,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) "bytes received", EBPF_COMMON_DIMENSION_BITS, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20081, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -573,7 +1012,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20082, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -582,7 +1021,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20083, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -591,7 +1030,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20084, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -600,7 +1039,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20085, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -609,7 +1048,7 @@ void ebpf_socket_create_apps_charts(struct ebpf_module *em, void *ptr) EBPF_COMMON_DIMENSION_CALL, NETDATA_APPS_NET_GROUP, NETDATA_EBPF_CHART_TYPE_STACKED, - 20086, + order++, ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], root, em->update_every, NETDATA_EBPF_MODULE_NAME_SOCKET); @@ -1387,37 +1826,59 @@ static void read_socket_hash_table(int fd, int family, int network_connection) } /** + * Fill Network Viewer Port list + * + * Fill the strcture with values read from /proc or hash table. + * + * @param out the structure where we will store data. + * @param value the ports we are listen to. + * @param proto the protocol used for this connection. + * @param in the strcuture with values read form different sources. + */ +static inline void fill_nv_port_list(ebpf_network_viewer_port_list_t *out, uint16_t value, uint16_t proto, + netdata_passive_connection_t *in) +{ + out->first = value; + out->protocol = proto; + out->pid = in->pid; + out->tgid = in->tgid; + out->connections = in->counter; +} + +/** * Update listen table * * Update link list when it is necessary. * * @param value the ports we are listen to. * @param proto the protocol used with port connection. + * @param in the strcuture with values read form different sources. */ -void update_listen_table(uint16_t value, uint8_t proto) +void |