Browse Source

1

nodeinfo-routing-update
jeka 7 months ago
parent
commit
ca1e522a38
  1. 1
      src/control_server.c
  2. 112
      src/etcp.c
  3. 7
      src/etcp_connections.c
  4. 9
      src/etcp_connections.h
  5. 19
      tools/etcpmon/etcpmon_gui.c
  6. 1
      tools/etcpmon/etcpmon_protocol.h

1
src/control_server.c

@ -876,6 +876,7 @@ static void send_metrics(struct control_server* server, struct control_client* c
link_info[i].bandwidth = link->bandwidth;
link_info[i].nat_changes_count = link->nat_changes_count;
link_info[i].rtt_last = link->rtt_last;
link_info[i].rtt_avg10 = link->rtt_avg10;
link_info[i].tt_last = link->tt_last;
link_info[i].init_timer_active = (link->init_timer != NULL) ? 1 : 0;
link_info[i].keepalive_timer_active = (link->keepalive_timer != NULL) ? 1 : 0;

112
src/etcp.c

@ -21,8 +21,8 @@
// Constants from spec (adjusted for completeness)
#define MAX_INFLIGHT_BYTES 65536 // Initial window
#define RETRANS_K1 2.0f // RTT multiplier for retrans timeout
#define RETRANS_K2 1.5f // Jitter multiplier
#define RETRANS_K1 32 // RTT multiplier for retrans timeout
#define RETRANS_K2 32 // Jitter multiplier
#define ACK_DELAY_TB 20 // ACK timer delay (2ms in 0.1ms units)
#define BURST_DELAY_FACTOR 4 // Delay before burst
#define BURST_SIZE 5 // Packets in burst (1 delayed + 4 burst)
@ -555,7 +555,9 @@ static void ack_timeout_check(struct ETCP_CONN* etcp) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
uint64_t now = get_time_tb();
int64_t timeout = 1000;//(uint64_t)(etcp->rtt_avg_10 * RETRANS_K1) + (uint64_t)(etcp->jitter * RETRANS_K2);
int32_t timeout = (etcp->rtt_avg_10 * RETRANS_K1 + etcp->jitter * RETRANS_K2) / 16;
if (timeout<50) timeout=50;
if (timeout>10000) timeout=10000;
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "starting check, now=%llu, timeout=%llu, rtt_avg_10=%u, jitter=%u",
(unsigned long long)now, (unsigned long long)timeout, etcp->rtt_avg_10, etcp->jitter);
@ -898,37 +900,6 @@ void etcp_ack_recv(struct ETCP_CONN* etcp, uint32_t seq, uint16_t ts, uint16_t d
return;
}
// Calculate RTT if timestamps are valid
/* if (ts != (uint16_t)-1 && dts != (uint16_t)-1) {
uint16_t rtt = timestamp_diff(ts, dts);
etcp->rtt_last = rtt;
// Update RTT averages (exponential smoothing)
if (etcp->rtt_avg_10 == 0) {
etcp->rtt_avg_10 = rtt;
etcp->rtt_avg_100 = rtt;
} else {
// RTT average over 10 packets
etcp->rtt_avg_10 = (etcp->rtt_avg_10 * 9 + rtt) / 10;
// RTT average over 100 packets
etcp->rtt_avg_100 = (etcp->rtt_avg_100 * 99 + rtt) / 100;
}
// Update jitter calculation (max - min of last 10 RTT samples)
etcp->rtt_history[etcp->rtt_history_idx] = rtt;
etcp->rtt_history_idx = (etcp->rtt_history_idx + 1) % 10;
uint16_t rtt_min = UINT16_MAX, rtt_max = 0;
for (int i = 0; i < 10; i++) {
if (etcp->rtt_history[i] < rtt_min) rtt_min = etcp->rtt_history[i];
if (etcp->rtt_history[i] > rtt_max) rtt_max = etcp->rtt_history[i];
}
etcp->jitter = rtt_max - rtt_min;
// DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] RTT updated - last=%u, avg_10=%u, avg_100=%u, jitter=%u",
// etcp->log_name, rtt, etcp->rtt_avg_10, etcp->rtt_avg_100, etcp->jitter);
}
*/
// Update connection statistics
etcp->unacked_bytes -= acked_pkt->ll.len;
etcp->bytes_sent_total += acked_pkt->ll.len;
@ -960,10 +931,6 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
uint16_t len = pkt->data_len;
uint16_t ts = pkt->timestamp; // Received timestamp
// Note: Assume packet starts with sections after timestamp (but timestamp is already extracted in connections?).
// Protocol.txt: timestamp is first 2B, then sections.
// But in conn_input, pkt->data is after timestamp? Assume data starts with first section.
while (len >= 1) {
uint8_t type = data[0];
@ -987,32 +954,83 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
case ETCP_SECTION_TIMESTAMP: {
uint16_t cur_ts=get_current_timestamp();
uint16_t ret_ts=data[1] | (data[2]<<8);// cur_ts=ret_ts = RTT
pkt->link->rtt_last=cur_ts-ret_ts;
uint16_t new_rtt=cur_ts-ret_ts;
pkt->link->rtt_last=new_rtt;
uint8_t old_idx = pkt->link->rtt_history_index;
uint16_t old_val = pkt->link->rtt_history[old_idx];
pkt->link->rtt_history[old_idx] = new_rtt;
pkt->link->rtt_history_index = (old_idx + 1) % 10;
if (pkt->link->rtt_history_count < 10) pkt->link->rtt_history_count++;
if (new_rtt >= pkt->link->rtt_max_val) {
pkt->link->rtt_max_val = new_rtt;
pkt->link->rtt_max_idx = old_idx;
} else if (old_val == pkt->link->rtt_max_val) {
pkt->link->rtt_max_idx = 255;
}
uint8_t rtt_cnt = pkt->link->rtt_history_count;
if (rtt_cnt == 1) {
pkt->link->rtt_avg10 = new_rtt;
} else {
uint32_t sum = 0;
if (pkt->link->rtt_max_idx == 255) {
uint16_t max_val = 0;
uint8_t max_pos = 0;
for (uint8_t i = 0; i < rtt_cnt; i++) {
uint16_t v = pkt->link->rtt_history[i];
sum += v;
if (v > max_val) {
max_val = v;
max_pos = i;
}
}
pkt->link->rtt_max_val = max_val;
pkt->link->rtt_max_idx = max_pos;
} else {
for (uint8_t i = 0; i < rtt_cnt; i++) {
sum += pkt->link->rtt_history[i];
}
}
pkt->link->rtt_avg10 = (sum - pkt->link->rtt_max_val) / (rtt_cnt - 1);
}
int recv_dt_tx1=data[3] | (data[4]<<8);// localtime удаленной стороны момента принятия пакета - timestamp этого пакета (на стороне отправителя, т.е. у нас)
int recv_dt_tx=recv_dt_tx1 - pkt->link->rtt_last/2;
int recv_dt_rx=cur_ts - pkt->link->rtt_last/2 - ts;
if (pkt->link->recv_dt_avg_rx==0) pkt->link->recv_dt_avg_rx=recv_dt_rx*256;
if (pkt->link->recv_dt_avg_tx==0) pkt->link->recv_dt_avg_tx=recv_dt_tx*256;
pkt->link->recv_dt_avg_rx +=(recv_dt_rx*256 - pkt->link->recv_dt_avg_rx)/256;
pkt->link->recv_dt_avg_tx +=(recv_dt_tx*256 - pkt->link->recv_dt_avg_tx)/256;
pkt->link->tt_last = recv_dt_tx1;// - pkt->link->recv_dt_avg_tx/256;
pkt->link->rt_last = cur_ts - ts - pkt->link->recv_dt_avg_tx/256;
int recv_dt_rx=cur_ts - pkt->link->rtt_last/2 - 1000 - ts;
int recv_dt_tx=recv_dt_tx1 - pkt->link->rtt_last/2 - 1000;
if (pkt->link->recv_dt_avg_rx==0) pkt->link->recv_dt_avg_rx=recv_dt_rx*65536;
if (pkt->link->recv_dt_avg_tx==0) pkt->link->recv_dt_avg_tx=recv_dt_tx*65536;
pkt->link->recv_dt_avg_rx +=((int32_t)(recv_dt_rx*65536 - pkt->link->recv_dt_avg_rx))/32;
pkt->link->recv_dt_avg_tx +=((int32_t)(recv_dt_tx*65536 - pkt->link->recv_dt_avg_tx))/32;
pkt->link->rt_last = cur_ts - ts - pkt->link->recv_dt_avg_rx/65536;
pkt->link->tt_last = recv_dt_tx1 - pkt->link->recv_dt_avg_tx/65536;
//tts_correction += ((NOW - RTT/2 - TTS) - tts_correction)/16 (инициализируем сразу по 1 пакету)
data+=5; len-=5;
int d_rtt=pkt->link->rtt_avg10 - pkt->link->rtt_last;
if (d_rtt<0) d_rtt=-d_rtt;
pkt->link->jitter +=((int32_t)(d_rtt*65536 - pkt->link->jitter))/32;
struct ETCP_LINK* c=etcp->links;
int rtt_sum=0;
int rtt_a10_max=0;
int tt_sum=0;
int j_sum=0;
int cnt=0;
while (c) {
rtt_sum += c->rtt_last;
if (rtt_a10_max < c->rtt_avg10) rtt_a10_max = c->rtt_avg10;
tt_sum += c->tt_last;
j_sum += c->jitter/32768;
cnt++;
c=c->next;
}
etcp->rtt_last=rtt_sum/cnt;
etcp->rtt_avg_10=rtt_a10_max;
etcp->tt_last=tt_sum/cnt;
etcp->jitter=j_sum/cnt;
break;
}
case ETCP_SECTION_PAYLOAD: {

7
src/etcp_connections.c

@ -566,6 +566,13 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
link->ip_port_hash = sockaddr_hash(remote_addr);
link->last_recv_local_time = get_time_tb(); // Initialize to prevent immediate timeout
// RTT sliding window initialization
link->rtt_history_index = 0;
link->rtt_history_count = 0;
link->rtt_max_val = 0;
link->rtt_max_idx = 0;
// rtt_history[] is already zeroed by calloc
// insert_link(conn, link);
if (insert_link(conn, link) < 0) {
// откатываем то, что успели

9
src/etcp_connections.h

@ -97,7 +97,14 @@ struct ETCP_LINK {
size_t total_encrypted;
size_t total_decrypted;
uint16_t rtt_last; // round trip (время отправки + приёма)
uint16_t rtt_last; // round trip (время отправки + приёма)
uint16_t rtt_history[10]; // Circular buffer for last 10 RTT values
uint8_t rtt_history_count; // Number of valid entries in history (0-10)
uint8_t rtt_history_index; // Current write position in history buffer
uint32_t jitter; // Current jitter [>>16] x0.1 ms
uint16_t rtt_max_val; // Current max RTT in history
uint8_t rtt_max_idx; // Index of max (255 = needs recalc)
uint16_t rtt_avg10; // round trip average (excl. max)
uint32_t recv_dt_avg_tx; // дельта времени для отправленных пакетов (относительное время отправки) x256
uint32_t recv_dt_avg_rx; // дельта времени для принятых пакетов (относительное время отправки) x256

19
tools/etcpmon/etcpmon_gui.c

@ -931,10 +931,10 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
if (!app || !metrics) return;
HWND hMain = app->hWndMain;
/* ETCP Metrics — обновляем ТОЛЬКО при изменении */
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_LAST, "%u us", metrics->etcp.rtt_last * 100);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_AVG10, "%u us", metrics->etcp.rtt_avg_10 * 100);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_RTT_AVG100, "%u us", metrics->etcp.rtt_avg_100 * 100);
UpdateEditIfChanged(hMain, IDC_EDIT_ETCP_JITTER, "%u us", metrics->etcp.jitter * 100);
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_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_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_ACKS, "%u", metrics->etcp.ack_count);
@ -1028,7 +1028,7 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
snprintf(line1, sizeof(line1),
"Link %u: Status=%s, EncErr=%u, DecErr=%u, "
"SndErr=%u, RcvErr=%u, Enc=%llu, Dec=%llu, "
"BW=%u Kbps, NAT=%u, RTT=%u us, TT=%u us",
"BW=%u Kbps, NAT=%u,",
links[i].local_link_id,
links[i].status ? "UP" : "DOWN",
links[i].encrypt_errors,
@ -1038,13 +1038,14 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
(unsigned long long)links[i].total_encrypted,
(unsigned long long)links[i].total_decrypted,
links[i].bandwidth,
links[i].nat_changes_count,
links[i].rtt_last * 100,
links[i].tt_last * 100);
links[i].nat_changes_count);
snprintf(line2, sizeof(line2),
" Timers: Init=%s, KA=%s, Shaper=%s | "
" RTT=%.1f ms, avg10=%.1f ms, TT=%.1f ms Timers: Init=%s, KA=%s, Shaper=%s | "
"KAsent=%u, KArecv=%u",
(float)links[i].rtt_last/10.0f,
(float)links[i].rtt_avg10/10.0f,
(float)links[i].tt_last/10.f,
links[i].init_timer_active ? "ON" : "OFF",
links[i].keepalive_timer_active ? "ON" : "OFF",
links[i].shaper_timer_active ? "ON" : "OFF",

1
tools/etcpmon/etcpmon_protocol.h

@ -180,6 +180,7 @@ struct etcpmon_link_metrics {
uint32_t bandwidth; /* Configured bandwidth (Kbps) */
uint32_t nat_changes_count; /* NAT address changes */
uint32_t rtt_last; /* Last RTT (0.1ms units) */
uint32_t rtt_avg10; /* avg RTT (0.1ms units) */
uint32_t tt_last; /* Last transmit time (0.1ms units) */
/* Timer flags (1 = active, 0 = NULL) */

Loading…
Cancel
Save