当前位置: 首页 > news >正文

从 BBRv2 到 BBRv3

BBRv3 已经有段时间了,今天正好碰到一个 BBRv2 限制住总吞吐的问题,正好因为 cwnd_gain 所导致,徒手增大了它又带来了丢包,进一步降低了 inflight_lo,进而又限制住了 cwnd,导致无足够的数据包撑起好不容易 probe 到的 maxbw,吞吐逐渐下滑…这是个典型的循环依赖,BBRv3 解决了这个问题(相当于 bug),这就有必要写个总结备忘。

BBR 提出一个与以往不同的全新拥塞控制方法,它改变了人们对拥塞的定义和看法,但 BBR 远不仅仅是一个 rate-based cca。

BBR 的假设过于理想和朴素,现实部署不得不考虑相互作用,收敛和公平性等问题,于是 BBRv2 引入了对 Loss signal 的响应来限制 inflight 总量,详见我在 2022 年底写的一篇总结 从 BBR 到 BBRv2。

BBRv1 的问题出在 max-bw filter,如果每条 flow 都坚持 10-round 的 maxbw,意味着经过同一瓶颈的所有 flow 对 bw 都是高估的,幸亏有 cwnd secondary control 缓解了症状,即便如此,持续的冲突和丢包带来高重传率在全局意义上反而降低了带宽利用率,事与愿违。

不管承认不承认,BBRv2 已经弱化了 pacing control,最终还是拥抱(无论用不用这个词)了 AIMD,见以下函数:

/* Estimate a short-term lower bound on the capacity available now, based* on measurements of the current delivery process and recent history. When we* are seeing loss/ECN at times when we are not probing bw, then conservatively* move toward flow balance by multiplicatively cutting our short-term* estimated safe rate and volume of data (bw_lo and inflight_lo). We use a* multiplicative decrease in order to converge to a lower capacity in time* logarithmic in the magnitude of the decrease.** However, we do not cut our short-term estimates lower than the current rate* and volume of delivered data from this round trip, since from the current* delivery process we can estimate the measured capacity available now.** Anything faster than that approach would knowingly risk high loss, which can* cause low bw for Reno/CUBIC and high loss recovery latency for* request/response flows using any congestion control.*/
static void bbr2_adapt_lower_bounds(struct sock *sk)

整个逻辑是,BBR 使用 max-bw filter 高估了 bw,而 minrtt 的使用又低估了 rtt,BDP 可认为正负相抵,接下来,cwnd_gain 因子补充了 delayed ack 等协议本身带来的 inflight 损失。BBRv1 到此为止不再继续对 flow 发送做约束,但 rtt 的低估远不如 bw 的高估对 buffer 和丢包的影响更大。

这很容易理解,因为 rtt = minrtt(RTprop) + wait,BBR 的 BDP 本就没有把排队 packet 算在内,所以 bw 的高估空带来了丢包,这问题在 BBRv2 中被修正。

BBRv2 在 BBRv1 停止的地方更进一步,引入 inflight_lo,inflight_hi 约束 inflight,为了弥补 cwnd_gain 对 cwnd 控制的模糊性,让 AIMD-based inflight_lo 作为更加精细的 cwnd secondary control:

loss:if (inflight_lo == 0xffffffff)inflight_lo = cwnd;inflight_lo = (1 - alpha) * inflight_locwnd = cwnd_gain * maxbw * minrtt;
cwnd = min(cwnd, inflight_lo);

这就是个 AIMD,只是把 AI/SS 过程交给了 BBR-style Probe(事实上是个 Slow-Start),而不是 Reno-style ACK-clock Additive Increase:

/* In BBR_BW_PROBE_UP, not seeing high loss/ECN/queue, so raise inflight_hi. */
static void bbr2_probe_inflight_hi_upward(struct sock *sk,const struct rate_sample *rs)
{.../* For each bw_probe_up_cnt packets ACKed, increase inflight_hi by 1. */bbr->bw_probe_up_acks += rs->acked_sacked;if (bbr->bw_probe_up_acks >=  bbr->bw_probe_up_cnt) {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;}if (bbr->round_start)bbr2_raise_inflight_hi_slope(sk);
}
// 注意 ⚠️ 下面的函数!一个 SS 过程
/* Each round trip of BBR_BW_PROBE_UP, double volume of probing data. */
static void bbr2_raise_inflight_hi_slope(struct sock *sk)

而 MD 照旧。

看清了这一切之后,事实上 BBRv2 将一切效率都交给了 ProbeBW 的 probe-phase,剩下的退回到 AIMD。问题是,BBRv2 好意的 probe-phase 有问题,于是就有了 BBRv3。这就是 BBRv3 的背景。
BBRv3 的内容参见 BBRv3: Algorithm Bug Fixes and Public Internet Deployment

先看第一个 bugfix:
在这里插入图片描述

先看 BBRv2 的处理,我尽量写上注释:

case BBR_BW_PROBE_UP:// BBRv2 新增逻辑,对 Loss 的反应:// 丢包率太高,或者 ECN 率太高,并且if (bbr->prev_probe_too_high &&   // inflight 超过了 inflt_hi(而 inflt_hi 来自 Probe_up 的 AI 过程)  inflight >= bbr->inflight_hi) { bbr->stopped_risky_probe = 1;is_risky = true; // 有丢包风险,所以退出 Probe} // 继承 BBRv1 的逻辑:// Probe 至少 minrtt 时间,且 inflight 达到 gain*BDPelse if (bbr2_has_elapsed_in_phase(sk, bbr->min_rtt_us) && inflight >= bbr_inflight(sk, bw,bbr->params.bw_probe_pif_gain)) {is_queuing = true; // 产生了队列,所以退出 Probe}if (is_risky || is_queuing) {bbr->prev_probe_too_high = 0;  /* no loss/ECN (yet) */bbr2_start_bw_probe_down(sk);  /* restart w/ down */}break;

新增逻辑没毛病,问题在继承的部分,BBRv1 本就是个思想,相当于一个硬编码的 POC。

意识到固定的退出条件不靠谱很重要,既然可 drain to target,probe 到顶也就最合理,我的意思并不是拼命挤带宽,而是 “挤带宽吃力到一定程度” 时退出 probe,换句话说,只要带宽资源仍足够宽松,就持续 probe。

BBRv3 放弃了 inflight > gain * BDP 这个退出条件:

case BBR_BW_PROBE_UP:if (bbr->prev_probe_too_high &&inflight >= bbr->inflight_hi) {bbr->stopped_risky_probe = 1;is_bw_probe_done = true;} else {if (tp->is_cwnd_limited &&// 解除循环依赖:放开 inflight_hi 对 inflight 进而对 bw 的限制!tcp_snd_cwnd(tp) >= bbr->inflight_hi) {/* inflight_hi is limiting bw growth */bbr_reset_full_bw(sk); // 让 Probe phase 自行重新探测带宽,直到吃力!bbr->full_bw = ctx->sample_bw;} else if (bbr->full_bw_now) {/* Plateau in estimated bw. Pipe looks full. */is_bw_probe_done = true;}}if (is_bw_probe_done) {bbr->prev_probe_too_high = 0;  /* no loss/ECN (yet) */bbr_start_bw_probe_down(sk);  /* restart w/ down */}break;

这就是我去年在 inflight 守恒算法中的逻辑,一直 probe 到带宽增量小于某个可接受的阈值,说明没有公平带宽供给自己使用了,随即停止 probe。

下面简单看看第二个 bugfix:
在这里插入图片描述

这也是个典型问题,本质上也是个循环依赖问题,解法也简单:

case BBR_PROBE_BW:bbr->pacing_gain = bbr_pacing_gain[bbr->cycle_idx];bbr->cwnd_gain         = bbr_param(sk, cwnd_gain);if (bbr_param(sk, bw_probe_cwnd_gain) &&bbr->cycle_idx == BBR_BW_PROBE_UP)bbr->cwnd_gain += BBR_UNIT * bbr_param(sk, bw_probe_cwnd_gain) / 4;break;

我早就有提及:BBR cwnd_gain 的循环依赖。我的原意是将 cwnd_gian 作为一个 srtt - minrtt 的函数来定义。

总之,BBRv2 到 BBRv3,算法对 inflight 的约束更加精细,这也更加契合了 AIMD 动力学。虽然 pacing rate 仍是 primary control,但它能 control 的实在太少且不稳定,而经充分论证并历经实践的 AIMD 作为 inflight 约束算法让 cwnd secondary control 发挥更加重要且显式的作用。

另一方面,BBRv2 和 BBRv3,相比 BBRv1,“吞吐性能进一步降低”,“性能在变差”,但拥塞控制的首要目标是拥塞控制,不是提高吞吐。

关于 BBRv2 和 BBRv3 的其它想法和讨论,参见我的另两篇:BBRv2 的 inflight 补偿(也是个 AIMD 补偿) 和 BBRv3 来啦。

浙江温州皮鞋湿,下雨进水不会胖。


http://www.mrgr.cn/news/96750.html

相关文章:

  • Windows搭建AI大模型应用开发环境以及踩过的坑
  • sourceinsight 4.0 任意配置主题颜色风格的方法
  • RCU机制以及内存优化屏障
  • 【408--考研复习笔记】计算机网络----知识点速览
  • 【Golang】Windows系统键鼠空闲监测练习
  • STM32CubeMX的使用方法:使用STM32CubeMX生成基于STM32F103+HLA库的初始化代码,并在此基础上写出LED点灯程序
  • 数据结构实验1.3: 有序顺序表的归并
  • android 设置状态栏背景
  • 大模型-提示词(Prompt)技巧
  • OpenLayers:海量图形渲染之矢量切片
  • 4.1学习总结 拼图小游戏+集合进阶
  • 嵌入式EMC设计面试题及参考答案
  • 企业或个人linux服务器搭建
  • kubernetes》》k8s》》Deployment》》ClusterIP、LoadBalancer、Ingress 内部访问、外边访问
  • SOME/IP-SD -- 协议英文原文讲解10
  • 速查Linux常用指令
  • 【Harmonyos】项目开发总结--摇杆拖动侧重实现(适用游戏摇杆)
  • [GESP202503 C++六级题解]:P11963:环线
  • 论文阅读笔记:Denoising Diffusion Implicit Models (3)
  • 利用Canvas在紫微斗数命盘上画出三方四正