From 5420a07ffcd9fb14a69af96dcc5cfb4fba3f5bde Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 16:51:24 +0200 Subject: [PATCH] Refresh RTO before RTT callbacks can close the link --- src/transport_layer/etcp.c | 4 ++-- tests/Makefile.am | 3 ++- tests/test_etcp_windows.c | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/transport_layer/etcp.c b/src/transport_layer/etcp.c index 0c0f3367..ea0adde5 100644 --- a/src/transport_layer/etcp.c +++ b/src/transport_layer/etcp.c @@ -1466,14 +1466,14 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) { etcp->rtt_avg_10=rtt_max; etcp->tt_last=tt_sum/cnt; etcp->jitter=j_sum/cnt; - if (etcp->rtt_last) { + if (new_rtt != prev_rtt) etcp_tx_update_rto(pkt->link); + if (!etcp->close_requested && etcp->rtt_last) { uint64_t now_tb = get_time_tb(); if (now_tb - etcp->last_rtt_cb_time > RTT_CB_PERIOD_TB) { topo_node_ping_update_rtt(etcp->instance->topo_groups, etcp->peer_node_id, etcp->rtt_last); etcp->last_rtt_cb_time = now_tb; } } - if (new_rtt != prev_rtt) etcp_tx_update_rto(pkt->link); break; } case ETCP_SECTION_PAYLOAD: { diff --git a/tests/Makefile.am b/tests/Makefile.am index e98e11a0..25945d3d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1083,7 +1083,8 @@ test_etcp_windows_LDADD = $(LIBUTUN) $(COMMON_LIBS) test_etcp_windows_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=get_time_tb -Wl,--wrap=get_time_us \ -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=memory_pool_alloc_impl \ -Wl,--wrap=bbr_main -Wl,--wrap=uasync_set_timeout -Wl,--wrap=uasync_call_soon -Wl,--wrap=ll_alloc_lldgram \ - -Wl,--wrap=u_malloc_impl -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl -Wl,--wrap=random_bytes + -Wl,--wrap=u_malloc_impl -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl -Wl,--wrap=random_bytes \ + -Wl,--wrap=topo_node_ping_update_rtt test_etcp_router_tcp_SOURCES = test_etcp_router_tcp.c test_etcp_router_tcp_LDADD = $(LIBUTUN) $(COMMON_LIBS) diff --git a/tests/test_etcp_windows.c b/tests/test_etcp_windows.c index 491cd513..20affc85 100644 --- a/tests/test_etcp_windows.c +++ b/tests/test_etcp_windows.c @@ -21,6 +21,7 @@ static struct ETCP_LINK *a, *b; static unsigned sends, fail_alloc, fail_send, fail_tx_timer, bbr_calls, saw_cwnd_limited, saw_app_limited; static unsigned fail_shaper_timer; static unsigned fail_rto_timer; +static unsigned close_rtt_callback; static unsigned pacer_clock_active, capture_shaper, shaper_arm_count, pacer_ready_count, pacer_ready_action; static uint64_t pacer_now_tb; static int captured_shaper_delay; @@ -49,6 +50,12 @@ uint64_t __wrap_get_time_tb(void) { uint64_t __real_get_time_us(void); uint64_t __wrap_get_time_us(void) { return ack_clock_active ? ack_now_us : __real_get_time_us(); } +void __real_topo_node_ping_update_rtt(struct TOPO_GROUPS*, uint64_t, uint16_t); +void __wrap_topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uint16_t rtt) { + if (close_rtt_callback) { close_rtt_callback = 0; etcp_connection_close(conn); return; } + __real_topo_node_ping_update_rtt(groups,node_id,rtt); +} + void* __real_uasync_call_soon(struct UASYNC*, void*, timeout_callback_t); void* __wrap_uasync_call_soon(struct UASYNC* loop, void* arg, timeout_callback_t callback) { if (fail_normalizer_timer && conn && arg == conn->normalizer) { fail_normalizer_timer--; return NULL; } @@ -159,6 +166,7 @@ static void setup(void) { sends = fail_alloc = fail_send = fail_tx_timer = bbr_calls = saw_cwnd_limited = saw_app_limited = 0; fail_shaper_timer = 0; fail_rto_timer = 0; + close_rtt_callback = 0; pacer_clock_active = capture_shaper = shaper_arm_count = pacer_ready_count = pacer_ready_action = 0; captured_shaper_delay = 0; captured_shaper_callback = NULL; captured_shaper_arg = NULL; fail_rx_data = fail_rx_fragment = fail_ack_entry = 0; @@ -770,9 +778,9 @@ static void rto_path_rtt_growth(void) { teardown(); } -/* Timestamp сокращает срок без новых DATA/ACK; OOM пересчёта безопасно закрывает conn внутри RX. */ +/* Timestamp сокращает срок без DATA/ACK; проверяем OOM и close из уведомления RTT внутри RX. */ static void rto_timestamp_rearm(void) { - for (unsigned oom = 0; oom < 2; oom++) { + for (unsigned mode = 0; mode < 3; mode++) { setup(); b->link_status = 0; a->data_rtt_us = 20000; a->rtt_last = 1000; ack_now_us = get_time_us(); ack_clock_active = 1; fill(a,1,1000); @@ -782,9 +790,9 @@ static void rto_timestamp_rearm(void) { pkt->link = a; pkt->data_len = 5; memset(pkt->data,0,5); pkt->data[0] = ETCP_SECTION_TIMESTAMP; uint16_t ret = get_current_timestamp()-200; pkt->data[1] = ret; pkt->data[2] = ret>>8; - fail_rto_timer = oom; + fail_rto_timer = mode == 1; close_rtt_callback = mode == 2; etcp_conn_input(pkt); - if (oom) CHECK(conn->close_requested && !conn->callbacks_running && !fail_rto_timer); + if (mode) CHECK(conn->close_requested && !conn->callbacks_running && !fail_rto_timer && !close_rtt_callback); else { DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "Timestamp RTO rearm: RTO_us=%u old_deadline=%llu new_deadline=%llu expected=%llu", etcp_tx_rto_us(a),(unsigned long long)old_deadline,(unsigned long long)a->retrans_deadline_us,