TCP Congestion Control Algorithm Evolution: From Tahoe to BBRv3 — Principles, Performance, and Linux Practice

🔊

TCP congestion control is a critical determinant of network transport performance and a cornerstone of internet stability. Whether it’s webpage loading speed in web services, smoothness of live video streaming, inter-container communication in cloud-native applications, or download efficiency in P2P transfers, all rely on TCP congestion control to coordinate bandwidth allocation. A single BitTorrent node, for example, may maintain hundreds of concurrent TCP connections, and choosing the wrong algorithm can severely degrade bandwidth utilization. Since Van Jacobson’s seminal 1988 paper at SIGCOMM, congestion control algorithms have evolved over nearly four decades — from heuristic loss-based methods to precise model-based measurement. This article covers 12 major congestion control algorithms, explaining their core ideas, strengths, weaknesses, and applicable scenarios, from Tahoe and Reno to CUBIC, BBR, and Copa.

Fundamentals of Congestion Control

All TCP congestion control algorithms work around the Congestion Window (CWND) — the maximum amount of unacknowledged data the sender can have in flight:

1
Throughput ≈ min(CWND, Receive Window) / RTT

This formula reveals two constraints on TCP throughput: the sender’s window (CWND) and the receiver’s window (Receiver Window), with the smaller of the two determining actual throughput. CWND is dynamically adjusted by the congestion control algorithm, while the receive window is determined by the receiver’s buffer size.

The core differences between algorithms manifest in three dimensions:

  1. CWND growth rate (slow start vs congestion avoidance) — determines connection startup and bandwidth probing efficiency
  2. Congestion detection signal (packet loss vs delay vs bandwidth measurement) — determines how the algorithm perceives network state
  3. Rate reduction strategy (multiplicative decrease vs model-driven adjustment) — determines recovery speed after congestion events
mermaid
flowchart TD
    A["Connection established<br/>CWND = IW"] --> B["Slow Start<br/>CWND doubles per RTT"]
    B -->|"CWND &#8805; ssthresh"| C["Congestion Avoidance<br/>CWND +1 MSS per RTT"]
    C -->|"Packet loss / Timeout"| D{"Signal type"}
    D -->|"3 duplicate ACKs"| E["Fast Retransmit + reduce"]
    D -->|"Timeout"| F["CWND = 1<br/>restart Slow Start"]
    E --> C
    F --> B
    style A fill:#2196F3,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#4CAF50,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#FF9800,color:#fff
    style F fill:#f44336,color:#fff

TCP Tahoe (1988)

Van Jacobson’s 1988 SIGCOMM paper introduced the original congestion control framework, later known as TCP Tahoe. Tahoe defined three core phases:

  • Slow Start: After connection establishment, CWND starts from an initial window (typically 10 segments) and increases by 1 MSS per ACK received, achieving exponential growth to quickly probe available bandwidth.
  • Congestion Avoidance: Once CWND reaches the slow start threshold (ssthresh), it increases by only 1 MSS per RTT, shifting to linear growth for cautious bandwidth utilization.
  • Fast Retransmit: Upon receiving 3 duplicate ACKs, the lost segment is retransmitted immediately without waiting for a timeout.

Tahoe’s limitation is that after packet loss, it falls back to slow start (CWND = 1 MSS), re-probing bandwidth from scratch every time. On high-bandwidth links, this results in significant bandwidth waste and lengthy recovery times. This flaw directly motivated the creation of Reno, which introduced fast recovery to avoid the inefficiency of restarting slow start after every loss.

TCP Reno (1990)

Reno added Fast Recovery on top of Tahoe, forming the complete AIMD (Additive Increase Multiplicative Decrease) model. Its core philosophy can be summarized in one sentence: increase linearly under light load, back off exponentially when congestion is detected.

mermaid
flowchart TD
    SS["Slow Start<br/>CWND = IW<br/>Exponential growth"] -->|"CWND ≥ ssthresh"| CA["Congestion Avoidance<br/>+1 MSS per RTT<br/>Linear growth"]
    CA -->|"Packet loss"| LOSS{"Signal type"}
    LOSS -->|"3 duplicate ACKs"| FR["Fast Recovery<br/>ssthresh = CWND/2"]
    LOSS -->|"Timeout"| TO["Timeout<br/>ssthresh = CWND/2<br/>CWND = 1"]
    FR -->|"New ACK"| CA
    TO --> SS
    style SS fill:#2196F3,color:#fff
    style CA fill:#4CAF50,color:#fff
    style LOSS fill:#9C27B0,color:#fff
    style FR fill:#FF9800,color:#fff
    style TO fill:#f44336,color:#fff

