BBRv1 总结
基于丢包的拥塞控制算法缺陷
- Bufferbloat导致的高延迟 现代网络设备内置了非常大的缓冲区,基于丢包的算法会持续增加发送速率,直到填满缓冲区导致丢包才降速。大量的数据卡在网络设备的缓冲区中,导致排队延迟增大,从而使得整体的网络出现极高的延迟和抖动。
- 无法区分拥塞性丢包与随机性丢包 在无线网络(如Wi-Fi、4G/5G)中,丢包很常见,导致在无线网络环境下,即使网络带宽很充足,发送速率也可能因为随机的无线丢包而长期维持在一个很低的水平。
- 在Long-Fat网络上的效率低下 当这类网络发生一次丢包时,算法会立即将发送速率大幅降低)。然后以一个相对缓慢的线性速度来恢复速率。这导致带宽利用率严重不足。
BBR:基于建模的控制拥塞算法
拥塞与瓶颈
对于一个网络连接来说,在任意时刻,它在每个方向都有且只有一段最慢的链路,称之为瓶颈(bottleneck) 。
- 瓶颈决定了连接的最大数据传输速率,就好像一根水管最细处决定了它整体的水流量。
- 瓶颈是持久队列形成的地方。

对于瓶颈链路,只有当它的离开速率大于到达速率时,这个队列才会收缩,否则就会不断堆积,而一条链路上其他的队列也会朝着瓶颈移动(因为它的传输速率最小)。
不管一条连接会经过多少条链路,以下两个物理特性决定了传输的性能:
- 瓶颈带宽 (Bottleneck Bandwidth, BtlBw):整个网络连接上最细的管道的最大数据传输速率。
- 最小往返传播时间 (Round-trip Propagation Time, RTprop):数据包在完全不排队的情况下,往返一次所需的最短时间。这个值可以反映出物理链路的固有延迟。
带宽延迟积
BBR通过建模计算出一个理想的在途数据量,即 带宽延迟积 (Bandwidth-Delay Product, BDP):
\[BDP=BtlBw×RTprop\]BDP代表了为了恰好填满整个网络管道,同时又不在路由器中产生额外排队,发送方需要发出的数据量。
RTT、吞吐量与Inflight Data
- Inflight data: 代表了在特定时间点,网络路径中正在传输的数据量。
- BDP: 带宽延迟积。代表为了恰好填满整个网络管道而又不在任何地方产生排队,所需要注入的数据量。
- BufSize: 网络路径中瓶颈路由器的缓冲区大小。这是路由器在转发数据包之前,能够暂存数据包的最大容量。
- 吞吐量: 单位时间内,接收端成功接收到的数据量。

- 当$ 0 < Inflight < BDP $时,由于Inflight data不足以填满管道,数据包在路由器中无需排队等待。
    - RTT: 此时RTT约等于RTprop,且RTT会维持在一个稳定且最低的水平。
- 吞吐量:此时吞吐量的瓶颈不是网络的带宽,而是发送端注入数据的速率。接收端能接收多快,完全取决于发送端发送了多少。
 
- 当$ BDP < Inflight < BDP + BufSize$时,超出BDP的数据量将形成一个队列,存放在路由器的缓冲区中。数据包必须等待队列中它前面的数据包被发送后才能被转发,这产生了排队时延。
    - $ RTT = RTprop + Queuing Delay = RTprop + \frac{Inflight - BDP}{BtlBw} $ RTT会随着Inflight data的增加而线性增长。
- 吞吐量:此时网络管道已经被完全填满,吞吐量达到了系统的上限,继续增加Inflight data不会再提升吞吐量。
 
- 当$ Inflight > BDP + BufSize $时,在途数据量不仅超过了网络管道的容量,还超过了路由器缓冲区的存储极限时,网络进入严重拥塞状态。当缓冲区被填满后,后续到达的数据包将被路由器直接丢弃。
    - RTT:Queuing Delay达到最大值,RTT也达到峰值。
