Leave BBR startup after a full round of excessive queue delay

This commit is contained in:
evgeny committed 2026-10-23 10:58:38 +02:00
1 parent d57a729b92
commit 227104e224
3 files changed
+22 -2

No files matched your search

+18
View File
@@ -282,6 +282,22 @@ static void bbr_check_full_bw_reached(struct bbr* bbr, const struct bbr_rate_sam
bbr->full_bw_reached |= bbr->full_bw_now;
}
/* Ограничение задержки завершает разгон только после целого раунда с устойчивой очередью. */
static void bbr_check_startup_delay(struct bbr* bbr, const struct bbr_rate_sample* rs) {
if (bbr->mode != BBR_STARTUP) return;
if (bbr->round_start) {
if (!rs->is_app_limited && bbr->queue_budget_us && bbr->min_rtt_us != UINT32_MAX &&
bbr->startup_rtt_min_us != UINT32_MAX &&
(uint64_t)bbr->startup_rtt_min_us > (uint64_t)bbr->min_rtt_us + bbr->queue_budget_us) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[L%u] STARTUP delay exit: round_min_us=%u base_us=%u budget_us=%u BW_q16=%u",
bbr->link_id, bbr->startup_rtt_min_us, bbr->min_rtt_us, bbr->queue_budget_us, bbr_max_bw(bbr));
bbr->full_bw_reached = 1;
}
bbr->startup_rtt_min_us = UINT32_MAX;
}
if (rs->rtt_us && rs->rtt_us < bbr->startup_rtt_min_us) bbr->startup_rtt_min_us = rs->rtt_us;
}
static void bbr_raise_inflight_hi_slope(struct bbr* bbr, uint32_t cwnd, uint32_t mss)
{
uint32_t growth_this_round = 1U << bbr->bw_probe_up_rounds;
@@ -836,6 +852,7 @@ void bbr_init(struct bbr* bbr)
bbr->prior_cwnd = 0;
bbr->queue_budget_us = BBR_QUEUE_BUDGET_US;
bbr->queue_cwnd_cap = 0;
bbr->startup_rtt_min_us = UINT32_MAX;
bbr->delivered = 0;
bbr->next_rtt_delivered = 0;
@@ -926,6 +943,7 @@ void bbr_main(struct bbr* bbr, const struct bbr_rate_sample* rs,
bbr_update_ack_aggregation(bbr, rs, cwnd, mss);
bbr_check_loss_too_high_in_startup(bbr, rs, mss);
bbr_check_full_bw_reached(bbr, rs, sample_bw);
bbr_check_startup_delay(bbr, rs);
bbr_check_drain(bbr, rs, sample_bw, mss, inflight_bytes);
bbr_update_cycle_phase(bbr, rs, sample_bw, mss, inflight_bytes,
is_cwnd_limited, cwnd);
+2
View File
@@ -8,6 +8,7 @@
* Транспорт применяет окно с верхним ограничением конфига и не повышает его до собственного минимума.
* Целевое окно PROBE_BW включает 2*BDP и ACK-резерв, в PROBE_UP дополнительно 2*MSS.
* Общий предел этого окна — max(4*MSS, BW*(min_rtt+queue_budget_us)); init задаёт бюджет 20мс.
* В STARTUP превышение min_rtt+бюджет всеми RTT целого раунда завершает разгон и включает DRAIN.
* Это цель по оценке полосы, не гарантия физической задержки: STARTUP/DRAIN, минимум окна,
* неизвестная/изменившаяся полоса и очереди вне наблюдаемого пути могут превышать бюджет. */
#pragma once
@@ -74,6 +75,7 @@ struct bbr {
uint32_t inflight_latest;
uint32_t queue_budget_us; // целевое время очереди в PROBE_BW, мкс; init задаёт 20мс, 0 отключает ограничение
uint32_t queue_cwnd_cap; // последний предел DATA: max(4*MSS, BW*(min_rtt+budget)); 0 — ограничение не активно
uint32_t startup_rtt_min_us; // минимум достоверных RTT текущего ACK-раунда STARTUP; UINT32_MAX — измерений нет
uint8_t mode;
uint8_t cycle_idx;
uint16_t pacing_gain;
+2 -2
View File
@@ -71,12 +71,12 @@ void __wrap_bbr_main(struct bbr* model, const struct bbr_rate_sample* sample, ui
const struct dummynet_stats* ds = dummynet_get_stats(channels[p], side);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BBR %s mask=%x side=%d path=%u mode=%u cycle=%u sample=%u/%uus rtt=%u "
"min_rtt=%u inflight=%u cwnd=%u pace=%u hi=%u lo=%u app=%d limited=%d DATA_MSS=%u "
"bw_q16=%u/%u bw_lo=%u extra=%u/%u budget_us=%u queue_cap=%u queue_max_us=%llu", case_name, enabled_mask,
"bw_q16=%u/%u bw_lo=%u extra=%u/%u budget_us=%u queue_cap=%u queue_max_us=%llu time_ms=%llu measuring=%u", case_name, enabled_mask,
side, p, model->mode, model->cycle_idx, sample->delivered, sample->interval_us, sample->rtt_us,
model->min_rtt_us, inflight, *cwnd, *pacing, model->inflight_hi, model->inflight_lo,
sample->is_app_limited, limited, mss, model->bw_hi[0], model->bw_hi[1], model->bw_lo,
model->extra_acked[0], model->extra_acked[1], model->queue_budget_us, model->queue_cwnd_cap,
(unsigned long long)ds->max_queue_delay_us);
(unsigned long long)ds->max_queue_delay_us, (unsigned long long)((now-started)/1000), measuring);
}
}
}