专栏文章
专栏文章
网络算法系列
1. 网络算法 #01:轮询与加权轮询 2. 网络算法 #02:最小连接数 3. 网络算法 #03:Jump Consistent Hash 4. 网络算法 #04:Rendezvous Hashing 5. 网络算法 #05:TCP 拥塞控制(CUBIC 与 BBR) 6. 网络算法 #06:QUIC 丢包恢复与拥塞控制 7. 网络算法 #07:经典一致性哈希(虚拟节点) 8. 网络算法 #08:P2C(Power of Two Choices) 9. 网络算法 #09:TCP 滑动窗口与流量控制 10. 网络算法 #10:Maglev Hashing

网络算法 #05:TCP 拥塞控制(CUBIC 与 BBR)

发布于 2026-06-04 04:44 👁 6 次阅读
#网络算法#TCP#拥塞控制#CUBIC#BBR#Linux内核

TCP 拥塞控制解决发送方如何感知网络容量、在不造成拥塞的前提下最大化吞吐的问题,CUBIC 是 Linux 默认算法,BBR 是 Google 2016 年提出的基于带宽探测的新一代算法。

相关文章Rendezvous Hashing · QUIC 丢包恢复与拥塞控制

tcp congestion

目录

章节 说明
问题背景 为什么需要拥塞控制,核心矛盾是什么
基础概念 cwnd、rwnd、ssthresh、RTT 精确定义
经典 TCP Reno 四阶段完整伪代码与执行追踪
CUBIC 算法 三次函数增长模型,Linux 默认实现
BBR 算法 基于带宽探测的主动感知,四状态机
BBR 状态机执行追踪 从 STARTUP 到 PROBE_BW 的具体数值演示
CUBIC vs BBR 核心差异 设计哲学、适用场景、公平性对比
异常与边界场景 带宽突变、RTT 突变、多流竞争、ECN
参考资料 论文、RFC、内核文档

问题背景

核心矛盾

TCP 发送方不知道路径上瓶颈链路的带宽,只能通过试探来学习:

1986 年 Van Jacobson 观察到 ARPANET 上吞吐量从 32 Kbps 骤降至 40 bps 的"拥塞崩溃"现象,随后在 RFC 1122/1323 中提出了慢启动与拥塞避免机制。

网络模型假设

发送方 ──── 路径(瓶颈链路 BtlBw)──── 接收方
            └── 路由器队列(Buffer)

基础概念

变量 全称 维护方 含义
cwnd Congestion Window 发送方 发送方允许在途(未确认)的最大字节数,单位 MSS 或字节
rwnd Receiver Window 接收方通告 接收方缓冲区剩余空间,通过 TCP 头部 Window 字段传递
ssthresh Slow Start Threshold 发送方 区分慢启动与拥塞避免阶段的阈值,初始值通常为 64 KB
RTT Round-Trip Time 发送方测量 一个数据段从发出到收到 ACK 的时间,用于计算 RTO
MSS Maximum Segment Size 协商 单个 TCP 段最大数据字节数,通常 1460 字节(以太网)
BDP Bandwidth-Delay Product 计算值 BtlBw × RTprop,充满管道所需字节数

实际发送窗口send_window = min(cwnd, rwnd)


经典 TCP Reno

3.1 四个阶段

阶段一:慢启动(Slow Start)

触发条件:连接建立初期,或超时重传后(cwnd 重置为 1 MSS)

// 慢启动:每收到一个 ACK,cwnd 增加 1 MSS → 每 RTT 翻倍(指数增长)
初始化:
    cwnd    = 1 MSS        // 初始拥塞窗口
    ssthresh = 64 KB       // 初始慢启动阈值(实现相关,RFC 建议更大)