- 吞吐量:一旦发生丢包,会触发重传机制,实际的有效数据吞吐量会因为重传和发送速率的降低而显著下降。
 
BBR核心思想
BBR算法的核心目标就是让在途数据量(Inflight Data)始终维持在BDP附近, 从而获得最小的RTT和最大的吞吐量。

BBR的实现
BBRv1通过一个状态机来运作,主要包含四个状态。

- 
    启动 (Startup) 阶段:快速起步,探测上限 当一个连接刚开始时,BBR处于启动状态。这个阶段的目标是尽快地找到网络的瓶颈带宽 BtlBw。- 行为:在此阶段,BBR表现得非常激进。每当收到一个ACK确认包,它就会将发送速率翻倍,呈现指数级增长。
- 退出条件:当BBR发现,即使发送速率在增加,但测量到的带宽(送达速率)连续几次不再有明显增长时,它就认为已经达到了瓶颈带宽。此时就会退出启动阶段。
 
- 
    排空 (Drain) 阶段:消除过量,降低延迟 在启动阶段的末期,由于发送速率超过了实际的瓶颈带宽,必然会在网络路径的路由器中造成一定的数据积压(排队)。排空阶段的目标就是迅速消除这些排队,将延迟降下来。 - 行为:BBR会立即将发送速率降低到刚刚测量到的BtlBw。由于发送速率与瓶颈处理速率匹配,积压在队列中的数据包会被逐渐处理掉。
- 退出条件:当飞行中的数据量降低到与BDP(BtlBwxRTprop)相等时,意味着多余的排队已经基本被“排空”。此时,BBR进入下一个稳定阶段。
 
- 行为:BBR会立即将发送速率降低到刚刚测量到的
- 
    探测带宽 (ProbeBW) 阶段:稳定运行,周期探测 这是BBR在大部分时间里所处的状态,在此阶段,BBR的任务是在稳定发送的同时,周期性地探测网络带宽是否发生了变化。 ProbeBW阶段由一个持续8个RTT的周期性循环组成,这个循环使用了不同的步调增益 (pacing gain) 来调整发送速率。pacing_gain是一个乘数,发送速率 = BtlBw × pacing_gain。 这个8个RTT的周期可以分解为:时间 pacing_gain目的 第1个RTT 1.25 提升速率:发送速率比当前测得的瓶颈带宽高25%,主动探测是否有更多可用带宽。这会轻微增加队列。 第2个RTT 0.75 排空队列:发送速率降至瓶颈带宽的75%,以排空上一个RTT中可能产生的队列。 接下来6个RTT 1.0 稳定发送:以等于瓶颈带宽的速率发送,平稳地利用网络。 这个“增-减-平稳”的循环探测机制,使得BBR能够: - 及时发现带宽增加:通过周期性的1.25倍速率探测,如果网络状况变好,BBR能迅速更新其BtlBw估计。
- 保持低延迟:探测带宽增加所造成的排队会立即在下一个RTT被0.75倍的速率排空,避免了延迟积压。
- 公平共享带宽:在稳定期以1.0的速率发送,将带宽让给其他需要探测的连接。
 
- 及时发现带宽增加:通过周期性的
- 
    探测RTT (ProbeRTT) 阶段:测量真实延迟 BBR需要知道最真实的 RTprop(无排队延迟)。但是,如果在ProbeBW阶段,网络中一直存在少量排队,那么测量到的RTT就会一直偏高。这样RTprop的估计值就会不准确,进而影响BDP的计算。- 触发条件:如果BBR发现,在超过10秒的时间里,它都没有测量到一个更低的RTT值,它就会强制进入ProbeRTT状态。
- 行为:在此状态下,BBR会大幅降低发送速率,将飞行中的数据量减少到非常小的值(通常只有4个数据包)。
- 持续时间:这个状态会持续大约200毫秒,或者一个RTT,确保有足够的时间让网络中的排队完全消失,从而测量到最真实的RTprop。之后,BBR会根据新的网络模型返回到Startup或ProbeBW阶段。
 
