summaryrefslogtreecommitdiffstats
path: root/collectors
diff options
context:
space:
mode:
authorthiagoftsm <thiagoftsm@gmail.com>2022-03-29 18:21:42 +0000
committerGitHub <noreply@github.com>2022-03-29 18:21:42 +0000
commit68684b59f704cdd1b4190f4be8b3bce95d60da75 (patch)
tree6c9cc03a116eac1ccd388136300c4a5b5f7ee4cf /collectors
parent0746b58e7abe6a63c8c07c626eef3cb8c0217a43 (diff)
Socket connections (eBPF) and bug fix (#12532)
Diffstat (limited to 'collectors')
-rw-r--r--collectors/ebpf.plugin/ebpf.c5
-rw-r--r--collectors/ebpf.plugin/ebpf.d/network.conf12
-rw-r--r--collectors/ebpf.plugin/ebpf.h1
-rw-r--r--collectors/ebpf.plugin/ebpf_apps.h3
-rw-r--r--collectors/ebpf.plugin/ebpf_socket.c713
-rw-r--r--collectors/ebpf.plugin/ebpf_socket.h70
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