Faculteit Ingenieurswetenschappen Vakgroep INTEC Voorzitter: Prof. Dr. Ir. P. LAGASSE
Draadloos internet op de trein
door Wim De Saegher
Promotor: prof. dr. ir. I. Moerman scriptiebegeleiders: Ir. B. Jooris Ir. T. Van Leeuwen Ir. N. Gheyssens Ir. D. Pareit
Afstudeerwerk ingediend tot het behalen van de academische graad van licentiaat in de informatica
Academiejaar 2006–2007
Bruikleen De auteur geeft de toelating deze scriptie voor consultatie beschikbaar te stellen en delen van de scriptie te kopi¨eren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichting de bron uitdrukkelijk te vermelden bij het aanhalen van resultaten uit deze scriptie.
Wim De Saegher, 13 augustus 2007
Woord vooraf Netwerken en internetwerken vervullen heden ten dage een steeds belangrijker wordende functie voor het opzoeken en delen van informatie tussen mensen en machines. De TCP/IP internetsuite wordt door meer dan ´e´en miljard[1] mensen dagelijks gebruikt om data van het ene punt naar het andere te versturen. Naar deze protocollen wordt nog steeds dagelijks onderzoek verricht, en regelmatig worden verbeteringen of aanpassingen voorgesteld en ge¨ımplementeerd. Een andere mogelijkheid tot verbetering ligt in het volledig vervangen van TCP, door een nieuw, moderner protocol dat de goede zaken van TCP overneemt en de zwakheden en kwetsbaarheden elimineert. SCTP is een populaire kandidaat, waarvoor reeds meerdere implementaties geschreven zijn, zowel op userlevel als kernellevel[2]. Het onderzoek naar SCTP is in volle gang, en regelmatig verschijnen vele verbeteringen. Deze thesis zal een van die verbeteringen voorstellen.
Dankwoord Een thesis is een werk dat niet door de handen van 1 persoon ontstaat. Ik zou graag enkele mensen bedanken zonder wie deze thesis nooit had kunnen worden wat ze nu is. Allereerst mijn promotor prof. Ingrid Moerman, die erin toestemde mij aan dit onderwerp te laten werken. Ze benadrukte het belang van een wetenschappelijke aanpak, hetgeen een groot deel van de vorm van deze thesis tot gevolg had. Ook mijn dank aan mijn begeleiders Tom Van Leeuwen en Bart Jooris, die me hebben ge¨ıntroduceerd tot de wereld van SCTP en me op weg zetten. Bedankt Tom, omdat je me de eerste stapjes liet zetten en voor je hints voor het allereerste testplan van SCTP en diens parameters. Bedankt Bart, voor alle zaken die je voor mij hebt klaargezet, alle technische problemen die je me hebt helpen overwinnen, de motiverende en aansporende woorden. Natuurlijk ook mijn speciale dank aan Nele Gheysens, die me specifiek op het probleem van fragmentatie wees, en Daan Pareit, die me meerdere keren terug op het goede pad zette. Bedankt ook aan beiden omdat ze me de kans gaven om verder te denken en te werken op hun resultaten. Als laatste wens ik bij dezen ook mijn ouders te bedanken voor de jarenlange steun, mijn vrienden voor hun onmisbare vriendschap en mijn vriendin voor alle dingen waarom ik zo van haar hou.
Wim.
Draadloos internet op de trein door Wim De Saegher Afstudeerwerk ingediend tot het behalen van de graad van licentiaat in de informatica Academiejaar 2006–2007 Universiteit Gent Faculteit Toegepaste Wetenschappen Vakgroep Elektronica en Informatiesystemen Voorzitter: Prof. Dr. Ir. P. LAGASSE Promotor: prof. dr. ir. I. Moerman Scriptiebegeleiders: Ir. B. Jooris Ir. T. Van Leeuwen Ir. N. Gheyssens Ir. D. Pareit
Samenvatting Deze scriptie biedt een uitbreiding op het SCTP protocol, die toelaat om data effici¨enter te fragmenteren. Een SCTP associatie bestaat uit meerdere verbindingen. De standaard SCTP fragmentatie zal met het oog op retransmissie in geval van faling de maximale pakketgrootte instellen op de kleinste MTU van deze verbindingen, waarbij, zeker bij verbindingen met opmerkelijke verschillen in MTU, vaak ineffici¨ent met netwerkbronnen wordt omgesprongen. Er wordt een nieuw chunktype voorgesteld waardoor data kan worden gefragmenteerd en geherfragmenteerd, zodat men data aan de MTU van het huidige pad kan versturen. Tevens wordt een implementatie in Click besproken die deze nieuwe datastructuur en algoritmes gebruikt. Trefwoorden: SCTP, mSCTP, Fragmentatie, Chunk Type, Click Modular Router.
Wireless internet onboard of a train. Wim De Saegher Supervisor(s): I. Moerman, T. Van Leeuwen, B. Jooris, N. Gheyssens, D. Pareit Abstract—This article proposes a way for SCTP to refragment data, thus enabling the retransmission of fragments using the full MTU of the underlaying path, instead of the minimal MTU over the set of paths. Keywords—fragmentation, mSCTP, SCTP, MTU.
I. I NTRODUCTION
A
S the number of internet users keeps increasing, the search to new technologies and improvements on existing technologies for communicating contintues. The Stream Transmission Control Protocol[1] was designed to provide a robust way of communication between host, introducing new features such as multihoming and multistreaming. These new features raise new questions, and if SCTP is to become the new TCP of the future, some honing and tuning is appropriate. One of the aspects that leaves options for improvement is how SCTP handles fragmentation: with the new multihoming, each connection within an association has its own inherent properties. An important property is the MTU of that path: it determines the size of segments that the path can transmit. Send a packet larger than a paths MTU and it will be dropped or fragmented. To handle all the different paths and their MTUs, SCTP uses an easy way out: it uses the minimum of the set of MTUs as the association-MTU. Other parts of the specification heavily rely on this feature: when it comes to fragmentation, the suggested algorithm uses this prerequisite to fragment data into chunks no larger than the aforementioned assocation-MTU, so that when a failure occurs during the transmission of a fragment, it can easily be retransmitted using another path of the association: it’s guaranteed to fit. This simplification comes with a price though: each path is not being used in the optimal way: sometimes a path capable of carrying very large segments will now be used to send tiny bits of information just because one other path in the association has a small MTU. Since performance is roughly proportional to MTU in many operating regimes[2], this can be rather wasteful, especially with significant differences between paths. With mSCTP and its feature of allowing new paths to be added dynamically, the assocation MTU can be subject to many fluctuations. A second issue is that since SCTP’s approach eliminates the need for refragmentation, it also eliminates all support: the existing data structures and algorithms are not capable of refragmenting data that has already been fragmented. For example, fragmented data chunks require stricly sequential numbering, which makes injecting a new packet impossible. If we want to use an optimal MTU per path, we will need to tackle this problem.
II. R EFRAGMENTATION Refragmentation enables us to use the paths MTU: in case of a transmission failure where the fragment needs to be resent using another path, it can be refragmented if that alternative path has a smaller MTU (or in combination with bundling in case of a larger MTU). III. DATA STRUCTURES AND ALGORITHMS To allow refragmentation, we introduce a new data chunk: the fragmented data chunk. It is very similar to an ordinary data chunk, but contains extra information its chunk header to allow refragmentation, see Figure 1. More specifically, a fragment offset was added, enabling us to indicate where the data in this fragment belongs into the original. Combined with the length, we can now use the pieces to solve the puzzle: we sort the fragments on offset to know which belongs where, and use the length to check for missing pieces. The last piece will have the MF-flag set to 0, and the sum its length and its offset will indicate the total length of the original data. We now know the puzzle is complete. Refragmenting now becomes easy: split fragments into as many fragments as required, keep the sum of lengths of the new fragments equal to the sum of the old fragments. To refragment one chunk or one fragment, simply copy all header flags into the fragments. Copy the offset into the first fragment, set the offset of the second fragment as the sum of the offset of the first and the length of the first, and set the MF-flags as appropriate.
Fig. 1. De SCTP Fragmented Data Chunk Header.
What remains is a way to know which pieces belong to which puzzle. This needs to be further examined. IV. I MPLEMENTATION This was implemented in C++ using click, a modular software router, to test our algorithms. V. E VALUATION The implementation was tested sending various packets over an SCTP association, and examining the SCTP packets for their chunks. It was discovered using wireshark that our algorithm
for fragmenting and sending was indeed correct and was nicely spreading the data over the fragments. Unfortunately, the receiver side code contains a bug, which causes the program to crash at times. We do believe this can be resolved, and it will prove the algorithms are correct. VI. C ONCLUSIONS Taking into account that Click is a simulation, these data should not be viewed as absolute values, instead the reader can deduct the strength of the algorithm by comparing the results before and after fragmentation. These relative values give an estimate as to what extent future implementations could benefit from this refragmentation algorithm. Unfortunately the current implementation allows for no real throughput measuring. ACKNOWLEDGMENTS The author would like to thank I. Moerman and T. Van Leeuwen, for the opportunity to research this subject, and B. Jooris, N. Gheyssens and D. Pareit for their excellent guidance on the subject. R EFERENCES [1] R. Stewart and M. Tuexen “RFC 2960: SCTP,” [2] Matt Mathis Raising the internet “http://www.psc.edu/ mathis/MTU/,”.
MTU
at
INHOUDSOPGAVE
i
Inhoudsopgave 1 Inleiding
1
1.1
Probleemstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.2
Overzicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.2.1
Doelstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.2.2
Structuur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2 TCP en SCTP
3
2.1
Korte historiek van TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.2
Beperkingen van TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.2.1
Betrouwbare dataoverdrachten en sequenti¨ele aflevering . . . . . . . . . .
4
2.2.2
Bytegeori¨enteerde natuur . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.2.3
Beperkte reikwijdte van TCP sockets . . . . . . . . . . . . . . . . . . . . .
4
2.2.4
Kwetsbaarheden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
Korte inleiding tot SCTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.3.1
Inleiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.3.2
Multistreaming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3.3
Multihoming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
2.3.4
State Cookie mechanisme . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
2.3.5
Chunks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
2.3.6
En nog veel meer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
Samenvatting van dit hoofdstuk . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
2.3
2.4
3 Uitbreidingen van SCTP
9
3.1
PR-SCTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
3.2
Auth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
INHOUDSOPGAVE
ii
3.3
ADDIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
3.4
mSCTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
3.5
Samenvatting van dit hoofdstuk . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4 Fragmentatie
12
4.1
Inleiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4.2
Fragmentatie bij IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4.3
Fragmentatie bij TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.4
Fragmentatie bij UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.5
Fragmentatie bij SCTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.5.1
Theorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Samenvatting van dit hoofdstuk . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
4.6
5 Herfragmentatie in SCTP
17
5.1
Inleiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
5.2
Herfragmentatie
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.2.1
Algemene idee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.2.2
Nieuw Chunk Type: het Fragmented Data Chunk . . . . . . . . . . . . .
18
5.2.3
Problemen bij dit voorstel . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Samenvatting van dit hoofdstuk . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.3
6 Implementatie in Click
22
6.1
Inleiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
6.2
Fragmentatie aan zenderzijde . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
6.2.1
Datastructuren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
Samenvatting van dit hoofdstuk . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
6.3
7 Conclusie
29
7.1
Stand van zaken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
7.2
Mogelijke uitbreidingen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
Bibliografie
31
1
Hoofdstuk 1
Inleiding 1.1
Probleemstelling
Het SCTP[3] biedt de mogelijkheid tot multihoming aan, die toelaat om bij het opzetten van een associatie meerdere verbindingen met elk hun eigen IP-adres te specifi¨eren. Dankzij onder andere de ADDIP uitbreiding[4] werd het mSCTP ontwikkeld, waar nieuwe verbindingen aan een bestaande associatie kunnen toegevoegd worden, in plaats van enkel tijdens het opzetten. Vooral voor mobiele hosts is dit bijzonder interessant, daar zij met deze technologie zichzelf een onverbroken netwerkverbinding kunnen verschaffen, zolang er minstens 1 actieve verbinding aanwezig is. Deze meerdere verbindingen hebben elk hun eigen eigenschappen, die onderling vaak erg verschillend zijn. E´en daarvan is de MTU (Maximum Transmission Unit), die bepaalt hoe groot ´e´en eenheid van informatie mag zijn. Deze verscheidenheid geeft problemen bij fragmentatie, vooral als gefragmenteerde pakketten moeten herverzonden worden over een andere verbinding dan ze oorspronkelijk voor gemaakt werden. Vaak zullen deze pakketten moeten worden geherfragmenteerd, maar SCTP ondersteunt geen herfragmentatie.
1.2 1.2.1
Overzicht Doelstelling
In deze scriptie wordt een manier voorgesteld om de fragmentatie van SCTP te verzorgen die effici¨enter is dan de oorspronkelijk voorgestelde manier[3], en die bovendien ook herfragmen-
1.2. OVERZICHT
2
tatie toelaat. Er wordt ook een bespreking gegeven van de implementatie in de Click Modular Router[5] die gebruikmaakt van de uitbreiding, waardoor de throughput van de standaardimplementatie vergeleken kan worden met de throughput na de verbetering.
1.2.2
Structuur
Na deze inleiding wordt in hoofdstuk 2 een korte inleiding op TCP en SCTP gegeven. Hoofdstuk 3 zal dan twee belangrijke voorgestelde uitbreidingen op SCTP toelichten, waarna de mSCTP draft gedestilleerd wordt. Daarna worden in hoofdstuk 4 een aantal gangbare manieren van fragmentatie in verschillende protocollen uiteengezet. Het effectieve voorstel voor een verbeterde fragmentatie wordt in hoofdstuk 5 besproken, waarna in hoofdstuk 6 de gebruikte datastructuren en algoritmes voor verzenden en ontvangen worden toegelicht. Als laatste zal hoofdstuk 7 de vergelijking maken tussen de resultaten zonder en met fragmentatie, en de conclusies van deze scriptie brengen. Ook worden enkele interessante mogelijke uitbreidingen aangetoetst.
3
Hoofdstuk 2
TCP en SCTP 2.1
Korte historiek van TCP
TCP/IP werd in het begin ontwikkeld als deel van ARPAnet, dat toen gebruik maakte van een aantal protocollen die uit bestaande technologi¨een werden overgenomen. In 1973 begon de ontwikkeling van een volledige suite van internetwerkprotocollen voor het toenmalige ARPAnet, en eigenlijk was er toen maar 1 belangrijk protocol, TCP[6], dat destijds nog stond voor Transmission Control Program. In december 1974 verscheen RFC 675[7] waarin TCP in detail beschreven werd. In 1977 vond een belangrijke evolutie in de ontwikkeling van TCP plaats toen Jon Postel voorstelde om het bestaande TCP op te splitsen in TCP/IP en het gelaagde model te gebruiken.[8] Pas in september 1981 werd RFC 793[9] gepubliceerd, waarin het DOD Standard Transmission Control Protocol volledig werd beschreven, en waarvan men de meest elementaire zaken vandaag nog in de implementaties van TCP terugvindt.
2.2
Beperkingen van TCP
Hoewel TCP de standaard bij uitstek is voor transport over IP-netwerken, en door de jaren vaak gebruikt werd als belangrijkste manier om data te verzenden, beginnen meer en meer applicaties hun eigen betrouwbare dataoverdrachtprotocollen te ontwerpen bovenop het UDP protocol om zo een aantal beperkingen van TCP te omzeilen of meer flexibiliteit te krijgen. Vier belangrijke beperkingen van TCP[3] worden hieronder kort aangehaald.
2.3. KORTE INLEIDING TOT SCTP
2.2.1
4
Betrouwbare dataoverdrachten en sequenti¨ ele aflevering
TCP biedt betrouwbare dataoverdracht en sequenti¨ele aflevering aan, maar sommige applicaties wensen misschien enkel de betrouwbare dataoverdracht zonder de strikte ordening van de pakketten, of soms is gedeeltelijke ordening voldoende. Bij TCP zal de HOL-blocking een onnodige vertraging veroorzaken: de ontvanger weigert pakketten te ontvangen zolang niet alle vorige pakketten ontvangen zijn, waardoor bij een faling niet ´e´en maar meerdere pakketten worden herverzonden.
2.2.2
Bytegeori¨ enteerde natuur
TCP is bytegeori¨enteerd waardoor applicaties er zelf voor moeten zorgen dat hun berichten van elkaar gescheiden kunnen worden, in tegenstelling tot bijvoorbeeld UDP dat berichtgeori¨enteerd is.
2.2.3
Beperkte reikwijdte van TCP sockets
Een TCP-verbinding is een kanaal tussen twee eindpunten, meerbepaald een socket tussen twee hosts. Voor elke host kan slechts ´e´en interface gebruikt worden, waardoor het falen van de interface tot direct gevolg heeft dat de TCP-verbinding zelf ook faalt.
2.2.4
Kwetsbaarheden
TCP is kwetsbaar voor verschillende soorten Denial Of Service attacks, waaronder de bekende SYN-floods[10], waarbij een kwaadwillige host een verbinding opzet naar een server door de eerste stap van de driewegshandruk uit te voeren. De server reserveert dan bronnen voor deze host, en wanneer dit proces vele malen herhaald wordt, raakt de server overbelast en zal hij nieuwe, mogelijk legitieme connecties weigeren.
2.3 2.3.1
Korte inleiding tot SCTP Inleiding
De vier aangehaalde beperkingen geven aanleiding tot de zoektocht naar een nieuw OSI laag 4 protocol, dat een alternatief biedt voor TCP en het op termijn misschien zelfs zou kunnen
2.3. KORTE INLEIDING TOT SCTP
5
vervangen.
Figuur 2.1: SCTP in het vijflagenprotocol
2.3.2
Multistreaming
SCTP kent multistreaming: verschillende stromen van berichten in ´e´en SCTP associatie. Daardoor moet enkel de volgorde van berichten per stroom gewaarborgd worden, zodat onnodige HOL-blocking tussen onafhankelijke stromen kan worden vermeden. Meer zelfs, SCTP voorziet order-of-arrival delivery, een mechanisme om de berichten aan de bovenliggende laag door te geven vanaf ze ontvangen zijn. Figuur 2.2 toont een voorbeeld waar Host A via 2 streams data zal versturen, en via 3 streams data zal ontvangen. Als er een transmissiefout optreedt in ´e´en van de stromen, zullen de pakketten in andere stromen daar niks van merken. Het aantal stromen wordt ingesteld bij het aanmaken van de verbinding, bij de INIT en INIT ACK chunks. De verzender geeft aan hoeveel uitwaartse stromen hij wenst te hebben in de associatie, en het maximaal aantal inkomende stromen.
2.3.3
Multihoming
Een volgende eigenschap van SCTP is multihoming: de mogelijkheid om meerdere IP-adressen toe te kennen aan ´e´en associatie. Dit biedt de mogelijkheid om een zekere redundantie in te bouwen die in het geval van faling van ´e´en van de (sub)netwerken nog steeds de associatie levend houdt en het mogelijk maakt de communicatie voort te zetten. Figuur 2.3 illustreert het geval waarbij een associatie bestaat uit twee paden, elk met hun eigen IP adres. Net zoals bij
2.3. KORTE INLEIDING TOT SCTP
6
Figuur 2.2: SCTP Multistreaming. Bron: [11]
multistreaming worden ook hier door middel van het INIT en INIT ACK chunk de IP-adressen duidelijk gemaakt: in de chunks kan een lijst van IP-adressen worden meegegeven (zowel IPv4 als IPv6 worden ondersteund) of zelfs hostnames die dan door DNS zullen worden opgezocht.
Figuur 2.3: SCTP MultiHoming.
2.3.4
State Cookie mechanisme
Het State Cookie mechanisme zorgt ervoor dat de ontvangende zijde de eerste aanvraag tot een verbinding kan beantwoorden en weer vergeten, zodat er geen bronnen worden gebruikt, hetgeen onder meer de kwetsbaarheid van TCP met betrekking tot SYN-floods vermijdt. Hiervoor wordt een vierwegshandruk gebruikt zoals getoond in Figuur 2.4. De ontvanger krijgt een INIT packet toegestuurd, en zal antwoorden met een INIT-ACK, waarbij hij een Cookie meestuurt. Hij
2.3. KORTE INLEIDING TOT SCTP
7
vergeet dan alle informatie van de zender zodat geen bronnen worden toegekend. Als de verzender de derde stap (Cookie Echo) niet uitvoert, ondervindt de server daar verder geen last van, in tegenstelling tot bij TCP. Wanneer de verzender de Cookie Echo uitvoert, zal de ontvanger antwoorden met een Cookie-Ack, waarna de associatie tot stand gebracht is. Een vierwegshandruk kan misschien kostelijker lijken dan een driewegshandruk, maar dit wordt gecompenseerd door het feit dat tijdens de laatste twee stappen ook al data kan worden meeverzonden.
2.3.5
Chunks
Om dit alles te bewerkstelligen werkt SCTP met chunks: in ´e´en pakket kunnen meerdere chunks gebundeld zitten, die SCTP controle-informatie of data bevatten (zie Figuur 2.5). Er werden een tiental verschillende soorten chunks gedefinie¨erd in [3], en vele uitbreidingen brengen nieuwe chunk types aan. Een aantal voorbeelden uit [3]: Payload Data (DATA), Initiation (INIT), Initiation Acknowledgement (INIT ACK), Selective Acknowledgement (SACK), Heartbeat Request (HEARTBEAT), Heartbeat Acknowledgement (HEARTBEAT ACK), Abort (ABORT), Shutdown (SHUTDOWN), Shutdown Acknowledgement (SHUTDOWN ACK), Operation Error (ERROR), State Cookie (COOKIE ECHO), Cookie Acknowledgement (COOKIE ACK), Shutdown Complete (SHUTDOWN COMPLETE). Deze thesis zal later het Fragmented Payload Data (FRAGMENTED DATA) chunk introduceren.
Figuur 2.4: SCTP
Four
handshake.
way
2.4. SAMENVATTING VAN DIT HOOFDSTUK
2.3.6
8
En nog veel meer. . .
SCTP werd ook ontwikkeld om TCP-vriendelijk te zijn: wanneer beide protocollen door elkaar gebruikt worden, zullen maatregelen zoals congestion control vanuit TCP ook invloed hebben op SCTP zodat beide protocollen niet met elkaar moeten concurreren, zoals UDP dat wel zal doen met TCP. SCTP ondersteunt ook een waaier van andere eigenschappen[12] zoals het bundelen van meerdere berichten in ´e´en pakket, de ondersteuning van
Figuur 2.5: SCTP
Packet
containing
chunks.
zowel geordende als ongeordende levering van data, een hartslag die controleert of elk pad nog actief is. . .
2.4
Samenvatting van dit hoofdstuk
In dit hoofdstuk werd eerst TCP beschreven: het ontstaan van TCP, huidige eigenschappen van TCP en de TCP/IP suite, en de tekortkomingen van beiden. Uit de tekortkomingen werd de zoektocht naar alternatieven aangebracht, waarna SCTP in het bijzonder nader werd toegelicht. Onder andere drie belangrijke eigenschappen van SCTP werden toegelicht: multistreaming, multihoming en het State Cookie.
9
Hoofdstuk 3
Uitbreidingen van SCTP 3.1
PR-SCTP
Gedeeltelijke betrouwbaarheid (Partial Reliability) is een uitbreiding op SCTP die 1 eindpunt toelaat om aan te geven aan het andere dat hij het cumulatieve ack punt vooruit moet bewegen, zodat er mogelijk enkele DATA chunks (die nog niet werden ontvangen of bevestigd) worden overgeslagen. Hiervoor werd een nieuw chunk type, FORWARD TSN, gedefini¨eerd, en werd een nieuwe parameter aan INIT en INIT ACK toegevoegd. Deze uitbreiding laat om met behulp van ´e´en enkele SCTP associatie het verzenden toe van zowel betrouwbare inhoud als inhoud die niet betrouwbaar hoeft te zijn. Onder betrouwbare inhoud verstaat men websites, bestanden, email. . . , onbetrouwbare inhoud is data zoals informatie die in dergelijke mate tijdsgebonden is dat het beter is een nieuw pakket te genereren met recentere informatie dan te blijven proberen de oude informatie door te sturen.
3.2
Auth
Door het gebruik van verificatie kan een ontvanger weten of de verzender van het verstuurde bericht werkelijk de persoon is die hij beweert te zijn, en wordt het voor aanvallers moeilijker om een zogenaamde man-in-the-middle aanval uit te voeren: vervalste berichten injecteren in een legitieme stroom zodat de ontvanger alle berichten voor echt houdt. Hiervoor wordt een sleutelpaar gebruikt waarmee boodschappen volgens een veilige hashing-methode (SHA-1 wordt voorgesteld als de standaardoptie) getekend worden. Er wordt gekozen welke soorten chunks
3.3. ADDIP
10
worden beveiligd, en die worden steeds gebundeld met een nieuw soort chunk, het AUTH chunk, doorgestuurd.
3.3
ADDIP
Deze extensie laat toe om dynamisch IP-adressen te beheren tijdens het bestaan van de associatie. Door middel van een nieuwe ASCONF-chunk worden IP-adressen tijdens het bestaan van de connectie toegevoegd en verwijderd, en kan een primary IP address worden aangegeven, een voorkeurs-IP-adres waar pakketjes heen gestuurd zullen worden, hetgeen in de standaard SCTP enkel mogelijk was tijdens het opzetten van de verbinding.
3.4
mSCTP
SCTP blijkt zich uitstekend te lenen voor de implementatie van Transport layer mobility, waarbij een bepaalde host bereikbaar blijft zonder zich daarvoor tot de netwerklaag te wenden, zoals bijvoorbeeld Mobile IP. De multihoming-eigenschap van SCTP zorgt ervoor dat een host onder verschillende adressen kan bekend zijn, en maakt zachte overdracht mogelijk: een mobiele host beweegt zich naar een nieuwe locatie en maakt verbinding met een nieuw netwerk, dat hem een IP-adres toekent. Hij is nu multihomed en bereikbaar onder twee IP-adressen. Dankzij de reeds eerder aangehaalde ADDIP-uitbreiding kan de mobiele host het nieuwe adres meedelen aan de server waarmee hij verbonden is, en misschien zelfs dit adres als primair adres instellen. Daarna kan hij zijn oorspronkelijke adres verwijderen: de migratie is nu geschied. Hij kan dit blijven herhalen zolang hij minstens ´e´en netwerk tot zijn beschikking heeft. Natuurlijk is het erg belangrijk dat er geen vijandige aanvallen kunnen plaatsvinden: een aanvaller zou zijn eigen IP-adres aan de verbinding kunnen toevoegen, en dan andere adressen verwijderen, om zo de verbinding te kapen. Daarvoor is het gebruik van een verificatiesysteem noodzakelijk.
3.5
Samenvatting van dit hoofdstuk
In dit hoofdstuk werden drie belangrijke voorgestelde uitbreidingen van SCTP besproken: PRSCTP dat gedeeltelijke betrouwbaarheid aanbiedt, Auth waardoor beide eindpunten zichzelf
3.5. SAMENVATTING VAN DIT HOOFDSTUK
11
kunnen authenticeren en AddIP waardoor tijdens de levensduur van een associatie op een dynamische manier IP-adressen kunnen worden toegevoegd en verwijderd, en het primaire pad kan worden aangepast. Deze laatste twee extensies geven aanleiding tot het mSCTP, een compleet en volwaardig protocol dat transportlaagmobiliteit ondersteunt.
12
Hoofdstuk 4
Fragmentatie 4.1
Inleiding
Communicatieprotocollen werken steeds met segmenten van informatie, pakketten of datagrammen genaamd. Vaak is data te groot om in ´e´en segment door te sturen, waardoor de data over verschillende segmenten zal worden verdeeld. Dit proces heet fragmentatie.
4.2
Fragmentatie bij IP
Als de IP laag data ontvangt zodat na toevoeging van de IP header het pakket groter is dan de onderliggende MTU, zal het deze data verdelen over meerdere IP datagrammen, en voor elk datagram dezelfde header met een aantal subtiele verschillen zetten, zodat de ontvanger weet hoe de data weer te reconstrueren. Figuur 4.1 toont de IP header zoals beschreven in [13]. Figuur 4.2 toont het geval waar een TCP pakket te groot is om in de IP laag te worden verzonden, en daarom in twee IP-pakketten gesplitst wordt. De twee pakketten worden dan afzonderlijk verzonden en de ontvanger zal na ontvangst van beide pakketten het originele pakket herstellen en doorgeven naar de TCP laag. De IP laag houdt dus rekening houden met de MTU van de onderliggende laag: wanneer het pakket te groot is, zal het gesplitst worden. De TCP laag moet hier geen rekening houden met de IP laag en kan deze gewoon als black box beschouwen omdat IP de fragmentatie voor zijn rekening zal nemen.
4.2. FRAGMENTATIE BIJ IP
13
Figuur 4.1: De IP header.
Het identification veld, het bronadres en doeladres, vormen samen met het protocol een unieke sleutel waarop fragmenten mogen geclassificeerd worden. Alle pakketten die dezelfde waarden voor deze velden hebben, bevatten dus gefragmenteerde data van eenzelfde origineel. Wanneer een dergelijk pakket ofwel een aangevinkte MF-bit ofwel een Fragment offset groter dan nul bevat, zal de ontvanger
Figuur 4.2: Fragmentatie in de IP laag.
deze behandelen als een fragment, en deze bijvoorbeeld in een tijdelijke buffer opslaan. Als een pakket niet het laatste pakket vormt, zal de MF-bit aangezet worden. Slechts wanneer de ontvanger een pakket zonder MF-bit ontvangt, kan hij controleren of hij alle pakketten ontvangen heeft, en ze aan de hand van de fragment offset op de juiste positie in het gereconstrueerde origineel plaatsen. Wanneer het pakket volledig is, kan het doorgegeven worden aan de bovenliggende laag. Een belangrijke opmerking hierbij is dat bij het fragmenteren van een pakket alleen de data wordt opgesplitst, en telkens een header voor de data wordt gezet, in tegenstelling tot bijvoorbeeld
4.3. FRAGMENTATIE BIJ TCP
14
bij IP in IP encapsulation[14] waar het originele datagram, zowel header als data, in een nieuw datagram gestopt wordt.
4.3
Fragmentatie bij TCP
De TCP-laag zal zelf geen fragmentatie aanbieden aan de applicaties: ofwel moet de applicatie zelf zijn data fragmenteren, ofwel zal de onderliggende IP-laag voor de fragmentatie zorgen.
4.4
Fragmentatie bij UDP
Omdat UDP een onbetrouwbaar protocol is om data te verzenden, werd geen ondersteuning voor fragmentatie ingebouwd[15]. Het verliezen van ´e´en enkel fragment zou immers tot gevolg hebben dat het hele pakket verloren is. Het protocol werd ook ontwerpen opdat gebruikers data konden verzenden zonder veel protocol-mechaniek. Er werd dan ook gekozen om ook hier fragmentatie door de IP-laag te laten verzorgen.
4.5 4.5.1
Fragmentatie bij SCTP Theorie
SCTP voorziet in transportlaagfragmentatie: wanneer een SCTP-pakket groter is dan de MTU van de onderliggende laag, zal het pakket worden gefragmenteerd in de transportlaag zelf, hetgeen als voordeel heeft dat de IP-pakketten niet meer gefragmenteerd moeten worden waardoor de werkdruk niet bij routers, firewalls en NAT’s terechtkomt. Omdat SCTP gebruik kan maken van MTU-discovery, zal een SCTP-pakket meteen gefragmenteerd worden naar de meest optimale grootte, en zal herfragmentatie binnen dezelfde route niet nodig zijn, hetgeen bij IP wel vaak het geval is. Een SCTP verzender mag fragmentatie gebruiken bij het verzenden van berichten, maar een SCTP ontvanger moet fragmentatie ondersteunen bij het ontvangen van berichten. Zoals getoond in Figuur 4.3 bevat de algemene header van SCTP geen ondersteuning tot fragmentatie: SCTP kan dus geen hele pakketten fragmenteren. Figuur 4.4 maakt duidelijk dat de SCTP datachunk header wel ondersteuning biedt voor fragmentatie. De SCTP specificatie gebruikt 2 bits om fragmentatie aan te geven, zoals te zien is in figuur 2: de B-bit (beginning fragment) geeft aan of een fragment het eerste fragment is van een bericht,
4.5. FRAGMENTATIE BIJ SCTP
15
Figuur 4.3: De SCTP Common Header. Bron: [3]
Figuur 4.4: De SCTP datachunk header. Bron: [3]
de E-bit (ending fragment) geeft aan of een fragment het laatste fragment is van een bericht. Als een fragment het enige fragment is van een bericht, bevat het fragment natuurlijk zowel begin als einde, en zijn beide bits aangevinkt. Wanneer beide bits op 0 staan, is het fragment gewoon een onderdeel van een bericht dat uit meer dan 2 fragmenten bestaat. De ordening van de fragmenten wordt eenvoudig afgelezen uit de TSN’s, die strikt opeenvolgend zijn. Wanneer de andere partij multihomed (meerdere interfaces bevat waarop ontvangen kan worden) is, mag de ene een maximale grootte kiezen niet groter dan de MTU van het Associatiepad, die gedefinieerd wordt als de kleinste MTU van alle afzonderlijke paden. Dit om bij faling van de verzending van een gefragmenteerd bericht een herfragmentatie te vermijden, omdat de header daar niet op voorzien is: de besparing op de reconstructie-informatie (B/E bit + TSN, vergelijk met IP : MF, Total length, fragment offset) maakt een herfragmentatie niet mogelijk. Verder in dit document wordt een implementatie voorgesteld die een uitbreiding aanbiedt om zo herfragmentatie mogelijk te maken en een link optimaal te gebruiken.
4.6. SAMENVATTING VAN DIT HOOFDSTUK
4.6
16
Samenvatting van dit hoofdstuk
In dit hoofdstuk werd fragmentatie bij verschillende protocollen in detail besproken: het enige vermelde transportlaagprotocol dat geen beroep op de IP-laag voor zijn fragmentatie is SCTP, dat zelf heel eenvoudig datachunks kan fragmenteren. Deze eenvoud brengt wel beperkingen met zich mee: zo is het onmogelijk om een eenmaal gefragmenteerd datachunk te herfragmenteren.
17
Hoofdstuk 5
Herfragmentatie in SCTP 5.1
Inleiding
De standaard SCTP fragmentatie zoals beschreven in [3] laat geen herfragmentatie toe. Het lijkt alsof hier met opzet voor gekozen is, omdat uit deze beslissing ook enkele voordelen komen: • De ondersteuning in de headerstructuur is minimalistisch: er worden slechts 2 bits gebruikt. De B-bit en de E-bit kunnen samen de vier noodzakelijke staten onderscheiden: het datachunk is het eerste fragment, het laatste pakket, het enigste fragment, of in fragment dat volgt op een ander fragment en nog gevolgd wordt door een volgende fragment. • Belangrijker is echter de keuze om opeenvolgende TSNs te kiezen om de ordening van fragmenten aan te duiden: de ontvanger hoeft slechts vanaf het pakket met de B-bit actief, alle volgende pakketten, tot het pakket met de E-bit actief te verzamelen en daaruit het originele bericht terug samen te stellen. Dit elimineert de nood aan een fragment offset of soortgelijk veld, dat meer plaats in de header inneemt.
Aangezien herfragmentatie niet ondersteund wordt, moet worden vermeden dat er zich ooit de noodzaak toe voordoet. Daarom wordt meteen gefragmenteerd aan de kleinst mogelijke MTU, namelijk de kleinste MTU van alle paden uit de associatie. Dit is duidelijk geen optimaal gebruik van netwerkbronnen, zeker als de MTU’s van de verscheidene paden veel van elkaar verschillen. De aanwezigheid van ´e´en pad met een kleine MTU kan zo de performantie van de hele associatie enorm negatief be¨ınvloeden.
5.2. HERFRAGMENTATIE
18
Daarbij komt nog dat door de ADDIP uitbreiding (en dus bij mSCTP) dynamisch paden aan een associatie kunnen worden toegevoegd. Wanneer dergelijk pad gekozen wordt om een reeds gefragmenteerd bericht dat verloren gegaan is te herverzenden, en dit pad heeft een kleinere MTU dan het pad waar het fragment oorspronkelijk op verzonden werd, is het pakket voorgoed verloren en zal dit aan de bovenliggende laag moeten gemeld worden, tenzij men terugvalt op de ondersteuning geboden door de IP-laag, hetgeen men net wou vermijden.
5.2 5.2.1
Herfragmentatie Algemene idee
Om toch te kunnen herfragmenteren, stellen we een gelijkaardige werkwijze voor als die van IP: er wordt een fragment offset gebruikt om aan te geven welke bytes een pakket bevat, bij herfragmentatie van dat pakket worden eenvoudigweg de offsets aangepast naar de nieuwe inhoud van het fragment. Aangezien de bestaande SCTP Common Header al gedefinieerd is, is het niet preferabel deze aan te passen of aan te vullen. Hetzelfde geldt voor de Data chunk header. Een offici¨ele oplossing zou bijvoorbeeld de invoering van een extra chunktype (zoals ASCONF werd gebruikt bij mSCTP) zijn, waarin fragment offset kan worden gebruikt.
5.2.2
Nieuw Chunk Type: het Fragmented Data Chunk
Figuur 5.1: De SCTP Fragmented Data Chunk Header.
5.2. HERFRAGMENTATIE
19
Figuur 5.1 toont de structuur van het voorgestelde Fragmented Data Chunk, die vrij gelijkaardig is aan die van het gewone Data Chunk. We zullen de verschillen hieronder bespreken. Zoals we in [3] lezen, moet een chunktype gekozen worden, net zoals ADDIP 0xC1 (decimaal 193) gebruikt voor zijn ASCONF Chunk en 0x80 (decimaal 128) voor de ASCONF-ACK[4]. We mogen een waarde kiezen zoals beschreven in de RFC. Belangrijk bij de keuze zijn de eerste twee bits van het type: zij bepalen wat de ontvanger moet doen wanneer hij het chunktype niet herkent (het hele pakket negeren, het hele pakket negeren en een foutboodschap terugsturen, enkel dat chunk negeren, enkel dat chunk negeren en een foutboodschap terugsturen). Aangezien het niet nodig is het hele pakket te negeren maar we wel verkiezen dat de verzender weet dat de ontvanger de fragmentatie-uitbreiding niet ondersteunt, verkiezen we de vierde mogelijkheid. Daarom werd 0xC8 (200)10 als type gekozen. Wanneer zou blijken dat een andere uitbreiding deze waarde aanneemt, kan dit desnoods nog gewijzigd worden. De rest van de chunkheader kiezen we dezelfde als die van een normale DATA chunk, met een extra 32 bit waarde fragment offset. De chunkflags bevatten een MF-vlag, die net als bij IP aangeeft of er nog fragmenten komen (MF op 1) of dit het laatste fragment was (MF op 0). Om een te groot bericht nu te verzenden, zal de verzender het bericht opsplitsen in fragmenten van de huidige MTU van dat pad (in tegenstelling tot de standaard werkwijze uit de RFC, waar een bericht wordt opgesplitst naar de MTU van de gehele associatie, die het minimum is van alle MTU’s). Elk afzonderlijk onderdeel vormt dan een chunk dat doorgestuurd wordt. Wanneer een chunk niet meer in een pakket past, kan de chunk worden geherfragmenteerd. Voor elke chunk zal de MF-vlag op 1 staan, enkel bij de laatste chunk wordt deze op 0 gezet. Wanneer deze laatste chunk nog geherfragmenteerd wordt, volgt men dezelfde werkwijze. De ontvanger bewaart de chunks in een aparte buffer, tot hij een chunk met MF = 0 krijgt. Hij zal dan proberen om het bericht te reconstrueren. Als alle fragmenten ontvangen zijn, geeft hij het bericht door.
5.2.3
Problemen bij dit voorstel
Volgorde De fragmenten worden in juiste volgorde verstuurd, maar komen niet noodzakelijk in de juiste volgorde aan. De ontvanger moet de juiste volgorde van de fragmenten kunnen bepalen. Een mogelijke oplossing bestaat eruit dat de ontvanger eenvoudig de fragmenten kan sorteren op
5.2. HERFRAGMENTATIE
20
fragment offset. Wanneer dubbels voorkomen in fragment offset, kan ofwel het grootste pakket behouden worden, ofwel het laatst aangekomen pakket genegeerd worden, ofwel alle pakketten genegeerd worden. Onze implementatie sorteert de pakketten niet: hun data wordt eenvoudigweg meteen op de juiste plaats in het originele pakket gekopieerd.
Onderscheid De verzender kan meerdere berichten tegelijk fragmenteren en sturen, de ontvanger moet weten welke fragmenten bij welk bericht horen. Om dit te bewerkstelligen bevindt zich in de gefragmenteerdedatachunk header een veld belong TSN. Dit zal worden ingevuld met de TSN van het originele te fragmenteren datachunk. Elk fragment van het bericht heeft dus deze belong TSN gemeenschappelijk, zodat de ontvanger eenvoudig weet welke fragmenten bij hetzelfde origineel horen. Onze implementatie in click zou kunnen gebruikmaken van ongebruikte velden in de standaardheaders, zoals de stream identifier, de stream sequence number of de payload protocol identifier. Omwille van de genericiteit werd hiervoor niet geopteerd, wanneer men de nadruk sterker naar performantie wil richten kan men hier nog steeds voor opteren: men spaart dan vier bytes uit in elke fragmented-dataheader.
Volledigheid Het moment waarop de ontvanger gaat samenvoegen, is afhankelijk van de implementatie: • Er kan gekozen worden om de lijst van fragmenten gesorteerd te houden en meteen na ontvangst van een fragment B te kijken of het fragment A ervoor strikt aansluit (A.offset = B.offset - A.length) of het fragment C erna strikt aansluit (C.offset = B.offset + B.length) en meteen te mergen. • Er kan gekozen worden om het samenvoegen pas te doen na ontvangst van een fragment met de MF-vlag op 0. Aangezien chunks in een andere volgorde kunnen aankomen dan ze verstuurd werden, zou het kunnen dat zelfs na ontvangst van een fragment met MF-vlag op 0 er nog steeds geen volledig chunk ontvangen is. Men zal dus ook bij elk volgend fragment deze controle moeten uitvoeren. • Er kan gekozen worden om op het moment dat de ontvanger inactief is, de lijst te sorteren en samen te voegen, of dit kan in een aparte thread gebeuren.
5.3. SAMENVATTING VAN DIT HOOFDSTUK
21
• Andere implementaties of combinaties blijven ook mogelijk. Onze implementatie gebruikt de tweede mogelijkheid: pas als een chunk ontvangen werd met de MF-vlag op 0 zal het oorspronkelijke pakket kunnen worden doorgestuurd. Aangezien echter na ontvangst van het eerste fragment reeds een pakket werd aangemaakt, moet steeds worden gecontroleerd of alle tussenliggende pakketten effectief werden ontvangen: hiervoor werd een variabele filled aangemaakt, die het aantal gevulde bytes bijhoudt. Telkens een fragment aankomt en in het pakket wordt gekopieerd, wordt filled verhoogt met de lengte van dat pakket. Wanneer filled gelijk is aan de lengte van het pakket en het fragment met de MF-vlag op 0 werd ontvangen (zodat zeker is dat de totale lengte van het oorspronkelijke pakket gekend is) wordt het gereconstrueerde pakket doorgegeven.
Time-out De ontvanger mag niet eeuwig blijven wachten op fragmenten, omdat hij bij het wachten bronnen toekent die anders eeuwig toegekend zouden blijven. Om dit te verhelpen wordt een timer gebruikt, en bij elke ontvangst van een fragment wordt de timer voor die belong TSN gereset. Wanneer lange tijd geen fragment van een bepaalde belong TSN ontvangen wordt, zal de timer aflopen. De timer zal vernietigd worden na reconstructie van het pakket. Deze functie wordt momenteel nog niet door onze implementatie ondersteund.
5.3
Samenvatting van dit hoofdstuk
In dit hoofdstuk werd beschreven hoe herfragmentatie met SCTP mogelijk gemaakt kan worden. Hiervoor werd een nieuw Chunk type ingevoerd, het Fragmented Data Chunk Type, dat de herfragmenteerbare data zal dragen. Er werd uitgelegd hoe daardoor herfragmentatie mogelijk wordt, en hoe uit de fragmenten terug volledige pakketten worden samengesteld.
22
Hoofdstuk 6
Implementatie in Click 6.1
Inleiding
De beschreven algoritmes werden ge¨ımplemteerd in Click[16], specifiek gericht op het encapsuleren van pakketten in SCTP pakketten, deze dan te versturen over een SCTP link en dan weer te decapsuleren naar originele vorm. In de komende secties worden enkele fragmenten uit de code getoond en besproken.
6.2
Fragmentatie aan zenderzijde
6.2.1
Datastructuren Listing 6.1: Een datachunk fragmenteren in twee fragmented-datachunks.
void Trains CDM : : s c t p f r a g m e n t p a c k e t ( Packet ∗ p t e s t , Packet ∗∗ chunk1 , Packet ∗∗ chunk2 , u i n t 3 2 t r e s t h e a d e r , Trains TCB ∗ t c b ) { u i n t 8 t ∗ pinp ; u i n t 3 2 t TSN = n t o h l ( tcb−>n e x t t s n ( ) ) ; // c r e a t e fchunk1 , a w r i t e a b l e p a c k e t . // W r i t a b l e P a c k e t ∗ fchunk1 = Packet : : make ( ( r e s t h e a d e r + s i z e o f ( struct t r a i n s c h u n k h e a d e r ) + s i z e o f ( struct t r a i n s f r a g m e n t e d d a t a h e a d e r ) ) ) ; memset ( fchunk1−>data ( ) , ’ \0 ’ , fchunk1−>l e n g t h ( ) ) ; // s e t a t r a i n s chunk h e a d e r f o r fchunk1 , t y p e i s f r a g m e n t e d d a t a p a c k e t , f l a g s are 0 for the f i r s t , 1 for the l a s t , length i s r e s t h e a d e r struct t r a i n s c h u n k h e a d e r ∗ tckh = ( struct t r a i n s c h u n k h e a d e r ∗ ) ( fchunk1−>data ( ) ) ; tckh−>type = FRAGMENTED DATA TYPE; // Fragmented Data Type .
6.2. FRAGMENTATIE AAN ZENDERZIJDE
23
tckh−>f l a g s = 0 ; // E e r s t e fragment , morefragments op 0 tckh−>l e n g t h = n t o h s ( fchunk1−>l e n g t h ( ) ) ; // s e t a f r a g m e n t e d d a t a chunk h e a d e r f o r f c h u n k 1 pinp = ( u i n t 8 t ∗ ) ( tckh +1); struct t r a i n s f r a g m e n t e d d a t a h e a d e r ∗ t f d h = ( struct t r a i n s f r a g m e n t e d d a t a h e a d e r ∗ ) ( pinp ) ; // s e t g e n e r a t e d TSN. tfdh −>TSN = TSN ; // S e t t h e t h e s i d s s e q p a y l o a d . tfdh −>stream ID=p t e s t −>stream ID ; tfdh −>s t r e a m s e q=p t e s t −>s t r e a m s e q ; tfdh −>p a y l o a d p r I D=p t e s t −>p a y l o a d p r I D ; // s e t t h e f r a g m e n t o f f s e t t o 0 . tfdh −>f r a g m e n t o f f s e t = 0 ; // s e t t h e orig TSN t o t h e TSN from p t e s t ( or p t e s t o r i g T S N i f f r a g m e n t e d ) tfdh −>belong TSN = TSN ; // copy t h e f i r s t r e s t h e a d e r b y t e s from p t e s t i n t o f c h u n k 1 pinp = ( u i n t 8 t ∗ ) ( t f d h +1); memcpy ( pinp , p t e s t −>data ( ) , r e s t h e a d e r ) ; ∗ chunk1 = ( Packet ∗ ) fchunk1 ; // . . . chunk2 i s an alogu e , w i t h t h e s e i m p o r t a n t d i f f e r e n c e s : u i n t 3 2 t f c h u n k 2 l e n g t h = p t e s t −>l e n g t h ( ) − r e s t h e a d e r ; W r i t a b l e P a c k e t ∗ fchunk2 = Packet : : make ( f c h u n k 2 l e n g t h + s i z e o f ( struct t r a i n s c h u n k h e a d e r ) + s i z e o f ( struct t r a i n s f r a g m e n t e d d a t a h e a d e r ) ) ; // s e t newly g e n e r a t e d TSN. tfdh −>TSN = n t o h l ( tcb−>n e x t t s n ( ) ) ; // s e t f r a g m e n t o f f s e t t o r e s t h e a d e r tfdh −>f r a g m e n t o f f s e t = n t o h l ( r e s t h e a d e r ) ; tfdh −>belong TSN = TSN ; Listing 6.2: Elke TCBbuffer bevat een fragmented chunk, met getters en setters.
Packet ∗ f r a g m e n t e d p a c k e t ; Packet ∗ g e t f r a g m e n t e d p a c k e t ( ) { return f r a g m e n t e d p a c k e t ; } void s e t f r a g m e n t e d p a c k e t ( Packet ∗ p ) { fragmented packet = p ; }
6.2. FRAGMENTATIE AAN ZENDERZIJDE
24
Bij het versturen van een datachunk dat te groot is om nog gebundeld te worden bij het huidige pakket, wordt het datachunk gesplist in 2 fragmented data chunks, zoals getoond in Listing 6.1. Het eerste chunk wordt dan in het pakket gebundeld, waarna het pakket verstuurd wordt. Het tweede chunk wordt opgeslagen in de TCB Buffer (zie Listing 6.2) en zal bij het vullen van het volgende pakket als eerste worden ingevoegd, waar de methode recursief gebruikt wordt: als het voormalige tweede chunk niet geheel in dat pakket past, wordt het nogmaals gefragmenteerd, het nieuwe eerste chunk wordt verzonden en het tweede chunk wordt weer aangeboden bij het vullen van het volgende pakket. De make packet methode is onderverdeeld in twee delen: het eerste deel bekijkt de sackbuffer, de resendbuffer, het fragmentatiechunk en de databuffer, en berekent de grootte van het volgende pakket. Vervolgens wordt het pakket aangemaakt, waar ook de IP-header en algemene SCTPheader worden ingesteld, en in het tweede deel van de methode wordt het pakket gevuld met chunks. In Listing 6.3 wordt getoond hoe gecontroleerd wordt of het gefragmenteerde chunk in zijn geheel in het pakket past, indien dit niet zo is wordt de pakketgrootte gewoon maximaal gekozen: het fragment zal geherfragmenteerd worden. Listing 6.3: Deel 1 van de methode controleert of het gefragmenteerde chunk in het pakket past.
Packet ∗ f r a g m e n t e d p a c k e t = tcb−>b u f f e r −>g e t f r a g m e n t e d p a c k e t ( ) ; i f ( f r a g m e n t e d p a c k e t != 0 ) { i f ( t h i s p a c k e t l e n g t h + f r a g m e n t e d p a c k e t −>l e n g t h ( ) < p r i m l i n k −>get pmtu ( ) ) { thispacketlength = thispacketlength + f r a g m e n t e d p a c k e t −>l e n g t h ( ) ; } else { t h i s p a c k e t l e n g t h = p r i m l i n k −>get pmtu ( ) ; } } Listing 6.4: Het toevoegen van een datachunk in zijn geheel is onmogelijk, dus wordt het gefragmenteerd.
i f ( s e n d l e n g t h > p r i m l i n k −>get pmtu ( ) ) { u i n t 3 2 t d i f f = s e n d l e n g t h − p r i m l i n k −>get pmtu ( ) ; Packet ∗ chunk2 ; // z e e r t i j d e l i j k c h u n k j e d a t d i r e c t de r e t r a n s wordt . s c t p f r a g m e n t p a c k e t ( p t e s t , &chunk1 , &chunk2 , r e s t h e a d e r , t c b ) ; tcb−>b u f f e r −>s e t f r a g m e n t e d p a c k e t ( chunk2 ) ; W r i t a b l e P a c k e t ∗ o u t g o i n g p a c k e t 2 = Packet : : make ( p r i m l i n k −>get pmtu ( ) ) ; memset ( o u t g o i n g p a c k e t −>data ( ) , ’ \0 ’ , o u t g o i n g p a c k e t 2 −>l e n g t h ( ) ) ; memcpy ( o u t g o i n g p a c k e t −>data ( ) , o u t g o i n g p a c k e t −>data ( ) , o u t g o i n g p a c k e t −>l e n g t h ( ) ) ; pinp = ( u i n t 8 t ∗ ) ( o u t g o i n g p a c k e t 2 −>data ( ) + o u t g o i n g p a c k e t −>l e n g t h ( ) ) ;
6.2. FRAGMENTATIE AAN ZENDERZIJDE
25
memcpy ( pinp , chunk1−>data ( ) , chunk1−>l e n g t h ( ) ) ; struct c l i c k i p ∗ i p h 2 = ( c l i c k i p ∗ ) o u t g o i n g p a c k e t 2 −>data ( ) ; o u t g o i n g p a c k e t 2 −>s e t i p h e a d e r ( iph2 , s i z e o f ( c l i c k i p ) ) ; // de nieuwe l e n g t e moet worden a a n g e p a s t , andere v e l d e n g o e d g e z e t . iph2−>i p l e n = h t o n s ( o u t g o i n g p a c k e t 2 −>l e n g t h ( ) ) ; iph2−>ip sum = 0 ; iph2−>ip sum = c l i c k i n c k s u m ( ( unsigned char ∗ ) iph2 , s i z e o f ( c l i c k i p ) ) ; o u t g o i n g p a c k e t 2 −>s e t d s t i p a n n o ( d s t I P ) ; return o u t g o i n g p a c k e t 2 ;
Wanneer het toevoegen van een datachunk in zijn geheel het te verzenden pakket groter zou maken dan toegestaan is, zal dit datachunk gefragmenteerd worden. Listing 6.4 illustreert het aanroepen van sctp fragment packet. Deze versie van de implementatie gebruikt een klein truukje: omdat de grootte van het pakket niet perfect op voorhand berekend werd, wordt hier gewoon een tweede packet aangemaakt en de data van het eerste gekopieerd. Niet vergeten alle annotaties goed te zetten. Met behulp van een netwerkdiagnosetool zoals tcpdump of wireshark kunnen verzonden pakketjes bekeken en geanalyseerd worden. Het gefragmenteerde-datachunk zal daar getoond worden als RESERVED. Dit chunk kan byte-per-byte worden bekeken om de correctheid van de implementatie aan de zijde van de verzender na te gaan. Helaas bevat de implementatie van het ontvangende algoritme ergens nog een fout, waardoor het programma instabiel kan worden. In Listing 6.5, 6.6 en 6.7 worden nog enkele fragmentjes code getoond. Listing 6.5: Het selecteren van de gefragmenteerde datachunks op basis van de typeflag in de chunkheader.
W r i t a b l e P a c k e t ∗ chunk ; struct t r a i n s c h u n k h e a d e r ∗ tckh = ( struct t r a i n s c h u n k h e a d e r ∗ ) ( p−>data ( ) ) ; L = n t o h s ( tckh−>l e n g t h ) ; switch ( tckh−>type ) { // c a s e data , c a s e s a c k . . . case FRAGMENTED DATA TYPE: { f r a g m e n t e d d a t a r c v d = true ; chunk = Packet : : make (L ) ; memcpy ( chunk−>data ( ) , p−>data ( ) , L ) ; bool b = r c v f r a g m e n t e d d a t a ( chunk , t c b ) ; newtsn = newtsn | | b ; } break ; Listing 6.6: Het toevoegen van een datachunk in zijn geheel is onmogelijk, dus wordt het gefragmenteerd.
i f ( tckh−>type == 2 0 0 ) { Packet ∗ temp = a d d f r a g m e n t ( t e s t p a c k e t , t c b ) ;
6.2. FRAGMENTATIE AAN ZENDERZIJDE
26
i f ( temp != 0 ) { output ( 0 ) . push ( temp ) ; tcb−> t s n s t r . chunkmap . remove ( ∗ i t ) ; } }
Listing 6.7: Het samenvoegen fragmenten tot ´e´en pakket.
Packet ∗
Trains CRM : : a d d f r a g m e n t ( Packet ∗ fragm , Trains TCB ∗ t c b )
{ struct t r a i n s c h u n k h e a d e r ∗ tckh = ( struct t r a i n s c h u n k h e a d e r ∗ ) ( fragm−>data ( ) ) ;
i f ( tckh−>type != 2 0 0 ) { // s a n i t y c h e c k : o n l y a c c e p t f r a g m e n t e d d a t a chunks . return 0 ; } u i n t 3 2 t l e n g t h = h t o n s ( tckh−>l e n g t h ) ; length = length − s i z e o f ( struct t r a i n s c h u n k h e a d e r ) − s i z e o f ( struct t r a i n s f r a g m e n t e d d a t a h e a d e r ) ; u i n t 8 t f l a g s = tckh−>f l a g s ;
struct t r a i n s f r a g m e n t e d d a t a h e a d e r ∗ t f d h = ( struct t r a i n s f r a g m e n t e d d a t a h e a d e r ∗ ) ( tckh +1); u i n t 3 2 t t h i s b e l o n g t s n = n t o h l ( tfdh −>belong TSN ) ; u i n t 3 2 t f r a g m e n t o f f s e t = n t o h l ( tfdh −>f r a g m e n t o f f s e t ) ; u i n t 3 2 t end = f r a g m e n t o f f s e t + l e n g t h ; W r i t a b l e P a c k e t ∗ pakket ; bool l a s t ; uint32 t f i l l e d ;
composition struct ∗ container ; c o n t a i n e r = tcb−>b u f f e r −>g e t c o m p o s i t i o n ( t h i s b e l o n g t s n ) ; i f ( c o n t a i n e r == 0 ) { pakket = Packet : : make ( end ) ; f i l l e d = 0; last = false ; } else {
6.2. FRAGMENTATIE AAN ZENDERZIJDE
27
pakket = c o n t a i n e r −>pakket ; l a s t = c o n t a i n e r −>l a s t ; f i l l e d = c o n t a i n e r −> f i l l e d ; }
u i n t 3 2 t d i f f l e n = end − pakket−>l e n g t h ( ) ;
W r i t a b l e P a c k e t ∗ p3 ; i f ( pakket−>l e n g t h ( ) < end ) { p3 = Packet : : make ( end ) ; memset ( p3−>data ( ) , ’ \0 ’ , p3−>l e n g t h ( ) ) ; memcpy ( p3−>data ( ) , pakket−>data ( ) , pakket−>l e n g t h ( ) ) ;
i f ( ! p3 ) { DEBUGDO( 5 , c l i c k c h a t t e r ( ” Packet make p3 FAILED ! ! ! No more memory? ” ) ) ; a s s e r t ( 0 ) ; // E x i t . } } else { p3 = pakket ; // p o i n t e r now a l s o p o i n t s t o p a k k e t . // Whether i t t o o k t h e i f or t h e e l s e , p3 i s v a l i d now . }
// g e t i t a f t e r t h e h e a d e r u i n t 3 2 t ∗ p i n f = ( u i n t 3 2 t ∗ ) ( t f d h +1); // p u t i t a t t h e o f f s e t u i n t 3 2 t ∗ pinp = ( ( u i n t 3 2 t ∗ ) p3−>data ( ) ) + f r a g m e n t o f f s e t ;
memset ( pinp , ’ \0 ’ , l e n g t h ) ; // s e t l a s t b i t t o z e r o memcpy ( pinp , p i n f , l e n g t h ) ; // copy d a t a from fragm t o p3
f i l l e d += l e n g t h ; l a s t = ( f l a g s == 0? f a l s e : true ) ; // a b i t v e r b o s e , b u t ok .
// c o u l d go a f t e r t h e n e x t i f , no need t o s t o r e i t when t h e p a c k e t i s c o m p l e t e . tcb−>b u f f e r −>a d d f r a g m e n t ( t h i s b e l o n g t s n , l a s t , f i l l e d , p3 ) ;
6.3. SAMENVATTING VAN DIT HOOFDSTUK
28
/∗ Check i f we have a c o m p l e t e p a c k e t ∗/
// t h e l a s t p3 was r e c e i v e d // ( so t h e l e n g t h i s r e l i a b l e // and t h e r e c e i v e d l e n g t h e q u a l s t h e t o t a l l e n g h t . // Composition c o m p l e t e ! i f ( ( l a s t ) && ( f i l l e d == p3−>l e n g t h ( ) ) ) { return p3 ; } return 0 ; }
6.3
Samenvatting van dit hoofdstuk
In dit hoofdstuk werd een implementatie in Click toegelicht. Aan de hand van verschillende fragmenten code werd de globale werking van het programma geschetst.
29
Hoofdstuk 7
Conclusie 7.1
Stand van zaken
In deze scriptie werd een nieuw SCTP chunk type voorgesteld dat fragmentatie en herfragmentatie van datachunks toeliet, iets wat tot heden volgens de standaard SCTP specificatie niet mogelijk was. Wanneer men uitbreidingen op SCTP zoals mSCTP gaat beschouwen, waar de grootte van de minimale MTU sterk kan schommelen tijdens de uitvoering van het programma, begrijpt men dat herfragmentatie interessant is. Er werd een implementatie in C++ geschreven die gebruik maakte van het Click platform, om zo de degelijkheid van het algoritme aan te tonen. Dit is gelukt voor het algoritme bij verzending: wanneer de verzonden pakketten onderzocht worden ziet men duidelijk de headerstructuur van het gefragmenteerde-datachunk en het deel van de data. De implementatie van de ontvanger bevat een bug waardoor het hele programma soms crasht, hetgeen uitvoerig testen niet mogelijk maakte.
7.2
Mogelijke uitbreidingen
Enkele interessante uitbreidingen zijn: • Het debuggen van de ontvangerszijde zodat de applicatie niet meer crasht en pakketten aan de gebruiker worden doorgegeven.
7.2. MOGELIJKE UITBREIDINGEN
30
• Aan de verzenderzijde: het correct berekenen van de pakketlengte, het herfragmenteren van gefragmenteerde-datachunks en het fragmenteren van chunks groter dan de MTU zelf. • Het beheren van geheugen in de applicatie, opsporen van geheugenlekken. • Het testen op juistheid van de compositie van gefragmenteerde data. • Het testen van throughput, processorgebruik en geheugengebruik van de implementatie. • Het toevoegen van (een optie voor) padding van datachunks zodat packet-analysers deze correct kunnen inlezen. • Het aanpassen van een populaire packet-analyser zoals Wireshark zodat deze het gefragmenteerdedata chunk kan herkennen. • Het herschikken van de header zodat de niet-gebruikte velden (zoals streamvelden en payload) voor fragmentatie kunnen gebruikt worden, of het specifiek maken van dergelijke headers omwille van performantie.
BIBLIOGRAFIE
31
Bibliografie [1] Miniwatts Marketing Group. Internet world stats, February 2007. [2] R. Stewart. Sctp implementations, August 2007. [3] M. Tuexen and R. Stewart. RFC 2960: SCTP, October 2000. [4] R. Stewart et al. Sctp dynamic address reconfiguration, June 2007. [5] E. Kohler. The click modular router, February 2001. [6] V. Cerf. A partial specification of an international transmission protocol, 1973. [7] Y. K. Dalal V. G. Cerf and C. A. Sunshine. RFC 675: Specification of Internet Transmission Control Program, December 1974. [8] J. Postel. Comments on Internet Protocol and tcp, August 1977. [9] J. Postel. RFC 793: Transmission control protocol, September 1981. [10] CERT. Cert advisory ca-1996-21 tcp syn flooding and ip spoofing attacks, September 1996. [11] Paul. D. Amer Preethi Natarajan, Janardhan R. Iyengar and Randall Stewart. Sctp: An innovative transport layer protocol for the web, August 2007. [12] R. Stewart and Q. Xie. Stream Control Transmission Protocol (SCTP): A Reference Guide. Addison Wesley, 2002. [13] J. Postel. RFC 791: Internet Protocol, September 1981. [14] C. Perkins. RFC 2003: Ip encapsulation within ip, October 1996. [15] J. Postel. RFC 768: User datagram protocol, August 1980. [16] University of California. The click modular router, August 2007.