- 触发条件:如果BBR发现,在超过10秒的时间里,它都没有测量到一个更低的RTT值,它就会强制进入

核心状态变量
- BtlBw (Bottleneck Bandwidth): 瓶颈带宽的估计值。
    - 更新方式: BBR维护一个在时间窗口内(通常是过去6-10个RTT)观察到的DeliveryRate的最大值。这是一个滑动窗口最大值滤波器(max-filter)。
- BtlBw = max(BtlBw_filter_window, DeliveryRate)
 
- 更新方式: BBR维护一个在时间窗口内(通常是过去6-10个RTT)观察到的
- RTprop (Round-trip Propagation Time): 最小往返传播时延的估计值。代表了数据包在没有任何排队情况下的物理往返时间。
    - 更新方式: BBR维护一个在较长时间窗口内(BBR中是10秒)观察到的RTT样本的最小值。这是一个滑动窗口最小值滤波器(min-filter)。
- RTprop = min(RTprop_filter_window, RTT_sample)
 
- 更新方式: BBR维护一个在较长时间窗口内(BBR中是10秒)观察到的
- pacing_rate (Sending Rate): BBR计算出的数据包发送速率。这是BBR作为基于速率的算法的直接输出。
    - 计算方式: pacing_rate = BtlBw × pacing_gain。其中的pacing_gain是BBR在不同阶段使用的核心调节器。
 
- 计算方式: 
- cwnd (Congestion Window): 拥塞窗口。在BBR中,它不是主要的拥塞控制器,而是一个辅助性的上限,用于确保inflight数据量不会远超于BDP,同时兼容传统的基于丢包的恢复机制。- 计算方式: cwnd的目标值是target_cwnd = BDP × cwnd_gain。BDP = BtlBw × RTprop。cwnd_gain通常与pacing_gain联动。
- BBR会确保cwnd >= target_cwnd,以允许数据包能以pacing_rate顺利发出。
 
- 计算方式: 
- inflight: 在途数据量。已发送但尚未被确认的数据总量。
- DeliveryRate: 瞬时交付速率。在每次收到ACK时计算,用于更新BtlBw。- 计算方式: 当一个ACK到达时,该ACK确认了N字节的数据。假设这个数据包是第k个被发送的,上一个被ACK的数据包是第j个。DeliveryRate = N / (send_timestamp_k - send_timestamp_j)。它反映了数据在网络中的实际交付速率。
 
- 计算方式: 当一个ACK到达时,该ACK确认了
Startup
目标: 快速指数级地增加发送速率,以最快速度探测到网络的瓶颈带宽BtlBw。
核心参数:
- pacing_gain: 2.89 (精确值为- 2/ln(2))
- cwnd_gain: 2.89 (精确值为- 2/ln(2))
算法逻辑与计算:
- 设置速率: pacing_rate = BtlBw × 2.89。在连接刚开始时,BtlBw会有一个初始值,然后随着每次测量的DeliveryRate迅速增长。
- 设置拥塞窗口: target_cwnd = BtlBw × RTprop × 2.89。cwnd被设置为不小于这个目标值,以确保不会限制数据的发送。
- 每次收到ACK:
    - 计算DeliveryRate并尝试更新BtlBw。
- 由于BtlBw在Startup阶段持续增长,pacing_rate也随之指数级增长。
 