on_ack_received(acked_bytes):
    if cwnd < ssthresh:
        cwnd += MSS                        // 慢启动:每 ACK 增加 1 MSS
        // 效果:每 RTT 内发 cwnd/MSS 个包,收到 cwnd/MSS 个 ACK
        //       cwnd += cwnd,即每 RTT 翻倍
    else:
        cwnd += MSS * MSS / cwnd           // 拥塞避免:每 RTT 增加约 1 MSS
        // 公式推导:每个 ACK 增加 MSS²/cwnd,
        //           一个 RTT 内有 cwnd/MSS 个 ACK,
        //           总增加 = (cwnd/MSS) * (MSS²/cwnd) = MSS

阶段二:拥塞避免(Congestion Avoidance)

触发条件:cwnd >= ssthresh

on_ack_received(acked_bytes):
    if cwnd >= ssthresh:
        cwnd += MSS * MSS / cwnd           // 每 RTT 线性增加 1 MSS

阶段三:快速重传(Fast Retransmit)

触发条件:收到 3 个重复 ACK(dup ACK),说明某段丢失但后续段到达

// 重复 ACK 计数器
dup_ack_count = 0

on_ack_received(ack_seq):
    if ack_seq == last_ack_seq:            // 收到重复 ACK
        dup_ack_count += 1
        if dup_ack_count == 3:             // 三次重复 ACK → 快速重传
            retransmit(last_ack_seq)       // 立即重传丢失段,不等超时
            ssthresh = max(cwnd / 2, 2 * MSS)   // 阈值减半
            cwnd     = ssthresh            // 窗口设为新阈值(进入快速恢复)
            dup_ack_count = 0
    else:
        dup_ack_count = 0                  // 收到新 ACK,重置计数
        // 正常 ACK 处理(慢启动或拥塞避免)

阶段四:快速恢复(Fast Recovery)

触发条件:快速重传后,从 ssthresh 继续拥塞避免(不回到慢启动)

// 快速恢复:cwnd 已设为 ssthresh,直接进入拥塞避免阶段
// 区别于超时:超时后 cwnd 重置为 1 MSS,从慢启动重新开始
on_timeout():
    ssthresh = max(cwnd / 2, 2 * MSS)
    cwnd     = 1 * MSS                    // 超时:重置为 1,重新慢启动
    dup_ack_count = 0

3.2 执行追踪(Reno,MSS=1,ssthresh=8)

RTT  事件              cwnd   ssthresh  说明
---  ---------------  -----  --------  --------------------------
0    连接建立           1      8         初始状态
1    1个ACK            2      8         慢启动,翻倍
2    2个ACK            4      8         慢启动,翻倍
3    4个ACK            8      8         cwnd==ssthresh,进入拥塞避免
4    8个ACK            9      8         线性+1
5    9个ACK            10     8         线性+1
6    收到3个dup ACK     5      5         ssthresh=10/2=5, cwnd=5
7    从ssthresh继续     6      5         拥塞避免,线性+1

3.3 TCP Reno 的局限性


CUBIC 算法

4.1 问题背景

Linux 2.6.19(2006年)将默认拥塞控制从 BIC 改为 CUBIC。核心改进:用三次函数替代线性增长,在高 BDP 网络中快速恢复到历史最大窗口。

4.2 核心数据结构

struct cubic_state {
    u32 W_max;        // 上次丢包时的 cwnd(历史最大窗口,单位 MSS)
    u32 W_last_max;   // 上上次丢包时的 W_max,用于快速收敛
    u32 K;            // cwnd 增长达到 W_max 的时间点(秒)
    u32 t_epoch;      // 上次丢包/窗口减小的时间戳(秒)
    u32 cwnd;         // 当前拥塞窗口(MSS)
    u32 ssthresh;     // 慢启动阈值
    // 常数
    // C = 0.4(CUBIC 缩放因子,控制增长速度)
    // beta = 0.7(乘性减少因子,比 Reno 的 0.5 更保守)
};

4.3 三次函数增长模型

W_cubic(t) = C * (t - K)³ + W_max

其中:
  t = 当前时间 - t_epoch(距上次丢包的时间,秒)
  K = ∛(W_max * (1 - beta) / C)
    = ∛(W_max * 0.3 / 0.4)
  C = 0.4(论文推荐值)
  beta = 0.7(乘性减少因子)