During slow start, Reno exponentially probes available bandwidth — each ACK received increments CWND by one MSS (Maximum Segment Size), effectively doubling it every RTT. When CWND reaches the slow start threshold (ssthresh), it transitions to congestion avoidance, incrementing by only 1 MSS per RTT for linear growth. Upon detecting packet loss (three duplicate ACKs), it immediately halves ssthresh to CWND/2, sets CWND to ssthresh, and enters fast recovery.

Reno Classic AIMD Sawtooth CWND Evolution

Reno’s limitation: Conservative on high-bandwidth high-latency paths. Consider a link with 100ms RTT and 1Gbps bandwidth — BDP is approximately 12.5MB. After a single packet loss, CWND halves and requires thousands of RTTs to recover to its original size, meaning several minutes of recovery time with severe bandwidth waste.

TCP Vegas (1994)

Vegas, proposed by Brakmo and Peterson, was the first delay-based congestion control algorithm, marking the transition from reactive to predictive congestion control.

Vegas estimates network queuing by monitoring RTT changes, proactively adjusting the sending rate before packet loss occurs. It maintains two key measurements: BaseRTT (the minimum observed RTT, representing no queuing delay) and CurrentRTT (the currently measured RTT). It detects congestion by comparing the difference between expected and actual throughput:

$$ Diff = \left(\frac{CWND}{BaseRTT} - \frac{CWND}{CurrentRTT}\right) \times BaseRTT $$

When Diff falls below threshold α, bandwidth is considered abundant and CWND is increased. When Diff exceeds threshold β, congestion is anticipated and CWND is decreased. Typical values for α and β are 2 and 4, respectively.

mermaid
flowchart TD
    A["Measure RTT<br/>BaseRTT / CurrentRTT"] --> C["Compute Diff<br/>= CWND/BaseRTT &#8722; CWND/CurrentRTT"]
    C --> D{"Diff value"}
    D -->|"Diff < &#945;"| E["Bandwidth abundant<br/>CWND += 1"]
    D -->|"&#945; &#8804; Diff &#8804; &#946;"| F["Stable zone<br/>CWND held"]
    D -->|"Diff > &#946;"| G["Congestion imminent<br/>CWND &#8722;= 1"]
    style A fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#4CAF50,color:#fff
    style F fill:#FF9800,color:#fff
    style G fill:#f44336,color:#fff

Vegas’ innovation lies in its forward-looking congestion avoidance — it reacts as soon as queuing begins, rather than waiting for buffer overflow and packet loss. Under ideal conditions, this maintains extremely low queuing delay and avoids the characteristic “sawtooth” oscillation of traditional AIMD algorithms.

Vegas Delay-Based Smooth CWND Evolution

However, when sharing a bottleneck link with loss-based algorithms like Reno or CUBIC, Vegas behaves too “politely” — it gives up bandwidth due to the minor queuing delay it introduces, allowing aggressive loss-based flows to take over. This compatibility issue has severely limited Vegas’ real-world deployment.

TCP NewReno (1996)

NewReno, proposed by Floyd and Henderson, is a targeted improvement to Reno’s fast recovery mechanism, specifically addressing performance issues when multiple packets are lost within a single window.

Reno’s fast recovery has a flaw: when multiple packets are lost in the same window, the first new ACK received during fast recovery (acknowledging the first retransmitted packet) causes Reno to exit fast recovery, even though other lost packets remain unretransmitted. This forces Reno to enter and exit fast recovery repeatedly, fixing only one loss at a time.

NewReno’s key improvement is Partial ACK detection logic: if the ACK received during fast recovery acknowledges only a portion of the outstanding data (a partial ACK), NewReno does not exit fast recovery. Instead, it immediately retransmits the next lost packet while keeping CWND unchanged. It only exits fast recovery when an ACK acknowledges all data that was outstanding when fast recovery began.

mermaid
flowchart TD
    A["3 duplicate ACKs<br/>enter Fast Recovery"] --> B["Retransmit lost packet"]
    B --> C{"ACK received?"}
    C -->|"Partial ACK<br/>data still unacknowledged"| D["Retransmit next lost packet<br/>stay in Fast Recovery"]
    D --> C
    C -->|"Full ACK<br/>all data acknowledged"| E["Exit Fast Recovery<br/>enter Congestion Avoidance"]
    style A fill:#2196F3,color:#fff
    style B fill:#FF9800,color:#fff
    style C fill:#9C27B0,color:#fff
    style D fill:#FF9800,color:#fff
    style E fill:#4CAF50,color:#fff

This improvement makes NewReno significantly outperform Reno on links with random packet loss, and it requires no modifications to the receiver — it is a fully sender-side improvement. NewReno was later standardized as RFC 2582 (later updated by RFC 3782).

TCP Westwood+ (2002)

Westwood+, proposed by Mascolo and colleagues, specifically addresses the throughput degradation caused by random packet loss in wireless networks. Its core idea is to use bandwidth estimation rather than simple loss signals to adjust the congestion window.

Westwood+ continuously estimates available bandwidth by monitoring ACK arrival rates. When packet loss is detected, instead of Reno’s brute-force halving of CWND, it calculates a new window value based on the estimated bandwidth:

$$ ssthresh = \frac{BWEst \times RTT_{min}}{MSS} $$

Westwood+ Bandwidth-Aware Congestion Window Evolution

This bandwidth-aware rate reduction strategy excels on wireless links with random packet loss — when packet loss is caused by channel noise rather than congestion, the bandwidth estimate does not drop significantly, preventing excessive CWND reduction.

The original Westwood used only sender-side measurements. Westwood+ added receiver-side ACK filtering to eliminate the effects of ACK Compression, making bandwidth estimation more accurate.

BIC (2004)

BIC (Binary Increase Congestion Control), proposed by Xu, Harfoush, and Rhee, was designed for high-bandwidth long-distance networks and is the predecessor of CUBIC.

BIC uses binary search to find the bandwidth boundary. When congestion occurs, the current window $W_{max}$ is recorded. During recovery, binary search is performed between $W_{min}$ (the post-congestion window value) and $W_{max}$, quickly approaching but not exceeding the previous window ceiling. Above $W_{max}$, a Max Probing strategy gradually expands the search range to discover new bandwidth limits.

BIC performs well in high BDP networks but has two notable problems: first, its window function shape is not smooth — the piecewise binary search causes window oscillations at transition points; second, it is too aggressive in low-bandwidth networks, lacking friendliness when coexisting with traditional algorithms like Reno. These issues motivated the design of CUBIC.

BIC Binary Search Congestion Window Evolution

TCP Hybla (2004)

Hybla, proposed by Caini and Firrincieli, is specifically designed for long-RTT links such as satellite communications.

Hybla’s core observation is that in traditional TCP, connections with long RTTs have much slower window growth during congestion avoidance compared to short-RTT connections. Hybla compensates for this unfairness by introducing an “RTT normalization” factor, simulating the behavior of an ideal reference connection so that long-RTT flows achieve equivalent window growth rates to short-RTT flows.

In extreme scenarios like GEO satellite links (RTT ≈ 500ms), Hybla can improve throughput by several times over standard Reno. Its main limitation is that parameter selection depends on prior knowledge of the link type, making it less effective in environments with dynamically changing link characteristics.

Hybla RTT-Normalized Congestion Window Evolution

TCP CUBIC (2005)

CUBIC is currently the default congestion control algorithm in the Linux kernel, proposed by Injong Rhee and colleagues, specifically designed to address Reno’s inefficiency in high BDP (Bandwidth-Delay Product) networks.

Cubic Growth Function

CUBIC’s most fundamental innovation is using a cubic function to drive window growth:

$$W(t) = C \times (t - K)^3 + W_{max}$$

Where $t$ is the time elapsed since the last congestion event, $W_{max}$ is the window size at the time of congestion, $C$ is a scaling constant (default 0.4), and $K = \sqrt[3]{W_{max} \times \beta / C}$ is the time needed for the window to recover to $W_{max}$.

