@cryptotaxi247 / netdata-1 / commits / c77e3d5b1

add port service names to network viewer (#18107)

* add port service names to network viewer * use unique function names

Costa Tsaousis committed Jul 10, 2024 at 22:33 UTC c77e3d5b1262c76065a6326b71ca6b92ee10c14d
3 files changed +130 -14
CMakeLists.txt
+1
@@ -1182,6 +1182,7 @@ set(SYSTEMD_JOURNAL_PLUGIN_FILES
1182 src/collectors/systemd-journal.plugin/systemd-journal-dyncfg.c
1183 src/libnetdata/maps/system-users.h
1184 src/libnetdata/maps/system-groups.h
1185 + src/libnetdata/maps/system-services.h
1186 )
1187
1188 set(STREAMING_PLUGIN_FILES
src/collectors/network-viewer.plugin/network-viewer.c
+37 -14
@@ -2,6 +2,7 @@
2
3 #include "collectors/all.h"
4 #include "libnetdata/libnetdata.h"
5 +
6 #include "libnetdata/required_dummies.h"
7
8 static SPAWN_SERVER *spawn_srv = NULL;
@@ -24,6 +25,7 @@ static SPAWN_SERVER *spawn_srv = NULL;
25
26 #include "libnetdata/maps/local-sockets.h"
27 #include "libnetdata/maps/system-users.h"
28 +#include "libnetdata/maps/system-services.h"
29
30 #define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections"
31 #define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer"
@@ -35,6 +37,7 @@ static SPAWN_SERVER *spawn_srv = NULL;
37 netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
38 static bool plugin_should_exit = false;
39 static USERNAMES_CACHE *uc;
40 +static SERVICENAMES_CACHE *sc;
41
42 ENUM_STR_MAP_DEFINE(SOCKET_DIRECTION) = {
43 { .id = SOCKET_DIRECTION_LISTEN, .name = "listen" },
@@ -153,18 +156,7 @@ static void local_socket_to_json_array(struct sockets_stats *st, LOCAL_SOCKET *n
156 string_freez(u);
157 }
158
156 - if(!aggregated) {
157 - buffer_json_add_array_item_string(wb, local_address);
158 - buffer_json_add_array_item_uint64(wb, n->local.port);
159 - }
160 - buffer_json_add_array_item_string(wb, n->network_viewer.aggregated_key.local_address_space);
161 -
162 - if(!aggregated) {
163 - buffer_json_add_array_item_string(wb, remote_address);
164 - buffer_json_add_array_item_uint64(wb, n->remote.port);
165 - }
166 - buffer_json_add_array_item_string(wb, n->network_viewer.aggregated_key.remote_address_space);
167 -
159 + struct socket_endpoint *server_endpoint;
160 const char *server_address;
161 const char *client_address_space;
162 const char *server_address_space;
@@ -175,6 +167,7 @@ static void local_socket_to_json_array(struct sockets_stats *st, LOCAL_SOCKET *n
167 server_address = local_address;
168 server_address_space = n->network_viewer.aggregated_key.local_address_space;
169 client_address_space = n->network_viewer.aggregated_key.remote_address_space;
170 + server_endpoint = &n->local;
171 break;
172
173 case SOCKET_DIRECTION_OUTBOUND:
@@ -182,15 +175,36 @@ static void local_socket_to_json_array(struct sockets_stats *st, LOCAL_SOCKET *n
175 server_address = remote_address;
176 server_address_space = n->network_viewer.aggregated_key.remote_address_space;
177 client_address_space = n->network_viewer.aggregated_key.local_address_space;
178 + server_endpoint = &n->remote;
179 break;
180
181 case SOCKET_DIRECTION_NONE:
182 server_address = NULL;
183 client_address_space = NULL;
184 server_address_space = NULL;
185 + server_endpoint = NULL;
186 break;
187 }
188
189 + if(server_endpoint) {
190 + STRING *serv = system_servicenames_cache_lookup(sc, server_endpoint->port, server_endpoint->protocol);
191 + buffer_json_add_array_item_string(wb, string2str(serv));
192 + }
193 + else
194 + buffer_json_add_array_item_string(wb, "[unknown]");
195 +
196 + if(!aggregated) {
197 + buffer_json_add_array_item_string(wb, local_address);
198 + buffer_json_add_array_item_uint64(wb, n->local.port);
199 + }
200 + buffer_json_add_array_item_string(wb, n->network_viewer.aggregated_key.local_address_space);
201 +
202 + if(!aggregated) {
203 + buffer_json_add_array_item_string(wb, remote_address);
204 + buffer_json_add_array_item_uint64(wb, n->remote.port);
205 + }
206 + buffer_json_add_array_item_string(wb, n->network_viewer.aggregated_key.remote_address_space);
207 +
208 if(aggregated) {
209 buffer_json_add_array_item_string(wb, server_address);
210 }
@@ -618,6 +632,14 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
632 RRDF_FIELD_OPTS_VISIBLE,
633 NULL);
634
635 + // Portname
636 + buffer_rrdf_table_add_field(wb, field_id++, "Portname", "Server Port Name",
637 + RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
638 + 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
639 + RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
640 + RRDF_FIELD_OPTS_VISIBLE,
641 + NULL);
642 +
643 if(!aggregated) {
644 // Local Address
645 buffer_rrdf_table_add_field(wb, field_id++, "LocalIP", "Local IP Address",
@@ -938,14 +960,15 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
960 netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
961 if(verify_netdata_host_prefix(true) == -1) exit(1);
962
941 - uc = system_usernames_cache_init();
942 -
963 spawn_srv = spawn_server_create(SPAWN_SERVER_OPTION_CALLBACK, "setns", local_sockets_spawn_server_callback, argc, (const char **)argv);
964 if(spawn_srv == NULL) {
965 fprintf(stderr, "Cannot create spawn server.\n");
966 exit(1);
967 }
968
969 + uc = system_usernames_cache_init();
970 + sc = system_servicenames_cache_init();
971 +
972 // ----------------------------------------------------------------------------------------------------------------
973
974 if(argc == 2 && strcmp(argv[1], "debug") == 0) {
src/libnetdata/maps/system-services.h new
+92
@@ -0,0 +1,92 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_SYSTEM_SERVICES_H
4 +#define NETDATA_SYSTEM_SERVICES_H
5 +
6 +#include "libnetdata/libnetdata.h"
7 +#include <netdb.h>
8 +
9 +// --------------------------------------------------------------------------------------------------------------------
10 +// hashtable for caching port and protocol to service name mappings
11 +// key is the combination of protocol and port packed into a uint64_t, value is service name (STRING)
12 +
13 +#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
14 +#define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
15 +#include "libnetdata/simple_hashtable.h"
16 +
17 +typedef struct servicenames_cache {
18 + SPINLOCK spinlock;
19 + SIMPLE_HASHTABLE_SERVICENAMES_CACHE ht;
20 +} SERVICENAMES_CACHE;
21 +
22 +static inline uint64_t system_servicenames_key(uint16_t port, uint16_t ipproto) {
23 + return ((uint64_t)ipproto << 16) | (uint64_t)port;
24 +}
25 +
26 +static inline const char *system_servicenames_ipproto2str(uint16_t ipproto) {
27 + return (ipproto == IPPROTO_TCP) ? "tcp" : "udp";
28 +}
29 +
30 +static inline const char *static_portnames(uint16_t port, uint16_t ipproto) {
31 + if(port == 19999 && ipproto == IPPROTO_TCP)
32 + return "netdata";
33 +
34 + if(port == 8125)
35 + return "statsd";
36 +
37 + return NULL;
38 +}
39 +
40 +static inline STRING *system_servicenames_cache_lookup(SERVICENAMES_CACHE *sc, uint16_t port, uint16_t ipproto) {
41 + uint64_t key = system_servicenames_key(port, ipproto);
42 + spinlock_lock(&sc->spinlock);
43 +
44 + SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_get_slot_SERVICENAMES_CACHE(&sc->ht, key, &key, true);
45 + STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
46 + if (!s) {
47 + const char *st = static_portnames(port, ipproto);
48 + if(st) {
49 + s = string_strdupz(st);
50 + }
51 + else {
52 + struct servent *se = getservbyport(htons(port), system_servicenames_ipproto2str(ipproto));
53 +
54 + if (!se || !se->s_name) {
55 + char name[50];
56 + snprintfz(name, sizeof(name), "%u/%s", port, system_servicenames_ipproto2str(ipproto));
57 + s = string_strdupz(name);
58 + }
59 + else
60 + s = string_strdupz(se->s_name);
61 + }
62 +
63 + simple_hashtable_set_slot_SERVICENAMES_CACHE(&sc->ht, sl, key, s);
64 + }
65 +
66 + s = string_dup(s);
67 + spinlock_unlock(&sc->spinlock);
68 + return s;
69 +}
70 +
71 +static inline SERVICENAMES_CACHE *system_servicenames_cache_init(void) {
72 + SERVICENAMES_CACHE *sc = callocz(1, sizeof(*sc));
73 + spinlock_init(&sc->spinlock);
74 + simple_hashtable_init_SERVICENAMES_CACHE(&sc->ht, 100);
75 + return sc;
76 +}
77 +
78 +static inline void system_servicenames_cache_destroy(SERVICENAMES_CACHE *sc) {
79 + spinlock_lock(&sc->spinlock);
80 +
81 + for (SIMPLE_HASHTABLE_SLOT_SERVICENAMES_CACHE *sl = simple_hashtable_first_read_only_SERVICENAMES_CACHE(&sc->ht);
82 + sl;
83 + sl = simple_hashtable_next_read_only_SERVICENAMES_CACHE(&sc->ht, sl)) {
84 + STRING *s = SIMPLE_HASHTABLE_SLOT_DATA(sl);
85 + string_freez(s);
86 + }
87 +
88 + simple_hashtable_destroy_SERVICENAMES_CACHE(&sc->ht);
89 + freez(sc);
90 +}
91 +
92 +#endif //NETDATA_SYSTEM_SERVICES_H