函数特性:
  t=0 时:W_cubic(0) = C*(0-K)³ + W_max = -C*K³ + W_max = W_max*(1-beta) = 0.7*W_max
  t=K 时:W_cubic(K) = 0 + W_max(恢复到丢包前水平)
  t>K 时:超过 W_max,继续探测更高带宽

4.4 完整伪代码

// CUBIC 初始化
cubic_init():
    W_max    = 0
    K        = 0
    t_epoch  = 0
    cwnd     = 1 * MSS
    ssthresh = INITIAL_SSTHRESH    // 通常 64KB / MSS

// 收到 ACK 时更新 cwnd
cubic_on_ack(now):
    if cwnd < ssthresh:
        cwnd += MSS                // 慢启动阶段,指数增长
        return

    t = now - t_epoch              // 距上次丢包的时间(秒)

    // 计算 CUBIC 目标窗口
    W_cubic_t = C * (t - K)^3 + W_max    // C=0.4

    // 与 TCP 友好性(Reno 等效窗口)比较,取较大值
    // Reno 等效:W_est += MSS * (3*beta/(2-beta)) / cwnd * per_ack
    // 实现上简化为:W_est = W_max * beta + 3*(1-beta)/(1+beta) * t/RTT
    W_tcp_friendly = W_est(t)

    target = max(W_cubic_t, W_tcp_friendly)

    if target > cwnd:
        cwnd += (target - cwnd) / cwnd    // 每 ACK 增量,分摊到一个 cwnd
    else:
        cwnd unchanged                     // 不减少

// 检测到丢包(3 个 dup ACK)
cubic_on_loss():
    W_last_max = W_max
    W_max      = cwnd              // 记录丢包时窗口

    // 快速收敛:如果本次 W_max 小于上次,说明带宽减少,更快收缩
    if W_max < W_last_max:
        W_max = W_max * (2 - beta) / 2    // W_max = W_max * 0.85

    ssthresh = max(cwnd * beta, 2 * MSS)   // ssthresh = 0.7 * cwnd
    cwnd     = ssthresh

    // 重新计算 K,t_epoch 重置
    K       = cbrt(W_max * (1 - beta) / C)
    t_epoch = now

// 超时
cubic_on_timeout():
    W_max    = cwnd
    ssthresh = max(cwnd * beta, 2 * MSS)
    cwnd     = 1 * MSS            // 回到慢启动
    K        = cbrt(W_max * (1 - beta) / C)
    t_epoch  = now

4.5 执行追踪(CUBIC,W_max=20,beta=0.7,C=0.4,MSS=1)

事件           t(s)   K(s)   cwnd   ssthresh  W_cubic(t)  说明
-----------   -----  -----  -----  --------  ----------  -------------------
丢包发生       0      2.94   20     14        14.0        K=∛(20*0.3/0.4)≈2.94
               0.5    2.94   14     14        14.0-1.27≈12.7 → 保持14(min)
               1.0    2.94   14     14        ≈13.4       W_cubic=0.4*(1-2.94)³+20≈13.4
               1.5    2.94   15     14        ≈15.9       超过cwnd,增长
               2.0    2.94   16     14        ≈18.3       接近W_max,加速
               2.94   2.94   20     14        20.0        恢复到W_max
               3.5    2.94   21     14        21.3        超过W_max,继续探测
新丢包         3.5    ←      21→14  14        重置         W_max=21, K重新计算

CUBIC vs Reno 增长速度对比(相同 W_max=20,t=2s 时):


BBR 算法

5.1 设计哲学:从丢包感知到带宽感知

传统算法(Reno/CUBIC):
  感知信号 = 丢包(被动等待队列溢出)
  问题:
    ① 浅队列路由器:少量数据就丢包,带宽利用率低
    ② 无线链路随机丢包:误触发窗口减半
    ③ 高 BDP 链路:恢复太慢

