Browse Source

chatgui: fix RTT display 10x overstatement (DB stores 0.1ms, displayed as ms); remove unused rtt_avg_100

topo_upd
Evgeny 2 months ago
parent
commit
11ab897fe5
  1. 1
      src/control_server.c
  2. 3
      src/transport_layer/etcp.c
  3. 1
      src/transport_layer/etcp.h
  4. 4
      src/transport_layer/etcp_dump.c
  5. 79
      task.txt
  6. 2
      tools/chatgui/src/accountlist.cpp
  7. 2
      tools/chatgui/src/memberlistmodel.cpp
  8. 2
      tools/chatgui/src/nodespage.cpp
  9. 2
      tools/chatgui/transport/chat_status.c
  10. 8
      tools/chatgui/transport/chat_sync.c
  11. 3
      tools/etcpmon/etcpmon_gui.c
  12. 1
      tools/etcpmon/etcpmon_protocol.h

1
src/control_server.c

@ -1064,7 +1064,6 @@ static void send_metrics(struct control_server* server, struct control_client* c
rsp->etcp.peer_node_id = conn->peer_node_id; rsp->etcp.peer_node_id = conn->peer_node_id;
rsp->etcp.rtt_last = conn->rtt_last; rsp->etcp.rtt_last = conn->rtt_last;
rsp->etcp.rtt_avg_10 = conn->rtt_avg_10; rsp->etcp.rtt_avg_10 = conn->rtt_avg_10;
rsp->etcp.rtt_avg_100 = conn->rtt_avg_100;
rsp->etcp.jitter = conn->jitter; rsp->etcp.jitter = conn->jitter;
rsp->etcp.bytes_sent_total = conn->bytes_sent_total; rsp->etcp.bytes_sent_total = conn->bytes_sent_total;
rsp->etcp.retrans_count = conn->retransmissions_count; rsp->etcp.retrans_count = conn->retransmissions_count;

3
src/transport_layer/etcp.c

@ -240,7 +240,6 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
etcp->mtu = ETCP_RFC791_MIN_MTU; // Default MTU per RFC 791 etcp->mtu = ETCP_RFC791_MIN_MTU; // Default MTU per RFC 791
etcp->next_tx_id = 1; etcp->next_tx_id = 1;
etcp->rtt_avg_10 = 10; // Initial guess (1ms) etcp->rtt_avg_10 = 10; // Initial guess (1ms)
etcp->rtt_avg_100 = 10;
etcp->rtt_history_idx = 0; etcp->rtt_history_idx = 0;
memset(etcp->rtt_history, 0, sizeof(etcp->rtt_history)); memset(etcp->rtt_history, 0, sizeof(etcp->rtt_history));
@ -451,7 +450,6 @@ void etcp_conn_reset(struct ETCP_CONN* etcp) {
etcp->unacked_bytes = 0; etcp->unacked_bytes = 0;
etcp->rtt_last = 0; etcp->rtt_last = 0;
etcp->rtt_avg_10 = 0; etcp->rtt_avg_10 = 0;
etcp->rtt_avg_100 = 0;
etcp->jitter = 0; etcp->jitter = 0;
etcp->last_rtt_cb_time = 0; etcp->last_rtt_cb_time = 0;
etcp->bytes_sent_total = 0; etcp->bytes_sent_total = 0;
@ -856,7 +854,6 @@ void etcp_stats(struct ETCP_CONN* etcp) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTT metrics:", etcp->log_name); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTT metrics:", etcp->log_name);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rtt_last: %u (0.1ms)", etcp->log_name, etcp->rtt_last); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rtt_last: %u (0.1ms)", etcp->log_name, etcp->rtt_last);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rtt_avg_10: %u (0.1ms)", etcp->log_name, etcp->rtt_avg_10); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rtt_avg_10: %u (0.1ms)", etcp->log_name, etcp->rtt_avg_10);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] rtt_avg_100: %u (0.1ms)", etcp->log_name, etcp->rtt_avg_100);
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] jitter: %u (0.1ms)", etcp->log_name, etcp->jitter); DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] jitter: %u (0.1ms)", etcp->log_name, etcp->jitter);
// Counters // Counters

1
src/transport_layer/etcp.h

