Transport

TCP Congestion Control

Slow start, congestion avoidance, and fast recovery algorithms.

TCP Congestion Control: Scope and Purpose

TCP shares links and forwarding resources with other flows. For example, while a host downloads a file from a server in London, its segments cross several links and routers before reaching New York. Available capacity, queueing, and round-trip time can vary during the transfer, including between a quiet period such as 3 AM and a busy period.

When offered traffic exceeds the capacity of a link, queues grow at routers. that process traffic on the overloaded path can become bottlenecks. A full queue increases delay and can cause the router to drop arriving packets. This condition is network congestion.

Queueing delay grows when arrivals remain above a link's service rate, while propagation delay depends mainly on the path length and medium. TCP cannot measure a router queue directly, so its sender uses acknowledgments as an ACK clock and changes its sending window in response to observed feedback.

TCP therefore needs two separate limits. Flow Control uses the receiver's advertised window to keep data within the receiver's available buffer. Congestion Controluses the sender's congestion window and network signals to limit traffic entering the shared path. The two mechanisms protect different resources.

How TCP Infers Congestion

TCP can receive an explicit signal through ECN (Explicit Congestion Notification), but classic TCP congestion control infers congestion from acknowledgments, retransmission timers, and loss. The sender observes these events instead of directly reading the state of every router on the path.

ECN allows a capable network device to mark packets instead of dropping them when congestion is building, provided the endpoints negotiated ECN. The receiver echoes the indication in acknowledgments, and the sender reduces its sending rate according to the congestion-control algorithm.

A primary loss-based signal is packet loss. Queue overflow is one common cause, but loss and delay can also have other causes, so the signal is an inference rather than proof of a congested router. TCP has two main ways of detecting that a packet may have been lost:

  • Retransmission Timeout (RTO)

    A TCP sender normally runs one retransmission timer for the earliest unacknowledged segment. It expects to receive an acknowledgment (ACK) from the receiver before this timer expires. If the timer runs out, TCP treats the segment as lost or excessively delayed. This is a severe congestion signal because the sender has received no timely acknowledgment for that segment.

  • Triple Duplicate ACKs

    This is a faster heuristic. Suppose the sender sends segments 1, 2, 3, 4, and 5, segment 3 is lost, and segments 4 and 5 arrive. The receiver sends duplicate cumulative ACKs for the end of segment 2. After three duplicate ACKs, the sender infers that the next segment is missing and retransmits it without waiting for RTO. Reordering or duplicated packets can also produce duplicate ACKs, so the heuristic is not proof of loss.

Congestion Control Variables

To implement its congestion control strategy, TCP maintains two critical state variables on the sender side for each connection.

  • Congestion Window (cwnd)

    The 'cwnd' is the sender's limit on bytes in flight, meaning sent but not yet acknowledged. TCP adjusts it from congestion signals. It works with the receiver's advertised window ('rwnd'); the number of bytes the sender may transmit is the minimumof 'cwnd' and 'rwnd'. This respects both the path's congestion state and the receiver's buffer.

    FlightSize is the amount of data outstanding at the time of a congestion event. It can be smaller than the congestion window when the application or receiver is limiting transmission, so using FlightSize for the threshold calculation avoids assuming that the whole window was in flight.

  • Slow Start Threshold (ssthresh)

    The 'ssthresh' is a control variable used to select Slow Start or the more conservative Congestion Avoidance phase. It may initially be large. After loss, a sender following RFC 5681 sets it to the larger of half the outstanding FlightSize and 2 SMSS. The exact response depends on the loss signal and the congestion-control algorithm.

    When 'cwnd' is below 'ssthresh', the Reno-style sender uses Slow Start. At or above the threshold it uses Congestion Avoidance, so the threshold changes the growth rule rather than representing a measured link capacity.

Phase 1: Slow Start - The Search for Bandwidth

When a new TCP connection begins, the sender has only limited information about the path capacity. It could be a fast fiber link or a slow satellite connection. Sending a large burst immediately could cause congestion, while sending too cautiously would underuse a fast path. TCP uses the Slow Start algorithm to probe the path.

The growth during this phase can be approximately exponentialwhile each acknowledgment increases the window. It is called "slow" because the sender begins with a limited window instead of immediately sending a full estimate of path capacity.

Newly acknowledged data drives the ACK clock. If acknowledgments arrive in a burst, the implementation must still respect its congestion-window limit and may apply byte-counting or delayed-ACK safeguards to prevent an artificial burst from producing excessive growth.

Mechanism of Slow Start

  1. The connection begins with an initial Congestion Window ('cwnd'). Experimental RFC 6928 permits an upper bound of min⁡(10 MSS,max⁡(2 MSS,14600 bytes))\min(10\,\text{MSS},\max(2\,\text{MSS},14600\,\text{bytes})), although an implementation may choose a smaller value. This limit is measured in .
  2. For each acknowledgment (ACK) that confirms new data, the sender increases 'cwnd' by no more than one SMSS; byte-counting algorithms may use the number of newly acknowledged bytes.
  3. Since a sender might send multiple segments in a single round-trip, it can receive multiple ACKs in response. The effect is that 'cwnd' approximately doubles every Round-Trip Time (RTT).

SMSS denotes the sender's usable segment size, while MSS is advertised by a peer. The actual increase is also bounded by the amount of newly acknowledged data and by the receiver window, so the doubling description is an approximation for a continuously backlogged sender.