mermaid
flowchart TD
    B["W(t) = C×(t&#8722;K)³ + Wmax<br/>t = time since last loss"] --> D{"Window Position"}
    D -->|"Below Wmax"| E["Concave growth<br/>Fast catch-up"]
    D -->|"Above Wmax"| G["Convex growth<br/>Probe new ceiling"]
    E --> H{"Packet loss?"}
    G --> H
    H -->|"Yes"| I["CWND × 0.7<br/>Record new Wmax"]
    I --> B
    style B fill:#2196F3,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#4CAF50,color:#fff
    style G fill:#FF9800,color:#fff
    style H fill:#9C27B0,color:#fff
    style I fill:#f44336,color:#fff

CUBIC S-Curve Congestion Window Evolution

Three Key Properties of CUBIC

CUBIC’s core idea is to use time rather than ACK arrivals to drive window growth, making the growth rate independent of RTT:

  • Concave growth: Fast recovery far below $W_{max}$. After a loss event, CUBIC’s window function rises sharply, quickly pulling CWND back to pre-congestion levels — precisely where Reno performs worst.
  • Convex growth: Active probing above $W_{max}$. Once CWND exceeds the previous congestion window value, the function curve accelerates, actively searching for new bandwidth ceilings.
  • RTT fairness: Flows with different RTTs achieve similar window increments over a fixed time period. In Reno, short-RTT flows grow their congestion windows faster and can “starve” long-RTT flows. CUBIC eliminates this RTT bias.

Why CUBIC Replaced BIC

CUBIC’s predecessor was BIC (Binary Increase Congestion Control), which used binary search to probe bandwidth boundaries — it performed well in high-bandwidth networks but was too aggressive in low-bandwidth scenarios, and its window function shape was not smooth. CUBIC replaced BIC’s piecewise binary search with a smooth cubic function, preserving high BDP efficiency while improving friendliness in low-bandwidth networks.

DCTCP (2010)

DCTCP (Data Center TCP), proposed by Alizadeh and colleagues, is purpose-built for data center networks. Data centers are characterized by high bandwidth (10Gbps-40Gbps), low latency (microseconds), limited buffers, and traffic patterns dominated by short bursts.

DCTCP’s core innovation is fine-grained congestion control using ECN (Explicit Congestion Notification) signals. Switches mark packets when the queue length exceeds a threshold, the receiver computes the fraction of marked packets $F$, and the sender calculates a congestion factor $\alpha$:

$$ \alpha = (1 - g) \times \alpha + g \times F $$

Where $g$ is a smoothing factor (default 1/16). When congestion occurs, CWND is set to $CWND \times (1 - \alpha/2)$, rather than being brutally halved. The more severe the congestion, the more aggressive the reduction; the milder the congestion, the gentler the reduction.

mermaid
flowchart TD
    A["Queue > threshold<br/>Switch marks ECN"] --> C["Receiver computes marked fraction F"]
    C --> D["Sender updates congestion factor<br/>&#945; = (1&#8722;g)&#945; + gF"]
    D --> E{"On congestion"}
    E -->|"Mild &#945; small"| F["CWND &#215; (1&#8722;&#945;/2)<br/>slight reduction"]
    E -->|"Severe &#945; large"| G["CWND &#215; (1&#8722;&#945;/2)<br/>large reduction"]
    style A fill:#2196F3,color:#fff
    style C fill:#FF9800,color:#fff
    style D fill:#FF9800,color:#fff
    style E fill:#9C27B0,color:#fff
    style F fill:#4CAF50,color:#fff
    style G fill:#f44336,color:#fff

DCTCP’s remarkable achievement is the ideal combination of low latency + high throughput — in production environments, DCTCP reduces tail latency by over 90% while maintaining close to 100% link utilization. However, DCTCP depends on switch ECN support and is only suitable for controlled data center environments.

DCTCP ECN-Aware Gradual CWND Evolution

BBR’s Paradigm Revolution (2016)

Google’s 2016 release of BBR (Bottleneck Bandwidth and Round-trip propagation time) fundamentally changed the traditional paradigm of congestion control. The core insight: Packet loss is not equivalent to congestion.

In wireless networks, cellular networks, and similar environments, packets may be lost due to signal interference or channel attenuation — not because the network link is congested. Traditional loss-based algorithms mistakenly reduce their sending rate in such cases, causing severe bandwidth waste.

