Transmission Control Protocol (TCP)
Cíl kapitoly
V této kapitole si připomenete vlastnosti protokolu TCP a prohloubíte znalosti
o jeho dynamickém chování. Tyto znalosti jsou důležité hlavně pro pochopení mechanismů,
které se v síti používají pro nepřímé řízení chování zdrojů datových toků využívajících
protokolu TCP.
Prekrekvizity
Před prostudováním této kapitoly se seznamte s úvodním popisem protokolu TCP
(Dostálek, kap. 9).
Funkce TCP - opakování
- Obousměrný spolehlivý datový proud mezi dvěma aplikacemi
- Aplikace v rámci stroje (IP adresy) identifikovány portem
- Identifikace spojení: čtveřice < lokální IP adresa, lokální port, vzdálená IP adresa, vzdálený port >.
- Dělení datového proudu na segmenty (max. délka segmentu dána Path MTU).
- TCP řeší opakované vysílání ztracených segmentů, resekvencování, rušení duplikovaných segmentů.
Záhlaví TCP a jeho enkapsulace
Sliding Window
Bajty v datovém proudu se číslují (v obou směrech nezávisle), sekvenční číslo je číslem
prvního bajtu v daném segmentu.
Délka segmentu
- Volbou MSS (Maximum Segment Size) protokolu TCP strana specifikuje, jak velké segmenty
je ochotna akceptovat.
- Volba MSS smí být pouze v SYN segmentu.
- Není-li volba MSS uvedena, použije se pro cíle na stejné LAN MTU této místní LAN, pro ostatní
cíle pak implicitní hodnota 536 (576B - 20B (IP Header) - 20B (TCP Header)).
576 je minimální délka IP paketu.
Potvrzování
Detekce ztraceného segmentu na vysílači:
- vypršení timeoutu
- duplicitní ACK téhož sekvenčního čísla - indikuje, že na přijímač přicházejí další segmenty, ale nějaký segment chybí.
Dva stejné ACK mohou být způsobeny jen příchodem v obráceném pořadí (je předpoklad,
že segmenty ještě dojdou), za indikaci výpadku segmentu se proto obvykle považují
tři a více následující duplicitní ACK.
Nagleův algoritmus
Používá se pro interaktivní aplikace generující krátké pakety (tzv. tinygramy).
- Krátké pakety zatěžují pomalé WAN linky
- Do sítě může být zaslán současně vždy jen jeden krátký paket, další až po příchodu ACK - tím se vkládaná zátěž automaticky upravuje podle odezvy sítě
- V mezičase se data pro odeslání na vysílači střádají (až do MSS)
- Nutné vypnout pro některé aplikace (XWindow - jednostranné realtime info o pohybu myši)
Strategie retransmisí, výpočet timeoutu
Retransmission Timeout (RTO) odvozen z vyhlazeného Round-trip Time (RTT).
Chápání RTT:
čas mezi odesláním segmentu s určitým
sekvenčním číslem a prvním ACK potvrzujícím toto sekvenční číslo (přímo nebo inkluzivně).
Výpočet RTO - původní verze
Nechť M je aktuální změřený RTT, R je vyhlazovaný RTT.
R=a.R+(1-a).M
RTO=R.b
a je koeficient pro vyhlazení, obvykle 0.9.
b je faktor variance zpoždění, doporučuje se hodnota 2.
Výpočet RTO - aktualizovaná verze pro vyšší fluktuaci RTT
Využívá se průměru a střední odchylky RTT.
A je vyhlazená hodnota RTT
D je vyhlazená variance
Err=M-A
A=A+g.Err (g=1/8)
D=D+h.(|Err|-D) (h=1/4)
RTO=A+4.D
Karnův algoritmus
Pokud vyprší timeout a dojde k retransmisi, nepřispívá RTT od následujícího ACK k výpočtu
vyhlazeného RTT. Nelze totiž rozlišit, zda jde o opožděný ACK původních nebo již opakovaných dat.
Fast Retransmit
- Při detekci tří duplicitních ACK se vyšle znovu segment, o němž se předpokládá, že je ztracený, aniž by se čekalo na timeout.
- Předpokladem použití Fast Retransmit je, aby přijímač při příchodu segmentu mimo pořadé gemeroval okamžitě duplicitní ACK.
- Fast Retransmit se samozřejmě použije jen tehdy, když jsou zmíněné
tři duplicitní ACK přijaty do normální retransmise příslušného segmentu od vypršení timeoutu.
- Fast Retransimit je užitečný pro velká okna - nemusí se opakovat tak velké množství dat, jako by se opakovalo při postupném vypršení timeoutu všech po ztraceném segmentu vyslaných a kvůli němu nepotvrzených segmentů.
Navazování spojení
Three-way handshake:
- Náhodná volba Intial Sequence Number (ISN) - obrana proti případným zatoulaným a pozdě dorazivším segmentům
- Příznak SYN se co do sekvenčních čísel jeví, jako by měl délku 1B
-
Pokud server neodpovídá na SYN: postupné prodlužování časů mezi opakovanými pokusy,
po 75 sekundách se aplikaci hlásí chyba (BSD implementace).
Stavový diagram TCP - stavy při navazování spojení:
Listening Queue
- fronta udržující spojení, která již prošla three-way handshake
- zřizuje se voláním listen(socket,BACKLOG), spojení aplikace přebírá voláním accept(socket)
- pokud ve frontě není místo, došlý SYN se ingoruje. SYN bude klientem opakován, mezi tím
se ve frontě může uvolnit místo.
Ukončování spojení
- FIN+ACK nezávisle v obou směrech (aktivní a pasivní uzavření spojení)
- možnost jednostranného uzavření spojení (half-close) pro indikaci
konce přenášení dat ve směru od stanice, která poslala FIN.
Příklad použití half-close: rsh myhostname.cz sort < datafile
- Příznak FIN se co do sekvenčních čísel jeví, jako by měl délku 1B
Stavy stavového diagramu TCP při ukončování spojení:
Stav 2MSL (Maximum Segment Lifetime)
- týká se strany, která aktivně uzavřela spojení (tedy vysílá poslední ACK):
strana musí být schopna zopakovat poslední ACK, pokud se tento ztratí.
- při ztrátě posledního ACK příjde opakovaný poslední FIN
- maximální doba čekání na případný opakovaný FIN:
předpokládaná max. doba šíření posledního ACK sítí + předpokládaná
max. doba šíření opakovaného FIN sítí (2 * Maximum Segment Lifetime, odtud 2MSL].
- informace o právě uzavřeném socketu se tedy musí v jádře OS podržet po dobu 2MSL, po tuto dobu tedy nelze
znovu otevřít stejnou dvojici socketů (se stejnou lokální IP adresou, lokálním portem, vzdálenou IP adresou
a vzdáleným portem). Doba 2MSL je podle implementace 2 minuty nebo 30 s.
Některé implementace bohužel tuto podmínku zesilují (zjednodušují) a nedovolují
po dobu 2MSL znovu otevřít tentýž lokální port. To je problém při restartu serverů na well-known portech.
U klientů nevadí, protože porty klientů jsou dynamicky přidělované OS.
Odmítnutí spojení
Indikuje se příznakem RST
- při pokusu navázat spojení na port, na kterém žádný server neběží
- pokud některá komunikující strana zjistí, že protějšek je nedůvěryhodný
Řízení toku dat
- řízení přijímačem - inzerování velikosti přijímacího okna (podle místa v přijímacím bufferu).
WINDOW 16 bit, TCP volba SCALE v SYN segmentu (posun hodnoty WINDOW o n bitů)- užitečné zejména pro velké součiny bandwidth*delay.
- řízení vysílačem - regulace vysílacího okna (podle provozu v síti (zpětná vazba přes ACK) a pomalý náběh)
Syndrom hloupého okna (Silly Window Syndrome)
K syndromu hloupého okna dochází, pokud přijímač opakovaně nabízí krátké přijímací
okno, namísto aby počkal, až bude moci nabídnout větší. Syndrom vede k neefektivnímu vysílání
po krátkých segmentech.
Pomalý náběh (Slow start)
- při zřizování nového TCP spojení možnost skokového nárůstu zátěže, zahlcení sítě a zneprůchodnění všech (i již navázaných) spojení.
- principem je přizpůsobení rychlosti vysílání segmentů do sítě rychlosti přicházejících ACK
- používá se jen pro spojení mimo LAN
Vysílač upravuje šířku vysílacího okna (CWND,"Congestion Window"), ta se udržuje v bajtech.
Také udržuje hodnotu SSTHRESH, což je hodnota velikosti CWND,
od které již začíná hrozit zahlcení.
Cílem je udržovat CWND blízko nad hodnotou SSTHRESH, kde však ještě nedochází k zahlcení
Postup:
na počátku CWND inicializováno na 1 segment (MSS bajtů)
při přijetí každého ACK k vyslanému segmentu (možná inkluzivního) zvětšení CWND o jeden segment (MSS)
pokračuje se do ztráty prvního segmentu
Výsledkem je exponenciální řada počtu vysílaných segmentů (1,2,4,8,16,...).
Předcházení zahlcení (Congestion Avoidance)
Možné důvody zahlcení
- data se z rychlejší sítě posílají na pomalejší
- přeplnění front směrovače (sčítáním datových toků)
Implementace algoritmů Congestion Avoidance a Slow Start se obvykle spojuje.
- Inicializace: CWND=1xMSS, SSTHRESH=65535 B.
- Maximální vysílané množství bajtů: min(CWND,WINDOW)
- Chování při odsílání segmentu:
Je-li CWND < SSTHRESH: chování podle Slow start (exponenciální nárůst CWND),
jinak podle Congestion Avoidance (lineární nárůst CWND)
- Chování při ztrátě segmentu: SSTHRESH=min(CWND/2,WINDOW), nejméně však 2*MSS
- ztráta detekována vypršením timeoutu: CWND=1xMSS, následuje Slow start
- ztráta detekována duplicate ACK: jen úprava SSTHRESH=CWND/2 (ale minimálně 2*MSS)
- Úprava CWND v oblasti nad SSTHRESH (Congestion Avoidance):
přičítá se (MSSxMSS/CWND + MSS/8) v celočíselné aritmetice.
(Druhý člen vede k rychlejšímu otevírání okna pro větší segmenty)
Pomalý start se znovu spouští při detekci výpadku segmentu timeoutem, ne při detekci
duplicitním ACK (při tom stále ještě nějaké segmenty procházejí).
Persist Timer
- periodické zjišťování velikosti přijímacího okna druhé strany (window probes)
- řeší deadlock, pokud přijímač přijímaci okno uzavřel, pak zase otevřel, ale otevírací
ACK se ztratil
- window probes jsou běžné segmenty s opakovaným posledním sekvenčním číslem a délkou nula,
příjímač na ně musí odpovědět ACK s aktuální hodnotou velikosti přijímacího okna (WINDOW)
Keepalive Timer
- slouží k detekci rozpadlého spojení (možnost uvolnění zdrojů serveru)
- lze zapnout volbou v Sockets API
- rozporuplné, není v normě, testování idle spojení by spíše měla řešit sama aplikace
- spojení se zruší i kvůli dočasnému výpadku konektivity