This growth allows TCP to probe the approximate available capacity. Slow Start continues until 'cwnd' reaches 'ssthresh' or congestion is detected. Once the threshold is reached, a Reno-style sender transitions to Congestion Avoidance.

Phase 2: Congestion Avoidance - Gently Probing for More

After Slow Start, a Reno-style TCP sender enters the more conservative Congestion Avoidance phase. It probes for additional capacity with a controlled increase rather than the exponential growth used earlier.

This behavior is part of Additive Increase, Multiplicative Decrease (AIMD). Congestion Avoidance is the additive-increase part of the Reno-style algorithm.

Mechanism of Congestion Avoidance

Instead of doubling 'cwnd' every RTT, the sender increases it in a linear, additive way. The target is approximately 1 SMSS per RTT for the basic algorithm.

The increment per ACK becomes smaller as 'cwnd' grows. Summed over roughly one window of acknowledgments, the increments produce the target of one segment per RTT, which makes the rule independent of the number of ACKs used to deliver that window.

This is achieved by increasing 'cwnd' by a small fraction for each ACK. The basic approximation is cwnd=cwnd+SMSS×(SMSS/cwnd)\text{cwnd} = \text{cwnd} + \text{SMSS} \times (\text{SMSS} / \text{cwnd}) for each ACK. When one window of data is acknowledged, the total increase is about 1 SMSS. The connection remains in Congestion Avoidance until loss or an explicit congestion signal is detected.

Reacting to Congestion: Multiplicative Decrease

The multiplicative-decrease part of AIMD governs the reduction after TCP detects congestion. The response depends on whether loss was detected by RTO, duplicate ACKs, ECN, or another recovery algorithm.

Reaction to a Timeout (RTO)

A Retransmission Timeout is treated as a severe congestion signal. The basic RFC 5681 response is:

  1. The 'ssthresh' is set to the larger of half of FlightSize and 2 SMSS for the first timeout on that segment.
  2. The 'cwnd' is reset to its small initial value (e.g., 1 SMSS).
  3. The connection re-enters the Slow Start phase.

Resetting 'cwnd' to the loss window reduces the sender's offered load before Slow Start probes the path again.

A timeout also causes the retransmission timer to be restarted for the retransmitted data. Repeated timeout events therefore keep the sender conservative until acknowledgments provide evidence that the path can carry more traffic.

Reaction to Triple Duplicate ACKs: Fast Retransmit and Fast Recovery

Three duplicate ACKs indicate a likely gap while later segments continue to reach the receiver. Reordering can produce the same signal, but the sender uses it to invoke Fast Retransmit and Fast Recovery without waiting for RTO.

The duplicate ACK threshold refers to three ACKs beyond the first cumulative ACK for the same sequence range. Selective acknowledgments can identify additional received ranges, while classic Reno relies on cumulative acknowledgments and therefore has less information about multiple losses.

  1. Fast Retransmit: Upon receiving the third duplicate ACK, the sender retransmits the segment indicated by the cumulative ACK without waiting for the RTO timer.
  2. Fast Recovery:Instead of resetting 'cwnd' to 1, TCP performs a multiplicative decrease:
    • The 'ssthresh' is set to the larger of half of FlightSize and 2 SMSS.
    • In classic Reno, 'cwnd' is temporarily set to 'ssthresh' plus 3 SMSS while the three duplicate ACKs represent data that has left the network.
    TCP then directly enters the Congestion Avoidance phase, continuing its linear growth from this new, lower starting point.

Classic Reno then deflates 'cwnd' to 'ssthresh' after recovery and continues with Congestion Avoidance. NewReno modifies recovery for multiple losses by responding to partial acknowledgments.

The Evolution of Congestion Control

Reno's classic combination of Slow Start, Congestion Avoidance, and Fast Recovery remains the reference model for TCP congestion control. Faster and longer paths, often called Long Fat Networks (LFNs), with a large bandwidth-delay product exposed slower recovery and motivated algorithms with different growth functions.

The bandwidth-delay product is especially important on long paths: a sender may need a large in-flight window to reach the available rate, while a loss-based controller can fill queues before it receives a loss signal. Later algorithms change the control variable or the window-growth function to address this trade-off.

  • TCP NewReno

    NewReno extends Reno's fast recovery for connections that cannot use TCP Selective Acknowledgment. It uses partial acknowledgments to infer and retransmit additional losses in the same window without leaving recovery after the first missing segment.

  • CUBIC

    CUBIC is a Standards Track TCP congestion-control algorithm that uses a cubic window-increase function instead of Reno's linear increase. RFC 9438 reports adoption as a default in Linux, Windows, and Apple stacks. Its concave and convex phases improve scalability and stability on fast, long-distance paths while retaining Reno-friendly behavior.

    CUBIC uses elapsed time since the last congestion event in its window function, which reduces dependence on the ACK rate. The standard still requires the algorithm to respond to congestion signals and to coexist fairly with Reno-style traffic.

  • BBR (Bottleneck Bandwidth and Round-trip propagation time)

    BBR, originally developed by Google, uses a model-based approach. It measures delivery rate and round-trip time and can account for loss or ECN signals according to the algorithm version, then controls both sending rate and in-flight data. Its goals include high throughput with lower queueing delay than a purely loss-based controller, reducing the queue growth known as bufferbloat; the current IETF specification is an Experimental Internet-Draft rather than a published RFC.

    BBR separates an estimate of bottleneck bandwidth from a propagation-delay estimate and periodically probes each one. Its behavior and version-specific details come from the implementation or draft specification, so it should not be described as the default behavior of every TCP stack.

Related articles