DimensionTraditional loss-based (Reno / CUBIC)BBR (model-driven)
SignalPacket lossBandwidth + RTT
AssumptionLoss = congestionMeasure BtlBw + RTprop
ActionLoss → slow downOperate at BDP point
On lossy linksBandwidth utilization drops sharplyMaintains high throughput

Packet loss ≠ congestion is BBR’s starting point: on wireless networks packets are frequently lost to signal interference, and slowing down in response is pure waste.

BBR’s Key Innovations

  • Loss-independent: Maintains high throughput even with up to 15% packet loss, while CUBIC’s throughput drops dramatically at just 1% loss.
  • Proactive BDP estimation: By measuring bottleneck bandwidth (BtlBw) and propagation delay (RTprop), BBR calculates the optimal amount of data for the link and operates at the BDP point — neither queuing nor wasting capacity.
  • Bufferbloat avoidance: BBR does not fill up buffers even when they are large, avoiding excessive queuing delay — critical for latency-sensitive applications such as real-time audio/video and online gaming.

BBR Model-Driven CWND Evolution

BBR Version Evolution

Since its initial release, BBR has gone through three major versions:

VersionYearCore Improvements
BBR v12016First model-based congestion control, achieving high throughput with low latency; suffered from poor coexistence fairness with Reno/CUBIC and high packet loss during STARTUP
BBR v22019Added ECN signal support, improved fairness when coexisting with Reno/CUBIC, reduced STARTUP phase packet loss
BBR v32023Fixed bandwidth convergence bugs, reduced STARTUP gain from 2.89 to 2.77, further decreased queuing delay, optimized short-flow performance

Key Drivers of Version Evolution

BBR’s version evolution reflects the deepening understanding of “ideal congestion control” in both academia and industry:

  1. Coexistence fairness: BBR v1 was too aggressive when sharing a bottleneck link with other algorithms, preempting CUBIC flows’ bandwidth. v2 and v3 progressively improved this through more conservative contention strategies.
  2. STARTUP oscillation: The initial version’s exponential gain during STARTUP was too high (2.89), causing frequent over-probing and packet loss. v3 reduced the gain to 2.77, significantly reducing startup oscillation.
  3. Bandwidth convergence: In multi-flow bottleneck sharing scenarios, v1 and v2 suffered from unstable bandwidth allocation. v3 achieved faster and more stable convergence through algorithmic optimization.

PCC (2016)

PCC (Performance-oriented Congestion Control), proposed by Dong and colleagues, was released in the same year as BBR but takes a fundamentally different approach — framing congestion control as an online learning problem.

PCC makes no prior assumptions about congestion signals (whether loss, delay, or bandwidth), instead directly optimizing the sending rate through experimentation. Its core is a Monitor-Compare-Arrange loop: the sender slightly adjusts the sending rate in one direction (+Δt), observes utility changes; then adjusts in the other direction (-Δt), compares results, and continues in the direction that yields better performance.

mermaid
flowchart TD
    A["Current rate r"] --> B["Try r + &#916;<br/>measure utility U&#8314;&#8314;"]
    B --> C["Try r &#8722; &#916;<br/>measure utility U&#8315;"]
    C --> D{"U&#8314;&#8314; > U&#8315;?"}
    D -->|"Yes"| E["Raise rate"]
    D -->|"No"| F["Lower rate"]
    E --> A
    F --> A
    style E fill:#4CAF50,color:#fff
    style F fill:#f44336,color:#fff

PCC’s utility function combines throughput and latency metrics:

$$ U = \frac{Throughput^{\alpha}}{Latency^{\beta}} $$

The advantage of this approach is that it requires no assumptions about network behavior, automatically adapting to various link conditions. However, it has higher computational overhead and may converge more slowly. The subsequent PCC Vivace improved convergence speed by introducing an online gradient ascent algorithm.

Copa (2018)

Copa, proposed by Arun and Balakrishnan, is the latest generation of delay-aware congestion control. It returns to Vegas’ delay-probing approach but employs a more sophisticated “Carrier Sensing” mechanism.

Copa dynamically adjusts the sending rate by sensing queuing delay $d_{queued}$. Its core parameter $\lambda$ determines the CWND increase per ACK:

