Historically, the Linux kernel has relied on loss-based TCP congestion control algorithms, specifically CUBIC or Reno. These algorithms increase the transmission window until they detect packet loss, at which point they halve the window. On modern, high-bandwidth, high-latency networks (often referred to as Long Fat Networks, or LFNs), or on networks with shallow buffers experiencing “bufferbloat”, loss-based algorithms perform terribly. They mistake buffer drops for actual congestion, artificially throttling throughput.
Developed by Google, BBR (Bottleneck Bandwidth and Round-trip propagation time) fundamentally changes this paradigm. Instead of reacting to packet loss, BBR actively measures the actual maximum bandwidth and the minimum round-trip time (RTT) of the connection. By modeling the network dynamically, BBR can pump data at the exact rate the network can handle, practically eliminating bufferbloat and drastically increasing throughput on lossy or high-latency links.
Understanding the BBR Architecture
TCP CUBIC is “reactive.” It blindly pushes data until a packet drops. In contrast, TCP BBR is “proactive.”
BBR operates in a continuous cycle of four states:
- Startup: BBR exponentially increases the sending rate, probing the network to find the absolute maximum bottleneck bandwidth (similar to TCP Slow Start, but much faster).
- Drain: Once the bottleneck is found, BBR immediately drops the sending rate to drain the router buffers it just filled during Startup.
- ProbeBW: The steady state. BBR spends the vast majority of its time here, gently probing for more bandwidth and then backing off slightly, hovering exactly at the network’s capacity without filling buffers.
- ProbeRTT: Periodically (every 10 seconds), BBR drops its sending rate significantly for a fraction of a second to measure the true, unloaded minimum Round-Trip Time of the link.
Prerequisites for Enabling TCP BBR
TCP BBR requires Linux Kernel version 4.9 or higher. However, for production workloads, Kernel 5.4 or newer (which includes BBRv2 enhancements) is highly recommended.
Check your current kernel version:
uname -r
BBR also requires the Fair Queue (fq) packet scheduler to function optimally. While BBR can work with fq_codel in newer kernels, standard fq ensures the pacing required for BBR’s bandwidth modeling.
Step 1: Enabling BBR via sysctl
To enable BBR, you must modify the kernel parameters using sysctl. This can be done live without rebooting the server.
First, verify what congestion control algorithm your system is currently using (it is almost certainly cubic):
sysctl net.ipv4.tcp_congestion_control
To switch to BBR, you need to change both the default queuing discipline (qdisc) and the congestion control algorithm.
Open the sysctl configuration file in a text editor:
sudo nano /etc/sysctl.d/99-bbr.conf
Add the following two lines:
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
Apply the changes immediately:
sudo sysctl --system
Step 2: Verifying the Configuration
After applying the sysctl settings, verify that the kernel has successfully loaded the BBR module and applied it to the IPv4 stack.
sysctl net.ipv4.tcp_congestion_control
This should now output net.ipv4.tcp_congestion_control = bbr.
You can also verify that the BBR kernel module is actively loaded into memory:
lsmod | grep bbr
Step 3: Measuring the Performance Impact
The true test of BBR is on high-latency links. If you are serving content from a server in London to a client in Sydney (where RTT is ~250ms), CUBIC will struggle to utilize a 1 Gbps pipe due to the TCP Window scaling mathematics and minor packet loss. BBR will instantly ramp up to utilize the full pipe.
You can benchmark the difference using the iperf3 utility.
On your Linux server (running BBR), start the iperf3 server:
iperf3 -s
On a remote client (preferably with high latency to the server), run the test:
iperf3 -c <server_ip> -t 30
You can dynamically toggle the server back to cubic (sudo sysctl -w net.ipv4.tcp_congestion_control=cubic) and run the test again to observe the stark difference in throughput.
Step 4: Monitoring BBR States with ss
Linux provides profound visibility into the TCP stack. You can view the internal state variables of the BBR algorithm for every active TCP connection using the ss (socket statistics) command.
ss -tni
This command lists all active TCP connections (-t), resolves them numerically (-n), and shows internal TCP information (-i). Look for the bbr output string, which will show you the exact bottleneck bandwidth BBR has calculated for that specific connection (e.g., bbr:(bw:980Mbps,mrtt:45.2ms,pacing_gain:1)).
Conclusion
Deploying TCP BBR is arguably the single most effective performance optimization a systems administrator can apply to a web server, VPN gateway, or content delivery node. By shifting away from archaic loss-based algorithms to a model driven by mathematical bandwidth calculation, BBR ensures maximum throughput and minimum latency across global networks.