BBR(Bottleneck Bandwidth and RTT):
  感知信号 = 带宽(BtlBw)+ 最小 RTT(RTprop)
  目标:以瓶颈带宽发送,不在队列中积压数据(工作在 BDP 点)

5.2 核心数据结构

struct bbr_state {
    // 带宽估算(滑动窗口最大值)
    u64  btlbw;          // 瓶颈带宽估算(bps),= delivered / interval
    u64  btlbw_filter;   // 10 RTT 内的最大带宽(WindowedMaxFilter)

    // RTT 估算
    u32  rtprop;         // 最小 RTT(ns),= min(RTT) over last 10s
    u64  rtprop_stamp;   // rtprop 最后更新时间

    // 发送速率控制
    u64  pacing_rate;    // 实际发送速率 = btlbw * pacing_gain
    u32  cwnd;           // 拥塞窗口 = btlbw * rtprop * cwnd_gain
    
    // 状态机
    enum bbr_mode mode;  // STARTUP / DRAIN / PROBE_BW / PROBE_RTT
    u32  pacing_gain;    // 发送速率增益(定点数,1.0=2048)
    u32  cwnd_gain;      // 窗口增益

    // PROBE_BW 轮转
    u8   cycle_idx;      // pacing_gain 周期索引(0-7)
    u64  cycle_stamp;    // 当前 pacing_gain 阶段开始时间

    // 统计
    u64  delivered;      // 累计已确认交付字节数
    u64  delivered_stamp;// delivered 上次记录时间
};

// pacing_gain 周期(PROBE_BW 状态,8个相位)
// 相位0: 1.25 → 探测更高带宽
// 相位1: 0.75 → 排空多余队列
// 相位2-7: 1.0  → 稳定巡航
pacing_gain_cycle[8] = {1.25, 0.75, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}

5.3 四个状态

状态 目标 pacing_gain cwnd_gain 退出条件
STARTUP 指数探测最大带宽 2.885 2.885 btlbw 连续 3 轮无增长
DRAIN 排空 STARTUP 积压队列 1/2.885≈0.35 2.885 in_flight ≤ BDP
PROBE_BW 周期性探测带宽,稳态运行 轮转[1.25,0.75,1.0×6] 2 PROBE_RTT 触发
PROBE_RTT 降低 cwnd 测量最小 RTT 当前值 1 持续 200ms 后恢复

5.4 完整伪代码

// BBR 初始化
bbr_init():
    mode          = STARTUP
    pacing_gain   = 2.885        // ≈ 2/ln2,指数增长
    cwnd_gain     = 2.885
    btlbw         = 0
    rtprop        = +∞
    rtprop_stamp  = now()
    cycle_idx     = 0
    delivered     = 0

// 每个 ACK 到达时调用
bbr_on_ack(rtt, delivered_delta, interval):
    // 1. 更新带宽估算
    bw_sample = delivered_delta / interval        // 采样带宽
    btlbw = WindowedMax(btlbw_filter, bw_sample, 10 * rtprop)  // 10 RTT 窗口最大值

    // 2. 更新最小 RTT
    if rtt < rtprop:
        rtprop       = rtt
        rtprop_stamp = now()

    // 3. 状态机转换
    bbr_update_mode()

    // 4. 更新发送参数
    pacing_rate = btlbw * pacing_gain
    cwnd        = max(btlbw * rtprop * cwnd_gain, 4 * MSS)  // 不低于4MSS