- 计算
退出条件:
- BBR会持续跟踪BtlBw的增长情况。如果在连续3个TT周期内,新测得的BtlBw相比之前的峰值没有显著增长(增长幅度小于25%),BBR就认为已经找到了瓶颈带宽的上限。此时,它会退出Startup阶段,进入Drain阶段。
StartUp会指数级增长cwnd和pacing rate,快速探测到当前网络环境的天花板,记录下此时的RTT和BW 。
Drain
目标: 排空在Startup阶段末期因速率过冲而在瓶颈路由器中产生的排队。
核心参数:
- pacing_gain: 0.346 (精确值为- ln(2)/2,即Startup增益的倒数)
- cwnd_gain: 2.89 (与Startup相同,确保cwnd不会成为排空过程的瓶颈)
算法逻辑与计算:
- 设置速率: pacing_rate = BtlBw × 0.346。此时的BtlBw是Startup阶段找到的峰值带宽。由于发送速率远低于瓶颈带宽,路由器中的队列会被迅速消耗。
- 设置拥塞窗口: 维持与Startup阶段相同的cwnd_gain,确保cwnd足够大。
退出条件:
- 当在途数据量 inflight下降到等于或略低于当前估计的BDP (BtlBw × RTprop) 时,BBR认为队列已被排空。此时,它会退出Drain阶段,进入常态运行的ProbeBW阶段。
Probe_BW
- 目标: 在大部分时间内以接近瓶颈带宽的速率稳定发送,同时周期性地探测是否存在更大的可用带宽。
- 核心参数:
    - pacing_gain: 在一个8个RTT的周期内,按顺序使用以下值:[1.25, 0.75, 1, 1, 1, 1, 1, 1]
- cwnd_gain: 2
 
- 算法逻辑与计算:
    - 周期性增益: BBR会维护一个指针,指向当前周期中的pacing_gain值。该指针每经过一个RTT周期就向前移动一次。
- 设置速率: pacing_rate = BtlBw × current_pacing_gain。- 在增益为1.25的RTT内: 以超出瓶颈带宽25%的速率发送,主动探测更高带宽。如果网络容量变大,此时的DeliveryRate会创新高,从而更新BtlBw。这个过程会产生少量排队。
- 在增益为0.75的RTT内: 以低于瓶颈带宽25%的速率发送,用于排空上一个RTT中产生的队列,使延迟回归正常。
- 在增益为1的6个RTT内: 以等于瓶颈带宽的速率发送,平稳地利用带宽,并将探测机会让给其他网络流,以实现公平性。
 
- 在增益为1.25的RTT内: 以超出瓶颈带宽25%的速率发送,主动探测更高带宽。如果网络容量变大,此时的
- 设置拥塞窗口: target_cwnd = BtlBw × RTprop × 2。cwnd_gain为2是为了允许在探测带宽时,inflight能够达到1.25 × BDP,并为网络中的一些瞬时抖动提供缓冲。
 
- 周期性增益: BBR会维护一个指针,指向当前周期中的
- 退出条件:
    - ProbeBW是BBR的稳定运行状态,它会一直在此状态循环。唯一的退出条件是触发了ProbeRTT。
 
Probe_RTT
- 目标: 主动减少在途数据量,使网络中的排队完全消失,从而有机会测量到真实、无干扰的RTprop。
- 触发条件:
    - 当RTprop的值在10秒内没有更新(即没有测量到更低的RTT)时,BBR会强制进入此状态。
 
- 当
- 核心参数:
    - 此阶段不使用pacing_gain和cwnd_gain进行控制。
 
- 此阶段不使用
- 算法逻辑与计算:
    - 保存当前cwnd: BBR会先保存进入此状态前的cwnd值,以便退出时恢复。
- 强制降低inflight: BBR会将cwnd强制设定为一个非常小的值,通常是4 MSS 。
- 限制发送: 由于cwnd极小,发送端会被阻塞,inflight会迅速下降到4个数据包的水平。
- 持续时间: 此状态持续时间为max(rtt, 200ms),并等待inflight确实下降到目标值以下,确保网络中的队列有足够的时间被排空。
 
- 保存当前cwnd: BBR会先保存进入此状态前的
- 退出条件:
    - 在持续至少200毫秒并成功将inflight降低后,BBR会退出ProbeRTT状态。
- 退出后,如果网络长时间空闲,可能会回到Startup阶段;否则,将直接返回ProbeBW阶段,并恢复之前保存的cwnd值,继续进行带宽探测。
 
- 在持续至少200毫秒并成功将