Saturate BBR byte windows instead of wrapping at large BDP

This commit is contained in:
evgeny committed 2026-10-23 00:24:35 +02:00
1 parent 3d6f855d34
commit 716db3a820
2 files changed
+23 -5

No files matched your search

+7 -5
View File
@@ -414,7 +414,8 @@ static void bbr_probe_inflight_hi_upward(struct bbr* bbr, const struct bbr_rate_
bbr->bw_probe_up_cnt > 0) {
delta = bbr->bw_probe_up_acks / bbr->bw_probe_up_cnt;
bbr->bw_probe_up_acks -= delta * bbr->bw_probe_up_cnt;
bbr->inflight_hi += delta;
uint64_t raised = (uint64_t)bbr->inflight_hi + delta;
bbr->inflight_hi = raised > UINT32_MAX ? UINT32_MAX : (uint32_t)raised;
bbr->try_fast_path = 0;
}
if (bbr->round_start)
@@ -749,19 +750,20 @@ static void bbr_set_cwnd(struct bbr* bbr, const struct bbr_rate_sample* rs,
if (!acked)
goto done;
target_cwnd = bbr_bdp(bbr, bw, gain, mss);
target_cwnd += bbr_ack_aggregation_cwnd(bbr, mss);
uint64_t target = (uint64_t)bbr_bdp(bbr, bw, gain, mss) + bbr_ack_aggregation_cwnd(bbr, mss);
target_cwnd = target > UINT32_MAX ? UINT32_MAX : (uint32_t)target;
target_cwnd = bbr_quantization_budget(bbr, target_cwnd, mss);
uint64_t grown = (uint64_t)local_cwnd + acked;
bbr->try_fast_path = 0;
if (bbr->full_bw_reached) {
local_cwnd += acked;
local_cwnd = grown > UINT32_MAX ? UINT32_MAX : (uint32_t)grown;
if (local_cwnd >= target_cwnd) {
local_cwnd = target_cwnd;
bbr->try_fast_path = 1;
}
} else if (local_cwnd < target_cwnd || local_cwnd < 2 * (uint32_t)bbr->init_cwnd * mss) {
local_cwnd += acked;
local_cwnd = grown > UINT32_MAX ? UINT32_MAX : (uint32_t)grown;
} else {
bbr->try_fast_path = 1;
}
+16
View File
@@ -127,6 +127,21 @@ static int test_large_ack_aggregation(void) {
PASS(); return 0;
}
/* Большой BDP и прибавление ACK не должны оборачивать окно до нескольких пакетов. */
static int test_cwnd_saturation(void) {
MSEG("large BDP and acknowledged bytes saturate cwnd");
struct bbr s = { .now_tb = 10000 }; bbr_init(&s);
s.mode = BBR_PROBE_BW; s.full_bw_reached = 1; s.cycle_idx = BBR_BW_PROBE_CRUISE;
s.cycle_mstamp_tb = s.now_tb; s.probe_wait_us = 2000000;
uint32_t cwnd = UINT32_MAX - 500, pacing = 0;
struct bbr_rate_sample rs = { .delivered = 10000, .interval_us = 1, .rtt_us = 1000000,
.acked_sacked = 1000, .tx_in_flight = UINT32_MAX - 500 };
bbr_main(&s, &rs, &cwnd, &pacing, 1400, UINT32_MAX - 500, 0);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "BBR saturated window: cwnd=%u expected=%u", cwnd, UINT32_MAX);
if (cwnd != UINT32_MAX) FAIL("BDP plus ACK and cwnd plus ACK must saturate, not wrap");
PASS(); return 0;
}
static int test_init(void)
{
MSEG("bbr_init — startup mode");
@@ -246,6 +261,7 @@ int main(void)
test_probe_growth_bytes();
test_probe_packet_budget();
test_large_ack_aggregation();
test_cwnd_saturation();
test_init();
test_startup_growth();
test_full_bw();