Wake ETCP pacer at its first permitted transmit time

This commit is contained in:
evgeny committed 2026-10-24 02:49:25 +02:00
1 parent 42c4195f2e
commit deac10e3f6
2 files changed
+11 -3

No files matched your search

+6 -1
View File
@@ -15,10 +15,11 @@
// Forward declarations
static void shaper_timer_cb(void* arg); // Shaper wait callback
// Ждём первого TB, в котором долг строго меньше разрешённого допуска, а не его полного погашения.
static void shaper_arm(struct ETCP_LINK* link) {
uint64_t now = get_time_tb();
if (link->shaper_timer || !link->bbr_pacing_rate || link->shaper_load_time_tb < now + SHAPER_BURST_DELAY_TB) return;
uint64_t delay = link->shaper_load_time_tb - now + !!link->shaper_sub_nanotime;
uint64_t delay = link->shaper_load_time_tb - now - SHAPER_BURST_DELAY_TB + 1;
if (delay > INT_MAX) delay = INT_MAX;
link->shaper_timer = uasync_set_timeout(link->etcp->instance->ua, (int)delay, link, shaper_timer_cb, "etcp_shaper");
if (!link->shaper_timer) {
@@ -26,6 +27,10 @@ static void shaper_arm(struct ETCP_LINK* link) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] cannot schedule pacing link=%u rate_Bps=%u delay_tb=%llu",
conn->log_name, link->local_link_id, link->bbr_pacing_rate, (unsigned long long)delay);
conn->callbacks_running++; etcp_connection_close(conn); conn->callbacks_running--;
} else {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "[%s] pacing arm link=%u rate_Bps=%u now_tb=%llu debt_until_tb=%llu fraction=%llu delay_tb=%llu",
link->etcp->log_name, link->local_link_id, link->bbr_pacing_rate, (unsigned long long)now,
(unsigned long long)link->shaper_load_time_tb, (unsigned long long)link->shaper_sub_nanotime, (unsigned long long)delay);
}
}
+5 -2
View File
@@ -1,7 +1,10 @@
/* etcp_loadbalancer — выбор доступного линка одного ETCP_CONN с учётом cwnd, inflight и pacing/shaper.
* select_link возвращает заимствованный готовый линк или NULL. send шифрует/отправляет пакет и учитывает shaper,
* link_ready вызывает link_ready_for_send_fn при готовности физического линка/shaper;
* окно пробуждает etcp_conn_wake_sender без изменения UP/DOWN. Все вызовы — uasync-поток соединения. */
* окно пробуждает etcp_conn_wake_sender без изменения UP/DOWN. Все вызовы — uasync-поток соединения.
* Pacer допускает положительный долг строго меньше 1мс; неиспользованный кредит также ограничен 1мс.
* Таймер ждёт первого допустимого TB: debt_until_tb - SHAPER_BURST_DELAY_TB + 1, а не полного погашения долга.
* Дробь меньше 1TB не меняет эту строгую границу; callback повторно проверяет готовность перед уведомлением. */
#ifndef ETCP_LOADBALANCER_H
#define ETCP_LOADBALANCER_H
@@ -15,7 +18,7 @@ extern "C" {
#define TIMEBASE_NS 100000ULL // 0.1ms base
#define SUB_MODULO 1000000ULL // Sub-nanotime modulo
#define DELTA_TIME_NS 10000ULL // Delta for inactivity
#define SHAPER_BURST_DELAY_TB 10ULL // 10 = 1ms burst allowance
#define SHAPER_BURST_DELAY_TB 10ULL // 1мс: строгая граница положительного долга и предел накопленного кредита
/* Применить pacing в B/s, пересчитать оставшийся долг/таймер по новой ставке и разбудить готовый отправитель.
* 0 явно отключает pacing; положительная скорость не округляется до Kbit/s. При OOM таймера закрытие отложено. */