// 状态机转换逻辑
bbr_update_mode():
    switch mode:
        case STARTUP:
            if btlbw_no_growth_for(3_rounds):    // 连续3轮带宽不增长
                mode        = DRAIN
                pacing_gain = 1.0 / 2.885        // ≈ 0.35,快速排空
                cwnd_gain   = 2.885

        case DRAIN:
            in_flight = packets_in_flight * MSS
            if in_flight <= btlbw * rtprop:      // 队列已排空
                mode        = PROBE_BW
                cycle_idx   = 0
                pacing_gain = pacing_gain_cycle[0]  // 1.25
                cwnd_gain   = 2.0
                cycle_stamp = now()

        case PROBE_BW:
            // 每个 RTT 推进一个 pacing_gain 相位
            if now() - cycle_stamp >= rtprop:
                cycle_idx   = (cycle_idx + 1) % 8
                pacing_gain = pacing_gain_cycle[cycle_idx]
                cycle_stamp = now()
            // 检查是否需要 PROBE_RTT
            if now() - rtprop_stamp >= 10s:       // 10s 未更新最小 RTT
                mode        = PROBE_RTT
                cwnd_gain   = 1.0

        case PROBE_RTT:
            cwnd = max(4 * MSS, ...)               // 降低 cwnd
            if probe_rtt_done():                   // 持续200ms且in_flight≤4MSS
                rtprop_stamp = now()               // 重置计时器
                mode         = STARTUP if not_filled_pipe else PROBE_BW
                restore_cwnd_gain()

// BBR 对丢包的处理(不触发窗口减半)
bbr_on_loss():
    // BBR 不把丢包作为拥塞信号
    // 但遵守 TCP 重传机制(快速重传、超时重传)
    // cwnd 短暂设为 in_flight(保守),不做乘性减少
    cwnd = min(cwnd, in_flight)    // 不减半,仅保守处理

5.5 带宽测量细节

// 带宽采样(每个 ACK)
on_ack(ack):
    now_delivered  = total_delivered         // 当前累计交付
    now_time       = now()

    // 记录该数据包发出时的状态
    bw_sample = (now_delivered - pkt.delivered) /
                (now_time      - pkt.delivered_time)

    // 使用 Windowed Max Filter(滑动窗口最大值)
    // 窗口大小 = 10 RTT,保留近期最大带宽
    btlbw = WindowedMax(btlbw, bw_sample, window=10*rtprop)

BBR 状态机执行追踪

场景:100 Mbps 链路,RTprop=20ms,从 STARTUP 开始

时间(ms)  状态       btlbw(Mbps)  rtprop(ms)  cwnd(KB)  pacing_rate(Mbps)  事件
------   -------    -----------  ----------  --------  -----------------  ----
0        STARTUP    0            +∞          4MSS      0                  初始化
20       STARTUP    12           20          ~10       34.6               第1轮ACK,btlbw=12
40       STARTUP    25           20          ~20       72.1               第2轮,btlbw增长
60       STARTUP    50           20          ~40       144.3              第3轮,翻倍
80       STARTUP    100          20          ~80       288.5              接近瓶颈
100      STARTUP    100          20          ~80       288.5              btlbw无增长第1轮
120      STARTUP    100          20          ~80       288.5              btlbw无增长第2轮
140      STARTUP    100          20          ~80       288.5              btlbw无增长第3轮→转DRAIN
140      DRAIN      100          20          ~80       35.0               pacing_gain=0.35
160      DRAIN      100          20          ~50       35.0               排空队列中
180      DRAIN      100          20          25(=BDP)  35.0               in_flight≤BDP→转PROBE_BW
180      PROBE_BW   100          20          50        125.0              phase0: gain=1.25
200      PROBE_BW   100          20          50        75.0               phase1: gain=0.75,排空
220      PROBE_BW   100          20          50        100.0              phase2-7: gain=1.0,稳态
...
10000    PROBE_RTT  100          20          4MSS      100.0              10s未更新rtprop→降cwnd
10200    PROBE_BW   100          20          50        100.0              200ms测量完成,恢复

// BDP 计算:100Mbps × 20ms = 2.5MB → cwnd ≈ 2.5MB × 2(cwnd_gain) = 5MB
// 实际 cwnd(KB) = 100*1000000/8 * 0.020 * 2 / 1024 ≈ 488 KB(图中简化为50KB演示)

PROBE_BW 一轮 pacing_gain 周期(稳态,btlbw=100Mbps,RTprop=20ms)