@ -197,7 +197,6 @@ struct ETCP_CONN {
uint16_t tt_last;// transmission time (время пакета до меня) uint16_t tt_last;// transmission time (время пакета до меня)
// uint16_t rxt_last;// recv relative time (бустро регаирует на изменение задержки rx и медленно на изменение задержки tx) // uint16_t rxt_last;// recv relative time (бустро регаирует на изменение задержки rx и медленно на изменение задержки tx)
uint16_t rtt_avg_10; uint16_t rtt_avg_10;
uint16_t rtt_avg_100;
uint16_t jitter; uint16_t jitter;
uint64_t last_rtt_cb_time; // время последнего вызова ping_update_rtt (0.1ms) uint64_t last_rtt_cb_time; // время последнего вызова ping_update_rtt (0.1ms)
uint32_t bytes_sent_total; uint32_t bytes_sent_total;

4
src/transport_layer/etcp_dump.c

@ -65,8 +65,8 @@ void etcp_dump_conn_state(struct ETCP_CONN* conn) {
conn->next_tx_id, conn->last_rx_id, conn->last_delivered_id, conn->rx_ack_till); conn->next_tx_id, conn->last_rx_id, conn->last_delivered_id, conn->rx_ack_till);
/* --- RTT --- */ /* --- RTT --- */
DUMP_LINE("RTT: last=%u avg10=%u avg100=%u jitter=%u", DUMP_LINE("RTT: last=%u avg10=%u jitter=%u",
conn->rtt_last, conn->rtt_avg_10, conn->rtt_avg_100, conn->jitter); conn->rtt_last, conn->rtt_avg_10, conn->jitter);
/* --- STATS --- */ /* --- STATS --- */
DUMP_LINE("STATS: bytes_sent=%u retrans=%u reinit=%u reset=%u ack_pkts=%u", DUMP_LINE("STATS: bytes_sent=%u retrans=%u reinit=%u reset=%u ack_pkts=%u",

79
task.txt

@ -0,0 +1,79 @@
## Текущая задача: отладка merkle sync в chatgui
### Контекст
Две инстанции chatgui обмениваются мемберами (участниками) каналов через merkle sync.
Одна на Linux (node `41eab6811e3ff67b`), вторая на Windows (node `32a3a1ee5625ceb9`).
### Что уже исправлено (vetka topo_upd)
1. **`conn_mgr.c:276`** — убрано требование `links_up` при поиске существующего коннекта.
Раньше второй `conn_mgr_connect_node` (для второй группы/канала) не находил первый коннект
потому что тот был в handshake (links_up=0) и создавал дублирующий линк → два init-таймера
→ два потока INIT-пакетов → бесконечный цикл реинициализации ETCP.
2. **`etcp_connections.c:insert_link_queue`** — детект коллизии адреса: если адрес уже занят
ДРУГИМ коннектом → жирная ошибка + return -1 (вместо молчаливой замены).
3. **`etcp.c:etcp_conn_set_peer_node_id`** — детект коллизии peer_id: если key уже занят
другим коннектом → жирная ошибка + return (не переиндексировать).
4. **`merkle_sync.c`** — исправлен формат сообщений:
- Отправитель клал type ПЕРЕД ch_len+ns: `[svc][TYPE][ch_len][ns]...`
- Получатель (`_recv_cb`) ожидал `[svc][ch_len][ns][TYPE]...` (как у chat_sync)
- Переставлены байты в `_send_hashes`, `_send_batch`, MSG_REQUEST builder
- Результат: handle_hashes/handle_request/handle_batch начали реально получать сообщения
5. **`merkle_sync.c`** — `_handle_batch` теперь вызывает `_session_done(s, MT_OK)` после
обработки всех терминальных бакетов. До этого сессия никогда не завершалась,
таймер истекал → retry → к тому моменту соединение уже отваливалось.
### Текущее состояние
Merkle sync обменивается сообщениями и завершает сессии (`session SYNCED` в логах).
Но данные мемберов не совпадают: Linux имеет 3 мембера в канале, Windows — 2.
### Найденная проблема (исследуется)
В логах `handle_batch` показывает `len=7` для обоих каналов с обеих сторон.
Это означает что в BATCH-сообщении данные мемберов = всего 2 байта (count=0).
При этом `merkle_tree_hash` показывает НЕнулевой bitmap (00008000) → `update_bucket_hash`
находит мемберов в бакете. Но `get_items` для того же бакета возвращает 0 записей.
**Гипотеза:** `update_bucket_hash` и `get_items` используют разную логику фильтрации
для одного и того же level/prefix → SQL запрос в `get_items` не находит мемберов.
Файлы: `tools/chatgui/transport/member_sync.c` функции `_member_update_bucket_hash` и `_member_get_items`.
### Данные из БД (Linux)
Канал 17611191138590969914: 3 мембера
- 4749809422690154107 (0x41eab6811e3ff67b — Linux self)
- 3648938168119840441 (0x32a3a1ee5625ceb9 — Windows peer)
- 5749221071098079620 (0x4fc9561a7dfde984 — третий узел)
Канал 10175004475814804132: 2 мембера
- 3648938168119840441 (0x32a3a1ee5625ceb9)
- 4749809422690154107 (0x41eab6811e3ff67b)
Merkle tree для канала 176111...:
```
level=1 prefix=0x4000000000000000 member_count=1 hash=F612B771...
level=2 prefix=0x41E0000000000000 member_count=1 hash=F612B771...
level=3 prefix=0x41EA000000000000 member_count=1 hash=F612B771...
level=4 prefix=0x41EAB00000000000 member_count=1 hash=F612B771...
level=5 prefix=0x41EAB68000000000 member_count=1 hash=F612B771...
```
### Логи
Linux: `/home/vnc1/proj/utun3/tools/chatgui/build/chatgui.log`
Windows: `/home/vnc1/proj/utun3/tools/chatgui/build/chatgui2.log`
Конфиг: `db_sync=debug` включён.
### БД
Linux: `/home/vnc1/proj/utun3/tools/chatgui/build/chat_data/chats.db`
Windows: `C:/ARM/_uTun/utun2/tools/chatgui/build/chat_data/chats.db` (доступа нет)

2
tools/chatgui/src/accountlist.cpp

@ -156,7 +156,7 @@ void AccountList::showMemberDetail(quint64 nodeId) {
.arg(port) .arg(port)
.arg(protoStr(proto)) .arg(protoStr(proto))
.arg(addrTypeStr(addrType)) .arg(addrTypeStr(addrType))
.arg(rtt > 0 ? QString::number(rtt) : "-"); .arg(rtt > 0 ? QString::number(rtt / 10) : "-");
ac++; ac++;
} }
if (ac == 0) text += " addresses: none\n"; if (ac == 0) text += " addresses: none\n";

2
tools/chatgui/src/memberlistmodel.cpp

@ -22,7 +22,7 @@ QVariant MemberListModel::data(const QModelIndex& index, int role) const {
if (role == Qt::DecorationRole) return QVariant::fromValue(QIcon(it->avatar)); if (role == Qt::DecorationRole) return QVariant::fromValue(QIcon(it->avatar));
if (role == Qt::UserRole + 1) { if (role == Qt::UserRole + 1) {
QString sub; QString sub;
if (it->rtt >= 0) sub += QString("rtt=%1ms").arg(it->rtt); if (it->rtt >= 0) sub += QString("rtt=%1ms").arg(it->rtt / 10);
if (it->natType >= 0) { if (it->natType >= 0) {
static const char* nat[] = {"NET","DIR","EIM","STR"}; static const char* nat[] = {"NET","DIR","EIM","STR"};
const char* nt = (it->natType <= 3) ? nat[it->natType] : "?"; const char* nt = (it->natType <= 3) ? nat[it->natType] : "?";

2
tools/chatgui/src/nodespage.cpp

@ -217,7 +217,7 @@ void NodesPage::refreshNodes() {
.arg(port) .arg(port)
.arg(protoStr(proto)) .arg(protoStr(proto))
.arg(addrTypeStr(addrType)) .arg(addrTypeStr(addrType))
.arg(rtt > 0 ? QString::number(rtt) : "-"); .arg(rtt > 0 ? QString::number(rtt / 10) : "-");
} }
ac++; ac++;
} }

2
tools/chatgui/transport/chat_status.c

@ -97,7 +97,7 @@ static void chat_core_collect_status(void) {
struct ETCP_LINK* link = conn->links; struct ETCP_LINK* link = conn->links;
while (link) { while (link) {
char rtt_str[32]; rtt_str[0] = '\0'; char rtt_str[32]; rtt_str[0] = '\0';
if (link->rtt_last > 0) snprintf(rtt_str, sizeof(rtt_str), " / rtt=%ums", link->rtt_last); if (link->rtt_last > 0) snprintf(rtt_str, sizeof(rtt_str), " / rtt=%ums", link->rtt_last / 10);
off += snprintf(buf + off, sizeof(buf) - off, " LINK#%d: %s /NAT=%s%s\n", off += snprintf(buf + off, sizeof(buf) - off, " LINK#%d: %s /NAT=%s%s\n",
link_idx, link_idx,
link->link_status ? "UP" : "DOWN", link->link_status ? "UP" : "DOWN",

8
tools/chatgui/transport/chat_sync.c

@ -427,14 +427,6 @@ static void cs_on_conn_down(struct ETCP_CONN* conn, void* arg) {
cs_on_peer_status_changed(peer, 0); cs_on_peer_status_changed(peer, 0);
uint16_t rtt = conn->rtt_avg_100;
if (rtt > 0 && peer != 0 && g_cs->inst->topo_sqlite_db) {
sqlite3* db = g_cs->inst->topo_sqlite_db;
sqlite3_stmt* st = NULL;
sqlite3_prepare_v2(db, "UPDATE node_addresses SET rtt=? WHERE node_id=?", -1, &st, NULL);
if (st) { sqlite3_bind_int(st, 1, (int)rtt); sqlite3_bind_int64(st, 2, (sqlite3_int64)peer); sqlite3_step(st); sqlite3_finalize(st); }
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: conn_down saved rtt=%u for node %016llx", CS_ID, rtt, (unsigned long long)peer);
}
cs_cancel_proto_timers(g_cs); cs_cancel_proto_timers(g_cs);
if (g_cs->pending_invite_node_id == peer) { if (g_cs->pending_invite_node_id == peer) {
DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: conn down while waiting invite resp peer=%016llx, timers cancelled, state kept for retry on reconnect", DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC, "%s: conn down while waiting invite resp peer=%016llx, timers cancelled, state kept for retry on reconnect",

3
tools/etcpmon/etcpmon_gui.c

@ -873,8 +873,6 @@ static void CreateTooltips(struct etcpmon_app* app)
"etcp.rtt_last / ETCP Connection\r\nRound-trip time of the last packet (RTT), units 0.1 ms"); "etcp.rtt_last / ETCP Connection\r\nRound-trip time of the last packet (RTT), units 0.1 ms");
AddTooltip(app->hToolTip, app->hEditEtcpRttAvg10, AddTooltip(app->hToolTip, app->hEditEtcpRttAvg10,
"etcp.rtt_avg_10 / ETCP Connection\r\nAverage RTT over last 10 packets, units 0.1 ms"); "etcp.rtt_avg_10 / ETCP Connection\r\nAverage RTT over last 10 packets, units 0.1 ms");
AddTooltip(app->hToolTip, app->hEditEtcpRttAvg100,
"etcp.rtt_avg_100 / ETCP Connection\r\nAverage RTT over last 100 packets, units 0.1 ms");
AddTooltip(app->hToolTip, app->hEditEtcpJitter, AddTooltip(app->hToolTip, app->hEditEtcpJitter,
"etcp.jitter / ETCP Connection\r\nRTT spread (max - min), units 0.1 ms"); "etcp.jitter / ETCP Connection\r\nRTT spread (max - min), units 0.1 ms");
AddTooltip(app->hToolTip, app->hEditEtcpBytesSent, AddTooltip(app->hToolTip, app->hEditEtcpBytesSent,
@ -1624,7 +1622,6 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
/* ETCP Metrics — обновляем ТОЛЬКО при изменении */ /* ETCP Metrics — обновляем ТОЛЬКО при изменении */
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_LAST, "%.1f ms", metrics->etcp.rtt_last/10.f); UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_LAST, "%.1f ms", metrics->etcp.rtt_last/10.f);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_AVG10, "%.1f ms", metrics->etcp.rtt_avg_10/10.f); UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_AVG10, "%.1f ms", metrics->etcp.rtt_avg_10/10.f);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_AVG100, "%.1f ms", metrics->etcp.rtt_avg_100/10.f);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_JITTER, "%.1f ms", metrics->etcp.jitter/10.f); UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_JITTER, "%.1f ms", metrics->etcp.jitter/10.f);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_BYTES_SENT, "%llu", (unsigned long long)metrics->etcp.bytes_sent_total); UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_BYTES_SENT, "%llu", (unsigned long long)metrics->etcp.bytes_sent_total);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RETRANS, "%u", metrics->etcp.retrans_count); UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RETRANS, "%u", metrics->etcp.retrans_count);

1
tools/etcpmon/etcpmon_protocol.h

@ -152,7 +152,6 @@ struct etcpmon_etcp_metrics {
uint64_t peer_node_id; /* Connection identifier */ uint64_t peer_node_id; /* Connection identifier */
uint32_t rtt_last; /* Last RTT (0.1ms units) */ uint32_t rtt_last; /* Last RTT (0.1ms units) */
uint32_t rtt_avg_10; /* Average RTT over 10 packets */ uint32_t rtt_avg_10; /* Average RTT over 10 packets */
uint32_t rtt_avg_100; /* Average RTT over 100 packets */
uint32_t jitter; /* Jitter (max-min RTT) */ uint32_t jitter; /* Jitter (max-min RTT) */
uint64_t bytes_sent_total; /* Total bytes sent */ uint64_t bytes_sent_total; /* Total bytes sent */
uint32_t retrans_count; /* Retransmission count */ uint32_t retrans_count; /* Retransmission count */

Loading…
Cancel
Save