Onion Information
Simulacijski modeli TCP-ovih algoritama za upravljanje zagušenjem - GASERI
Prisjetimo se da je jedna od prednosti TCP-a u odnosu na UDP kontrola zagušenja. Zagušenje je pojava kada čvor prima ili šalje toliku količinu podataka da se javljaju gubici paketa, blokiranje novih veza ili pak stvaranje velikog reda čekan...
Onion Details
Page Clicks: 0
First Seen: 03/15/2024
Last Indexed: 10/23/2024
Onion Content
Preskoči na sadržaj Simulacijski modeli TCP-ovih algoritama za upravljanje zagušenjem Prisjetimo se da je jedna od prednosti TCP-a u odnosu na UDP kontrola zagušenja. Zagušenje je pojava kada čvor prima ili šalje toliku količinu podataka da se javljaju gubici paketa, blokiranje novih veza ili pak stvaranje velikog reda čekanja. TCP se brine o tome da do ovakvih situacija ne dođe time što ima ugrađenu kontrolu zagušenja. Kontrola zagušenja će u slučaju da se ovakvo ponašanje mreže primijeti poduzeti potrebne mjere da zagušenje smanji ili otkloni. TCP algoritmi za kontrolu zagušenja koje opisujemo u nastavku razvijeni s ciljem smanjenja intenziteta kojim pošiljatelji šalju pakete u mrežu u slučaju da uoče veće opterećenje mreže. Ovdje ćemo samo "zagrebati po površini"; problematika izbjegavanja zagušenja mreže, uz optimalno iskorištenje njenih kapaciteta, spada među najvažnije i najaktivnije teme u području istraživanja i razvoja računalnih mreža. Varijanta TCP RFC793 RFC 793 definira da TCP vrši ponovni prijenos podataka u slučaju isteka vremena. Veličina prozora pošiljatelja se pritom ne mijenja, već ovisi samo o oglašenom prozoru primatelja. To uzrokuje česta zagušenja mreže, te su tijekom 80-tih godina predloženi algoritmi za upravljanje zagušenjem koji mijenjaju veličinu prozora pošiljatelja, koji se naziva i prozor zagušenja (engl. congestion window ). Varijante TCP Tahoe i TCP Reno Marshall Kirk McKusick, jedan od voditelja razvoja Berkeley Software Distribution (kraće BSD) Unixa na Sveučilištu u Berkeleyu tijekom 80-tih godina, u predavanju A Narrative History of BSD opisuje detaljno način na koji se razvijao TCP unutar BSD Unixa i ideje koje su prethodile. Za TCP algoritme za upravljanje zagušenjem značajne su dvije verzije BSD Unixa: 4.3BSD-Tahoe izdana 1988. godine, čija implementacija TCP-a se očekivano naziva TCP Tahoe , te 4.3BSD-Reno izdana 1990. godine, čija implementacija TCP-a se naziva TCP Reno . Osnovni algoritmi koje TCP koristi za upravljanje zagušenjem su: spori početak (engl. slow-start ), izbjegavanje zagušenja (engl. congestion avoidance ), brzo ponovno slanje (engl. fast retransmit ), brzi oporavak (engl. fast recovery , koristi ga samo TCP Reno). Spori početak (engl. slow start ) je jedan od algoritama koji TCP koristi za kontrolu zagušenja u mreži. On povećava cwnd za 1 MSS za svaki primljeni ACK, što ima za posljedicu udvostručenje cwnd -a svaki RTT, odnosno eksponencijalni porast. To se događa sve dok se ne dogodi gubitak paketa ili dok se ne dosegne unaprijed zadana maksimalna vrijednost veličine prozora ssthresh (prag sporog početka (engl. slow-start threshold ), veličina je dana u bajtovima, većina implementacija ima inicijalnu vrijednost 65536), a zatim se prelazi u izbjegavanje zagušenja. Ako se dogodi gubitak paketa za vrijeme sporog početka, TCP pretpostavlja da je to zbog zagušenja mreže i poduzima korake da smanji opterećenje, odnosno prelazi u fazu izbjegavanja zagušenja (engl. congestion avoidance ), u kojoj povećava cwnd za 1 MSS svaki RTT, što ima za posljedice linearni (aditivni) porast veličine prozora. TCP u toj fazi radi po metodi aditivnog porasta i multiplikativnog pada . Preciznije, veličina prozora se računa po formuli \[ cwnd \gets cwnd + MSS \times \frac{MSS}{cwnd}. \] Kada dođe do gubitka paketa (što se indicira istekom vremena ili primitkom dupliciranih ACK-ova), polovina trenutne veličine prozora cwnd sprema se u ssthresh . U slučaju da je došlo do isteka vremena, pored navedenog se cwnd postavlja na veličinu 1 MSS, i do ssthresh koristi spori početak, a od ssthresh koristi izbjegavanje zagušenja. Brzo ponovno slanje (engl. fast retransmit ) smanjuje vrijeme koje pošiljatelj čeka prije ponovnog slanja izgubljenog segmenta, a radi tako da kada TCP pošiljatelj dobije tri duplikata ACK-a (tj. četiri identična ACK-a) s istim sekventnim brojem, pošiljatelj smatra da je paket s idućim višim sekventnim brojem izgubljen, i da neće naknadno stići. Pošiljatelj će tada ponovno slati taj paket bez da čeka da njegov istek vremena. Tu postoji razlika kod TCP varijanti Tahoe i Reno. Kod TCP varijante Tahoe tri duplikata ACK-a tretiraju se kao istek vremena, cwnd se smanjuje na 1 MSS, segment se šalje, i prelazi se u spori početak. Kod TCP varijante Reno tri duplikata ACK-a tretiraju čine da se cwnd smanjuje na pola, segment se šalje, i prelazi se u brzi oporavak. U fazi brzog oporavka (engl. fast recovery ) TCP Reno šalje segment koji je označen od strane tri duplikata ACK-a i očekuje potvrdu cijelog prozora prije prelaska u izbjegavanje zagušenja. Ako potvrda stigne, vrijednost cwnd postavlja na ssthresh , time se preskače spori početak i nastavlja upravljanje veličinom prozora korištenjem izbjegavanja zagušenja. Ako ne stigne potvrda cijelog prozora, TCP prelazi u spori početak. Dodatak: varijanta TCP NewReno je poboljšana verzija Reno varijante TCP protokola. Eksperimentalno pokazuje bolje rezultate od Reno varijante u slučaju velikog broja grešaka. Kod Reno protokola brzo ponovno slanje događa se nakon primitka 3 ponovljena ACK te se čeka potvrda cijelog prozora slanja da bi se prozor pomaknuo na iduće pakete, dok NewReno za svaki ponovljeni ACK šalje još jedan novi (prethodno ne poslani) paket ne čekajući potvrdu cijelog prozora ubrzavajući time popunjavanje praznina u redosljedu paketa. Također za svaki ACK koji stigne smatra da idući paket u nizu fali te ga počinje slati (u fazi brzog ponovnog slanja). NewReno ima i jedan nedostatak, naime u slučaju da paketi stignu u pogrešnom redosljedu uz pomak veći od 3 paketa (u slijednom broju) smatra se da je paket izgubljen i ulazi se u fazu brzog ponovnog slanja. Pošto je takvo ponašanje uočeno dorađen je sa sustavom potvrđivanja paketa nakon što je primljen ponovljeni paket koji je bio van redosljeda tako što se sekventni brojevi uvećavaju te se šalju ACK paketi bez da je ponovljeno slanje svih ostalih paketa ukoliko je samo jedan paket van redosljeda. Note Na Wikipedijinoj stranici s taksonomijom algoritama za upravljanje zagušenjem možete pročitati više o varijantama TCP-a koje postoje i njihovim svojstvima. Praćenje promjene veličine prozora zagušenja Cilj nam je pratiti promjenu veličine prozora zagušenja TCP-a. Rezultate, pored ispisa na ekran, želimo zapisati u datoteku za kasniju analizu i crtanje grafova. Primjer koji opisujemo u nastavku ima istu topologiju mreže i iste aplikacije kao prethodni primjer. Nakon stvaranja čvorova i instalacije mrežnih kartica i veze tipa točka-do-točke, instalacije TCP/IP protokolarnog stoga i dodjele IP adresa, potrebno je postaviti on-off aplikaciju i odvod za pakete. Međutim, kako bi simulacija stvorila TCP mrežne utičnice koje koriste željeni algoritam za upravljanje zagušenjem (Tahoe ili Reno), potrebno je unaprijed postaviti parametre tvornice TCP mrežnih utičnica. Postoji nekoliko načina za to, a najjednostavniji i najčešće korišten je pomoću sustava konfiguracije implementiranog u klasi Config . Način rada s klasom Config je vrlo sličan načinu rada s klasom Simulator , obzirom da se također radi o statičkoj klasi, te načinu rada sa sustavom atributa. Konkretno, da bi promijenili algoritam za upravljanje zagušenjem, treba promijeniti vrijednost ključa "ns3::TcpL4Protocol::SocketType" . Config :: SetDefault ( "ns3::TcpL4Protocol::SocketType" , StringValue ( "ns3::TcpTahoe" )); Podsjetimo se da je Config::SetGlobal() i Config::SetDefault() potrebno izvesti prije stvaranja objekata simulacije. Za TCP Reno bi stavili "ns3::TcpReno" kao vrijednost atributa umjesto "ns3::TcpTahoe" . Sada stvaramo on-off aplikaciju i odvod za pakete na isti način kao i ranije. Informacija o veličini prozora zagušenja nalazi se u TCP mrežnoj utičnici koju će aplikacija koristiti. Da bi dosegli tu utičnicu, prvo pomoću metode GetObject<>() iz pametnog pokazivača app dohvaćamo objekt tipa OnOffApplication ; zatim pomoću metode GetSocket() tog objekta dohvaćamo pokazivač na odgovarajuću mrežnu utičnicu koji pohranjujemo u varijablu appSocket . Ovo dohvaćanje objekta odgovarajućeg tipa potrebno je zato što ApplicationContainer sadrži pokazivače na objekte tipa Application kako bi omogućio spremanje različitih aplikacija u isti kontejner, a objekti tipa Application nemaju metodu GetSocket() . Pored toga, povezujemo povratni poziv na izvor CongestionWindow . Ptr appSocket = app -> GetObject () -> GetSocket (); appSocket -> TraceConnectWithoutContext ( "CongestionWindow" , MakeCallback ( & CwndChange )); Prikladna funkcija CwndChange() za taj povratni poziv je tipa void i prima dva argumenta tipa uint32_t (što je na većini operacijskih sustava i program-prevoditelja samo fancy naziv za tip unsigned int ). void CwndChange ( uint32_t oldCwnd , uint32_t newCwnd ) { std :: cout stream = asciiTraceHelper . CreateFileStream ( "vjezba-tcp-tahoe.cwnd" ); Sada je potrebno pokazivač stream proslijediti kod povezivanja sustava za praćenje. Za to se koristi tzv. povezani povratni poziv (engl. bound callback ). Funkcija MakeBoundCallback() koja stvara povezani povratni poziv slična je funkciji MakeCallback() , ali je proširuje na način da omogućuje prosljeđivanje argumenata funkciji koja se koristit kao povratni poziv. Preciznije, svi argumenti od drugog nadalje postaju argumenti funkcije povratnog poziva od prvog nadalje. appSocket -> TraceConnectWithoutContext ( "CongestionWindow" , MakeBoundCallback ( & CwndChangeWriteFile , stream )); Posljednja dva argumenta funkcije CwndChangeFileWrite() su tipa uint32_t , kao i kod funkcije CwndChange() . Njihove će vrijednosti proslijediti appSocket kod poziva, odnosno onda kad se promijeni veličina prozora zagušenja; uočite da je MakeBoundCallback() u gornjem primjeru ne prosljeđuje vrijednosti ta dva argumenta. Funkcija CwndChangeFileWrite() pored ispisa na ekran vrši i ispis u datoteku. Sam način na koji to radi nije nam značajan; dovoljno je znati da je sučelje vrlo slično standardnom streamu std::ofstream . Obzirom nam je dovoljna funkcionalnost koja je ovdje navedena, načinom rada i dubljim razumijevanjem sučelja OutputStreamWrapper -a ovdje se nećemo baviti. void CwndChangeWriteFile ( Ptr stream , uint32_t oldCwnd , uint32_t newCwnd ) { std : cout GetStream () GetApplication ( 0 ), stream ); Unutar funkcije DoCwndTraceConnectOnSocketAfterAppStarts() prvo provjeravamo je li proslijeđeni pokazivač na aplikaciju različit od nul-pokazivača, da bi izbjegli dereferenciranje nul-pokazivača. Zatim deklariramo varijablu appSocket tipa Ptr i u nju dohvaćamo pokazivač na mrežnu utičnicu, za koji također provjeravamo je li različit od nul-pokazivača. Naposlijetku na toj utičnici izvodimo povezivanje izvora za praćenje sa odgovarajućim povezanim povratnim pozivom i streamom. void DoCwndTraceConnectOn...