相位  持续(ms)  pacing_gain  pacing_rate(Mbps)  效果
----  --------  -----------  -----------------  ------------------
0     20        1.25         125                超速发送,探测带宽上界
1     20        0.75         75                 降速,排空phase0积压
2     20        1.0          100                稳定
3     20        1.0          100                稳定
4     20        1.0          100                稳定
5     20        1.0          100                稳定
6     20        1.0          100                稳定
7     20        1.0          100                稳定(周期结束)
// 每个相位持续约 1 RTT(20ms),完整周期 = 8 RTT = 160ms
// 如果phase0探测到更高带宽,btlbw更新,后续稳态速率提升

CUBIC vs BBR 核心差异

7.1 设计哲学对比

维度 CUBIC BBR
拥塞信号 丢包(被动,队列溢出后感知) 带宽+RTT(主动探测,不等丢包)
工作点 满队列(高吞吐但高延迟) BDP 点(平衡吞吐与延迟)
丢包响应 窗口减少到 0.7×cwnd 不减窗口(不视丢包为拥塞信号)
RTT 公平性 较差(短 RTT 流占优) 较好(基于带宽不受 RTT 影响)
高 BDP 网络 恢复慢(三次函数改善) 快速充满管道(STARTUP 指数探测)
低延迟要求 会在队列中积压数据 主动控制队列,延迟更低
浅队列路由器 适应性好(丢包就减速) 可能加剧丢包(不响应丢包)
与 CUBIC 竞争 公平 BBR 可能占用更多带宽

7.2 适用场景

CUBIC 更适合

BBR 更适合

7.3 BBR 的已知问题

问题1:浅队列公平性
  现象:BBR 流与 CUBIC 流竞争时,BBR 可能获取不成比例的带宽
  原因:CUBIC 丢包就减速,BBR 不减速,导致 CUBIC 流被"饿死"
  缓解:部署 FQ(公平队列)调度器,per-flow 限速

问题2:RTT 膨胀
  BBR v1:PROBE_RTT 期间 cwnd 降至 4MSS,可能导致短暂吞吐下降
  BBR v2:改进 PROBE_RTT,减少影响

问题3:多流竞争不公平
  同一瓶颈上多条 BBR 流:btlbw 各自独立估算,可能过于乐观
  BBR v2:引入丢包信号辅助限速(L_target=2%),改善公平性

异常与边界场景

场景一:带宽突然增加(扩容或路由切换)

初始状态:btlbw=100Mbps,PROBE_BW 稳态运行

带宽变化:路径切换,瓶颈带宽从 100Mbps → 200Mbps

BBR 的处理:
  t=0:    pacing_rate = 100Mbps(旧 btlbw)
  t=RTT:  phase0 以 1.25×100=125Mbps 探测
          实际吞吐=125Mbps(新带宽充足,无队列积压)
          新 bw_sample = 125Mbps → btlbw 更新为 125Mbps
  t=2RTT: phase0 再次以 1.25×125=156Mbps 探测
          bw_sample ≈ 156Mbps → btlbw=156Mbps
  t=N×RTT: 通过 PROBE_BW 周期性探测,btlbw 逐渐逼近 200Mbps
  
  收敛时间:约 log₁.₂₅(200/100) = 3.1 个探测相位 ≈ 3 RTT
  特点:无需丢包,主动感知带宽增长

场景二:RTT 突然增加(路由变化或网络抖动)

初始状态:rtprop=20ms,PROBE_BW 稳态

RTT 变化:拥塞或路由切换,RTT 从 20ms → 50ms

