etcp_router: add congestion counters, fix tx_seq rollback on etcp_send failure, add router metrics to etcpmon GUI
- etcp_router.h: add 9 per-conn counters (pkts_sent/err/rcvd, ack_sent/recv/stale, dup/oob/sign_fail) - etcp_router.c: increment counters at 13 event points; fix tx_seq rollback on etcp_send failure (was causing phantom inflight=256 deadlock); add DEBUG_ERROR on all 5 ignored etcp_send returns; fix router_ack_do_send to update timestamps only on success - etcpmon_protocol.h: add etcpmon_router_metrics (14 aggregated fields) - control_server.c: iterate router_conns to fill aggregated router metrics - etcpmon_gui: new 'Router Congestion' block with queue depths and all counters, Debug Levels shifted down, window 1300->1440 - test_etcp_router_unit: fix test_ack_timer for correct no-BGP-route behavior
This commit is contained in:
1 parent
de8cce521a
commit
7329fa65f1
7 files changed
+229
-23
No files matched your search
@@ -11,6 +11,7 @@
|
||||
#include "tun_if.h"
|
||||
#include "route_lib.h"
|
||||
#include "route_bgp.h"
|
||||
#include "etcp_router.h"
|
||||
#include "route_node.h"
|
||||
#include "pkt_normalizer.h"
|
||||
#include "../tools/etcpmon/etcpmon_protocol.h"
|
||||
@@ -1171,6 +1172,29 @@ static void send_metrics(struct control_server* server, struct control_client* c
|
||||
memset(&rsp->tun, 0, sizeof(rsp->tun));
|
||||
}
|
||||
|
||||
/* Fill router congestion metrics — aggregate over all router_conns */
|
||||
memset(&rsp->router, 0, sizeof(rsp->router));
|
||||
if (instance->router_conns) {
|
||||
struct ll_entry* re;
|
||||
while ((re = queue_data_get(instance->router_conns)) != NULL) {
|
||||
struct ETCP_ROUTER_CONN* rc = (struct ETCP_ROUTER_CONN*)re;
|
||||
rsp->router.total_inflight += (uint32_t)(rc->tx_seq - rc->tx_acked);
|
||||
if (rc->send_q) rsp->router.total_send_q += (uint32_t)queue_entry_count(rc->send_q);
|
||||
if (rc->recv_q) rsp->router.total_recv_q += (uint32_t)queue_entry_count(rc->recv_q);
|
||||
rsp->router.pkts_sent += rc->c_pkts_sent;
|
||||
rsp->router.pkts_send_err += rc->c_pkts_send_err;
|
||||
rsp->router.pkts_rcvd += rc->c_pkts_rcvd;
|
||||
rsp->router.ack_sent += rc->c_ack_sent;
|
||||
rsp->router.ack_recv += rc->c_ack_recv;
|
||||
rsp->router.dup_dropped += rc->c_dup_dropped;
|
||||
rsp->router.oob_dropped += rc->c_oob_dropped;
|
||||
rsp->router.stale_ack += rc->c_stale_ack;
|
||||
rsp->router.sign_fail += rc->c_sign_fail;
|
||||
queue_data_put_with_index(instance->router_conns, re);
|
||||
}
|
||||
rsp->router.total_conns = (uint32_t)queue_entry_count(instance->router_conns);
|
||||
}
|
||||
|
||||
/* Fill link metrics */
|
||||
struct etcpmon_link_metrics* link_info = (struct etcpmon_link_metrics*)(buffer + sizeof(*hdr) + sizeof(*rsp));
|
||||
link = conn->links;
|
||||
|
||||
+65
-13
@@ -58,7 +58,7 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
|
||||
size_t sig_len = is_signed ? SC_SIGN_SIZE : 0;
|
||||
size_t total_len = SVC_ROUTE_HDR_SIZE + pl_len + sig_len;
|
||||
uint8_t* dgram = u_malloc(total_len);
|
||||
if (!dgram) { if (!seq_flags) rconn->tx_seq--; return -1; }
|
||||
if (!dgram) { if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1; }
|
||||
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)dgram;
|
||||
hdr->cmd = ETCP_ID_SVC_ROUTE;
|
||||
hdr->dst_node_id = rconn->remote_node_id;
|
||||
@@ -91,29 +91,29 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
|
||||
if (!conn) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: no route to %016llx svc_id=%u",
|
||||
(unsigned long long)rconn->remote_node_id, rconn->svc_id);
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; return -1;
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
struct sc_stream_sign_state sign_state;
|
||||
if (sc_stream_sign_init(&conn->crypto_ctx, &sign_state) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: sign_init failed svc_id=%u", rconn->svc_id);
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; return -1;
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1;
|
||||
}
|
||||
size_t data_len = SVC_ROUTE_HDR_SIZE + pl_len;
|
||||
if (sc_stream_sign_update(&sign_state, dgram, data_len) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: sign_update failed svc_id=%u", rconn->svc_id);
|
||||
sc_stream_sign_cleanup(&sign_state); u_free(dgram); if (!seq_flags) rconn->tx_seq--; return -1;
|
||||
sc_stream_sign_cleanup(&sign_state); u_free(dgram); if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1;
|
||||
}
|
||||
size_t actual_sig_len = SC_SIGN_SIZE;
|
||||
if (sc_stream_sign_final(&sign_state, dgram + data_len, &actual_sig_len) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: sign_final failed svc_id=%u", rconn->svc_id);
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; return -1;
|
||||
u_free(dgram); if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct ll_entry* entry = queue_entry_new(0);
|
||||
if (!entry) { u_free(dgram); if (!seq_flags) rconn->tx_seq--; return -1; }
|
||||
if (!entry) { u_free(dgram); if (!seq_flags) rconn->tx_seq--; rconn->c_pkts_send_err++; return -1; }
|
||||
entry->dgram = dgram;
|
||||
entry->len = total_len;
|
||||
|
||||
@@ -123,7 +123,16 @@ static int router_send_one_flags(struct ETCP_ROUTER_CONN* rconn, const uint8_t*
|
||||
(int32_t)(rconn->tx_seq - rconn->tx_acked),
|
||||
is_signed,
|
||||
(unsigned long long)rconn->remote_node_id);
|
||||
return etcp_send(conn, entry);
|
||||
int ret = etcp_send(conn, entry);
|
||||
if (ret != 0) {
|
||||
if (!seq_flags) rconn->tx_seq--;
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
rconn->c_pkts_send_err++;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_send_one: etcp_send failed ret=%d svc_id=%u seq=%u", ret, rconn->svc_id, seq);
|
||||
} else {
|
||||
rconn->c_pkts_sent++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Отправка без conn (RST для неизвестного src)
|
||||
@@ -143,7 +152,11 @@ static void router_send_to(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t svc
|
||||
entry->len = SVC_ROUTE_HDR_SIZE;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCPROUTE, "router_send_to: seq_flags=0x%08x → %016llx svc_id=%u",
|
||||
seq_flags, (unsigned long long)dst, svc_id);
|
||||
etcp_send(conn, entry);
|
||||
int ret = etcp_send(conn, entry);
|
||||
if (ret != 0) {
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_send_to: etcp_send failed ret=%d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void router_send_close_to_service(struct ETCP_ROUTER_CONN* rconn) {
|
||||
@@ -199,8 +212,9 @@ static void router_drain_send_q(struct ETCP_ROUTER_CONN* rconn) {
|
||||
if ((int32_t)(rconn->tx_seq - rconn->tx_acked) >= ROUTER_MAX_INFLIGHT) break;
|
||||
struct ll_entry* e = queue_data_get(rconn->send_q);
|
||||
if (!e) { rconn->send_blocked = 0; break; }
|
||||
router_send_one(rconn, e->dgram, e->len);
|
||||
int s_err = router_send_one(rconn, e->dgram, e->len);
|
||||
queue_dgram_free(e); queue_entry_free(e);
|
||||
if (s_err != 0 && (int32_t)(rconn->tx_seq - rconn->tx_acked) >= ROUTER_MAX_INFLIGHT) break;
|
||||
}
|
||||
if (rconn->send_blocked && !rconn->send_resume_timer)
|
||||
rconn->send_resume_timer = uasync_set_timeout(rconn->inst->ua,
|
||||
@@ -245,8 +259,6 @@ static int router_enqueue_send(struct ETCP_ROUTER_CONN* rconn, const uint8_t* pa
|
||||
|
||||
static void router_ack_do_send(struct ETCP_ROUTER_CONN* rconn) {
|
||||
router_send_ack(rconn);
|
||||
rconn->last_sent_ack_seq = rconn->rx_seq;
|
||||
rconn->last_ack_sent_tb = get_time_tb();
|
||||
}
|
||||
|
||||
static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) {
|
||||
@@ -255,6 +267,7 @@ static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) {
|
||||
if (!conn) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router_ack: no route to %016llx svc_id=%u",
|
||||
(unsigned long long)rconn->remote_node_id, rconn->svc_id);
|
||||
rconn->last_ack_sent_tb = get_time_tb();
|
||||
return;
|
||||
}
|
||||
struct SVC_ROUTE_HDR* hdr = (struct SVC_ROUTE_HDR*)u_malloc(SVC_ROUTE_HDR_SIZE);
|
||||
@@ -273,7 +286,15 @@ static void router_send_ack(struct ETCP_ROUTER_CONN* rconn) {
|
||||
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCPROUTE, "ACK_SEND: svc_id=%u rx_seq=%u → %016llx",
|
||||
rconn->svc_id, rconn->rx_seq, (unsigned long long)rconn->remote_node_id);
|
||||
etcp_send(conn, entry);
|
||||
int ret = etcp_send(conn, entry);
|
||||
if (ret != 0) {
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_ack: etcp_send failed ret=%d svc_id=%u rx_seq=%u", ret, rconn->svc_id, rconn->rx_seq);
|
||||
return;
|
||||
}
|
||||
rconn->c_ack_sent++;
|
||||
rconn->last_sent_ack_seq = rconn->rx_seq;
|
||||
rconn->last_ack_sent_tb = get_time_tb();
|
||||
}
|
||||
|
||||
static void router_schedule_ack(struct ETCP_ROUTER_CONN* rconn) {
|
||||
@@ -338,6 +359,7 @@ static void router_deliver(struct ETCP_ROUTER_CONN* rconn, struct ETCP_CONN* con
|
||||
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCPROUTE, "router_deliver: svc_id=%u len=%zu from remote=%016llx",
|
||||
rconn->svc_id, payload_len, (unsigned long long)rconn->remote_node_id);
|
||||
rconn->c_pkts_rcvd++;
|
||||
cb(conn, svc_entry);
|
||||
}
|
||||
|
||||
@@ -415,6 +437,10 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
}
|
||||
if (sc_stream_sign_verify(&vfy_state, sig, SC_SIGN_SIZE) != SC_OK) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: signature verification FAILED for node %016llx svc_id=%u — dropping", (unsigned long long)hdr->src_node_id, hdr->svc_id);
|
||||
{
|
||||
struct ETCP_ROUTER_CONN* sr = router_conn_find(inst, hdr->src_node_id, hdr->svc_id);
|
||||
if (sr) sr->c_sign_fail++;
|
||||
}
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
@@ -440,9 +466,11 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
rconn->svc_id, hdr->seq, (int32_t)(rconn->tx_seq - rconn->tx_acked),
|
||||
queue_entry_count(rconn->send_q),
|
||||
(unsigned long long)hdr->src_node_id);
|
||||
rconn->c_ack_recv++;
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: stale ACK seq=%u tx_acked=%u from %016llx, ignoring",
|
||||
hdr->seq, rconn->tx_acked, (unsigned long long)hdr->src_node_id);
|
||||
rconn->c_stale_ack++;
|
||||
}
|
||||
rconn->last_dgram_ts = get_current_timestamp();
|
||||
if (rconn->send_blocked) router_drain_send_q(rconn);
|
||||
@@ -492,6 +520,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
if (d > ROUTER_MAX_INFLIGHT || d < -ROUTER_MAX_INFLIGHT) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router: seq=%u out of bounds, rx_seq=%u (d=%d), dropping",
|
||||
seq, rconn->rx_seq, d);
|
||||
rconn->c_oob_dropped++;
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
@@ -501,6 +530,7 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
if (((int32_t)(rconn->rx_seq - seq) > 0) ||
|
||||
queue_find_data_by_index(rconn->recv_q, &seq)) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCPROUTE, "router: dup seq=%u rx_seq=%u, dropping", seq, rconn->rx_seq);
|
||||
rconn->c_dup_dropped++;
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
return;
|
||||
}
|
||||
@@ -535,7 +565,11 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
|
||||
}
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: forwarding svc_id=%u → %016llx via %s",
|
||||
hdr->svc_id, (unsigned long long)hdr->dst_node_id, next->log_name);
|
||||
etcp_send(next, entry);
|
||||
int fwd_err = etcp_send(next, entry);
|
||||
if (fwd_err != 0) {
|
||||
queue_dgram_free(entry); queue_entry_free(entry);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "etcp_router: transit etcp_send failed ret=%d", fwd_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,6 +754,15 @@ void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t remote_node_i
|
||||
rconn->peer_sess_id = 0;
|
||||
rconn->start_sent = 0;
|
||||
rconn->send_blocked = 0;
|
||||
rconn->c_pkts_sent = 0;
|
||||
rconn->c_pkts_send_err = 0;
|
||||
rconn->c_pkts_rcvd = 0;
|
||||
rconn->c_ack_sent = 0;
|
||||
rconn->c_ack_recv = 0;
|
||||
rconn->c_dup_dropped = 0;
|
||||
rconn->c_oob_dropped = 0;
|
||||
rconn->c_stale_ack = 0;
|
||||
rconn->c_sign_fail = 0;
|
||||
}
|
||||
|
||||
void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t node_id, uint8_t svc_id,
|
||||
@@ -768,6 +811,15 @@ struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst,
|
||||
rconn->sess_id = 0;
|
||||
rconn->peer_sess_id = 0;
|
||||
rconn->start_sent = 0;
|
||||
rconn->c_pkts_sent = 0;
|
||||
rconn->c_pkts_send_err = 0;
|
||||
rconn->c_pkts_rcvd = 0;
|
||||
rconn->c_ack_sent = 0;
|
||||
rconn->c_ack_recv = 0;
|
||||
rconn->c_dup_dropped = 0;
|
||||
rconn->c_oob_dropped = 0;
|
||||
rconn->c_stale_ack = 0;
|
||||
rconn->c_sign_fail = 0;
|
||||
rconn->recv_q = queue_new(inst->ua, ROUTER_RECVQ_HASH_SIZE, 0, 4, "router_recv_q");
|
||||
if (!rconn->recv_q) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router_conn_get: queue_new(recv_q) failed"); queue_entry_free(&rconn->ll); return NULL; }
|
||||
rconn->send_q = queue_new(inst->ua, 0, 0, 0, "router_send_q");
|
||||
|
||||
@@ -56,6 +56,16 @@ struct ETCP_ROUTER_CONN {
|
||||
uint8_t sess_id; // наш session id (0-3)
|
||||
uint8_t peer_sess_id; // последний sess_id от peer'а
|
||||
uint8_t start_sent; // 0 = нужно отправить START в первом data
|
||||
|
||||
uint32_t c_pkts_sent; // успешные отправки данных
|
||||
uint32_t c_pkts_send_err; // ошибки отправки
|
||||
uint32_t c_pkts_rcvd; // получено и доставлено данных
|
||||
uint32_t c_ack_sent; // отправлено ACK
|
||||
uint32_t c_ack_recv; // получено ACK (последовательных)
|
||||
uint32_t c_dup_dropped; // дропнуто дубликатов seq
|
||||
uint32_t c_oob_dropped; // дропнуто out-of-bounds seq
|
||||
uint32_t c_stale_ack; // устаревших ACK
|
||||
uint32_t c_sign_fail; // signature verification failures
|
||||
};
|
||||
|
||||
#define ROUTER_CONN_HASH_SIZE 256
|
||||
|
||||
Reference in new issue
Block a user