Congestion Control as a Game
Every TCP sender that halves its congestion window on packet loss is paying a private cost for a public good. The bandwidth it gives up is immediately available to whoever did not back off, and the queue relief it buys is shared by everyone at the bottleneck. That is the exact shape of a commons problem, and the internet standards community has said so in its own documents for forty years: RFC 2914 warns that deliberately aggressive implementations would produce “a spiral of increasingly aggressive TCP implementations … leading back to the point where there is effectively no congestion avoidance and the Internet is chronically congested” (RFC 2914 §3.2). The strategic question — would a selfish sender defect, and would the network survive it? — was answered quantitatively by Akella, Seshan, Karp, Shenker and Papadimitriou at SIGCOMM 2002, who modelled TCP flows choosing their own AIMD parameters and computed the Nash equilibria (Akella et al. 2002). Their answer is uncomfortable: in the Reno-and-drop-tail internet of the 1990s the selfish equilibrium happened to coincide with the standard, and in every configuration deployed since then it does not. This note applies the vocabulary of Normal-Form Games and Payoff Matrices, Nash Equilibrium, The Price of Anarchy and Mechanism Design to congestion control. It does not re-derive AIMD — see Congestion Control Fundamentals and AIMD, TCP Congestion Control, CUBIC Congestion Control and BBR Congestion Control for the mechanism. The contribution here is strictly the strategic reading, including an honest account of where the game framing collapses.
What was verified, and when
Every RFC quoted was fetched as plain text from
rfc-editor.orgon 2026-08-29. Every paper was fetched as a PDF and its extracted text checked against its claimed title before citation. The BBR figures come fromdraft-ietf-ccwg-bbr-06, dated 6 July 2026, which is the current Internet-Draft specifying BBRv3 — version numbers in this area move, and a claim about “BBR” that does not name a version is close to worthless.
Mental Model — Three Games, Not One
The phrase “congestion control is a game” hides three different games with three different player sets, and conflating them is the single most common error in this area.
flowchart TB subgraph G1["Game 1 · The Parameter Game (Akella et al. 2002)"] A1["Players: individual flows<br/>Strategy: choose (alpha, beta)<br/>Payoff: own goodput<br/>Status: theoretical — nobody plays it"] end subgraph G2["Game 2 · The Algorithm Game (Mishra et al. 2022)"] A2["Players: websites / OS vendors / CDNs<br/>Strategy: pick CUBIC or BBR or Prague<br/>Payoff: aggregate throughput<br/>Status: actually played, slowly"] end subgraph G3["Game 3 · The Protocol Game"] A3["Players: applications<br/>Strategy: how many connections,<br/>TCP vs UDP, honest vs lying receiver<br/>Payoff: user-visible latency<br/>Status: played constantly, invisibly"] end G1 -->|"supplies the payoff<br/>function"| G2 G3 -->|"the defection<br/>that actually happens"| G2 G2 --> OUT["Observed outcome:<br/>a mixed CUBIC/BBR internet<br/>held together by AQM and defaults"]
The three games that “congestion control as a game” can mean. What it shows: the strategy space differs at each level — a continuous AIMD parameter, a discrete algorithm choice, and an application-level workaround respectively. The insight: Game 1 has the cleanest mathematics and the least empirical reality; Game 3 has the most reality and the least mathematics; Game 2 is where the two meet, because the entity that chooses a congestion control algorithm is a real economic actor with a measurable payoff. Any analysis that quietly slides between them is measuring one game and concluding about another.
The unifying feature of all three is the structure economists call a congestion externality: your payoff depends not on who else is present but on how many others chose the same resource, and your own consumption degrades theirs without your bearing the cost. The rest of this note works each level in turn.
Rosenthal’s Congestion Game, and How Badly TCP Fits It
The formal object named “congestion game” is due to Robert W. Rosenthal in 1973. His construction is deliberately spare. There are n players and t primary factors (resources). Each player’s pure strategy is the selection of a particular subset of the primary factors. Each factor k has a cost function C_k that depends only on X_k, the number of players who selected it. A player’s total cost is the sum of the costs of the factors they chose:
pi_i(r_1, ..., r_n) = SUM over k in r_i of C_k( X_k(r_1, ..., r_n) )
Walking the symbols: r_i is player i’s chosen subset; X_k counts how many of the n chosen subsets contain factor k; C_k(X_k) is the per-player cost of using factor k when X_k players are on it; pi_i is player i’s total cost, which they wish to minimise. Rosenthal’s example 1 is literally a road network with travel times increasing in the number of drivers (Rosenthal 1973, §1).
His theorem is short and genuinely useful: every game in this class has at least one pure-strategy Nash equilibrium. The proof is a one-page argument by construction. He writes down an integer program whose objective is
Phi(x) = SUM over k of SUM over y = 1 .. X_k of C_k(y)
— a sum, over every resource, of the cost that each successive user would have faced — and shows that any minimiser of Phi must already be an equilibrium. The mechanism of the proof is the part worth internalising: if some player j could improve by switching from strategy r_j to z_j, then the same switch strictly decreases Phi, contradicting minimality. Phi is what later work calls an exact potential function: a single global scalar that moves in lockstep with every individual player’s unilateral improvement. Because Phi takes finitely many values and strictly decreases at every improving deviation, best-response dynamics cannot cycle — they must terminate, and where they terminate is an equilibrium.
flowchart LR S0["Any strategy profile<br/>Phi = 17"] -->|"player j deviates,<br/>own cost falls by d"| S1["New profile<br/>Phi = 17 - d"] S1 -->|"player k deviates"| S2["Phi = 17 - d - e"] S2 -->|"no improving move left"| NE["Pure Nash equilibrium<br/>Phi at a local minimum"] style NE fill:#2d6a4f,color:#fff
Rosenthal’s potential argument as a descent. What it shows: every selfish improvement by any single player decreases one global quantity Phi by exactly the amount that player gained. The insight: this is why congestion games are the well-behaved corner of game theory — the existence proof is also an algorithm, and the equilibrium is reachable by nothing more sophisticated than letting players take turns being greedy. Contrast this with general finite games, where Nash’s existence theorem gives no such descent and finding an equilibrium is PPAD-complete.
Now the honesty. TCP congestion control is not a Rosenthal congestion game, and pretending otherwise is a category error that produces confident nonsense. Three specific mismatches:
| Rosenthal’s model | TCP reality |
|---|---|
| Strategy = a subset of resources chosen once | Strategy = a continuous control law applied every round-trip; the “resource” (the bottleneck link) is not chosen at all — routing picks it |
| Cost is additive across selected resources and depends only on the count of users | Payoff is goodput, a non-additive function of loss rate, RTT, and the parameters of every competitor, not merely how many there are |
| Players are identical and their contribution to congestion is one unit each | Flows are wildly heterogeneous: a flow with alpha = 40 loads the link roughly forty times as hard per round as one with alpha = 1 |
| One-shot simultaneous move | A continuously repeated game with feedback, where the “move” is a reaction to the opponents’ previous moves |
The correct statement is weaker and still worth making: TCP flows at a shared bottleneck form an anonymous game with congestion externalities — payoff depends on the aggregate load others impose, not on their identities. That is enough structure to borrow the intuitions of congestion games (potential-like convergence, the existence of pure equilibria in symmetric settings) but not enough to import Rosenthal’s theorem as a proof. Where the vault’s The Price of Anarchy note derives the 4/3 bound for selfish routing, note the same caution applies: Roughgarden & Tardos’s Theorem 4.5 bounds the ratio at 4/3 only for nonatomic flow (infinitely many agents each controlling a negligible fraction) with linear latency functions l_e(x) = a_e·x + b_e. Their more general Theorem 3.1 — a flow at Nash equilibrium for traffic rate r costs no more than an optimal flow at rate 2r, for arbitrary latency functions — is the one with wide applicability, and it is a bicriteria statement, not a ratio. Neither theorem is about TCP.
Uncertain
Verify: whether any published result bounds the price of anarchy of the TCP parameter game specifically. Reason: Akella et al. 2002 compute equilibrium goodput and loss numerically for a single dumbbell topology but never state a PoA ratio, and no source consulted here does either. To resolve: a survey of AGT applied to transport protocols, or a direct computation from their Equation 6 against the social optimum on the same topology. Do not cite “the price of anarchy of TCP is X” from this note. uncertain
The Payoff Function — What Defection Actually Buys
To reason strategically you need a payoff, and congestion control has an unusually good one, published inside a standards-track RFC. Section 4.3 of RFC 9438, specifying CUBIC, gives the steady-state average congestion window of a generalised AIMD control law AIMD(alpha, beta) — additive increase of alpha segments per round-trip, multiplicative decrease by factor beta on loss — as a function of the packet loss rate p:
____________________
/ alpha * (1 + beta)
AVG_AIMD(a, b) = / ---------------------
\/ 2 * (1 - beta) * p
Symbol by symbol: alpha is how many maximum-segment-sized units the window grows per round-trip while no loss is seen; beta is the retention factor on loss, so beta = 0.5 means “halve the window” and beta = 0.9 means “shave off a tenth”; p is the fraction of packets lost; the result is the average window in segments. Standard Reno is AIMD(1, 0.5) (RFC 5681). Because throughput is window divided by round-trip time, this formula is directly a payoff function for a flow that has chosen (alpha, beta).
The strategic content is visible immediately: the payoff is increasing in alpha and increasing in beta. More aggression on both axes pays. Holding p fixed and dividing by Reno’s coefficient gives the exact multiplier a unilateral defector earns:
Strategy (alpha, beta) | Coefficient sqrt(a(1+b)/(2(1-b))) | Throughput vs. Reno | Plain-English defection |
|---|---|---|---|
(1, 0.5) — Reno | 1.2247 | 1.00× | comply |
(2, 0.5) | 1.7321 | 1.41× | grow twice as fast |
(4, 0.5) | 2.4495 | 2.00× | grow four times as fast |
(10, 0.5) | 3.8730 | 3.16× | grow ten times as fast |
(1, 0.7) | 1.6833 | 1.37× | cut 30% instead of 50% (CUBIC’s beta) |
(1, 0.8) | 2.1213 | 1.73× | cut 20% |
(1, 0.9) | 3.0822 | 2.52× | cut 10% |
(1, 0.98) | 7.0356 | 5.75× | barely back off at all |
(15, 0.98) | 27.2489 | 22.2× | the equilibrium Akella et al. measured for SACK |
(Coefficients computed on 2026-08-29 from the RFC 9438 §4.3 formula; the “vs. Reno” column is the coefficient divided by sqrt(1.5) = 1.2247. The p in the denominator cancels in the ratio, which is precisely the caveat below.)
The p cancels only under the deviator’s assumption that p is unaffected by their deviation — the classic price-taker assumption, and the classic lie. In a shared bottleneck, aggression raises the loss rate for everyone including the aggressor. That is the entire tension: the private gradient of the payoff points toward aggression at fixed p, while the social gradient points the other way once p is allowed to respond. This is a textbook The Prisoner’s Dilemma in continuous strategy space, and its structure is what makes the equilibrium analysis non-trivial rather than a one-line “defect always.”
Note the second-order consequence embedded in the same formula. RFC 9438 derives CUBIC’s Reno-emulation constant from it by asking what alpha reproduces Reno’s average window at a given beta:
alpha_cubic = 3 * (1 - beta_cubic) / (1 + beta_cubic)
With CUBIC’s beta_cubic = 0.7, that gives alpha_cubic = 3 × 0.3 / 1.7 = 0.529 — CUBIC deliberately slows its additive increase to compensate for its gentler decrease, so that in the small-BDP regime where Reno performs well it earns no more than Reno does. This is a congestion-control algorithm voluntarily giving back the 1.37× defection payoff its beta = 0.7 would otherwise earn. It is, in the vocabulary of Mechanism Design, a self-imposed incentive constraint honoured by an implementer with no enforcement mechanism above them.
The same idea is generalised by TCP-Friendly Rate Control, which discards the window machinery entirely and computes a sending rate directly from a response function. RFC 5348 requires TFRC to use a simplified form of the Padhye et al. Reno throughput equation:
s
X_Bps = -----------------------------------------------------------
R*sqrt(2*b*p/3) + (t_RTO * (3*sqrt(3*b*p/8)*p*(1+32*p^2)))
with s the segment size in bytes, R the round-trip time in seconds, p the loss event rate between 0 and 1, t_RTO the retransmission timeout in seconds, and b the number of packets acknowledged per ACK. The strategic reading is worth stating plainly: TFRC is a protocol whose specification is “compute what a compliant Reno flow would get, and take exactly that.” It is voluntary compliance made explicit — an application declaring the payoff it is entitled to and then not exceeding it. That is the opposite of strategyproof design; it works only where the implementer wants it to.
The TCP Game — Akella et al.’s Nash Equilibria
The 2002 SIGCOMM paper is the canonical formalisation. Its setup: n TCP flows share one bottleneck of capacity C packets per unit time; every flow runs AIMD but is free to pick its own (alpha_i, beta_i); all flows use the same loss-recovery machinery (Tahoe, Reno, or SACK) and face the same router queue discipline (drop-tail or RED); all have identical round-trip times; all have infinite data to send; the buffer is fixed at one bandwidth-delay product. Crucially, the authors are explicit about what a flow cannot choose — loss recovery is set by the TCP implementation and queue behaviour by the operator, so “only Factor (i) is under complete control of a single end-user (the source), and is the only factor we allow users to adjust” (Akella et al. §3.2).
Why aggression is not automatically free
The paper’s central insight is one that naive intuition misses. Aggression raises the loss rate, and loss recovery is not free. They model recovery as a penalty function with three shapes:
- Severe (models Tahoe): after any loss, send nothing for
tau_Srounds, then restart atbeta·N. A slow-start from scratch. - Gentle (models SACK): on
Llosses, sendgamma·Lfewer packets next round. Proportional, no timeout. - Hybrid (models Reno): gentle for a single loss, severe beyond that — Reno times out when it loses more than one packet from a window.
The strategic consequence is sharp: a defector’s marginal gain from more aggression is offset by the marginal cost of the recovery it triggers, and the size of that offset is set by the loss-recovery algorithm — which the defector does not choose. Tahoe’s cliff-edge penalty is a natural deterrent. SACK’s smooth penalty removes it.
The closed form, walked
For gentle (SACK) flows behind a drop-tail queue with beta fixed at 0.5, the paper derives (their Equation 6) the goodput of flow n:
alpha_n * C
G_n = ---------------------------
R * ( A + alpha_n )
where A = alpha_1 + ... + alpha_{n-1}
Reading it: C is bottleneck capacity, R the base round-trip time, alpha_n the deviator’s increase parameter, and A the sum of everyone else’s. The flow’s share is alpha_n / (A + alpha_n) — its aggression as a fraction of total aggression. This is exactly the payoff structure of a Tullock contest or a proportional-share auction, and it has a devastating property: dG_n/d(alpha_n) = C·A / (R·(A + alpha_n)^2) > 0 for every finite alpha_n. The derivative never reaches zero. The paper’s conclusion is one sentence: “the value of G_n(alpha_n) is strictly increasing in alpha_n. Hence at Nash equilibrium, alpha_E could be arbitrarily large.”
The beta analysis reaches the same place by a different route. Comparing a deviator with beta_n > beta against the symmetric profile, they derive G_n(beta_n) > C(1+beta_n) / (2nR(1+beta)) > C/(nR) = G_n(beta) — the deviator strictly beats the fair share for any beta_n above the common beta. Hence beta_E -> 1: there is no interior stopping point on the decrease axis either. A flow that never backs off wins, right up to the boundary of the strategy space.
flowchart TB D["Deviator raises alpha or beta"] --> W["Wins a larger share:<br/>alpha_n / (A + alpha_n) rises"] D --> L["Raises aggregate load<br/>-> loss rate p rises for everyone"] L --> R1{"Which loss recovery<br/>is deployed?"} R1 -->|"Severe / Hybrid<br/>(Tahoe, Reno)"| P1["Timeout + slow start<br/>Cost is a cliff<br/>-> deterrent bites"] R1 -->|"Gentle<br/>(SACK)"| P2["Proportional retransmit only<br/>Cost is a gentle slope<br/>-> deterrent evaporates"] P1 --> E1["Nash equilibrium at or near<br/>alpha_E = 1 (Reno + drop-tail)<br/>Network operates efficiently"] P2 --> E2["Nash equilibrium at<br/>alpha_E = 40, loss rate 20.3%<br/>Network operates badly"] W --> E1 W --> E2 style E1 fill:#2d6a4f,color:#fff style E2 fill:#7f1d1d,color:#fff
The deterrence mechanism that the internet accidentally relied on. What it shows: aggression buys share but also buys loss; whether that loss deters depends entirely on how expensive the loss-recovery path is. The insight: SACK — an unambiguous engineering improvement, standardised precisely because it makes recovery cheap — is what removed the deterrent. The internet’s incentive-compatibility in the 1990s was an accident of TCP being bad at recovering from loss, and it was destroyed by fixing that.
The measured equilibria
Running the game to convergence in ns-2 on a 10 Mbps dumbbell with n = 10 flows, Akella et al. report:
| Loss recovery | Queue | Varying alpha (with beta = 0.5) | Varying beta (with alpha = 1) | Verdict |
|---|---|---|---|---|
| SACK (gentle) | drop-tail | alpha_E = 40, goodput 0.95 Mbps, loss 20.32% | beta_E = 0.98, goodput 1.00 Mbps, loss 1.80% | alpha equilibrium undesirable |
| SACK, both varied | drop-tail | (alpha_E, beta_E) = (15, 0.98), goodput 0.95 Mbps, loss 26% | — | undesirable |
| Tahoe (severe) | drop-tail | alpha_E = 49, goodput 0.60 Mbps, loss 11.44% | beta_E = 0.98, goodput 0.76 Mbps, loss 1.19% | undesirable (goodput too low) |
| Reno (hybrid) | drop-tail | alpha_E = 1 — the default! | beta_E = 0.98, network still efficient | efficient |
| SACK | RED | undesirable for all alpha variation | acceptable | undesirable |
| SACK | CHOKe+ | alpha_E = 3; both varied → (3, 0.90), goodput 0.98 Mbps, loss 4% | beta_E = 0.74 | efficient and reasonably fair |
The Reno/drop-tail row is the historically important one, and it is the paper’s most quoted result: in the combination that dominated the internet through the late 1990s, the selfish equilibrium coincided with the standard. alpha_E = 1 is what RFC 5681 tells you to do anyway. Nobody had to be virtuous. The paper’s summary states the consequence bluntly: “while in the past, network operators could rely on the behavior of end-users to ensure the stable, efficient operation of the network, the same cannot be said of today’s Internet.”
Note also what the beta column shows across every row: beta_E = 0.98 almost everywhere. A beta of 0.98 is not multiplicative decrease at all — subtracting 2% of a window is, for realistic windows, an additive decrease of about one packet. The paper flags this: “at values of beta_E close to 1, the decrease undergone by the flows upon incurring losses is equivalent to an additive decrease … However, the additive decrease makes this Nash equilibrium unfair.” Which brings us to the fairness argument that AIMD is supposedly built on.
AIMD’s Fairness Proof Is Not a Game-Theoretic One
The standard justification for AIMD is the vector-convergence argument of Chiu and Jain (1989): additive increase moves the operating point along a 45° line toward the equal-share diagonal, multiplicative decrease moves it along a ray through the origin and so preserves the current fairness ratio, and only the AIMD combination spirals inward onto the fair, efficient point. The geometry is worked in full in Congestion Control Fundamentals and AIMD and is not repeated here. What matters strategically is the fine print of the model, which is easy to miss because the picture is so persuasive.
Reading the paper directly (Chiu & Jain 1989, §1.3–1.4; the PDF is an image scan with no text layer, so it was rendered at 110 dpi with pdftoppm and read as images), the assumptions are stated plainly:
- “The users cooperate with the system” — cooperation is an assumption of the model, not a conclusion of it.
- The linear control is written
x_i(t+1) = a_I + b_I·x_i(t)on increase anda_D + b_D·x_i(t)on decrease, and the paper says: “Here,a_I,b_I,a_D,b_Dare constants.” One set of constants, shared by every user. The derivation that forcesb_I = 1anda_D = 0is a derivation over the common parameters of a homogeneous population. - “we assume that the feedback and control loop for all users is synchronous, that is, all users receive the same feedback and react to it.”
- Users are not aware of other users’ individual demands:
u_i(t)cannot be a function ofx_j(t)forj != i.
Assumption 2 is the load-bearing one. Chiu and Jain prove that if everyone runs the same control law, AIMD is the unique linear family that converges to fairness. They do not prove — and never claim — that any individual user prefers AIMD, or that a user who unilaterally switches to AIMD(4, 0.9) would be worse off. Their result is a statement about a designed system with obedient components, which is the correct frame for the OSI transport class they were writing for. It is a convergence theorem, not an equilibrium theorem.
flowchart LR subgraph CJ["Chiu-Jain 1989 — what is proved"] C1["All users run the<br/>same (a_I, b_I, a_D, b_D)"] --> C2["AIMD is the unique<br/>convergent linear law"] C2 --> C3["Converges to<br/>fair AND efficient"] end subgraph GAP["The strategic gap"] G1["User i deviates to<br/>(alpha=4, beta=0.9)"] --> G2["Chiu-Jain says nothing:<br/>heterogeneous parameters<br/>are outside the model"] G2 --> G3["RFC 9438 formula says:<br/>the deviator earns 4.36x"] end C1 -. "assumption<br/>silently violated" .-> G1 style C3 fill:#2d6a4f,color:#fff style G3 fill:#7f1d1d,color:#fff
The boundary of the AIMD fairness result. What it shows: the convergence proof lives entirely inside the homogeneous-parameter assumption; the deviation the strategic question asks about steps outside it on the first line. The insight: “AIMD converges to fairness” and “AIMD is incentive compatible” are different claims, and only the first has a proof. The 4.36× figure is AIMD(3, 0.9) from the RFC 9438 response function above — the gain a single flow gets by ignoring the convention while everyone else honours it, at unchanged loss rate.
This is why Nash Equilibrium and convergence analysis must be kept apart. A control law can be beautifully convergent and completely non-strategyproof, and AIMD is exactly that.
The Defection Channels That Actually Exist
The parameter game is a thought experiment; nobody edits alpha in a kernel. But defection has always been available through other doors, and every one of them has been documented in a primary source.
flowchart TB U["An application that wants<br/>more than its share"] --> C1["1 · Open N parallel connections<br/>Payoff: ~N x share<br/>Cost: none. No code changes."] U --> C2["2 · Lie as the receiver<br/>ACK division / DupACK spoofing /<br/>optimistic ACKing<br/>Payoff: unbounded<br/>Cost: 11-45 lines of kernel patch"] U --> C3["3 · Send over UDP with<br/>no congestion response<br/>Payoff: whatever you send<br/>Cost: reimplement reliability"] U --> C4["4 · Negotiate ECN, then<br/>conceal the CE marks<br/>Payoff: never back off<br/>Cost: modify the receiver"] U --> C5["5 · Choose an aggressive CCA<br/>Payoff: measurable, version-dependent<br/>Cost: one sysctl"] C1 --> D["All five are unilateral,<br/>none requires cooperation,<br/>and only #5 is visible on the wire<br/>as a policy choice"] C2 --> D C3 --> D C4 --> D C5 --> D
The real strategy space. What it shows: the five documented ways to consume more than a TCP-friendly share, ordered roughly by how little work they take. The insight: the cheapest defection — opening more connections — requires no protocol knowledge at all and is what actually happened historically; the most sophisticated ones were demonstrated in research and then largely closed by protocol fixes. Aggression is not a hypothetical.
Channel 1 — flow multiplication. RFC 2914 names it in the same breath as the aggression spiral: “There is a well-known way to achieve more aggressive performance without even changing the transport protocol, by changing the level of granularity: open multiple connections to the same place, as has been done in the past by some Web browsers. Thus, instead of a spiral of increasingly aggressive transport protocols, we would instead have a spiral of increasingly aggressive web browsers.” RFC 7567 repeats it fifteen years later and adds a second variant: applications that open “a large number of successive short TCP flows for a single session. This can lead to each individual flow spending the majority of time in the exponential TCP slow start phase, rather than in TCP congestion avoidance. The resulting traffic aggregate can therefore be much less responsive than a single standard TCP flow” (RFC 7567 §3). John Nagle saw the same hole in 1985, describing it in the language of impersonation: “malicious … hosts can overload the network by using many different source addresses in their datagrams, thereby impersonating a large number of different hosts and obtaining a larger share of the network bandwidth” (RFC 970). That is a Sybil attack on a fairness mechanism, named in an RFC eight years before the web existed.
Channel 2 — the misbehaving receiver. Savage, Cardwell, Wetherall and Anderson showed in 1999 that a receiver can drive a standard, unmodified sender arbitrarily fast, and that the vulnerabilities “stem from the sender behavior specified in RFC 2581 rather than implementation bugs” (Savage et al. 1999). Three attacks, all implemented in a Linux 2.2 patch the authors named “TCP Daytona”:
- ACK division (24 lines of code): the sender increments
cwndby one segment per ACK, but an ACK may acknowledge any byte offset. Split the acknowledgement of one segment intoMACKs andcwndgrowsMtimes as fast. - DupACK spoofing (11 lines): during fast recovery the sender inflates
cwndper duplicate ACK, assuming each corresponds to a distinct segment arriving. Nothing in the protocol enforces that association, so a receiver can manufacture duplicates. - Optimistic ACKing (45 lines): acknowledge data that has not arrived yet. In the authors’ test this halved the transfer time of a real
index.htmlfetch; they note a bolder implementation “could achieve far greater throughput.”
The authors’ diagnosis is a mechanism-design one. Their proposed fix is a singular nonce — a random value the sender puts in each segment and the receiver must echo — and they explain exactly why it cannot be a TCP option: “because Timestamps is an option, a receiver has the choice to not participate in its use. We cannot rely on misbehaving clients to voluntarily participate in their own policing.” That sentence is the entire discipline of mechanism design compressed to fourteen words. See Incentive Compatibility.
Channel 3 — unresponsiveness. A flow that simply does not react to loss takes what it takes. RFC 7567 classifies flows into TCP-friendly, non-responsive, and responsive-but-less-so, and observes that some applications “can even increase their traffic volume in response to congestion (e.g., by adding Forward Error Correction when loss is experienced)” — a strategy whose best response to punishment is more defection.
Channel 4 — concealing congestion signals. ECN marks congestion in the IP header instead of dropping the packet; the receiver is trusted to report marks back to the sender. A receiver that suppresses them gets a sender that never backs off. RFC 3168 anticipated this and reserved the second ECT codepoint to build an ECN nonce, a probabilistic proof-of-receipt that “allows the development of mechanisms for the sender to probabilistically verify that network elements are not erasing the CE codepoint, and that data receivers are properly reporting to the sender the receipt of packets with the CE codepoint set” (§20.2). The ending is instructive and is documented in RFC 8311 §3: “While the ECN nonce works as specified, and has been deployed in limited environments, widespread usage in the Internet has not materialized. A study of the ECN behavior of the top one million web servers using 2014 data found that after ECN was negotiated, none of the 581,711 IPv4 servers tested were using both ECT codepoints” — the signature the nonce would have produced. Of 17,028 IPv6 servers, four set both, which “might equally have been due to erroneous re-marking of the ECN field by a middlebox.” RFC 3540 was reclassified Historic and ECT(1) reassigned to L4S.
That is a complete mechanism-design story with an unhappy ending: a correct, cheap, spec’d anti-cheating device that nobody deployed, because the party who would have to implement it (the sender) gains nothing unless receivers are actually cheating, and the party tempted to cheat (the receiver) would have to opt in to being policed.
The Punishment Payoff — Congestion Collapse, Measured
A commons problem needs a bad outcome at the all-defect corner, or the analogy is empty. Congestion control’s is congestion collapse: “an increase in the network load results in a decrease in the useful work done by the network” (RFC 2914 §5). Two distinct forms exist. Classical collapse — the 1986 events that produced Jacobson’s algorithms — came from unnecessary retransmission and is fixed. The one that remains is collapse from undelivered packets: bandwidth consumed carrying packets that are dropped downstream before reaching the receiver.
RFC 2914 reproduces a simulation from Floyd & Fall 1999: three TCP flows and one unresponsive UDP flow share a congested 1.5 Mbps link; the UDP receiver’s access link is only 128 Kbps, so once the UDP source exceeds that, most of its packets are carried across the shared link and then discarded at the last hop. All figures are percentages of the 1.5 Mbps link:
| UDP arrival rate | UDP goodput | TCP goodput | Total goodput |
|---|---|---|---|
| 0.7 | 0.7 | 98.5 | 99.2 |
| 2.6 | 2.6 | 96.0 | 98.6 |
| 8.8 | 8.4 | 87.1 | 95.5 |
| 10.5 | 8.4 | 84.8 | 93.2 |
| 13.1 | 8.4 | 81.4 | 89.8 |
| 17.5 | 8.4 | 77.3 | 85.7 |
Read the last three rows carefully. Past 8.8% arrival, the defector’s own goodput stops improving — it is capped at 8.4 by its downstream bottleneck — while total useful work falls monotonically from 99.2 to 85.7. Every additional packet the aggressor sends is pure deadweight loss: it costs the compliant flows and gains the aggressor nothing. This is the cleanest quantitative demonstration in the standards corpus that the all-defect corner is worse for everyone, defector included, and it is the precise reason congestion control is a dilemma rather than a mere race.
The comparison to The Prisoner’s Dilemma holds structurally but is imperfect in one important way: in the canonical 2×2 game defection strictly dominates regardless of what the opponent does, whereas here the deviation gain shrinks and eventually inverts as more players defect. That makes it closer to an n-player commons game with an interior equilibrium than to a strict dominance game — and, as the next section shows, the interior equilibrium is exactly what has been measured on the real internet.
Defection by Algorithm Choice — BBR versus CUBIC
The parameter game is fiction. The algorithm game is real, and it has been measured. The strategy space here is discrete and small: a server operator picks a congestion control algorithm. On Linux this is one sysctl; the kernel’s compiled-in default, verified in net/ipv4/Kconfig at tag v6.16, is cubic (config DEFAULT_TCP_CONG ... default "cubic" as the final fallthrough), with bbr available as a build-time or runtime alternative.
BBRv1’s unfairness, and why it happened
Ware, Mukerjee, Seshan and Sherry gave the mechanism at IMC 2019 (Ware et al. 2019). Their finding, stated in one line: “under competition, BBR becomes window-limited by its ‘in-flight cap’ which then determines BBR’s bandwidth consumption.” BBRv1 is a rate-based algorithm when alone, but in competition it saturates against a safety limit that was never intended to be a fairness mechanism — the cap that stops BBR keeping more than 2 × RTT_est × BtlBw_est in flight, “included to allow BBR to handle delayed ACKs.”
Their simple model, for one BBR flow against any number of loss-based flows in a deeply buffered network (q >> c·l), is three equations:
inflight_cap = 2 * RTT_est * BtlBw_est (their Eq. 1)
BtlBw_est = (1 - p) * c (their Eq. 2)
RTT_est = p * q / c (their Eq. 3)
where c is link capacity in packets per second, q the bottleneck queue capacity in packets, l the uncongested RTT, and p the loss-based flows’ share of the link. Substituting 2 and 3 into 1 gives inflight_cap = 2(p − p²)q. Setting the cap equal to BBR’s own in-flight data, (1 − p)q, and solving:
2(p - p^2) q = (1 - p) q => 2p - 2p^2 = 1 - p => 2p^2 - 3p + 1 = 0 => p = 1/2
So BBR converges to 50% of the link in the idealised model, and the measured 35–40% falls out once ProbeRTT downtime is subtracted (their Eq. 10 scales the share by (d − Probe_time)/d). The extended model, allowing finite queues of X bandwidth-delay products and N competing BBR flows, gives p = 1/2 − 1/(2X) − 4N/q.
The strategic punchline is in what these equations do not contain: the number of competing loss-based flows. As the authors put it, “the calculations behind ProbeBW and the in-flight cap lack any signal to infer number of competing loss-based flows and adapt to achieve equal shares/fairness.” Hence one BBR flow takes roughly the same 40% whether it faces one CUBIC flow or sixteen. Against sixteen, fair share is 1/17 ≈ 5.9%, so 40% is roughly a 6.8× advantage. Against one, it is roughly parity — which is why the early Google presentations showing BBR being “generous” to a single CUBIC flow and the later independent studies showing it starving sixteen are both correct and were talking past each other.
flowchart TB subgraph V1["BBRv1 (2016) — the accusation"] A["No loss response in steady state"] --> B["Share set by in-flight cap<br/>2 x RTTest x BtlBwest"] B --> C["Cap has no term for<br/>number of competitors"] C --> D["~40% of link regardless of<br/>1 or 16 CUBIC flows<br/>(~6.8x fair share at N=16)"] end subgraph V3["BBRv3 (draft-ietf-ccwg-bbr-06, Jul 2026) — the answer"] E["BBR.LossThresh = 2%<br/>max tolerated loss per round<br/>while probing"] --> H F["BBR.Beta = 0.7<br/>multiplicative decrease<br/>on a lossy round"] --> H G["BBR.Headroom = 0.15<br/>capacity deliberately left<br/>for cross traffic"] --> H H["T_probe = min(T_bbr, T_reno)<br/>T_reno bounded at 62-63 round trips"] H --> I["Probing frequency explicitly<br/>throttled so Reno/CUBIC can<br/>reach 25 Mbps at 30 ms RTT"] end D -.->|"IMC 2019, and<br/>years of ccwg argument"| E style D fill:#7f1d1d,color:#fff style I fill:#2d6a4f,color:#fff
BBR’s fairness controversy and its resolution, by version. What it shows: BBRv1’s share was an accident of a safety constant; BBRv3 replaces the accident with three explicit deference parameters and a coexistence time scale. The insight: the fix is not “be nicer” but “make the deference a specified, numbered constant that an implementation either honours or visibly does not” — a mechanism-design move, executed inside an algorithm rather than inside a router.
What BBRv3 actually changed — read the draft, not the folklore
Getting the version right matters, because almost every popular account of “BBR is unfair” describes v1 behaviour that the current specification does not have. From draft-ietf-ccwg-bbr-06 (6 July 2026), which specifies BBRv3:
BBR.LossThresh= 2% — “a constant specifying the maximum tolerated per-round-trip packet loss rate when probing for bandwidth.” BBRv1 had no such loss response in steady state; this is the single largest behavioural change.BBR.Beta= 0.7 — a multiplicative decrease on each round trip with detected loss. Note this is CUBIC’sbeta, chosen so that BBR “does not react more dramatically than CUBIC’s 0.7x.”BBR.Headroom= 0.15 — capacity deliberately left unused “that can be used by cross traffic.”BBR.pacing_gain= 0.90 inProbeBW_DOWN— the draft says this value “is derived based on theProbeBW_UPpacing gain of 1.25, as the minimumpacing_gainvalue that allows bandwidth-based convergence to approximate fairness, and validated through experiments.” A constant chosen for fairness convergence, not for throughput.- A dual time scale for bandwidth probing. The draft is unusually explicit that this is a coexistence mechanism: “BBR has an explicit strategy for coexistence with Reno/CUBIC: to try to behave in a manner so that Reno/CUBIC flows coexisting with BBR can continue to work well in the primary contexts where they do today.” The probe interval is
T_probe = min(T_bbr, T_reno)whereT_bbris uniform on 2–3 seconds andT_renoismin(reno_bdp, 62 or 63)round trips.
The design targets are stated in engineering units, not in fairness abstractions: allow Reno/CUBIC to reach 40 Gbps in a datacenter (BDP ≈ 66 packets) and 25 Mbps at 30 ms RTT on a last mile (BDP ≈ 62 packets), because 25 Mbps at 30 ms is “typical parameters for common CDNs for large video services” — i.e. what 4K video needs. The 2-second lower bound on T_bbr is derived from exactly that: a Reno sawtooth climbing from BDP to 2·BDP at one segment per round trip needs BDP × RTT = 1.9 s of loss-free time.
And yet: the kernel most servers run is still BBRv1. Reading net/ipv4/tcp_bbr.c at Linux tag v6.16 directly, the header comment still says “The core algorithm does not react directly to packet losses or delays” and the documented state machine is the four-state STARTUP → DRAIN → PROBE_BW → PROBE_RTT of BBRv1 — not BBRv3’s ProbeBW_DOWN/CRUISE/REFILL/UP cycle. The only loss threshold in the file is bbr_lt_loss_thresh = 50 (in BBR_SCALE units, i.e. ≈20%), which is the long-term-sampling policer detector, not BBR.LossThresh. So the deference machinery described above is specification, not shipping mainline behaviour, as of v6.16.
Uncertain
Verify: what fraction of BBR traffic on the internet is v1 versus v2/v3. Reason: mainline Linux
v6.16is confirmed BBRv1 (read directly, above), and Google has run BBRv2/v3 in production on its own fleet, but no post-2024 census measuring the deployed-version mix was located during this research. The most recent census consulted, Mishra et al. IMC 2022, cites a late-2019 study putting BBR at “>40% of the Internet’s downstream traffic” without splitting by version. To resolve: a 2025–2026 CCA census that fingerprints v1 versus v3 behaviour. Do not cite “the internet runs BBRv3” from this note. uncertain
The Equilibrium of Algorithm Choice — a Measured Nash Equilibrium
If picking a CCA is a strategy, the obvious worry is a stampede: BBR beats CUBIC, therefore everyone switches to BBR, therefore CUBIC dies and the sawtooth era ends. Mishra, Tiu and Leong tested exactly this at IMC 2022 and reached the opposite conclusion (Mishra et al. 2022).
Their framing is explicitly game-theoretic and matches Game 2 above: “we formulate the interactions between CUBIC and BBR flows as a normal form game … we can abstract the setting in which websites chose their congestion control algorithms as a simple game in which some players (websites) try to maximize a utility (throughput) by selecting some pre-defined strategies (i.e. either running CUBIC or BBR).” Because all flows of the same type are symmetric, the game reduces to a single scalar — N_b, the number of BBR flows out of n — and the payoff to a BBR flow is its average share.
The existence argument is a clean intermediate-value argument that is worth following because it is the same shape as Rosenthal’s descent, in a different coordinate:
flowchart LR A["Point A: few BBR flows<br/>BBR average > fair share<br/>(Ware et al.'s 40% vs 1/17)"] --> C{"Does the line A-B cross<br/>the fair-share line?"} B["Point B: all flows BBR<br/>BBR average = fair share<br/>(by definition)"] --> C C -->|"No — stays above"| NE1["Equilibrium at B:<br/>an all-BBR internet"] C -->|"Yes — crosses at C"| NE2["Equilibrium at C:<br/>a MIXED CUBIC/BBR internet.<br/>Right of C, BBR earns less than CUBIC.<br/>Left of C, CUBIC earns less than BBR."] style NE2 fill:#2d6a4f,color:#fff
Mishra et al.’s equilibrium existence argument. What it shows: the average BBR share falls monotonically from “much better than fair” at low BBR penetration to “exactly fair” at total penetration; wherever that curve crosses the fair-share line, no flow of either type gains by switching. The insight: BBR’s advantage is a congestion externality against itself — it is an advantage over CUBIC specifically, and it dissipates as BBR’s share of the population grows. That is what turns a stampede into an interior equilibrium.
Their empirical results, over bottlenecks with up to 50 flows and buffer sizes swept in bandwidth-delay products, find at least one Nash equilibrium distribution in every configuration tested, and a striking structural regularity when RTTs differ: “In all Nash Equilibrium distributions, all the flows choosing to run CUBIC were the flows with the shortest RTTs.” The explanation is that the two algorithms have opposite RTT biases — loss-based CUBIC favours short-RTT flows because they get feedback sooner, while BBR favours long-RTT flows because a cwnd-limited BBR flow holds buffer share proportional to its RTT — so the equilibrium sorts players onto the algorithm that suits their position. They also confirm that BBRv2, being less aggressive, produces equilibria with a higher CUBIC share than BBRv1 does at the same buffer size.
Their prediction, stated as such: “We make a bold prediction that BBR is unlikely to completely replace CUBIC on the Internet in the near future.” Whether it holds is an empirical question that the passage of time will settle, and this note takes no position on it.
Where the Analogy Breaks
The MOC asks for the limits of the analogy, and they are substantial. Four of them are fatal to the naive reading.
1. The player is not the beneficiary. The entity that chooses cwnd is a kernel; the entity that benefits is a user who has never heard of cwnd. In Normal-Form Games and Payoff Matrices the player and the payoff-holder are the same agent by construction. Here they are separated by an operating-system vendor, a distribution maintainer, a sysctl default, and — for most traffic — a CDN operator whose incentives include not being blamed for congestion, which is a payoff term the model omits entirely. Akella et al. concede this in their own summary: the internet’s stability may simply be because “it is too difficult to modify end-hosts to behave greedily.” Barriers to entry, not incentive compatibility.
2. The strategy space is not what the model says. The parameter game gives players a continuous (alpha, beta). The real strategy set is: pick from a handful of shipped algorithms, open more connections, or write a UDP protocol. It is small, discrete, lumpy, and dominated by an option (parallel connections) the model does not contain at all.
3. Repetition and reputation are missing. Congestion control games are anonymous and one-shot per flow. There is no way to identify a defector across flows, no way to punish them selectively, and therefore none of the machinery that makes cooperation emerge in Iterated Games and the Shadow of the Future or Tit for Tat. The routers cannot retaliate against a specific offender without per-flow state — which is exactly the result the next section turns on.
4. Utility is not throughput. Every model above assumes flows maximise goodput. Real senders trade throughput against latency, and a video service optimising for rebuffer rate, an RPC service optimising for tail latency, and a backup job optimising for bytes-per-dollar have genuinely different objectives. Mishra et al. flag this as the boundary of their own analysis: they expect equilibria to survive utility functions that are “linear combinations of throughput and delay,” but note “it is still unclear how the flows will react where all the participating flows have drastically different utility functions.”
The honest summary: congestion control is a system whose incentive structure is a game, played by almost nobody. The game-theoretic reading is valuable not as a prediction of behaviour but as a stress test of the design — it tells you which properties of the internet’s congestion control depend on voluntary compliance, and would therefore break the moment someone decided not to comply.
Mechanism Design — Changing the Game Instead of Appealing to Citizenship
The engineering response to all of the above is not exhortation. It is Mechanism Design: redesign the router so that honest behaviour is individually optimal, and defection is either useless or self-punishing.
Nagle 1985 — the first statement of the idea
The founding text is RFC 970, and it is startling how explicit it is. Nagle proposes replacing the single FIFO queue per outgoing link with one queue per source host, serviced round-robin, and then writes:
“We have also improved the system from a game theory point of view. The optimal strategy for a given host is no longer to send as many packets as possible. The optimal strategy is now to send packets at a rate that keeps exactly one packet waiting to be sent in each packet switch, since in this way the host will be serviced each time the round-robin algorithm cycles, and the host’s packets will experience the minimum transit delay. This strategy is quite acceptable from the network’s point of view.”
Read that as a mechanism-design claim and it is a strong one: under fair queuing, the strategy that maximises the host’s own objective (minimum transit delay) coincides with the strategy the network wants. Nagle continues: “Badly-behaved hosts can send all the datagrams they want, but will not thereby increase their share of the network resources. All that will happen is that packets from such hosts will experience long transit times … This provides a strong incentive for badly-behaved hosts to improve their behavior.” He also, in the same page, identifies the mechanism’s own vulnerability — the Sybil attack quoted earlier — and declines to solve it.
flowchart TB subgraph FIFO["Single FIFO queue — the game as played"] F1["Aggressive flow<br/>sends 10x"] --> F2["Occupies 10x of<br/>the shared buffer"] F2 --> F3["Drops are proportional<br/>to occupancy"] F3 --> F4["Aggressor keeps 10x share<br/>DEFECTION PAYS"] end subgraph FQ["Per-flow queue, round robin — the game redesigned"] Q1["Aggressive flow<br/>sends 10x"] --> Q2["Its own queue grows;<br/>everyone else's does not"] Q2 --> Q3["Service rate is still 1/n;<br/>excess is dropped from<br/>the aggressor's own queue"] Q3 --> Q4["Aggressor gets 1/n share<br/>plus extra latency<br/>DEFECTION IS SELF-PUNISHING"] end style F4 fill:#7f1d1d,color:#fff style Q4 fill:#2d6a4f,color:#fff
Why per-flow queueing is mechanism design and not merely a scheduler. What it shows: under FIFO the cost of aggression is externalised onto every other flow; under per-flow queueing it is internalised into the aggressor’s own queue as delay and drops. The insight: fair queueing does not make aggression illegal — it makes aggression pointless, which is the only kind of enforcement that scales to an internet with no central authority.
This is why RFC 7567 writes the argument in incentive terms rather than in performance terms: “Network devices need to be able to protect themselves against unresponsive flows, and mechanisms to accomplish this must be developed and deployed. Deployment of such mechanisms would provide an incentive for all applications to become responsive by either using a congestion-controlled transport … or incorporating their own congestion control in the application.”
The impossibility result — per-flow state is not optional
Akella et al.’s most underrated contribution is a negative one, and it is a proper mechanism-design impossibility theorem (their §5.2). Suppose the router imposes a penalty P(g_i) on a flow as a function of its measured goodput g_i, and suppose the resulting symmetric equilibrium has some moderate beta < 1 (which is what fairness requires). Equilibrium means no flow gains by nudging its beta to beta + epsilon for arbitrarily small epsilon. But the goodput difference between AIMD(alpha, beta) and AIMD(alpha, beta + epsilon) is O(epsilon), so the mechanism must be “capable of detecting relative fluctuations smaller than 2·epsilon in g_i, that is, arbitrarily small fluctuations, and imposing penalties whenever such fluctuations occur.” They then invoke a communication-complexity lower bound: “It can be shown by a reduction from element disjointness that any randomized algorithm that detects such fluctuations with high probability must use space proportional to n — that is to say, must essentially maintain per-flow state.”
The conclusion is uncomfortable and precise: no stateless AQM can make a moderate multiplicative decrease a Nash equilibrium. You can diminish the advantage to imperceptibility — their CHOKe+ modification does exactly that, moving the SACK equilibrium from (alpha=15, beta=0.98) with 26% loss to (alpha=3, beta=0.90) with 4% loss and 0.98 Mbps goodput — but you cannot eliminate it without paying O(n) memory. Every real deployment is therefore a point on a spectrum between “cheap and approximately incentive-compatible” and “expensive and exactly so.”
| Mechanism | Per-flow state? | What it changes about the game | Primary source |
|---|---|---|---|
| Drop-tail FIFO | none | nothing — aggression is rewarded proportionally | baseline |
| RED | none | smooths drops; Akella et al. find its equilibria worse than drop-tail’s for alpha variation, because drop-tail’s bias against bursts was an accidental deterrent | RFC 7567 |
| CHOKe / CHOKe+ | none (samples k packets from the queue) | preferentially drops from flows over-represented in the buffer; “aggressive flows see only a very marginal improvement in goodput” | Akella et al. §5.1 |
| CoDel | none | controls sojourn time, not queue length — removes the bufferbloat that BBRv1’s in-flight cap exploits | RFC 8289 |
| FQ-CoDel | O(flows) hash buckets | isolation plus AQM; “flow isolation … results in packets being dropped more accurately from the largest flows than when only CoDel is used” | RFC 8290 §5.2 |
| DualQ Coupled AQM (L4S) | none for the coupling; optional per-flow queue protection | two queues with a coupled marking so L4S and Classic get equal rates; “whether the unresponsive flow classifies itself into the L or the C queue, the DualQ system behaves as if it has subtracted from the overall link capacity” | RFC 9332 §4.2.1 |
That last row is the subtlest and most interesting. In L4S the sender gets a new strategic choice — which queue to put itself in, by setting ECT(1) or ECT(0) — and the DualQ design’s incentive property is that this choice is worthless to a cheater: an unresponsive flow gets the same throughput whichever queue it declares. The mechanism is deliberately choice-neutral for the one strategy it newly exposes. Note also the conditional-priority scheduler that guards against short-term starvation, and the designers’ explicit caution that “a scheduler cannot be relied on to handle long-term overload since the right scheduler weight cannot be known for every scenario” — scheduling handles transients; congestion signalling has to handle the steady state.
Mechanism design by specification
The other half of L4S’s approach is not a router mechanism at all — it is a normative constraint on the strategy space, enforced by the standard rather than by the network. RFC 9331 §4 states that a Scalable congestion control “is not allowed to tag its packets with the ECT(1) codepoint unless it complies with” a numbered list, including:
- It MUST be capable of being replaced by a Classic congestion control.
- It MUST react to packet loss “in a way that will coexist safely with Classic congestion controls such as standard Reno.”
- It MUST implement monitoring to detect a bottleneck ECN AQM that does not support L4S — and if only offline detection is used and problems are found, “the Scalable congestion control MUST be replaced by a Classic congestion control, at least for the problem paths.”
These are incentive constraints written as protocol conformance requirements. Their enforcement is entirely social — nothing in the network checks them — which puts them in the same category as the CUBIC alpha_cubic derivation and BBRv3’s T_reno: deference designed in by the algorithm’s author and honoured voluntarily. The internet’s congestion control has, in practice, always been held together this way. What the game-theoretic analysis contributes is the ability to say precisely which of its properties are load-bearing on that voluntarism, and how much a defector would gain by withdrawing it.
Failure Modes and Gotchas
- Quoting “the price of anarchy is 4/3” about TCP. The 4/3 bound is Roughgarden & Tardos’s Theorem 4.5 and holds only for nonatomic selfish routing (infinitely many agents, each controlling a negligible fraction of flow) with linear edge latencies
l_e(x) = a_e·x + b_e, measuring total latency. It is not a bound on congestion control, it is not a universal bound, and for arbitrary latency functions the ratio is unbounded — their general result is the bicriteria Theorem 3.1 instead (a Nash flow at ratercosts no more than an optimal flow at rate2r). See The Price of Anarchy. - Treating the AIMD fairness result as an incentive result. Chiu & Jain assume one shared set of control constants and that “the users cooperate with the system.” Their theorem says nothing about a heterogeneous population, and therefore nothing about deviation.
- Saying “BBR is unfair” without a version. BBRv1 has no steady-state loss response; BBRv3 as specified has
BBR.LossThresh = 2%,BBR.Beta = 0.7,BBR.Headroom = 0.15and an explicitT_renocoexistence time scale. But mainline Linuxv6.16still ships BBRv1, so both the accusation and the fix can be true simultaneously depending on which kernel you are measuring. - Assuming loss rate is exogenous. Every “defecting pays
k×” figure in this note is a unilateral deviation at fixedp. Once a non-trivial fraction of flows defect,prises and the multiplier collapses. Mishra et al.’s interior equilibrium is exactly this effect made measurable. - Confusing scheduling with congestion signalling. RFC 9332 spells out the trap: a weighted-round-robin scheduler “can only guarantee Classic throughput if Classic sources are sending enough to use it — congestion signals can undermine scheduling because they determine how much responsive traffic of each class arrives for scheduling in the first place.” A scheduler cannot allocate traffic that congestion control has already suppressed.
- Expecting per-flow fairness to be the right fairness. RFC 8290 §6.1 is candid: an ISP may want fairness between customers, a transit provider between autonomous systems, and “the number of simultaneous flows experienced at a particular link can be too high for flow-based fairness queueing to be effective.” Choosing the equivalence class over which you enforce fairness is the mechanism-design decision; per-flow is a default, not a truth. It is also the granularity that channel 1 (parallel connections) exploits.
- Encrypted tunnels collapse the flow identity. RFC 8290 §6.2 notes that flows bunched inside an encrypted VPN “will be seen as one flow by the FQ-CoDel algorithm.” A mechanism that keys on a 5-tuple can be defeated — or accidentally defeated — by anything that hides the 5-tuple.
Alternatives and When to Choose Them
| Framing | Use it when | Do not use it when |
|---|---|---|
| Congestion game / potential function (Nash Equilibrium) | You need to know whether a pure equilibrium exists and whether greedy dynamics converge; the resources are discrete and cost depends only on load | Strategies are continuous control laws, players are heterogeneous, or the payoff is not additive over chosen resources — i.e. actual TCP |
| Control theory / convergence analysis (Chiu & Jain) | Designing a control law for a population you control, and you want stability and fairness convergence | Asking whether anyone would obey the law you designed |
| Mechanism design (Mechanism Design, Incentive Compatibility) | You own the bottleneck and can change the queueing discipline; you want a property that survives arbitrary end-host behaviour | You cannot change routers — then the only lever left is defaults and standards conformance |
| Price of anarchy (The Price of Anarchy) | Quantifying how much a specific, well-modelled selfish system loses versus optimum | Waving at “selfishness is bad” without a matched model and objective function |
| Repeated-game / reputation framings (Iterated Games and the Shadow of the Future) | Long-lived, identifiable participants — peering agreements, transit relationships, ISP-to-ISP interconnect | Anonymous per-flow congestion control, where nobody can identify or punish a repeat defector |
| Adversarial modelling (Security as an Adversarial Game) | The opponent’s goal is to hurt you, not to maximise their own throughput — e.g. low-rate DoS attacks that exploit RTO timing | Ordinary aggressive-but-rational senders, who stop when the marginal gain goes to zero |
The practical decision rule: if you control the bottleneck, do mechanism design; if you do not, the only thing you actually control is your own algorithm’s default, which puts you in Game 2.
Production Notes
The single most consequential production fact in this area is that defaults decide everything. Reading net/ipv4/Kconfig at Linux tag v6.16, DEFAULT_TCP_CONG falls through to "cubic" unless a distribution explicitly selects DEFAULT_BBR, DEFAULT_DCTCP, or one of the other options; tcp_set_default_congestion_control() in net/ipv4/tcp_cong.c is initialised from that string. A change of one Kconfig line, or one line in sysctl.conf, moves a whole fleet’s strategy — which is precisely why the strategic actor in Game 2 is a distribution maintainer or a CDN operator, not a user.
Three deployment lessons are worth carrying:
Anti-cheating mechanisms fail on deployment, not on correctness. The ECN nonce was specified, was correct, and reached essentially zero deployment — measured as 0 of 581,711 IPv4 servers using both ECT codepoints in 2014 data (RFC 8311 §3). Any mechanism whose benefit accrues to a party other than the one who must implement it should be assumed undeployable until proven otherwise.
Engineering improvements can silently destroy incentive properties. SACK (RFC 2018, Mathis, Mahdavi, Floyd & Romanow, October 1996) is unambiguously good: it makes loss recovery cheap and precise. It is also what turned the Nash equilibrium of the TCP game from alpha_E = 1 into alpha_E = 40 with 20% loss, because the deterrent against aggression was the expense of recovery. When you remove a cost, check what that cost was silently buying.
Fixing an unfairness accusation takes years and a working group. The BBRv1 fairness reports began around 2017, the mechanism was modelled at IMC 2019, and the specification containing the deference machinery is draft-ietf-ccwg-bbr-06 dated July 2026 — still an Internet-Draft, still Experimental, and still not what mainline Linux ships. In the meantime the internet ran on a mixed population, which is exactly the condition Mishra et al. predict is stable. That is either reassuring or alarming depending on whether you think an equilibrium reached by accident deserves the name.
For the operational side of the queueing mechanisms named here, see Bufferbloat and Active Queue Management, Queueing Disciplines qdisc, and Byte Queue Limits and Buffer Bloat.
See Also
- Games and Strategic Systems in C MOC — the parent MOC; this note is stage P8, The Vault’s Own Games
- Congestion Control Fundamentals and AIMD — the mechanism this note reads strategically, including the full Chiu–Jain vector geometry
- TCP Congestion Control — slow start, congestion avoidance, and the Linux implementation
- CUBIC Congestion Control — the cubic growth function and the Reno-friendly region whose constant is derived above
- BBR Congestion Control — the model-based algorithm whose fairness is the subject of the BBR section
- Bufferbloat and Active Queue Management — CoDel, FQ-CoDel, and why deep buffers are what BBRv1’s in-flight cap was exploiting
- Queueing Disciplines qdisc — how the Linux side of these mechanisms is actually configured
- The Price of Anarchy — the 4/3 bound, Braess’s paradox, and the exact conditions under which they hold
- Nash Equilibrium — the solution concept every result above is stated in
- The Prisoner’s Dilemma — the 2×2 template this game resembles but does not exactly match
- Mechanism Design and Incentive Compatibility — the design discipline the AQM section applies
- Rate Limiting as a Mechanism — the sibling P8 note on quotas and priority as allocation rules
- Multi-Tenancy and Fairness in LLM Serving — the same congestion game, one layer up the stack
- Security as an Adversarial Game — the sibling P8 note on when the opponent wants to hurt you rather than to win
- Consensus as a Coordination Game — the sibling P8 note on agreement protocols in equilibrium terms