mermaid
flowchart TD
    A["Measure queuing delay<br/>d = RTT &#8722; BaseRTT"] --> B["Compute growth rate<br/>&#955; = &#948; / d"]
    B --> C{"d < target delay?"}
    C -->|"Yes, low delay"| D["CWND += &#955;<br/>accelerate growth"]
    C -->|"No, high delay"| E["CWND &#8722;= &#955;<br/>actively yield"]
    style D fill:#4CAF50,color:#fff
    style E fill:#FF9800,color:#fff
$$ \lambda = \frac{\delta}{d_{queued}} $$

Where $\delta$ is a parameter (default 0.5). When queuing delay increases, $\lambda$ decreases, slowing window growth; when queuing delay decreases, $\lambda$ increases, accelerating growth. Copa aims to maintain a fixed queuing delay target (typically corresponding to 5 RTTs of queuing).

Copa’s elegance lies in achieving smooth congestion control by adjusting the growth rate rather than mechanically raising or lowering the window. In benchmarks, Copa matches or exceeds BBR in throughput while maintaining lower latency. It also includes a competitive mode that prevents starvation when coexisting with aggressive flows like CUBIC.

TCP Congestion Control Evolution Timeline

From 1988 to 2023, TCP congestion control algorithms have evolved from simple beginnings to sophisticated designs. The two timelines below illustrate the development of major algorithms:

Early Era (1988—2004)

mermaid
flowchart TD
    T["1988: Tahoe<br/>Slow Start + CA<br/>Fast Retransmit"]
    R["1990: Reno<br/>+ Fast Recovery<br/>AIMD Classic"]
    V["1994: Vegas<br/>Delay probing<br/>Predict congestion"]
    N["1996: NewReno<br/>Partial ACK<br/>Multi-loss fix"]
    W["2002: Westwood+<br/>BW estimation<br/>Wireless friendly"]
    B["2004: BIC<br/>Binary search<br/>High BDP efficiency"]

    T --> R
    R --> N
    R --> V
    N --> B
    V --> W
    style T fill:#2196F3,color:#fff
    style R fill:#2196F3,color:#fff
    style V fill:#9C27B0,color:#fff
    style N fill:#FF9800,color:#fff
    style W fill:#4CAF50,color:#fff
    style B fill:#f44336,color:#fff

Modern Era (2004—2023)

mermaid
flowchart TD
    H["2004: Hybla<br/>Satellite optimized<br/>RTT normalization"]
    C["2005: CUBIC<br/>Cubic function<br/>RTT independent"]
    D["2010: DCTCP<br/>Data center<br/>ECN marking"]
    P["2016: PCC<br/>Performance-driven<br/>Online learning"]
    BR["2016: BBR v1-3<br/>Model-driven<br/>BtlBw+RTprop"]
    O["2018: Copa<br/>Delay-aware<br/>Carrier sensing"]

    H --> C
    C --> D
    D --> P
    C --> BR
    BR --> O
    style H fill:#2196F3,color:#fff
    style C fill:#2196F3,color:#fff
    style D fill:#FF9800,color:#fff
    style P fill:#9C27B0,color:#fff
    style BR fill:#4CAF50,color:#fff
    style O fill:#9C27B0,color:#fff

These timelines clearly reveal the trajectory of congestion control evolution: from loss-based reactive control, to delay-based predictive control, and finally to model-driven and performance-driven intelligent control. This evolution reflects the technological demands of a changing internet — from simple wired networks to complex heterogeneous environments.

Linux Practical: View and Switch Algorithms

Now that we understand the theory, let’s explore how to work with congestion control algorithms on a real Linux system. The following commands let you view and switch the algorithm:

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# View the currently active congestion control algorithm
sysctl net.ipv4.tcp_congestion_control

# View available algorithms supported by the kernel
sysctl net.ipv4.tcp_available_congestion_control

# Temporarily switch to BBR (lost on reboot)
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

# Make it permanent: write to sysctl configuration
echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf

# Check kernel version (BBR requires Linux kernel ≥ 4.9)
uname -r

Example output:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Check current algorithm
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic

# Check available algorithms
$ sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic bbr

# Check kernel version (must be ≥ 4.9 for BBR)
$ uname -r
5.15.0-91-generic

If bbr does not appear in the output, the BBR kernel module has not been loaded. You can load it manually:

bash
1
2
3
4
5
# Load the BBR module
sudo modprobe tcp_bbr

# Confirm the module is loaded
lsmod | grep tcp_bbr

