@cryptotaxi247 / netdata-1 / commits / e065eda50

network-viewer: stabilize topology around self listeners (#22253)

network-viewer: fix self/listener topology projection

Costa Tsaousis committed Apr 23, 2026 at 07:57 UTC e065eda50bfe2e545e8ade975f5f8de808c89ae2
1 file changed +29 -3
src/collectors/network-viewer.plugin/network-viewer.c
+29 -3
@@ -1176,6 +1176,7 @@ static void local_sockets_cb_to_topology(LS_STATE *ls, const LOCAL_SOCKET *n, vo
1176 return;
1177
1178 NV_TOPOLOGY_CONTEXT *ctx = data;
1179 + bool hidden_listen_socket = (n->direction == SOCKET_DIRECTION_LISTEN && !ctx->options.sockets_listening);
1180 ctx->sockets_total++;
1181
1182 char local_ip[INET6_ADDRSTRLEN] = "";
@@ -1225,6 +1226,19 @@ static void local_sockets_cb_to_topology(LS_STATE *ls, const LOCAL_SOCKET *n, vo
1226 local_actor->sockets++;
1227 }
1228
1229 + if(hidden_listen_socket) {
1230 + NV_PROCESS_ACTOR hidden_owner = {
1231 + .pid = n->pid,
1232 + .ppid = n->ppid,
1233 + .uid = n->uid,
1234 + .net_ns_inode = n->net_ns_inode,
1235 + };
1236 + snprintf(hidden_owner.process, sizeof(hidden_owner.process), "%s", process_name);
1237 + topology_register_endpoint_owner(ctx, n->net_ns_inode, n->local.protocol, local_ip, n->local.port, &hidden_owner, true);
1238 + ctx->skipped_sockets++;
1239 + return;
1240 + }
1241 +
1242 char process_key[NV_TOPOLOGY_KEY_MAX];
1243 if(ctx->options.processes_by_pid) {
1244 snprintf(process_key, sizeof(process_key), "pid=%d|uid=%u|ns=%llu",
@@ -1290,7 +1304,8 @@ static void local_sockets_cb_to_topology(LS_STATE *ls, const LOCAL_SOCKET *n, vo
1304 }
1305
1306 bool remote_is_self = topology_ip_belongs_to_self(ctx, remote_ip, remote_address_space);
1293 - bool create_endpoint_actor = (!remote_is_self || n->direction == SOCKET_DIRECTION_LISTEN);
1307 + bool self_owned_listen_socket = (n->direction == SOCKET_DIRECTION_LISTEN && remote_is_self);
1308 + bool create_endpoint_actor = !remote_is_self;
1309 if(create_endpoint_actor) {
1310 char endpoint_actor_key[NV_TOPOLOGY_KEY_MAX];
1311 topology_actor_id_for_remote_endpoint(ctx, remote_ip, remote_address_space, endpoint_actor_key, sizeof(endpoint_actor_key));
@@ -1304,14 +1319,23 @@ static void local_sockets_cb_to_topology(LS_STATE *ls, const LOCAL_SOCKET *n, vo
1319 ra->sockets++;
1320 }
1321
1322 + if(self_owned_listen_socket) {
1323 + ctx->skipped_sockets++;
1324 + return;
1325 + }
1326 +
1327 const struct socket_endpoint *server_endpoint = NULL;
1328 uint16_t endpoint_port = n->remote.port;
1329 switch(n->direction) {
1330 case SOCKET_DIRECTION_LISTEN:
1331 + server_endpoint = &n->local;
1332 + endpoint_port = n->local.port;
1333 + break;
1334 +
1335 case SOCKET_DIRECTION_INBOUND:
1336 case SOCKET_DIRECTION_LOCAL_INBOUND:
1337 server_endpoint = &n->local;
1314 - endpoint_port = n->local.port;
1338 + endpoint_port = n->remote.port;
1339 break;
1340
1341 case SOCKET_DIRECTION_OUTBOUND:
@@ -1499,7 +1523,9 @@ static bool topology_prepare_context(NV_TOPOLOGY_CONTEXT *ctx, usec_t now_ut, co
1523
1524 LS_STATE ls = {
1525 .config = {
1502 - .listening = ctx->options.sockets_listening,
1526 + // Always collect listeners so inbound/outbound socket classification
1527 + // remains stable across topology socket filters.
1528 + .listening = true,
1529 .local = ctx->options.sockets_local,
1530 .inbound = ctx->options.sockets_inbound,
1531 .outbound = ctx->options.sockets_outbound,