From c7a530092db59ffa95df7933aa2de5d9a292f3fd Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 02:54:41 +0200 Subject: [PATCH] Check pacer reset callback against its actual contract --- doc/etcp_protocol.txt | 3 +++ src/transport_layer/etcp_loadbalancer.h | 2 +- tests/test_etcp_windows.c | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/etcp_protocol.txt b/doc/etcp_protocol.txt index 257787f4..526a5e0f 100644 --- a/doc/etcp_protocol.txt +++ b/doc/etcp_protocol.txt @@ -184,6 +184,9 @@ pending/частичный буфер normalizer; ограничение окн Прибавка равна ceil(payload_len * 10000000000 / bbr_pacing_rate), вычисляется целочисленно в uint64. - Накопленный кредит после простоя ограничивается 1 мс. При смене ставки пересчитывается оставшийся долг; таймер снимается и при необходимости назначается заново. При нулевой ставке pacing не ограничивает отправку. +- Положительный долг должен быть строго меньше 1 мс. Таймер ждёт первого допустимого TB: + shaper_load_time_tb - SHAPER_BURST_DELAY_TB + 1; дробь меньше TB не меняет эту строгую границу. + uasync округляет срок вверх до миллисекунды; callback повторно проверяет готовность перед уведомлением. - ACK/control и измерительная burst-серия не списывают DATA-pacing. Окно DATA проверяется и в burst. Конструктор исходящего UDP-линка запускает INIT сразу; TCP использует отдельный STCP connect/handshake. процесс установки соединения (рукопожатие): diff --git a/src/transport_layer/etcp_loadbalancer.h b/src/transport_layer/etcp_loadbalancer.h index a4465fd3..72bb2158 100644 --- a/src/transport_layer/etcp_loadbalancer.h +++ b/src/transport_layer/etcp_loadbalancer.h @@ -3,7 +3,7 @@ * link_ready вызывает link_ready_for_send_fn при готовности физического линка/shaper; * окно пробуждает etcp_conn_wake_sender без изменения UP/DOWN. Все вызовы — uasync-поток соединения. * Pacer допускает положительный долг строго меньше 1мс; неиспользованный кредит также ограничен 1мс. - * Таймер ждёт первого допустимого TB: debt_until_tb - SHAPER_BURST_DELAY_TB + 1, а не полного погашения долга. + * Таймер ждёт первого допустимого TB: shaper_load_time_tb - SHAPER_BURST_DELAY_TB + 1, а не погашения всего долга. * Дробь меньше 1TB не меняет эту строгую границу; callback повторно проверяет готовность перед уведомлением. */ #ifndef ETCP_LOADBALANCER_H #define ETCP_LOADBALANCER_H diff --git a/tests/test_etcp_windows.c b/tests/test_etcp_windows.c index 6f3a3256..8b997939 100644 --- a/tests/test_etcp_windows.c +++ b/tests/test_etcp_windows.c @@ -567,7 +567,9 @@ static void pacing_ready_lifecycle(void) { uint64_t end = get_time_us() + 1000000; while (!pacer_ready_count && get_time_us() < end) test_clock_poll(ua, 10); CHECK(pacer_ready_count == 1); - if (action == 1) CHECK(conn->reinit_pending && conn->session_required && conn->links); + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "Pacer callback result: action=%u state=%u initialized=%u reinit=%u session=%u links=%d", + action, conn->state, conn->initialized, conn->reinit_pending, conn->session_required, conn->links != NULL); + if (action == 1) CHECK(conn->reinit_pending && !conn->initialized && conn->reinit_count == 1 && conn->links); else CHECK(conn->state == 2 && !conn->links); test_clock_run_for(ua, 40); CHECK(pacer_ready_count == 1); etcp_conn_ref_free(conn); teardown();