Note that changing the congestion control algorithm is a system-wide operation — all new TCP connections will use the new algorithm. Established connections continue using the algorithm they were created with and are unaffected by the switch.

With the advent of eBPF technology, Linux also supports user-defined congestion control algorithms via BPF (BPF_PROG_TYPE_SOCK_OPS), offering new flexibility for congestion control research and deployment.

Performance Comparison

The performance gap between congestion control algorithms becomes stark on lossy links. The following table shows throughput comparison under identical network conditions (100ms RTT, 100Mbps bandwidth):

Packet Loss RateRenoCUBICBBR
0%100%100%100%
0.1%~50%~85%~99%
1%~10%~30%~95%
3%~3%~12%~88%
5%~1%~5%~80%
10%~0.5%~2%~60%

The data reveals a clear picture:

  • At 0.1% loss rate, CUBIC maintains about 85% throughput, but Reno has already lost half its bandwidth.
  • At 1% loss rate, CUBIC drops to ~30%, while BBR still maintains over 95% throughput — this is the typical loss range for wireless and cellular networks.
  • At 5% loss rate, Reno and CUBIC are practically unusable, while BBR still delivers about 80% throughput.

This explains why some network applications — such as P2P transfers and video streaming — often suffer from poor transport performance on wireless networks. It is not just the application-layer protocol at fault; the underlying TCP congestion control algorithm plays an equally critical role.

Algorithm Characteristics Comparison

Different congestion control algorithms vary significantly in their congestion signals, applicable scenarios, and design philosophies:

AlgorithmYearTypeCore Congestion SignalApplicable Scenario
Tahoe1988Loss-basedDup ACK / TimeoutHistorical reference
Reno1990Loss-basedDup ACKLow bandwidth, low latency
Vegas1994Delay-basedRTT variationLow-latency networks
NewReno1996Loss-basedPartial ACKModerate loss links
Westwood+2002BW estimationACK rate + LossWireless networks
BIC2004Loss-basedDup ACKHigh BDP networks
Hybla2004Loss-basedRTT normalizationSatellite links
CUBIC2005Loss-basedDup ACK (time-driven)Linux default / general
DCTCP2010HybridECN marking ratioData center
BBR v32016Model-basedBtlBw + RTpropHigh throughput / wireless
PCC2016Performance-drivenUtility functionGeneral / complex links
Copa2018Delay-basedQueuing delayGeneral / low latency

As the diversity of algorithm types and applicable scenarios demonstrates, there is no single “best” congestion control algorithm — the right choice depends on the specific network environment, application requirements, and deployment constraints.

References

  • Jacobson, V. (1988). Congestion avoidance and control. SIGCOMM ‘88.
  • Brakmo, L. S., & Peterson, L. L. (1995). TCP Vegas: End to end congestion avoidance on a global Internet. IEEE Journal on Selected Areas in Communications, 13(8).
  • Floyd, S., & Henderson, T. (1999). The NewReno modification to TCP’s fast recovery algorithm. RFC 2582.
  • Mascolo, S., et al. (2001). TCP Westwood: Bandwidth estimation for enhanced transport over wireless links. MobiCom ‘01.
  • Xu, L., Harfoush, K., & Rhee, I. (2004). Binary increase congestion control (BIC) for fast long-distance networks. INFOCOM 2004.
  • Caini, C., & Firrincieli, R. (2004). TCP Hybla: a TCP enhancement for heterogeneous networks. International Journal of Satellite Communications and Networking, 22(5).
  • Ha, S., Rhee, I., & Xu, L. (2008). CUBIC: a new TCP-friendly high-speed TCP variant. ACM SIGOPS Operating Systems Review, 42(5).
  • Alizadeh, M., et al. (2010). Data Center TCP (DCTCP). SIGCOMM ‘10.
  • Cardwell, N., et al. (2016). BBR: Congestion-based congestion control. ACM Queue, 14(5).
  • Dong, M., et al. (2015). PCC: Re-architecting congestion control for consistent high performance. NSDI ‘15.
  • Arun, V., & Balakrishnan, H. (2018). Copa: Practical delay-based congestion control for the internet. NSDI ‘18.
  • Cardwell, N., et al. (2022). BBR Congestion Control (IETF Draft). https://datatracker.ietf.org/doc/draft-cardwell-iccrg-bbr-congestion-control/