Verify RTT hold rounds and document filter timing

This commit is contained in:
evgeny committed 2026-10-24 17:26:59 +02:00
1 parent bb462bad69
commit dbda8a24d7
2 files changed
+27 -16

No files matched your search

+6
View File
@@ -129,6 +129,12 @@ RTT/min_rtt, формула RTO, политика окна и дедлайн ACK
Минимальное окно BBR — четыре DATA-фрагмента normalizer; максимальное — bbr_max_cwnd (по умолчанию 1048576).
8192 — нижняя допустимая граница настройки bbr_max_cwnd; транспорт не повышает до неё текущее окно.
PROBE_RTT осушает flight до max(4*MSS, 0.5*BDP), выдерживает >=200мс и раунд ACK, затем восстанавливает окно.
RTT-фильтры обновляются при обработке ACK. Короткий минимум принимает меньший достоверный RTT
либо текущее измерение после истечения 5с; RTT=0 означает отсутствие измерения.
Долгий min_rtt принимает короткий минимум, если он не больше прежнего, либо истекли его 10с.
Вместе со значением копируется метка короткого фильтра: повторное использование кеша не задаёт текущее время.
Завершение PROBE_RTT возобновляет короткое окно. Окна истекают строго после своей границы;
hold завершается при достижении срока и завершённом ACK-раунде. Метки RTT и срок hold — полные uint64 TB (100мкс).
MSS — размер DATA-фрагмента normalizer без заголовков; начальное окно UDP и STCP равно 4*MSS с верхним лимитом конфига.
В PROBE_BW действует дополнительный целевой бюджет очереди 20мс: всё окно, включая резервы ACK и PROBE_UP,
ограничивается max(4*MSS, BDP + BW*20мс) по min_rtt. STARTUP/DRAIN не ограничивают окно этой формулой,
+21 -16
View File
@@ -373,22 +373,27 @@ static int test_probe_rtt_lifecycle(void) {
/* Нулевой младший uint32 срока не означает отсутствие hold; ждать надо полные 200мс. */
static int test_probe_rtt_deadline_wrap(void) {
MSEG("PROBE_RTT hold at a zero low-32-bit deadline");
struct bbr s = {.now_tb=(UINT64_C(1)<<32)-2000}; bbr_init(&s);
s.mode = BBR_PROBE_RTT; s.full_bw_reached = 1;
uint32_t cwnd = 10000, pacing = 0;
struct bbr_rate_sample rs = {.delivered=1000,.interval_us=100000,.rtt_us=20000,
.acked_sacked=1000,.tx_in_flight=1000,.is_app_limited=1};
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PROBE_RTT zero deadline: now_tb=%llu deadline_tb=%llu expected_tb=%llu",
(unsigned long long)s.now_tb,(unsigned long long)s.probe_rtt_done_stamp_tb,
(unsigned long long)(UINT64_C(1)<<32));
if (!s.probe_rtt_done_stamp_tb) FAIL("zero low bits erased the active PROBE_RTT deadline");
s.now_tb += 1999; rs.prior_delivered = s.delivered;
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
if (s.mode != BBR_PROBE_RTT || !s.probe_rtt_round_done) FAIL("probe must hold for 200ms even with a complete round");
s.now_tb++; rs.prior_delivered = s.delivered;
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
if (s.mode != BBR_PROBE_BW) FAIL("probe did not finish at the 200ms deadline across TB wrap");
for (unsigned early_round = 0; early_round < 2; early_round++) {
struct bbr s = {.now_tb=(UINT64_C(1)<<32)-2000}; bbr_init(&s);
s.mode = BBR_PROBE_RTT; s.full_bw_reached = 1;
uint32_t cwnd = 10000, pacing = 0;
struct bbr_rate_sample rs = {.delivered=1000,.interval_us=100000,.rtt_us=20000,
.acked_sacked=1000,.tx_in_flight=1000,.is_app_limited=1};
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PROBE_RTT zero deadline: now_tb=%llu deadline_tb=%llu expected_tb=%llu early_round=%u",
(unsigned long long)s.now_tb,(unsigned long long)s.probe_rtt_done_stamp_tb,
(unsigned long long)(UINT64_C(1)<<32),early_round);
if (!s.probe_rtt_done_stamp_tb) FAIL("zero low bits erased the active PROBE_RTT deadline");
s.now_tb += 1999; rs.prior_delivered = early_round ? s.delivered : 0;
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
if (s.mode != BBR_PROBE_RTT || s.probe_rtt_round_done != early_round) FAIL("probe must wait for both 200ms and a complete round");
s.now_tb++;
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
if (s.mode != (early_round ? BBR_PROBE_BW : BBR_PROBE_RTT)) FAIL("probe deadline ignored the ACK-round requirement");
s.now_tb++; rs.prior_delivered = s.delivered;
bbr_main(&s,&rs,&cwnd,&pacing,1400,1000,0);
if (s.mode != BBR_PROBE_BW) FAIL("probe did not finish with both hold and ACK round complete");
}
PASS(); return 0;
}