From c2f4f048d74ac8315f55485d3ff07c866af2d70b Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 23 Oct 2026 00:05:48 +0200 Subject: [PATCH] Reproduce inflated delivery-rate samples when ACKs arrive together --- tests/test_etcp_windows.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test_etcp_windows.c b/tests/test_etcp_windows.c index 423e3555..908035ee 100644 --- a/tests/test_etcp_windows.c +++ b/tests/test_etcp_windows.c @@ -17,6 +17,7 @@ static struct utun_config cfg; static struct ETCP_CONN* conn; 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 struct bbr_rate_sample last_sample; 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) { @@ -47,6 +48,7 @@ void __real_bbr_main(struct bbr*, const struct bbr_rate_sample*, uint32_t*, uint void __wrap_bbr_main(struct bbr* model, const struct bbr_rate_sample* sample, uint32_t* cwnd, uint32_t* pacing, uint32_t mss, uint32_t inflight, int limited) { bbr_calls++; saw_cwnd_limited |= !!limited; saw_app_limited |= !!sample->is_app_limited; + last_sample = *sample; __real_bbr_main(model, sample, cwnd, pacing, mss, inflight, limited); } @@ -323,6 +325,25 @@ static void ack_without_data_pacing(void) { etcp_conn_wake_sender(conn); wait_sends(2); ack_all(); teardown(); } +/* ACK одной пачки приходят в один tick: скорость определяется доставкой всей группы, а не промежутком между ACK. */ +static void bbr_delivery_clock(void) { + setup(); b->link_status = 0; + a->bbr = u_calloc(1, sizeof(*a->bbr)); CHECK(a->bbr); bbr_init(a->bbr); + fill(a, 8, 1000); + uint64_t sent_tb = get_time_tb(); + test_clock_run_for(ua, 200); + for (unsigned seq = 1; seq <= 8; seq++) { + ack(seq); + uint64_t elapsed_us = (get_time_tb() - sent_tb) * 100; + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "Delivery sample: seq=%u delivered=%u acked=%u interval_us=%u flight_us=%llu", + seq, last_sample.delivered, last_sample.acked_sacked, last_sample.interval_us, (unsigned long long)elapsed_us); + CHECK(last_sample.delivered == seq * 1000 && last_sample.acked_sacked == 1000); + CHECK(last_sample.interval_us >= 19000 && last_sample.interval_us <= elapsed_us + 1000); + } + CHECK(a->bbr->delivered == 8000); + teardown(); +} + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG); @@ -330,7 +351,7 @@ int main(void) { size_t baseline = u_get_allocated_count(); void (*cases[])(void) = {selection, boundaries_ack_burst, late_ack_and_migration, lost_ack_and_shrink, grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness, - config_limits, timer_failure, immediate_send, ack_without_data_pacing}; + config_limits, timer_failure, immediate_send, ack_without_data_pacing, bbr_delivery_clock}; for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { cases[i](); CHECK(u_get_allocated_count() == baseline); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS ETCP window scenario %u", i);