BBR 算法原理三
标签: BBR 算法原理三 Python博客 51CTO博客
2023-04-17 18:23:53 258浏览
稳态行为(Steady-state behavior)
BBR 大部分时间都是在此状态
路径适配与控制循环
BBR 的发送速率和发送数据量只是估计出的 BtlBw 和 RTprop

Fig 2. RTT (blue), inflight (green), BtlBw max filter (black) and delivery rate (red) detail
从上到下四条横线:
- RTT
- inflight
- BtlBw 的估计值(状态)
- 它上面的那行表格是pacing_gain,它是一个固定数组,不断循环;
- 每个时刻使用的 pacing_gain 及其效果在图中是对齐的;
- 每个 gain 会在发送数据时使用,因此是早一个 RTT 窗口;这可以从图中从下往上、再从上往下的整个环路看出来。
- delivery rate(实际传输速率)
几点说明:
- 图中凸起的尖峰是 BBR 使用 pacing_gain 周期切换导致的,目的是判断 BtlBw 是否有增加。
- BBR 在大部分时间都将 inflight 数据量保持在一个 BDP,并用 BtlBw estimate 进行 pace,以此来最小化延迟。 这将瓶颈从链路前移到了发送端,因此发送端是无法看到 BtlBw 升高的。
稳态的收敛过程
BBR 会定期使用 pacing_gain > 1
考虑链路瓶颈带宽 BtlBw 的两种可能情况:
- 继续保持恒定(大部分情况)
- 突然增大(例如物理链路扩容)
如果 BtlBw 恒定,
- 增加的数据量会在瓶颈处创建一个 queue,这会导致 RTT 变大,但
deliveryRate
- 下一个 RTprop 窗口会以
pacing_gain < 1
如果 BtlBw 增大了,
deliveryRate
- 因此,BBR 会以指数级快速收敛到新的瓶颈速率。
图 3 展示了一个原本运行在 10-Mbps/40-ms

Fig 3. Bandwidth change
BBR 是一个 max-plus 控制系统(一种基于 max() 和加法操作的代数)的一个具体使用场景,这是一种基于非标准代数进行控制的新方式12。 这种方式允许 adaptation rate (由 max gain 控制)独立于 queue growth (由 average gain 控制)。 应用到这里,得到的就是一个简单、隐含的控制循环,其中,对物理限制的变化的适应过程, 由代表这些限制的 filters 自动处理。而传统控制系统则需要通过一个复杂状态机连接 起来的多个循环,才能完成同样效果。
BBR算法计算结果
bbr算法不仅会输出类似于Cubic 等算法结果的cwnd,其实他最主要的计算结果是pacing rate。
毕竟cwnd仅仅规定了当前的TCP最多可以发送多少数据,Cubic等算法中并没有规定怎么把这么多数据发出去,在Linux的实现中,如果发出去这么多数据呢?简单而粗暴,突发!忽略接收端通告窗口的前提下,Linux会把cwnd一窗数据全部突发出去,而这往往会造成路由器的排队,在深队列的情况下,会测量出rtt剧烈地抖动。
bbr在计算cwnd的同时,还计算了一个与之适配的pacing rate,该pacing rate规定cwnd指示的一窗数据的数据包之间,以多大的时间间隔发送出去。
计算过程:
bbr只关心应答了多少数据,以及花了多长时间,两者相除就可以计算出bw。 bw = delivered/interval_us
也就是说bbr根本不管某一个应答是重传后的ACK确认的,正常ACK确认的,还是说SACK确认的。当然sack等其他逻辑会关注
pacing rate怎么计算
用时间窗口内(默认10轮采样)最大BW。上一次采样的即时BW,用它来在可能的情况下更新时间窗口内的BW采样值集合。这次能否按照这个时间窗口内最大BW发送数据呢?
这样看当前的增益系数的值,设为G,那么BW*G就是pacing rate的值。
至于说cwnd的计算可能要稍微复杂一点,cwnd其实描述了一条网络管道传输能力性能(rwnd描述了接收端缓冲区),因此cwnd其实就是这个管道的容量,也就是BDP。
bbr一直在持续搜集最小的RTT值,而G是增益系数,一开始设定好,所以pacing rate就出来了。
pacing_rate 和 cwnd
bbr 算法输出 pacing_rate 和 cwnd 两个数据。pacing_rate 决定发包速率,cwnd 为窗口大小。每一次 ACK 都会根据当前的模式计算 pacing_rate 和 cwnd。注意在计算 pacing_rate 和 cwnd 时有 pacing_gain 和 cwnd_gain 两个参数,
bottleneck_bandwidth = windowed_max(delivered / elapsed, 10 round trips)
min_rtt = windowed_min(rtt, 10 seconds)
pacing_rate = pacing_gain * bottleneck_bandwidth
cwnd = max(cwnd_gain * bottleneck_bandwidth * min_rtt, 4)
BBR 状态机
BBR 算法也是基于状态机。状态机有STARTUP、DRAIN、PROBE_BW、PROBE_RTT四种状态。不同状态下 pacing_gain 和 cwnd_gain 的取值会有所不同。

STARTUP:初始状态,该状态下类似于传统拥塞控制的慢启动阶段。该状态下pacing_gain和cwnd_gain为 2/ln(2)+1。因为这是最小的能够达到 Reno 或者 CUBIC 算法启动速度的值
/* We use a high_gain value of 2/ln(2) because it's the smallest pacing gain
* that will allow a smoothly increasing pacing rate that will double each RTT
* and send the same number of packets per RTT that an un-paced, slow-starting
* Reno or CUBIC flow would:
*/
static const int bbr_high_gain = BBR_UNIT * 2885 / 1000 + 1;
/* The pacing gain of 1/high_gain in BBR_DRAIN is calculated to typically drain
* the queue created in BBR_STARTUP in a single round:
*/
static const int bbr_drain_gain = BBR_UNIT * 1000 / 2885;
/* The gain for deriving steady-state cwnd tolerates delayed/stretched ACKs: */
static const int bbr_cwnd_gain = BBR_UNIT * 2;
The startup stage of "pacing rate" relationship with time fixed point has the following:
The rate of change of the "pacing rate" is exactly equal to the current "pacing rate"
so,
let x be the time,Assuming that the RTT is constant, use it to normalize:
the BDP evolves as a function of time as f1(x)=2^x
the pacing rate evolves as a function of time as f2(x)=2^x
Let g(x) be the derivative of f1(x):
g(x)=f1'(x)=ln2*2^x
the derivative of f1'(x) is the rate, so g(x) is pacing rate.
let G be the pacing gain:
g(x+1) = G*g(x) = G*ln2*2^x = f2(x+1) = 2*2^x
so G*ln2*2^x = 2*2^x ==> G = 2/ln2
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论
您可能感兴趣的博客
