Bound BBR probe windows by the steady-state queue time budget

This commit is contained in:
evgeny committed 2026-10-23 01:01:25 +02:00
1 parent 4035794631
commit 599d8ad421
3 files changed
+26 -4

No files matched your search

+19
View File
@@ -797,6 +797,22 @@ static void bbr_bound_cwnd_for_inflight_model(struct bbr* bbr, uint32_t* cwnd, u
*cwnd = (uint32_t)(cap < *cwnd ? cap : *cwnd);
}
/* Общий предел окна: ACK aggregation и PROBE_UP используют тот же бюджет, а не добавляются после него. */
static void bbr_bound_cwnd_for_queue_budget(struct bbr* bbr, uint32_t* cwnd, uint32_t mss) {
uint32_t cap = 0, bw = bbr_bw(bbr);
if (bbr->mode == BBR_PROBE_BW && bbr->queue_budget_us && bw && bbr->min_rtt_us != UINT32_MAX) {
uint64_t limit = (uint64_t)bbr_bdp(bbr, bw, BBR_UNIT, mss) + (uint64_t)bw * bbr->queue_budget_us / BW_UNIT;
if (limit < BBR_CWND_MIN_TARGET * mss) limit = BBR_CWND_MIN_TARGET * mss;
cap = limit > UINT32_MAX ? UINT32_MAX : (uint32_t)limit;
}
if (cap != bbr->queue_cwnd_cap) {
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[L%u] queue budget: mode=%u budget_us=%u min_rtt_us=%u DATA_MSS=%u cap=%u previous=%u",
bbr->link_id, bbr->mode, bbr->queue_budget_us, bbr->min_rtt_us, mss, cap, bbr->queue_cwnd_cap);
bbr->queue_cwnd_cap = cap;
}
if (cap && *cwnd > cap) *cwnd = cap;
}
static int bbr_run_fast_path(struct bbr* bbr, int* update_model,
const struct bbr_rate_sample* rs, uint32_t sample_bw,
uint32_t mss, uint32_t inflight_packets,
@@ -828,6 +844,8 @@ void bbr_init(struct bbr* bbr)
bbr->initialized = 1;
bbr->init_cwnd = BBR_CWND_MIN_TARGET;
bbr->prior_cwnd = 0;
bbr->queue_budget_us = BBR_QUEUE_BUDGET_US;
bbr->queue_cwnd_cap = 0;
bbr->delivered = 0;
bbr->next_rtt_delivered = 0;
@@ -927,6 +945,7 @@ void bbr_main(struct bbr* bbr, const struct bbr_rate_sample* rs,
bbr_bound_cwnd_for_inflight_model(bbr, &cwnd, mss);
out:
bbr_bound_cwnd_for_queue_budget(bbr, &cwnd, mss);
bbr_advance_latest_delivery_signals(bbr, rs, sample_bw);
bbr->loss_in_cycle |= (rs->lost > 0);
if (bbr->on_cwnd_update) bbr->on_cwnd_update(bbr->cwnd_update_ctx, cwnd);
+4 -2
View File
@@ -5,8 +5,10 @@
* MSS — максимальный DATA-фрагмент normalizer, без заголовков; не wire-MTU и не размер кадра STCP.
* Минимальное окно — 4*MSS; PROBE_RTT осушает до max(4*MSS, 0.5*BDP), затем ждёт >=200мс и раунд ACK.
* Транспорт применяет окно с верхним ограничением конфига и не повышает его до собственного минимума.
* Целевое окно PROBE_BW включает 2*BDP и ACK-резерв, в PROBE_UP дополнительно 2*MSS;
* фиксированный предел времени физической очереди модель не задаёт. */
* Целевое окно PROBE_BW включает 2*BDP и ACK-резерв, в PROBE_UP дополнительно 2*MSS.
* Общий предел этого окна — max(4*MSS, BW*(min_rtt+queue_budget_us)); init задаёт бюджет 20мс.
* Это цель по оценке полосы, не гарантия физической задержки: STARTUP/DRAIN, минимум окна,
* неизвестная/изменившаяся полоса и очереди вне наблюдаемого пути могут превышать бюджет. */
#pragma once
#include <stdint.h>
+3 -2
View File
@@ -71,11 +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 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", 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], (unsigned long long)ds->max_queue_delay_us);
model->extra_acked[0], model->extra_acked[1], model->queue_budget_us, model->queue_cwnd_cap,
(unsigned long long)ds->max_queue_delay_us);
}
}
}