TCP congestion control и queueing

TCP механизми за регулация на трафика и congestion-control

В стандартните TCP имплементации има няколко механизма за предотвратяване на congestion:

  • TCP Slow-start – това е стандартният метод за увеличаване на количеството данни, което се изпраща – в началото експоненциално започвайки от един сегмент, а след определен момент – линейно(congestion-avoidance поведение), и регулация на това количество при наличие на задръстване (congestion) някъде по мрежата след източника на трафик;
  • TCP congestion-avoidance – работи заедно с TCP Slow-start и дефинира начин за регулация на нарастването на обема данни за изпращане при TCP – де факто представлява flow control при източника;
  • TCP Fast retransmit -дефинира ускорено препредаване на част от данни, при получаване на минимум 3 дубликатни квитанции (duplicate acknowledgements), без да се изчаква изтичането на TCP retransmission timeout-а.
  • TCP Fast recovery – след изпращането на липсващият сегмент от fast retransmit механизма, TCP продължава с линейно нарастване на количеството изпращана информация (congestion avoidance), вместо със започване на slow-start от самото начало;

TCP Slow-start

При установяване на TCP сесия една от променливите, които се инициализират в крайните възли е cwnd – congestion window. Тази променлива съдържа максималното количество информация, което може да бъде изпратено при следващото изпращане. Първоначално променливата се инициализира с размера на един сегмент – обикновено обявеният “прозорец” от отсрещната страна, или по подразбиране 536B или 512B. При всяко получаване на ACK от отсрещната страна, размера на cwnd се увеличава с размера на още един сегмент. При следващото получаване на ACK, размера се увеличава от размера на два сегмента, на 4, и т.н. нараствайки експоненциално. При всяко изпращане, максималното количество данни, което източника може да изпрати се ограничава до по-малкото от текущият cwnd и обявеният window size от отсрещната страна.

TCP congestion-avoidance

Принципа на congestion-avoidance залага на засичане на ситуации на congestion нагоре по мрежата, на базата на две условия – изтичане на TCP retransmission timeout без получаване на ACK, което се приема условно за доказателство за задръстване, или получаване на определен брой duplicate ACKs. При засичане на задръстване, TCP трябва да премине в режим на slow-start, като ефективно намали количеството данни които се изпращат, и постепенно увеличава това количество спрямо вече описания slow-start алгоритъм.

Съвместна работа на Slow-Start и Congestion-Avoidance

При установяване на TCP сесия още една от променливите, които се инициализират е ssthresh -Segment Size Threshold -размера на сегмента за изпращане, при достигане на който растежа на cwnd трябва да продължи линейно, вместо експоненциално. SSthresh се използва от congestion-avoidance механизма на TCP, като горна граница на експоненциалното нарастване на cwnd, и начало на линейното нарастване. След достиганенто на SSthresh (cwnd=ssthresh) и навлизането в период на congestion-avoidance, cwnd нараства с SS*SS/cwnd при получаване на ACK, което е линейно нарастване, и би трябвало да е еквивалентно на максимум един segment size (SS) увеличение (за разлика от удвояването при нормалния slow-start), при всяко получаване на ACK. SSthresh също така се променя динамично в зависимост от наличието на задръстване. Първоначално ssthresh се инициализира като 65535B, а cwnd – като обявения window size или 536B (512B)

При изпращане (максимум по-малкото от обявения window size и cwnd), ако TCP засече задръстване, на базата на retransmission timeout, TCP влиза в slow-start и установява cwnd на първоначалната стойност (1 сегмент => 536B или 512B). Допълнително, а също и ако TCP засече задръстване на базата на duplicate ACKs, текущата стойност на ssthresh се реинициализира като половината на текущия изпращан window size, т.е. границата на прекратяване на експоненциалното нарастване на cwnd се сваля по-надолу, и линейното нарастване на cwnd започва по-рано.

Съвместна работа на Fast retransmit и Fast recovery

При загуба на сегмент, или при получаване на сегмент извън поредният ред, получаващият TCP процес изпраща duplicate ACK. При получаването на duplicate ACK, изпращащият TCP не може да знае дали този duplicate ACK е вследствие на нормално пренареждане на пакети, или вследствие на загуба на сегмент. Поради това, се приема за нормално, че традиционно преподреждане на сегменти би генерирало само 1 или 2 duplicate ACKs, а ако се получат три или повече поредни duplicate ACKs, се счита, че е бил загубен сегмент, и той бива изпратен повторно без да се изчаква изтичането на TCP retransmission timeout (Fast retransmit). По принцип получаващият TCP може да генерира duplicate ACK само при положение, че е получен друг TCP сегмент, а не очаквания. Това показва, че все пак между двата възела се извършва обмен на данни, следователно трасето не е напълно задръстено. При получаването на трети подред duplicate ACK, изпращащият TCP предприема следните действия:

  • задава стойност на ssthresh = cwnd/2 (подобно на засичането на congestion при congestion avoidance) ;
  • препредава липсващият сегмент;
  • задава стойност на cwnd=ssthresh+3*SS (увеличава размера на cwnd с три сегмента – точно толкова, колкото са напуснали изпращащият ТCP и са били кеширани от получаващият TCP, от където и трите поредни duplicate ACKs);
  • при получаване на нов duplicate ACK, увеличава cwnd с 1 segment size – размера на cwnd се увеличава, защото получаването на още един duplicate ACK означава, че поне още един сегмент който е напуснал изпращащият TCP е бил получен от пoлучаващият TCP, следователно текущите congestion-условия позволяват предаването на това количество информация;
  • при получаване на ACK, което означава успешно получена нова информация от получаващият TCP(това е ACK на препредадения пакет в първият етап), на cwnd се задава стойност ssthresh (която предварително е била зададена на cwnd/2); Тук вече TCP се намира в congestion-avoidance, тъй като скоростта на предаване е намалена наполовина в сравнение със скоростта преди загубата на първият пакет. Оттук нататък cwnd ще нараства линейно с SS*SS/cwnd при получаване на ACK.

