Techzone/TCP Congestion Control — Deep Dive

TCP Congestion Control — Deep Dive

5 min readArticle

TCP congestion control is the sender-side mechanism that prevents any single TCP flow from overwhelming the network. The key state variable is cwnd (congestion window) — an internal limit at the sender that caps how much unacknowledged data can be in flight at once.

Core State Variables

Variable Meaning
cwnd Congestion window — sender's self-imposed limit (in MSS units)
ssthresh Slow start threshold — boundary between slow start and congestion avoidance
rwnd Receiver's advertised window — from TCP header
MSS Maximum Segment Size — typically 1460 bytes for 1500 MTU

Effective window = min(cwnd, rwnd) — the actual cap on in-flight data.

Phase 1: Slow Start

shell
Initial: cwnd = 1 MSS (or 10 MSS per RFC 6928), ssthresh = 65535 (or system default)

Per ACK received:  cwnd += 1 MSS
Per RTT:           cwnd doubles (exponential growth)

Stop when:  cwnd >= ssthresh  →  switch to congestion avoidance
            OR loss detected  →  react based on signal type

Slow start isn't slow — it grows exponentially. At 100ms RTT, cwnd hits 1MB in about 10 RTTs (~1 second).

Phase 2: Congestion Avoidance (AIMD)

Once cwnd >= ssthresh, switch to additive increase:

shell
Per ACK:  cwnd += MSS * MSS / cwnd    # ≈ 1 MSS per RTT
Per RTT:  cwnd += 1 MSS               # linear growth

This is Additive Increase. The window grows by one MSS per round trip instead of doubling.

Loss Detection and Response

Timeout (severe loss signal)

shell
Reaction:
  ssthresh = max(cwnd/2, 2*MSS)
  cwnd = 1 MSS
  re-enter slow start

This is brutal — drops cwnd to 1. Happens when the retransmit timer fires before 3 dup ACKs arrive.

Triple Duplicate ACK (mild loss signal)

Three dup ACKs mean one segment was lost but later ones arrived. Network isn't congested, just a drop.

TCP Reno Fast Recovery:

shell
ssthresh = max(cwnd/2, 2*MSS)
cwnd = ssthresh + 3*MSS   # 3 for the 3 dup ACKs
Fast retransmit lost segment
For each additional dup ACK: cwnd += 1 MSS  (inflate window)
On new ACK: cwnd = ssthresh, exit fast recovery

AIMD — The Core Principle

Additive Increase, Multiplicative Decrease:

  • Increase: Add 1 MSS per RTT when things are good (linear)
  • Decrease: Halve cwnd on congestion signal (multiplicative)

This is provably fair — if N flows share a bottleneck, each converges to 1/N of the capacity. It also converges even if flows start at different times.

CUBIC (Linux Default)

CUBIC replaces the linear increase with a cubic function of time since last loss event:

shell
W(t) = C * (t - K)^3 + Wmax

Where:
  Wmax = window at last loss point
  K = time to reach Wmax again = (Wmax * β / C)^(1/3)
  C = scaling constant (0.4)
  β = 0.7 (multiplicative decrease factor, vs 0.5 in Reno)

CUBIC grows more aggressively than Reno at high bandwidth-delay products (e.g., trans-oceanic links). Less conservative than Reno at recovering window after loss.

bash
# Verify CUBIC is active (Linux)
sysctl net.ipv4.tcp_congestion_control
# -> cubic

# See CUBIC-specific stats
ss -tin
# Look for: cwnd, ssthresh, rtt, mss in output

BBR — Bottleneck Bandwidth and RTT

BBR (Google, 2016) takes a completely different approach. Instead of reacting to loss, it models the network:

shell
Bottleneck Bandwidth (BtlBw) = max delivery rate observed
RTprop = min RTT observed

cwnd = BtlBw * RTprop  (the BDP — bandwidth delay product)

BBR alternates between probing for more bandwidth and draining the queue. It doesn't treat packet loss as the primary congestion signal — it targets the BDP directly.

bash
# Enable BBR on Linux (requires kernel 4.9+)
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
sudo sysctl -w net.core.default_qdisc=fq   # BBR needs fair queue scheduler

# Verify
sysctl net.ipv4.tcp_congestion_control
# -> bbr

# Watch BBR parameters on a live socket
ss -tin dst <ip>
# Output: bbrv2 style: pacing_rate, cwnd, delivery_rate

Observing Congestion Control with ss

bash
# Detailed TCP socket stats
ss -tin

# Example output breakdown:
# State Recv-Q Send-Q  Local Address:Port   Peer Address:Port
# ESTAB 0      0       192.168.1.5:45231   1.2.3.4:443
#   cubic wscale:7,7 rto:200 rtt:12.4/3.1 ato:40
#   mss:1448 pmtu:1500 rcvmss:1448 advmss:1448
#   cwnd:10 ssthresh:10 bytes_sent:5242880 bytes_retrans:1448
#   segs_out:3620 segs_in:1810 send 9.3Mbps lastsnd:0 lastrcv:0 lastack:4

# Key fields:
#   cwnd:10    = 10 MSS in flight allowed
#   ssthresh:10 = at threshold boundary
#   bytes_retrans = total retransmitted bytes (sign of congestion)
#   send 9.3Mbps = current sending rate

# Monitor live
watch -n 1 "ss -tin dst <target_ip> | grep -E 'cwnd|rtt|ssthresh'"

How Attackers Exploit Congestion Control

SYN Flood

bash
# Classic SYN flood exhausts server half-open connection queue
# cwnd is never reached — connection never completes
hping3 -S --flood -V -p 80 <target>

# Mitigation: SYN cookies
sudo sysctl -w net.ipv4.tcp_syncookies=1

Congestion Window Manipulation

python
# Concept: spoofed duplicate ACKs can trigger fast retransmit
# and cause the victim sender to back off cwnd
# Requires ability to inject ACK packets (on-path or via spoofing if sequence predictable)

Low-Rate DDoS (Shrew Attack)

Send periodic bursts timed to match TCP retransmit timeout (RTO):

  • Burst causes packet loss → TCP backs off (cwnd halves, slow start)
  • Wait for RTO (~200ms-1s), burst again
  • Maintains severe throughput reduction with minimal attacker bandwidth

ACK Throttling Defense

bash
# Detect abnormal retransmit rates
netstat -s | grep -i retransmit
# or
cat /proc/net/netstat | grep -i retrans

Tuning for High-Performance (not attack use)

bash
# Increase TCP buffer sizes for high-bandwidth links
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 67108864"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 67108864"

# Enable window scaling (should be on by default)
sudo sysctl -w net.ipv4.tcp_window_scaling=1

# Enable SACK (selective acknowledgment)
sudo sysctl -w net.ipv4.tcp_sack=1

Reference

techzonesite.comUnlock Your IT Potential