BBR 的处理:
  t=0:    rtprop=20ms(最小 RTT 记录)
          当前 RTT=50ms > rtprop,不更新 rtprop
          cwnd = btlbw × rtprop × cwnd_gain(用旧 rtprop)
          pacing_rate = btlbw × pacing_gain(不变)
  
  问题:cwnd 基于旧 rtprop(20ms),实际 RTT=50ms
        in_flight 可能超过 cwnd → 等效于窗口不足,吞吐下降约 60%
  
  10s后:触发 PROBE_RTT(10s 未更新 rtprop)
  PROBE_RTT 阶段:
    cwnd = 4 MSS(极小值)
    持续 200ms 测量 RTT
    如果 RTT 真的是 50ms(稳定的新 RTprop)→ rtprop=50ms 更新
    如果 RTT 降回 20ms(临时抖动)→ rtprop 仍=20ms,不更新
  
  更新后:cwnd = btlbw × 50ms × 2 = 原来的 2.5 倍,吞吐恢复

场景三:多流竞争(BBR 流公平性)

场景:同一 100Mbps 瓶颈上,2 条 BBR 流(flow1, flow2)

理想情况:各占 50Mbps
实际问题:
  flow1 的 btlbw_filter 记录到 80Mbps(历史峰值)
  flow2 的 btlbw_filter 记录到 70Mbps
  两流共同 pacing_rate = 80+70 = 150Mbps > 100Mbps(链路满载)
  → 队列积压,RTT 增加,但 BBR 不减速(不响应丢包)

缓解措施:
  1. FQ 调度器(tc-fq):每流独立限速,防止单流垄断
  2. BBR v2:引入 inflight_lo 基于丢包率限制 in_flight
  3. ECN:网络设备标记拥塞,BBR v2 可响应 CE 标记

场景四:ECN 配合使用

ECN(Explicit Congestion Notification,RFC 3168):
  路由器在队列开始满时,给数据包打 CE(Congestion Experienced)标记
  接收方通过 ACK 中的 ECE 标志通知发送方
  发送方收到 ECE → 减速(类似丢包处理)

CUBIC + ECN:
  收到 ECE → ssthresh = cwnd * 0.7,cwnd = ssthresh
  效果:在丢包前提前减速,减少实际丢包率

BBR v1 + ECN:
  BBR v1 基本忽略 ECN(设计上不响应丢包/ECN)
  可能导致在部署 ECN 的网络中行为不友好

BBR v2 + ECN:
  BBR v2 响应 CE 标记,调整 pacing_rate 和 inflight_lo
  在 ECN 环境中与 CUBIC 更公平
  
配置(Linux):
  sysctl net.ipv4.tcp_ecn=1         # 启用 ECN
  sysctl net.ipv4.tcp_congestion_control=bbr  # 使用 BBR
  tc qdisc add dev eth0 root fq     # 部署 FQ 调度器

参考资料

论文

  1. CUBIC: Sangtae Ha, Injong Rhee, Lisong Xu. CUBIC: A New TCP-Friendly High-Speed TCP Variant. ACM SIGOPS Operating Systems Review, 2008.
  2. BBR v1: Neal Cardwell, Yuchung Cheng, C. Stephen Gunn, Soheil Hassas Yeganeh, Van Jacobson. BBR: Congestion-Based Congestion Control. ACM Queue, 2016.
  3. BBR v2: Neal Cardwell et al. BBRv2: A Model-Based Congestion Control. IETF TSVWG, 2019.
  4. 原始拥塞控制: Van Jacobson, Michael J. Karels. Congestion Avoidance and Control. ACM SIGCOMM, 1988.

RFC

  1. RFC 5681 — TCP Congestion Control(Reno 规范)
  2. RFC 3168 — The Addition of Explicit Congestion Notification (ECN) to IP
  3. RFC 6582 — The NewReno Modification to TCP's Fast Recovery Algorithm

代码与文档

  1. Linux 内核 CUBIC 实现:net/ipv4/tcp_cubic.c
  2. Linux 内核 BBR 实现:net/ipv4/tcp_bbr.c
  3. Google BBR 技术博客:https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster

书籍

  1. Computer Networks: A Systems Approach, Peterson & Davie, Chapter 6
  2. TCP/IP Illustrated, Volume 1, W. Richard Stevens, Chapter 16
← 返回列表

评论 (0)

暂无评论,来留下第一条吧。

发表评论