Проблеми при работата на TCP и необходимостта от queueing

Без приложен допълнителен queueing, традиционното поведение на cisco интерфейс е използването на хардуерна FIFO-опашка за буфериране на данни преди изпращането им през интерфейса. Тази опашка се нарича TX-Ring (размерът може да се види с show interfaces) и той може да бъде променян с tx-ring-limit командата. Проблемът на този механизъм очевидно е липсата на диференциация между различните типове трафик, например малки и чувствителни към забавяне voip пакети могат да попаднат в ситуация на изчакване, заради по-големи пакети с данни, които са влезли в опашката преди тях. Поради относително непредвидимия характер на типовете пакети, попадащи във FIFO опашката в различните интервали от време, допълнителното забавяне на Voip пакетите ще бъде променливо (jitter) и не може да бъде предвидено, за да бъде адекватно компенсирано с jitter буфер от приемащата страна. Това би довело или до неадекватно качество на звука (заради jitter), или до неприемливо забавяне и walkie-talkie ефект (поради евентуална настройка на прекалено голям jitter буфер на приемащата страна, в стремеж да се компенсира големият jitter).

В периоди на задръстване на FIFO опашката, при неналичие на допълнителен queueing, всички пакети, пристигащи на входа на FIFO опашката биват дропвани, без разлика между различни типове пакети и разлика между TCP и UDP потоци. Това поведение е известно като tail-drop, и поради спецификата на работа на TCP потоците, то може да има интересни неприятни ефекти:

  • При дропване на пакети от TCP потоци, TCP ще регистрира загубата чрез изтичане на TCP retransmission timeout или duplicate ACKs (понеже не се дропват всички пакети от даден поток, а само тези които са в положение на tail-drop в даденият момент);
  • При регистриране на congestion, TCP ще редуцира cwnd спрямо стандартното си поведение, и ще навлезе в slow-start (или congestion-avoidance), което ще доведе до рязко намаляване на утилизацията на интерфейса от TCP потоци (понеже tail-drop не прави диференциация между потоци, можем да разчитаме, че в зависимост от количеството присъстващи TCP потоци, ще има tail-drop на пакети от много различни потоци), последванo от постепенно нарастване на тази утилизация (заради slow-start постепенното нарастване на cwnd), до момента на повторното достигане на период на congestion, когато ситуацията ще се повтори. Това е т.нар. TCP global synchronization, което е нежелан ефект поради намаленият ефективен капацитет за TCP потоците, и поради неефективното използване на свободен капацитет по време на slow-start нарастването;
  • В периоди на slow-start нарастване, съществува възможност наличните UDP пакети да заемат целия капацитет, освободен от TCP потоците в периода на slow-start, и да запълният FIFO опашката. По този начин следващият период на congestion (retransmission timeout, или duplicate ACKs) би настъпил доста по-бързо. Още по-лошото е, че поради спецификата на UDP той не разполага с механизми за подобряване на надеждността и за congestion-control, т.е. независимо от степента на tail-drop на UDP пакети, това няма да се отрази на количеството UDP трафик налично на интерфейса. По този начин е възможно в периоди на congestion и особено при голямо количество UDP трафик, поради недиференцираният tail-drop на FIFO-опашката и TCP global synchronization ефекта, да се получи ситуация, в която TCP потоците са изправени пред постоянен недостиг на ефективен капацитет – TCP Starvation.

За решаване на тези проблеми са въведени допълнителни механизми на software queueing, които се използват в периоди на congestion – най-популярните от тези механизми са способни да диференцират различни типове трафик в различни опашки (WFQ, CBWFQ, CBWFQ+LLQ) и да правят т.нар. RED (Random-Early-Detection), WRED (Weighted Random Early Detection), и CBRED (Class-Based RED), което отлага възникването на tail-drop, като започва да дропва пакети от определени типове трафик и определени потоци преди запълването на опашката. В едно планирано QoS решение, един early drop на част от TCP трафика може да бъде временно полезен (заради естественият механизъм на TCP congestion control при регистриране на drop, а също така повечето приложения, използващи TCP не са прекалено чувствителни към временни краткотраийни периоди на намален капацитет), и да освободи капацитет за типове трафик, които са по-чувствителни към загуби и забавяне (voice/video), и които са същевременно регулирани, за да се предотврати starvation.

Tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *