From 373e4b33c73665e924e9ae5638318f889c938210 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Tue, 30 Jun 2026 23:33:45 +0300 Subject: [PATCH] route_node_dump_all: dump all BGP nodes to log via debug INFO Add route_node_dump_all() in route_node.c that walks bgp->nodes list and outputs per-node info: node_id, name, version, pubkeys, IPv4/IPv6 addrs/sockets/subnets, paths with hop list, connectivity state, conn_mgr. Wire 'nodes' action in control_server to call this function. --- src/control_server.c | 3 + src/route_node.c | 152 +++++++++++++++++++++++++++++++++++++++++++ src/route_node.h | 2 + 3 files changed, 157 insertions(+) diff --git a/src/control_server.c b/src/control_server.c index 895ffe27..c5693242 100644 --- a/src/control_server.c +++ b/src/control_server.c @@ -765,6 +765,9 @@ static void handle_client_data(struct control_server* server, struct control_cli if (strncmp(cmd->action, "nat", 3) == 0) { DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nat' received, requesting NAT check for all links"); route_bgp_request_nat_check_all(server->instance->bgp); + } else if (strncmp(cmd->action, "nodes", 5) == 0) { + DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Action 'nodes' received, dumping all BGP nodes"); + route_node_dump_all(server->instance->bgp); } else { DEBUG_WARN(DEBUG_CATEGORY_CONTROL, "Unknown action received: '%s'", cmd->action); } diff --git a/src/route_node.c b/src/route_node.c index b7d23ed0..a0d6b24e 100644 --- a/src/route_node.c +++ b/src/route_node.c @@ -128,6 +128,158 @@ struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id) return e ? (struct NODEINFO_Q*)e : NULL; } +static int is_node_connectivity_active(struct NODE_CONNECTIVITY* c) { + return c->probe_status != PROBE_STATUS_NONE + || c->interface_status != PROBE_RESULT_UNKNOWN + || c->nat_status != PROBE_RESULT_UNKNOWN + || c->real_status != PROBE_RESULT_UNKNOWN + || c->probe_start_time != 0 + || c->ping_req_time != 0; +} + +static const char* probe_status_str(uint8_t s) { + switch (s) { case 0: return "NONE"; case 1: return "IN_PROGRESS"; case 2: return "DONE"; default: return "?"; } +} +static const char* probe_result_str(uint8_t s) { + switch (s) { case 0: return "UNKNOWN"; case 1: return "REACHABLE"; case 2: return "UNREACHABLE"; default: return "?"; } +} +static const char* conn_mgr_type_str(uint8_t t) { + switch (t) { case 1: return "DIRECT"; case 2: return "REVERSE"; case 3: return "INDIRECT"; default: return "NONE"; } +} + +void route_node_dump_all(struct ROUTE_BGP* bgp) { + if (!bgp || !bgp->nodes) return; + + DEBUG_INFO(DEBUG_CATEGORY_BGP, "=== BGP Nodes dump: %d nodes ===", queue_entry_count(bgp->nodes)); + + int idx = 0; + struct ll_entry* e = bgp->nodes->head; + while (e) { + struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e; + struct NODEINFO* ni = &nq->node; + int is_local = (bgp->local_node == nq); + const char* name_s = (ni->node_name_len > 0) ? (const char*)((const uint8_t*)ni + sizeof(struct NODEINFO)) : ""; + + DEBUG_INFO(DEBUG_CATEGORY_BGP, "--- Node #%d: id=%016llx name=\"%.*s\" ver=%u dirty=%u alien=%u%s ---", + idx, (unsigned long long)ni->node_id, ni->node_name_len, name_s, + ni->ver, nq->dirty, nq->alien, is_local ? " [LOCAL]" : ""); + + if (nq->best_socket) DEBUG_INFO(DEBUG_CATEGORY_BGP, " best_socket=%p", (void*)nq->best_socket); + + log_dump(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_BGP, " pubkey ", ni->public_key, SC_PUBKEY_SIZE); + log_dump(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_BGP, " ed25519", ni->ed25519_public_key, SC_PUBKEY_SIZE); + + const struct NODEINFO_IPV4_SOCKET_META* v4sm; + int v4sm_cnt = get_node_v4_sockets_meta(nq, &v4sm); + if (v4sm_cnt > 0) for (int i = 0; i < v4sm_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sock[%d]: id=%u type=%u", i, v4sm[i].id, v4sm[i].type); + } + + const struct NODEINFO_IPV4_ADDR* v4a; + int v4a_cnt = get_node_v4_addrs(nq, &v4a); + if (v4a_cnt > 0) { + const char* atn[] = {"INTERFACE","NAT","REAL"}; + for (int i = 0; i < v4a_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4addr[%d]: %s:%u %s sock=%u", + i, ip_to_str(v4a[i].addr, AF_INET).str, v4a[i].port, + (v4a[i].type<=2)?atn[v4a[i].type]:"?", v4a[i].socket_id); + } + } + + const struct NODEINFO_IPV6_SOCKET_META* v6sm; + int v6sm_cnt = get_node_v6_sockets_meta(nq, &v6sm); + if (v6sm_cnt > 0) for (int i = 0; i < v6sm_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sock[%d]: id=%u type=%u", i, v6sm[i].id, v6sm[i].type); + } + + const struct NODEINFO_IPV6_ADDR* v6a; + int v6a_cnt = get_node_v6_addrs(nq, &v6a); + if (v6a_cnt > 0) { + for (int i = 0; i < v6a_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6addr[%d]: %s:%u type=%u sock=%u", + i, ip_to_str(v6a[i].addr, AF_INET6).str, v6a[i].port, + v6a[i].type, v6a[i].socket_id); + } + } + + const struct NODEINFO_IPV4_SUBNET* sub4; + int sub4_cnt = get_node_routes(nq, &sub4); + if (sub4_cnt > 0) for (int i = 0; i < sub4_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sub[%d]: %s/%d", i, + ip_to_str(sub4[i].addr, AF_INET).str, sub4[i].prefix_length); + } + + const struct NODEINFO_IPV6_SUBNET* sub6; + int sub6_cnt = get_node_v6_routes(nq, &sub6); + if (sub6_cnt > 0) for (int i = 0; i < sub6_cnt; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sub[%d]: %s/%d", i, + ip_to_str(sub6[i].addr, AF_INET6).str, sub6[i].prefix_length); + } + + if (ni->tranzit_nodes > 0) { + const uint8_t* dyn = node_dyn_start(ni); + dyn = skip_name(dyn, ni->node_name_len); + dyn = skip_v4_sockets_meta(dyn, ni->local_v4_sockets); + dyn = skip_v4_addrs(dyn, ni->local_v4_addrs); + dyn = skip_v6_sockets_meta(dyn, ni->local_v6_sockets); + dyn = skip_v6_addrs(dyn, ni->local_v6_addrs); + dyn = skip_v4_subnets(dyn, ni->local_v4_subnets); + const struct NODEINFO_IPV6_SUBNET* sub6_dyn = (const struct NODEINFO_IPV6_SUBNET*)dyn; + dyn += ni->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET); + const struct NODEINFO_TRANZIT_NODE* tr = (const struct NODEINFO_TRANZIT_NODE*)dyn; + for (uint8_t i = 0; i < ni->tranzit_nodes; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " tranzit[%d]: node=%016llx rtt=%u linkq=%u", + i, (unsigned long long)tr[i].node_id, tr[i].rtt, tr[i].link_q); + } + } + + int path_idx = 0; + if (nq->paths) { + struct ll_entry* pe = nq->paths->head; + while (pe) { + struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe; + uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); + char hop_buf[256] = ""; + int hop_pos = 0; + for (uint8_t hi = 0; hi < path->hop_count && hop_pos < (int)sizeof(hop_buf)-20; hi++) { + hop_pos += snprintf(hop_buf + hop_pos, sizeof(hop_buf) - hop_pos, + "%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]); + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, " path[%d]: conn=%s hop_count=%u hops=[%s]", + path_idx, path->conn ? path->conn->log_name : "NULL", + path->hop_count, hop_buf); + path_idx++; + pe = pe->next; + } + } + + struct NODE_CONNECTIVITY* c = &nq->connectivity; + if (is_node_connectivity_active(c)) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu", + probe_status_str(c->probe_status), + probe_result_str(c->interface_status), c->interface_min_rtt, + probe_result_str(c->nat_status), c->nat_min_rtt, + probe_result_str(c->real_status), c->real_min_rtt, + c->pending_count, c->interface_min_rtt, c->nat_min_rtt, c->real_min_rtt, + (unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time); + } + + if (nq->conn_mgr_type != CONN_TYPE_NONE) { + char interm_buf[200] = ""; + int ipos = 0; + for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count && ipos < (int)sizeof(interm_buf)-19; i++) { + ipos += snprintf(interm_buf + ipos, sizeof(interm_buf) - ipos, + "%s%016llx", i ? "," : "", (unsigned long long)nq->conn_mgr_intermediaries[i]); + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, " conn_mgr: type=%s intermediates=[%s]", + conn_mgr_type_str(nq->conn_mgr_type), interm_buf); + } + + e = e->next; + idx++; + } +} + int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp) { if (!instance || !bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_update_my_nodeinfo: invalid args"); diff --git a/src/route_node.h b/src/route_node.h index 4159d96a..eebb5185 100644 --- a/src/route_node.h +++ b/src/route_node.h @@ -187,4 +187,6 @@ int get_node_v6_addrs(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_ADDR * struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id); +void route_node_dump_all(struct ROUTE_BGP* bgp); + #endif // ROUTE_NODE_H