1
CS 168, Spring 2025 @ UC Berkeley
Slides credit: Sylvia Ratnasamy, Rob Shakir, Peyrin Kao
Congestion Control, Part 1
Lecture 13 (Transport 3)
Congestion Control: Why do we need it?
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Recall: Congestion at Routers
If two packets arrive at the same time, the router will send one, and buffer the other.
The router maintains a queue of packets that still need to be sent.
If too many packets arrive close in time:
B
A
Router
I cannot send both A and B right now.
One of them will have to wait.
Congestion Delays Packets
For a typical queuing system with bursty arrivals:
Load
100% load
Average Packet Delay
Brief History of Congestion Control
In the 1980s, TCP did not implement congestion control.
This led to a congestion collapse.
In October of '86, the Internet had the first of what became a series of 'congestion collapses.' During this period, the data throughput from LBL to UC Berkeley (sites separated by 400 yards and two IMP hops) dropped from 32 Kbps to 40 bps. We were fascinated by this sudden factor-of-thousand drop in bandwidth and embarked on an investigation of why things had gotten so bad. In particular, we wondered if the 4.3BSD (Berkeley Unix) TCP was mis-behaving or if it could be tuned to work better under abysmal network conditions. The answer to both of these questions was "yes".
– Karels (UCB) and Jacobson (LBL)
Brief History of Congestion Control
How was congestion collapse solved in the 1980s?
The history of congestion control had a big impact on its design.
Fast-forward to today:
Congestion Control: Why is it hard?
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Congestion Control Challenges: Depends on Destination
At what rate should A send traffic?
It depends on the destination.
A
B
R1
R3
R7
R4
R2
R5
R6
G
F
E
D
C
10
2
1
4
4
10
10
4
5
10
Numbers are bandwidths, in Gbps.
Ignore bandwidth of host-to-router links.
Congestion Control Challenges: Depends on Path
At what rate should A → E send traffic?
It depends on the path through the network.
A
B
R1
R3
R7
R4
R2
R5
R6
G
F
E
D
C
10
2
1
4
4
10
10
4
5
10
Congestion Control Challenges: Depends on Competing Flows
At what rate should A → F send traffic?
It depends on others using the network.
A
B
R1
R3
R7
R4
R2
R5
R6
G
F
E
D
C
10
2
1
4
4
10
10
4
5
10
Congestion Control Challenges: Depends on Indirect Competition
What if G → D starts sending traffic?
G → D and A → F share no links, but they�still affected each other's bandwidth.
A
B
G
F
E
D
C
10
2
1
4
4
10
10
4
5
10
R1
R3
R7
R4
R2
R5
R6
Congestion Control is a Global Problem
The sender's optimal rate depends on:
Congestion control is a global problem.
Congestion Control as Resource Allocation Problem
Fundamentally, congestion control is a resource allocation problem.
Resource allocation is a classic problem (e.g. CPU scheduling, memory allocation).
But, congestion control has additional challenges.
Design Goals
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Design Goals
Goals for a good congestion control algorithm:
Our ultimate goal is a good tradeoff between these metrics.
Possible Approaches
Reservations:
Pricing/priorities:
Dynamic adjustment:
Possible Approaches
3 possible approaches: reservations, pricing, and dynamic adjustment.
All the algorithms we'll see are based on dynamic adjustment.
Congestion Control Protocols
Pricing
Reservations
Dynamic Adjustment
Dynamic Adjustment: Algorithm Sketch
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Dynamic Adjustment: Discovery
Discovery: Host A discovers it can send data at 10 Gbps.
A
B
R1
R3
R7
R4
R2
R5
R6
G
F
E
D
C
10
2
1
4
4
10
10
4
5
10
Dynamic Adjustment: Detection and Adjustment
Later, the R1 → R3 link goes down. A's traffic is rerouted.
Detection: A notices that 10 Gbps is congesting the network.
Adjustment: A decides to slow down to 1 Gbps.
A
B
G
F
E
D
C
2
1
4
4
10
10
4
5
10
R1
R3
R7
R4
R2
R5
R6
Dynamic Adjustment: Detection and Adjustment
Later, G → D starts sending traffic.
Detection: A notices that 1 Gbps is congesting the network.
Adjustment: A decides to slow down to 0.5 Gbps.
A
B
G
F
E
D
C
2
1
4
4
10
10
4
5
10
R1
R3
R7
R4
R2
R5
R6
Types of Dynamic Adjustment Algorithms
Solutions can be classified into 2 types, depending on where they're implemented:
Host-based congestion control: (TCP uses this one)
Router-assisted congestion control:
Congestion Control Protocols
Pricing
Reservations
Dynamic Adjustment
Router-assisted
Host-based
Today
Next time
Host-Based Dynamic Adjustment: Algorithm Sketch
Every host independently runs the same algorithm:
Host-Based Dynamic Adjustment: Algorithm Sketch
Every host independently runs the same algorithm:
Components of a solution:
Detecting Congestion
There are 2 ways for the host to detect congestion.
Remember: The host can't see the whole network.
Congestion Control Protocols
Pricing
Reservations
Dynamic Adjustment
Router-assisted
Host-based
Loss-based
Delay-based
Detecting Congestion
Loss-based detection: If we lose a packet, declare congestion.
Benefits:
Cons:
Detecting Congestion
Delay-based detection: If packets are delayed, declare congestion.
Discovering an Initial Rate
Goal for discovering initial rate: Estimate available bandwidth.
Start slow for safety.
Ramp up quickly for efficiency.
What kind of mathematical function starts slow but ramps up quickly?
Discovering an Initial Rate: Slow Start
Slow start is an algorithm for discovering the initial rate:
1
2
4
8
16
32
32 was the last safe rate.
64 – congestion detected!
Reacting to Congestion
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Host-Based Dynamic Adjustment: Algorithm Sketch
Every host independently runs the same algorithm:
Reacting to Congestion
Rate adjustment: How much do we increase/decrease by?
Goals for rate adjustment:
Ways to Adjust Rate
At a high level, we can either adjust quickly or slowly.
We can combine these rates in four ways:
Why AIMD? Intuition
Non-obvious fact: AIMD (Additive Increase, Multiplicative Decrease) is the best option.
Intuition: Sending too much is worse than sending too little.
General approach:
Loss
Loss
Loss
Loss
Why AIMD? Intuition
Non-obvious fact: Of the four options, AIMD is the only one that ensures fairness.
To see why, let's build a simple model:
Rate Adjustment Graph
Assume C = 1.
Efficiency line: X + Y = 1
Congestion: X + Y > 1
Everything above the efficiency line.
Unused capacity: X + Y < 1
Everything below the efficiency line.
1
1
Efficiency Line:
X + Y = 1
Congested
Inefficient
Rate Adjustment Graph
Fairness line: X = Y
The lines intersect at (0.5, 0.5).
This allocation is both fair and efficient.
1
1
Congested
Inefficient
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
Rate Adjustment Graph
(0.2, 0.5) is inefficient (below blue line).
Only 0.7 bandwidth used.
(0.7, 0.5) is inefficient (above blue line).
1.2 bandwidth used (capacity is C = 1).
(0.7, 0.3) is efficient, but unfair.
On blue line, but not on green line.
1 bandwidth used, but, 0.7 ≠ 0.3.
1
1
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
(0.2, 0.5)
(0.7, 0.5)
(0.7, 0.3)
Additive Adjustments on Graph
Recall: Both flows independently running identical algorithms.
Suppose current allocation is (X, Y).
If both increase additively: (X + a, Y + a).
If both decrease additively: (X – b, Y – b).
Notice: Allocations always stay on a line with slope = 1.
1
1
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
(X, Y)
(X+a, Y+a)
(X–b, Y–b)
Multiplicative Adjustments on Graph
Recall: Both flows independently running identical algorithms.
Suppose current allocation is (X, Y).
If both increase multiplicatively: (cX, cY).
If both decrease multiplicatively: (X/d, Y/d).
Notice: Allocations always stay on a line with slope = Y/X, going through the origin.
1
1
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
(X, Y)
(cX, cY)
(X/d, Y/d)
Rise
Run
=
cY – Y
cX – X
Y(c – 1)
X(c – 1)
=
Y
X
=
AIAD (Additive Increase, Additive Decrease) Dynamics
Increase: +1 Decrease: –2 C = 5
Start: X = 1 Y = 3 sum = 4, no congestion
First iteration: X = 2 Y = 4 sum = 6, congested
Second iteration: X = 0 Y = 2 sum = 2, no congestion
Third iteration: X = 1 Y = 3 back to where we started!
Notice: The difference in allocations stays the same!
AIAD maintains the same unfairness across iterations.
Y – X = 2
Y – X = 2
Y – X = 2
Y – X = 2
AIAD (Additive Increase, Additive Decrease) Adjustments on Graph
Increase: +a Decrease: –b
We keep moving along the line with slope 1.
AIAD does not converge to fairness.
Fairness Line:
X = Y
Efficiency Line:
X + Y = C
(X, Y)
(X+a, Y+a)
(X–b, Y–b)
MIMD (Multiplicative Increase, Multiplicative Decrease) Dynamics
Increase: ×2 Decrease: ÷4 C = 5
Start: X = 0.5 Y = 1 sum = 1.5, no congestion
First iteration: X = 1 Y = 2 sum = 3, no congestion
Second iteration: X = 2 Y = 4 sum = 6, congestion
Third iteration: X = 0.5 Y = 1 back to where we started!
Notice: The ratio of allocations stays the same!
MIMD maintains the same unfairness across iterations.
Y/X = 2
Y/X = 2
Y/X = 2
Y/X = 2
MIMD (Multiplicative Increase, Multiplicative Decrease) Adjustments on Graph
Increase: ×c Decrease: ÷d
We keep moving along the line connected to the origin.
MIMD does not converge to fairness.
1
1
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
(X, Y)
(cX, cY)
(X/d, Y/d)
MIAD (Multiplicative Increase, Additive Decrease) Dynamics
Increase: ×2 Decrease: –1 C = 5
Start: X = 1 Y = 3 sum = 4, no congestion
First iteration: X = 2 Y = 6 sum = 8, congestion
Second iteration: X = 1 Y = 5 sum = 6, congestion
Third iteration: X = 0 Y = 4 sum = 4, no congestion
Fourth iteration: X = 0 Y = 8 X stuck at 0 forever!
The gap in allocation doubles when we increase. before: Y – X. after: 2Y – 2X = 2(Y – X)
The gap in allocation stays the same when we decrease. (Same as AIAD.)
MIAD is maximally unfair. The gap increases until one person has all the bandwidth!
Y – X = 2
Y – X = 4
Y – X = 4
Y – X = 4
Y – X = 8
AIMD (Additive Increase, Multiplicative Decrease) Dynamics
Increase: +1 Decrease: ÷2 C = 5
Start: X = 1 Y = 2 sum = 3, ok
First iteration: X = 2 Y = 3 sum = 5, ok
Second iteration: X = 3 Y = 4 sum = 7, congestion
Third iteration: X = 1.5 Y = 2 sum = 3.5, ok
Fourth iteration: X = 2.5 Y = 3 sum = 5.5, congestion
Fifth iteration: X = 1.25 Y = 1.5 sum = 2.75, ok
Sixth iteration: X = 2.25 Y = 2.5 sum = 4.75, ok
Seventh iteration: X = 3.25 Y = 3.5 sum = 6.75, congestion
Eighth iteration: X = 1.625 Y = 1.75 sum = 3.375, ok
Ninth iteration: X = 2.625 Y = 2.75 approaching 2.5 each!
Y – X = 1
Y – X = 1
Y – X = 1
Y – X = 0.5
Y – X = 0.5
Y – X = 0.25
Y – X = 0.25
Y – X = 0.25
Y – X = 0.125
Y – X = 0.125
AIMD (Additive Increase, Multiplicative Decrease) Dynamics
The gap in allocation stays the same when we increase.
The gap in allocation halves when we decrease.
The gap approaches 0, so AIMD approaches fairness!
Y – X = 1
Y – X = 1
Y – X = 1
Y – X = 0.5
Y – X = 0.5
Y – X = 0.25
Y – X = 0.25
Y – X = 0.25
Y – X = 0.125
Y – X = 0.125
AIMD (Additive Increase, Multiplicative Decrease) Adjustments on Graph
Increase: +a Decrease: ÷d
AIMD converges to fairness!
1
1
Fairness Line:
X = Y
Efficiency Line:
X + Y = 1
Why AIMD? Intuition
Non-obvious fact: Of the four options, AIMD is the only one that ensures fairness.
AIMD embodies gentle increase, rapid decrease.
Out of the four options:
Hopefully more obvious now!
Host-Based Dynamic Adjustment: Algorithm Sketch
Every host independently runs the same algorithm:
Loss
Loss
Loss
Loss
Slow Start
This algorithm creates a sawtooth-shaped graph as the rate is adjusted.
AIMD
Implementing Congestion Control with Event-Driven Updates
Lecture 13, CS 168, Spring 2025
Congestion Control Principles
Dynamic Adjustment
Review: Setting Window Size
The sender maintains a window of W packets in flight.
Pick window size W to balance three goals:
W is the minimum of RWND and CWND.
Review: Measuring Packets vs. Bytes
Real TCP measures data in bytes.
In this lecture, we'll measure CWND in packets for convenience.
Windows and Rates
Congestion control is used to set the window size (CWND).
We talked about congestion control as adjusting the rate.
Possibly confusing fact: Window size and rate are directly correlated.
Host-Based Dynamic Adjustment: Algorithm Sketch
Every host independently runs the same algorithm:
How long is "some period of time"?
???
Event-Driven Updates
Instead of updating after "some period of time," CWND updates are event-driven.
Sender adjusts CWND each time something interesting happens in TCP.
Event-Driven Slow Start
Conceptual slow start: Double CWND after each RTT.
Event-driven slow start: Increase CWND by 1 after each ack.
Intuition:
t = 0 RTTs: CWND = 1 Send 1 packet
t = 1 RTT: get 1 ack CWND = 2 Send 2 packets
t = 2 RTTs: get 2 acks CWND = 4 Send 4 packets
t = 3 RTTs: get 4 acks CWND = 8 Send 8 packets
t = 4 RTTs: get 8 acks CWND = 16 Send 16 packets
Event-Driven Slow Start
Conceptual slow start: Double CWND after each RTT.
Event-driven slow start: Increase CWND by 1 after each ack.
Intuition:
Event-Driven Slow Start
Sender
Recipient
CWND = 1
CWND = 2
CWND = 3
CWND = 4
CWND = 5
CWND = 6
CWND = 7
CWND = 8
First RTT
Second RTT
Third RTT
Fourth RTT
Event-Driven Slow Start: SSTHRESH
Increase CWND by 1 after each ack.
Eventually, we encounter a packet loss.
SSTHRESH helps us remember the last safe rate.
Loss
Loss
Loss
Slow Start
AIMD
Loss
SSTHRESH
Event-Driven AIMD Adjustments: Additive Increase
Conceptual AIMD increase: Add 1 to CWND after each RTT.
Event-driven AIMD increase: Increase CWND by 1/CWND after each ack.
Intuition:
Implementation:
1
CWND
MSS
CWND
(1/CWND in packets) fraction rewritten in bytes by multiplying top and bottom by packet size: (MSS/CWND in bytes)
Total increase after each RTT should be MSS bytes, not 1 packet.
Note: Technically, increase on each ack is different, but approximation is close enough.
First update: 3.00 + (1/3.00) = 3.33
Second update: 3.33 + (1/3.33) = 3.63
Third update: 3.63 + (1/3.63) = 3.93 ≈ 4
Event-Driven AIMD Adjustments: Additive Increase
Event-driven AIMD increase: Increase CWND by a fraction after each ack.
After one RTT (aka one window) of packets, CWND increases by 1.
| Measured in packets: | Measured in bytes: (MSS = 50 bytes) |
Old CWND: | 3 packets | 150 bytes (3 packets) |
Fraction of increase per ack: | 1/CWND = 1/3 | MSS/CWND = 50/150 |
Total increase after 1 RTT: | +1 packet | MSS = +50 bytes |
Increase after each ack: | +1 packet × 1/3 = +1/3 | +50 bytes × 50/150 = +50/3 |
Increase after 3 acks: | 3 + (1/3) + (1/3) + (1/3)�= 4 packets | 150 + (50/3) + (50/3) + (50/3)�= 200 bytes |
Event-Driven AIMD Adjustments: Multiplicative Decrease
Conceptual AIMD decrease: Divide CWND in half when loss detected.
Event-driven AIMD decrease: Divide CWND in half when 3 duplicate acks detected.
CWND should never decrease below 1 packet (MSS bytes).
Event-Driven Adjustments: Timeout
When a packet is lost from timeout, abandon current rate and restart from slow-start.
Implementation: When timeout occurs:
Event-Driven Updates: SSTHRESH
SSTHRESH helps us remember the last safe rate.
During slow start: If CWND exceeds SSTHRESH, switch to additive increases.
Loss
Loss
Timeout
Slow Start
AIMD
Loss
SSTHRESH
SSTHRESH
Slow Start
AIMD
Loss
Summary: TCP Congestion Control
Detecting congestion:
Discovering an initial rate:
Adapting rate to congestion: