Kapittel 3 · Transportlaget

Metningskontroll
og evolusjon

Hvordan tusenvis av TCP-forbindelser deler et begrenset nettverk uten å kollapse det — fra slow start til CUBIC og QUIC.

00 · Motivasjon

Hvorfor metningskontroll?

Flow control beskytter én mottaker. Metningskontroll beskytter det delte nettverket mellom alle sendere.

Tenk deg en motorvei der hver sjåfør bestemmer sin egen fart. Uten noen form for regulering — trafikklys, fartsgrenser, påkjøringsramper — vil veien til slutt gå i lås. Metningskontroll i TCP er trafikklyset: en mekanisme som lar sende ren justere farten sin basert på hvor fullt nettverket virker å være, uten at noen sentral myndighet styrer det.

To vinduer, én begrensning

TCP-senderen styres av to vinduer som begge legger begrensninger:

VinduHva det beskytter
rwndReceive window — satt av mottakeren i TCP-headeren. Beskytter mottakerens buffer mot overflyt.
cwndCongestion window — vedlikeholdt av senderen lokalt, usynlig i headeren. Beskytter nettverket mot overbelastning.

Regelen er enkel:

Senderens lov

LastByteSent − LastByteAcked ≤ min(cwnd, rwnd)

Senderen kan aldri ha mer data «in flight» enn den minste av de to vinduene. I praksis, når nettverket er flaskehalsen, er cwnd < rwnd, og det er cwnd som styrer.

TCPs senderrate blir da omtrent:

Senderrate

rate ≈ cwnd / RTT  bytes/sek

cwnd er usynlig Merk at rwnd annonseres i TCP-headeren og kan observeres i en pakkefangst. cwnd derimot eksisterer bare internt hos senderen — den er aldri synlig på tråden.

Bottleneck-lenken

Når TCP øker sendraten, er det til slutt én lenke i stien som blir mettet — bottleneck-lenken. Ruterens utgangskø fyller seg opp, og pakker begynner å gå tapt. Nøkkelinnsikten:

To innsikter om bottleneck

1. Å øke sendraten utover bottleneck-kapasiteten gir ikke høyere gjennomstrømning — det gir bare mer pakketap.

2. Å øke sendraten utover bottleneck-kapasiteten øker RTT, fordi pakker venter lenger i køen.

Målet: «Keep the end-end pipe just full, but not fuller.»

To tilnærminger til metningskontroll

Det finnes to fundamentalt forskjellige måter å angripe metningsproblemet på:

TilnærmingHvordan det fungerer
End-to-endNettverket gir ingen eksplisitt tilbakemelding om metning. Senderen må selv utlede tilstanden — basert på observert tap (timeout eller dupliserte ACK-er) og forsinkelse. TCP bruker denne tilnærmingen.
NettverksassistertRutere gir eksplisitt tilbakemelding til senderen om metningsnivået — for eksempel via spesielle kontrollmeldinger, eller ved å sette bits i pakkeheaderen som signaliserer at en lenke nærmer seg metning.

Internettets TCP har tradisjonelt vært rent end-to-end: IP-laget gir ingen hjelp, og senderen er overlatt til seg selv. All informasjon om nettverkets tilstand må utledes indirekte — fra ACK-er som uteblir, fra forsinkelser som øker, eller fra pakker som forsvinner. Det er nettopp dette som gjør TCP-metningskontroll til et så elegant og utfordrende problem.

01 · Slow start

Eksponentiell opptrapping

Navnet er misvisende — slow start er faktisk den raskeste fasen av TCP. Vinduet dobles hver RTT.

Når en TCP-forbindelse nettopp er opprettet, vet senderen ingenting om nettverkets kapasitet. Å sende for mye umiddelbart kan forårsake metning. Å sende for lite kaster bort tid. Løsningen er å starte forsiktig og doble sendraten for hver RTT til man treffer en grense.

Mekanismen

Slow start-algoritmen

1. Start med cwnd = 1 MSS.
2. For hver mottatte ACK, øk cwnd med 1 MSS: cwnd = cwnd + MSS.
3. Effekten: cwnd dobles per RTT (eksponentiell vekst).

Eksempel

Med MSS = 1500 bytes og RTT = 200 ms:

RTTcwndSegmenter sendt
01 MSS1
12 MSS2
24 MSS4
38 MSS8
416 MSS16

Initiell rate: 1500 / 0.2 = 7.5 kB/s. Etter 4 RTT-er: 24 000 / 0.2 = 120 kB/s. Eksponentiell vekst rammer raskt opp til tilgjengelig kapasitet.

Når slutter slow start?

Slow start avsluttes ved ett av tre hendelser:

  • Timeout — cwnd settes tilbake til 1 MSS, ssthresh = cwnd/2, og slow start starter på nytt.
  • cwnd ≥ ssthresh — overgang til congestion avoidance (lineær vekst).
  • 3 dupliserte ACKs — overgang til fast recovery.
ssthresh ssthresh (slow start threshold) er en variabel som husker omtrent hvor det gikk galt sist. Den starter typisk på en høy verdi (f.eks. 64 KB) og halveres ved hvert tap. Den markerer grensen mellom eksponentiell og lineær vekst.
Sjekk forståelsen

Under slow start med cwnd = 4 MSS sender TCP 4 segmenter og mottar 4 ACKs. Hva blir ny cwnd?

02 · Congestion avoidance

Additive increase, multiplicative decrease

Når cwnd har nådd ssthresh, skifter TCP fra eksponentiell til forsiktig lineær vekst — og halverer brutalt ved tap.

AIMD (Additive Increase, Multiplicative Decrease) er kjernen i TCPs metningskontroll. Ideen er vakker i sin asymmetri: voks sakte oppover, kutt raskt nedover. Denne asymmetrien gir stabilitet og rettferdighet — egenskaper som ren eksponentiell vekst aldri kunne gitt.

Additive increase

I congestion avoidance-fasen øker cwnd med 1 MSS per RTT — ikke per ACK som i slow start. Formelen per ACK er:

Congestion avoidance — per ACK

cwnd = cwnd + MSS × (MSS / cwnd)

Siden det kommer omtrent cwnd/MSS ACKs per RTT, gir dette en total økning på 1 MSS per RTT — lineær vekst.

Multiplicative decrease

Ved pakketap halverer TCP vinduet:

Ved tap

ssthresh = cwnd / 2
cwnd = ssthresh  (ved 3 dup-ACKs, TCP Reno)
cwnd = 1 MSS  (ved timeout, alle varianter)

Sagtann-mønsteret

Resultatet er det karakteristiske sagtannmønsteret: cwnd vokser lineært oppover, faller brått ved tap, vokser lineært igjen. TCP «sonderer» stadig etter mer båndbredde.

cwnd (KB) tid additive increase loss!
AIMD-sagtannen. Lineær oppgang, brå halvering ved tap, lineær oppgang igjen. TCP prøver stadig å finne den rette sendraten.

Regneeksempel: congestion avoidance

Eksempel

Anta cwnd = 3000 bytes og MSS = 1500 bytes. Det betyr 2 segmenter i flight, altså 2 ACKs per RTT.

ACK 1: cwnd = 3000 + 1500×(1500/3000) = 3750
ACK 2: cwnd = 3750 + 1500×(1500/3750) = 4350

Netto økning over hele RTT-en: omtrent 1 MSS (fra 3000 til ~4500). Lineær vekst, som forventet.

Sjekk forståelsen

I congestion avoidance med cwnd = 10 MSS, hvor mye vokser cwnd på én RTT?

03 · Fast recovery

Reno vs. Tahoe

Ikke alle pakketap er like alvorlige. Tre dupliserte ACKs betyr at noe fortsatt kommer frem — og TCP kan reagere mildere.

Det er en vesentlig forskjell mellom en timeout og tre dupliserte ACKs. En timeout betyr: «Jeg har ikke hørt noe som helst på lenge — nettverket er kanskje helt nede.» Tre dupliserte ACKs betyr: «Ett segment gikk tapt, men andre segmenter kommer frem — for mottakeren sender jo ACKs.» TCP Reno utnytter denne forskjellen.

TCP Tahoe (den opprinnelige)

TCP Tahoe (1988) behandler alle tap likt:

Tahoe — ved ethvert tap

ssthresh = cwnd / 2
cwnd = 1 MSS
Start slow start på nytt

TCP Reno (forbedringen)

TCP Reno (1990) differensierer:

Reno — ved 3 dupliserte ACKs

ssthresh = cwnd / 2
cwnd = ssthresh + 3 MSS
Gå til fast recovery

Reno — ved timeout

ssthresh = cwnd / 2
cwnd = 1 MSS
Start slow start på nytt

Hva skjer i fast recovery?

Under fast recovery øker cwnd med 1 MSS for hver dupliserte ACK som ankommer (disse tyder på at etterfølgende segmenter kommer frem). Når en ny ACK ankommer (som bekrefter det retransmitterte segmentet), avsluttes fast recovery:

Ny ACK i fast recovery

cwnd = ssthresh
Gå til congestion avoidance

Sammenligning

HendelseTCP TahoeTCP Reno
Timeoutcwnd → 1 MSS, slow startcwnd → 1 MSS, slow start
3 dup-ACKscwnd → 1 MSS, slow startcwnd → ssthresh+3, fast recovery

Reno unngår den kostbare turen tilbake til 1 MSS ved dupliserte ACKs — noe som kan spare mange RTT-er med lav gjennomstrømning.

Sjekk forståelsen

TCP Reno registrerer 3 dupliserte ACKs mens cwnd = 20 MSS. Hva skjer?

04 · TCP CUBIC

Raskere tilbake med kubisk funksjon

AIMD er rettferdig, men langsom. CUBIC bruker en smartere kurve for å utnytte kapasiteten raskere.

Klassisk TCP bruker AIMD: lineær økning med 1 MSS per RTT. På en lenke med høy kapasitet og lang forsinkelse kan det ta mange RTT-er å fylle lenken etter et tap. CUBIC stiller spørsmålet: kan vi gjøre det bedre?

Innsikten

CUBIC-prinsippet

La Wmax være sendraten da det siste tapet skjedde. Etter et tap vet vi at nettverket sannsynligvis ikke har endret seg mye. Da er det trygt å raskt nærme seg Wmax igjen — men vi bør være forsiktige nær Wmax, fordi det var der det gikk galt sist.

Kubisk vekst

CUBIC øker cwnd som en funksjon av tiden siden siste tap, ikke av RTT:

  • Langt fra Wmax — store, raske økninger (kurven er bratt).
  • Nær Wmax — forsiktige, små økninger (kurven flater ut).
  • Forbi Wmax — sonderer forsiktig etter ny kapasitet (kurven stiger igjen).

Punktet K er tidspunktet der cwnd ville nå Wmax. K er tunbart. Kurven er symmetrisk rundt K — den ligner en kubisk funksjon (derav navnet).

cwnd tid W_max klassisk TCP TCP CUBIC K tap
TCP CUBIC vs. klassisk AIMD. CUBIC vokser raskt langt fra Wmax, bremser nær Wmax, og sonderer forsiktig forbi. Resultatet: høyere gjennomstrømning.
Standard i Linux TCP CUBIC er standard metningskontrollalgoritme i Linux og er den mest brukte varianten blant populære webservere i dag.
Sjekk forståelsen

Hva er den viktigste fordelen med CUBIC over klassisk AIMD?

05 · Rettferdighet

Er TCP fair?

Hvis K TCP-sesjoner deler en flaskehals med kapasitet R, bør hver ideelt sett få R/K.

Rettferdighet er ikke bare et akademisk spørsmål — det handler om internettets grunnleggende funksjon. Hvis én forbindelse kunne ta alt, ville alle andre sulte. AIMD har en elegant egenskap: under idealiserte forhold konvergerer parallelle TCP-forbindelser mot lik fordeling.

AIMD-konvergens

Betrakt to TCP-sesjoner som deler en bottleneck med kapasitet R. Plott gjennomstrømningen til sesjon 1 på x-aksen og sesjon 2 på y-aksen:

Sesjon 1 Sesjon 2 x1+x2=R lik fordeling A add. incr. B halver C D
AIMD-konvergens: Additive increase gir helning 1 (45°). Multiplicative decrease trekker mot origo. Over tid konvergerer de mot lik fordeling.

A → B: begge sesjoner øker additivt (helning 45°) til de treffer kapasitetsgrensen.
B → C: begge halverer cwnd (trekker mot origo), men dette flytter punktet nærmere den grønne linjen.
Gjenta — punktet konvergerer mot lik fordeling.

Forutsetningene

Rettferdighet gjelder under idealiserte antakelser

Samme RTT — forbindelser med lavere RTT øker raskere og får mer båndbredde i praksis.
Fast antall sesjoner — i virkeligheten kommer og går forbindelser.
Bare congestion avoidance — beviset antar lineær vekst, ikke slow start.

