BBRv1 四项改进:KCC 仓库补丁详解
BBRv1 四项改进:KCC 仓库补丁详解
KCC 拥塞控制仓库提供了一套基于 Google BBRv1 的补丁,打包为独立模块 bbr1。本文档对比 tcp_bbr.c(原版)与 tcp_bbr1.c(补丁后)的差异,逐条说明每个改动的背景、实现、收益与代价。
概览
| 改动点 | 原版行为 | 补丁行为 | 影响场景 |
|---|---|---|---|
| DRAIN 退出条件 | OR 逻辑(1 RTT 或 inflight ≤ BDP) | AND + 超时(1 RTT 且 inflight ≤ BDP,或 4×RTT 超时) | 多流共享瓶颈 |
| PROBE_BW up-phase 提前退出 | 固定条件(满 RTT + 丢包或达目标) | 可配置增加 app-limited 或无数据退出 | 短连接、突发流量 |
| PROBE_RTT 入口 | 所有流同时触发 | 基于 sk->sk_hash 添加抖动偏移 |
大规模并发 |
| LT 带宽采样 | 直接判定 policer | 增加拥塞门控(srtt > min_rtt+5ms 时拒绝) | 避免误判 |
以下逐条展开。
一、DRAIN 退出条件:从 OR 改为 AND
原版代码(tcp_bbr.c)
if (bbr->pacing_gain > BBR_UNIT)
return is_full_length && (rs->losses || inflight >= bbr_inflight(...));
/* pacing_gain < 1.0 */
return is_full_length || inflight <= bbr_inflight(sk, bw, BBR_UNIT);
DRAIN 阶段退出条件为:满 1 个 RTT 或者 inflight 已降至 BDP 以下。
问题
多流共享瓶颈时,单流 inflight 虽已达标,但多流叠加仍使瓶颈队列残留。过早退出 DRAIN 后进入 PROBE_BW 并以 1.25 倍增益发送,导致周期性延迟和丢包。
补丁后代码(tcp_bbr1.c)
{
bool drained = inflight <= bbr_inflight(sk, bw, BBR_UNIT);
return (is_full_length && drained) ||
tcp_stamp_us_delta(tp->delivered_mstamp, bbr->cycle_mstamp) >
bbr->min_rtt_us << 2;
}
改为 必须同时满足满 1 个 RTT 且 inflight ≤ BDP 才正常退出,另加 4 倍 min_rtt 超时兜底。
流程图
收益与代价
- 收益:多流公平性提升,尾部延迟降低,队列长度更稳定。
- 代价:单流、浅缓冲场景收敛稍慢(多出的等待时间通常远小于 200ms)。
二、PROBE_BW up-phase 提前退出选项
原版代码
PROBE_BW up-phase(pacing_gain = 1.25)的退出条件:
if (bbr->pacing_gain > BBR_UNIT)
return is_full_length && (rs->losses || inflight >= target);
必须满 1 个 RTT 且(发生丢包 或 达到目标 inflight)才退出。
问题
当应用层数据不足(app-limited)或发送队列为空时,无法真正填满管道,但仍需等待满 RTT,浪费探测时间。
补丁后代码
新增编译选项 bbr_probe_bw_up_limit(默认 0,即关闭):
(bbr_probe_bw_up_limit && (rs->is_app_limited || !tcp_send_head(sk)))
若开启,则在上述条件中增加一项:允许 app-limited 或无待发数据时提前退出 up-phase。
流程图
收益与代价
- 收益:短连接、突发流量场景减少无效等待,提高探测效率。
- 代价:默认关闭(
bbr_probe_bw_up_limit = 0),因为长连接高吞吐场景下提前退出可能降低探测准确性。由用户按需开启。
三、PROBE_RTT 抖动避让
原版代码
bbr_update_min_rtt() 中判断过滤器是否过期:
filter_expired = after(tcp_jiffies32,
bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ);
所有流同时过期,同时进入 PROBE_RTT(cwnd 降至 4),退出后又同时以 1.25 倍增益发送,造成周期性吞吐量塌陷。
补丁后代码
u32 jitter_jif = 0;
if (bbr->min_rtt_us != ~0U && bbr->min_rtt_us > 0)
jitter_jif = usecs_to_jiffies(
(u32)(sk->sk_hash & 0xFF) * bbr->min_rtt_us >> 6);
filter_expired = after(tcp_jiffies32,
bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ + jitter_jif);
每个流基于 sk->sk_hash 获得不同偏移,打散 PROBE_RTT 启动时间。
流程图
收益与代价
- 收益:彻底消除多流同步震荡,大规模并发下 RTT 和丢包率更平稳。
- 代价:个别流 PROBE_RTT 间隔可能延长至约 10.4 秒,min_rtt 刷新频率略微下降,对整体性能影响极小。
四、LT 带宽采样增加拥塞门控
原版代码
bbr_lt_bw_interval_done() 中,当两个采样区间 bw 一致且 loss 率达标后,直接启用 lt_bw。
问题
路径发生拥塞时,loss 可能由队列溢出而非 policer 导致。此时启用 LT 带宽会错误地限制发送速率。
补丁后代码
在判定为 policed 之前增加瞬时拥塞检查:
u32 srtt_us = tp->srtt_us >> 3;
if (srtt_us > bbr->min_rtt_us + 5000) {
bbr_reset_lt_bw_sampling(sk);
return;
}
若当前 srtt 比 min_rtt 高出 5ms 以上,认为路径存在排队,不启用 LT 带宽估计。
流程图
收益与代价
- 收益:避免因拥塞丢包误判为 policer,减少不必要的限速。
- 代价:5ms 阈值是经验值,某些高延迟路径可能误触发(概率较低)。
补丁集成说明
上述四项改动已完整集成于 KCC 仓库的 tcp_bbr1.c,编译后模块名为 bbr1(而非原版 bbr)。使用时需:
- 替换或额外编译
tcp_bbr1.c为内核模块; - 通过
sysctl net.ipv4.tcp_congestion_control = bbr1启用。
与原版 BBR 不冲突,可并行存在。
小结
| 改动 | 原版问题 | 补丁方案 | 适用场景 |
|---|---|---|---|
| DRAIN 退出 | 队列排空不彻底 | AND + 超时 | 多流共享瓶颈 |
| PROBE_BW up exit | app-limited 无效等待 | 可配置提前退出 | 短连接/突发流量 |
| PROBE_RTT 入口 | 同步震荡 | 哈希抖动 | 大规模并发 |
| LT 采样 | 拥塞误判 policer | 拥塞门控 | 避免限速错误 |
以上为 KCC bbr1 相对于原版 BBRv1 的全部改动。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)