Fix sockless TCP keepalive and require complete UTUN initialization

Receive keepalive through the owning ETCP link, preserve RX deadlines, and report routing metrics without TUN. Use independent netlink requests and track installed routes for rollback. Reject incomplete resource initialization and release partially constructed cores while preserving caller config ownership.

Validated startup failure and rollback, padded keepalive, standby, STCP traffic, transport lifecycle, dynamic sockets, and daemon startup. Real TUN/netlink checks passed in an isolated Linux network namespace; modified modules passed FreeBSD compilation checks.
This commit is contained in:
evgeny committed 2026-10-12 14:24:32 +02:00
1 parent bb256dccdc
commit 72e2c89e3b
19 files changed
+541 -375

No files matched your search

+19 -29
View File
@@ -1169,7 +1169,8 @@ static void send_metrics(struct control_server* server, struct control_client* c
rsp->etcp.busy_memory_blocks = (uint32_t)(u_get_allocated_count() - memory_pool_get_total_free_blocks());
/* Fill TUN metrics */
/* TUN отсутствует в режиме прокси; маршруты и BGP работают независимо. */
memset(&rsp->tun, 0, sizeof(rsp->tun));
if (instance->tun) {
rsp->tun.bytes_read = instance->tun->bytes_read;
rsp->tun.bytes_written = instance->tun->bytes_written;
@@ -1178,38 +1179,25 @@ static void send_metrics(struct control_server* server, struct control_client* c
rsp->tun.read_errors = instance->tun->read_errors;
rsp->tun.write_errors = instance->tun->write_errors;
/* Routing statistics */
rsp->tun.routed_packets = instance->routed_packets;
rsp->tun.dropped_packets = instance->dropped_packets;
/* TUN queues */
rsp->tun.tun_in_q_packets = (uint32_t)queue_entry_count(instance->tun->input_queue);
rsp->tun.tun_in_q_bytes = (uint32_t)queue_total_bytes(instance->tun->input_queue);
rsp->tun.tun_out_q_packets = (uint32_t)queue_entry_count(instance->tun->output_queue);
rsp->tun.tun_out_q_bytes = (uint32_t)queue_total_bytes(instance->tun->output_queue);
/* Routing table */
if (instance->rt) {
rsp->tun.rt_count = (uint32_t)instance->rt->count;
rsp->tun.rt_local = (uint32_t)instance->rt->stats.local_routes;
rsp->tun.rt_learned = (uint32_t)instance->rt->stats.learned_routes;
} else {
rsp->tun.rt_count = 0;
rsp->tun.rt_local = 0;
rsp->tun.rt_learned = 0;
}
}
/* BGP routing */
{ struct TOPO_GROUP* g = topo_groups_get_default(instance->topo_groups);
if (g) {
rsp->tun.rt_bgp_senders = (uint32_t)queue_entry_count(g->senders_list);
rsp->tun.rt_bgp_nodes = (uint32_t)queue_entry_count(g->nodes);
} else {
rsp->tun.rt_bgp_senders = 0;
rsp->tun.rt_bgp_nodes = 0;
} }
} else {
memset(&rsp->tun, 0, sizeof(rsp->tun));
/* Статистика маршрутизации не зависит от наличия TUN. */
rsp->tun.routed_packets = instance->routed_packets;
rsp->tun.dropped_packets = instance->dropped_packets;
if (instance->rt) {
rsp->tun.rt_count = (uint32_t)instance->rt->count;
rsp->tun.rt_local = (uint32_t)instance->rt->stats.local_routes;
rsp->tun.rt_learned = (uint32_t)instance->rt->stats.learned_routes;
}
struct TOPO_GROUP* group = topo_groups_get_default(instance->topo_groups);
if (group) {
rsp->tun.rt_bgp_senders = (uint32_t)queue_entry_count(group->senders_list);
rsp->tun.rt_bgp_nodes = (uint32_t)queue_entry_count(group->nodes);
}
/* Fill router congestion metrics — aggregate over all router_conns */
@@ -1300,11 +1288,13 @@ static void send_metrics(struct control_server* server, struct control_client* c
/* Log and send response */
if (server->log_file) {
log_hex_data(server->log_file, "TX", buffer, rsp_size);
fprintf(server->log_file, "%llu: [LOG] Sent RSP_METRICS rtt=%u bytes=%llu links=%d\n",
fprintf(server->log_file, "%llu: [LOG] Sent RSP_METRICS rtt=%u bytes=%llu links=%d tun=%d "
"routes=%u local=%u learned=%u bgp_senders=%u bgp_nodes=%u\n",
(unsigned long long)get_timestamp_ms(),
rsp->etcp.rtt_last,
(unsigned long long)rsp->etcp.bytes_sent_total,
links_count);
links_count, instance->tun != NULL, rsp->tun.rt_count, rsp->tun.rt_local, rsp->tun.rt_learned,
rsp->tun.rt_bgp_senders, rsp->tun.rt_bgp_nodes);
fflush(server->log_file);
}