Rettferdighet og UDP

UDP-applikasjoner (f.eks. videostrømming) deltar ikke i metningskontroll. De kan sende så fort de vil og tar dermed mer enn sin «rettferdige» andel. Det finnes ingen «internettpoliti» som håndhever rettferdighet.

Parallelle TCP-forbindelser

En nettleser som åpner 10 parallelle TCP-forbindelser til en server, får i praksis 10 × sin rettferdige andel sammenlignet med en applikasjon som bruker én forbindelse. Dette er en «lovlig» måte å jukse på — og det er utbredt.

06 · Evolusjon

Fra Tahoe til QUIC

TCP har utviklet seg i 40 år. Den nyeste evolusjonen flytter transportfunksjonaliteten opp til applikasjonslaget.

TCP og UDP har vært de to transportprotokollene i over fire tiår. I løpet av den tiden har TCP blitt forbedret gjentatte ganger — fra Tahoe via Reno til CUBIC. Men den mest radikale endringen er en helt ny tilnærming: QUIC, som bygger transportfunksjonalitet oppå UDP.

TCPs utvikling

ÅrMilepæl
1981RFC 793 — original TCP-spesifikasjon
1988TCP Tahoe — slow start og congestion avoidance (Jacobson)
1990TCP Reno — fast retransmit og fast recovery
2005BIC TCP
2008TCP CUBIC — kubisk vekstfunksjon, standard i Linux siden 2006 (RFC 8312 publisert 2018)

Forskjellige scenarier, forskjellige utfordringer

ScenarioUtfordring
Store overføringerMange pakker «in flight»; ett tap stenger hele pipelinen
TrådløstTap pga. støy forveksles med metning — TCP reduserer unødvendig
Lange forsinkelserEkstremt lang RTT gjør AIMD-oppramping smertefull
DatasentreLatenskritiske tjenester der selv millisekunders kø-forsinkelse teller

QUIC: Quick UDP Internet Connections

QUIC er en applikasjonslagsprotokoll bygd over UDP. Den implementerer pålitelighet, metningskontroll, kryptering og multipleksing — alt i brukerrommet, uten å vente på OS-oppdateringer. QUIC er grunnlaget for HTTP/3 og er standardisert i RFC 9000 (2021).

HTTP/2 over TCP HTTP/2 TLS 1.3 TCP IP Applikasjon Sikkerhet Transport Nettverk HTTP/3 over QUIC HTTP/3 QUIC pålitelighet + kryptering + metningskontroll per strøm UDP / IP
HTTP/2 over TCP krever separate håndtrykk for TCP og TLS. QUIC kombinerer alt i ett håndtrykk over UDP.

Forbindelsesetablering: 1-RTT og 0-RTT

Med TCP + TLS kreves det minst to serielle håndtrykk: først TCPs tre-veis håndtrykk (1 RTT), deretter TLS-håndtrykket (1 RTT til). Først etter 2 RTT kan applikasjonsdata sendes.

QUIC kombinerer transport- og krypterings-håndtrykket til én enkelt prosess. Klienten sender sin kryptografiske «hello» sammen med forbindelsesparametrene i første pakke, og serveren svarer med sin del — alt i 1 RTT.

Enda bedre: hvis klienten har koblet til serveren tidligere, kan den gjenbruke lagrede kryptografiske nøkler og sende applikasjonsdata allerede i første pakke — såkalt 0-RTT. Serveren kan begynne å behandle forespørselen uten å vente på et komplett håndtrykk.

TCP + TLS (2 RTT) Klient Server SYN SYN-ACK ACK } 1 RTT ClientHello ServerHello } 1 RTT HTTP-data QUIC (1 RTT) Klient Server CHLO SHLO } 1 RTT HTTP-data QUIC 0-RTT (gjentilkobling) Klient Server CHLO + data 0 RTT ventetid!
TCP+TLS bruker 2 RTT før data kan sendes. QUIC klarer det på 1 RTT — og ved gjentilkobling kan data sendes umiddelbart (0-RTT).

Strømmer: førsteklasses multipleksing

En sentral innovasjon i QUIC er at strømmer (streams) er et innebygd konsept i selve transportprotokollen. Innenfor én enkelt QUIC-forbindelse kan det opprettes mange parallelle strømmer — uten nye håndtrykk. Hver strøm har:

  • Egne sekvensnumre — uavhengig av de andre strømmene
  • Egen pålitelig levering — tap og retransmisjon i én strøm påvirker ikke andre
  • Egen flytkontroll — både per strøm og per forbindelse

I HTTP/3 tilsvarer hver strøm typisk én HTTP-forespørsel/respons. Nye strømmer kan opprettes med minimal overhead, noe som gjør multipleksing langt mer effektivt enn HTTP/2 over TCP.

QUIC og head-of-line blocking

Med TCP og HTTP/2 deler alle forespørsler én enkelt bytestrøm. Selv om HTTP/2 logisk multiplekser flere forespørsler, er de alle avhengige av TCPs pålitelige, ordnede levering. Hvis et segment tilhørende forespørsel 1 går tapt, må alle tre vente på retransmisjonen — selv om data for forespørsel 2 og 3 allerede er mottatt.

HTTP/2 over TCP Én TCP-forbindelse (én bytestrøm) GET 1 TAPT GET 2 GET 3 GET 2 og GET 3 blokkert — venter på retransmisjon HTTP/3 over QUIC Strøm 1 (GET 1) — tapt segment, retransmitterer Strøm 2 (GET 2) — leveres uforstyrret ✓ Strøm 3 (GET 3) — leveres uforstyrret ✓ Tap i strøm 1 blokkerer bare strøm 1
HTTP/2 over TCP: ett tapt segment blokkerer alle forespørsler (HOL-blocking). QUIC: hver strøm er uavhengig — tap i én påvirker ikke de andre.

Connection ID og mobilitet

TCP identifiserer en forbindelse med en 4-tuppel: (kilde-IP, kilde-port, dest-IP, dest-port). Hvis en av disse endres — for eksempel når telefonen bytter fra Wi-Fi til mobilnett — må TCP-forbindelsen avsluttes og opprettes på nytt, inkludert nye håndtrykk.

QUIC bruker i stedet en connection ID i pakkene sine. Denne ID-en er uavhengig av de underliggende IP-adressene og portene. Når en klient bytter nettverk, holder connection ID-en forbindelsen i live — klienten fortsetter å sende pakker med samme ID fra sin nye adresse, og serveren gjenkjenner forbindelsen uten re-etablering.

Metningskontroll i QUIC

QUIC implementerer sin egen metningskontroll, separat fra operativsystemets TCP-stabel. Som standard bruker QUIC algoritmer som likner på TCP CUBIC, men siden QUIC kjører i brukerrommet (user space) kan metningskontrollalgoritmen oppdateres uavhengig av OS. Google har for eksempel eksperimentert med og rullet ut BBR (Bottleneck Bandwidth and RTT) i sin QUIC-implementasjon, helt uten å måtte oppdatere operativsystemer.

Oppsummering: QUICs fordeler over TCP

EgenskapTCPQUIC
ForbindelsesetableringTCP-håndtrykk + TLS-håndtrykk = 2 RTTKombinert håndtrykk = 1 RTT (0-RTT ved gjentilkobling)
HOL-blockingEtt tapt segment blokkerer alle dataPer-strøm pålitelighet — tap blokkerer bare den berørte strømmen
Forbindelsesidentitet4-tuppel (IP + port) — brytes ved nettverksbytteConnection ID — overlever nettverksbytte
MultipleksingÉn bytestrøm (HTTP/2 multiplekser logisk, men TCP ser bare én strøm)Innebygde, uavhengige strømmer med egne sekvensnumre
OppdaterbarhetI OS-kjernen — krever kjerneoppgraderingI brukerrommet — oppdateres med applikasjonen
KrypteringValgfri (TLS er separat)Alltid på — TLS 1.3 er innebygd i protokollen
Sjekk forståelsen

Hva er hovedfordelen med QUICs per-strøm pålitelighet?

Sjekk forståelsen

Hvorfor kan en QUIC-forbindelse overleve at klienten bytter fra Wi-Fi til mobilnett?

✶ ✶ ✶

Med dette er hele kapittel 3 dekket: fra transportlagets tjenester og UDP, gjennom TCPs pålitelige dataoverføring, til metningskontroll, CUBIC og QUIC.

Interaktiv

cwnd gjennom fasene

Følg utviklingen av congestion window steg for steg — fra slow start, gjennom congestion avoidance, til tap og recovery.

CWND-utvikling

Steg-for-steg simulering