• Nem Talált Eredményt

A hálózati rétegnek nyújtott szolgáltatások

Az ábra olyan kétirányú rendszert mutat, amelyben két lézerforrás található

1. Az adatkapcsolati réteg tervezési szempontjai

1.1. A hálózati rétegnek nyújtott szolgáltatások

Az adatkapcsolati réteg feladata az, hogy szolgáltatásokat nyújtson a hálózati rétegnek. A legfőbb szolgáltatás az adatok átvitele az adógép hálózati rétegétől a vevőgép hálózati rétegéig. Az adógépen van egy funkcionális egység – nevezzük folyamatnak – a hálózati rétegben, amely átad néhány bitet az adatkapcsolati rétegnek, hogy az továbbítsa a célhoz. Az adatkapcsolati réteg feladata az, hogy továbbítsa a biteket a címzett géphez, hogy ott azokat át lehessen adni a hálózati rétegnek, ahogyan a 3.2.(a) ábrán látható. A valódi átvitel a 3.2.(b) ábra szerint megy végbe, de egyszerűbb két adatkapcsolati rétegbeli folyamatot elképzelni, melyek adatkapcsolati protokollal kommunikálnak. Emiatt ebben a fejezetben hallgatólagosan a 3.2.(a)ábra szerinti modellt fogjuk használni.

3.2. ábra - (a) Látszólagos (virtuális) kommunikáció. (b) Tényleges kommunikáció

Az adatkapcsolati réteget különféle szolgáltatások megvalósítására készíthetik fel. A ténylegesen megvalósított szolgáltatások rendszerről rendszerre változhatnak. Három ésszerű, általánosan megvalósított lehetőség:

1. Nyugtázatlan összeköttetés nélküli szolgáltatás.

2. Nyugtázott összeköttetés nélküli szolgáltatás.

3. Nyugtázott összeköttetés-alapú szolgáltatás.

Vizsgáljuk meg ezeket sorjában!

Nyugtázatlan összeköttetés nélküli szolgáltatás esetén a forrásgép egymástól független kereteket küld a célgép felé, amely nem nyugtázza a keretek megérkezését. Az Ethernet jó példa ilyen típusú protokollra. Semmiféle kapcsolatot nem építenek fel előzetesen, illetve nem bontanak le az átvitel után. Ha egy keret a vonali zaj miatt elveszik, nem történik kísérlet a hiba felfedezésére és helyreállítására az adatkapcsolati rétegben. Ez a szolgáltatási osztály abban az esetben megfelelő, ha a hibaarány nagyon alacsony, így a hibák javítása a felsőbb rétegekre hagyható, valamint valós idejű forgalom esetén (például beszédátvitel), amikor a későn érkező adat rosszabb, mint a hibás adat.

A következő lépés a megbízhatóság irányába a nyugtázott összeköttetés nélküli szolgáltatás. Ilyen szolgáltatás esetén sincs felépített kapcsolat, de minden egyes elküldött keret megérkezését nyugtázza a címzett állomás, így a küldő értesül arról, hogy a keret megérkezett-e, vagy sem. Ha egy keret nem érkezik meg meghatározott időn belül, újra lehet küldeni. Ez a szolgáltatás megbízhatatlan csatornák (például vezeték nélküli rendszerek) esetén hasznos. A 802.11 Wi-Fi is ilyen típusú szolgáltatást alkalmaz.

Talán érdemes hangsúlyozni, hogy a nyugtázás megvalósítása az adatkapcsolati rétegben sohasem elvárás, csak optimalizáció. A hálózati réteg mindig küldhet egy csomagot és megvárhatja a távoli partner által küldött nyugtát. Ha a nyugta az időzítő lejárta előtt nem érkezik meg, a küldő újraküldheti az egész üzenetet. A probléma ezzel a stratégiával az, hogy nem hatékony. Az adatkapcsolatok rendszerint hardveres okokból általában szigorúan korlátolt hosszúságú keretekkel és ismert terjedési késleltetéssel rendelkeznek. Ezeket a paramétereket a hálózati réteg nem ismeri. Ha például küldünk egy nagy csomagot, amely 10 keretből áll, és ezek közül átlagosan kettő elvész, nagyon sokáig tarthat, amíg a csomag hibátlanul megérkezik. Ha minden keretet egyenként nyugtázunk, és szükség esetén újraküldünk, sokkal gyorsabban jut át az egész üzenet.

Megbízható csatornákon, mint például az üvegszál, szükségtelen bonyolult adatkapcsolati protokoll használata, de vezeték nélküli átviteli csatornákon a csatorna megbízhatatlansága miatt nagyon is megéri.

Visszatérve a szolgáltatásokhoz, a legkifinomultabb szolgáltatás, amit az adatkapcsolati réteg a hálózati rétegnek nyújthat: az összeköttetés-alapú szolgáltatás. Ezt alkalmazva a forrás- és a címzett számítógép felépít egy összeköttetést, mielőtt az adatátvitelt megkezdenék. Minden elküldött keret sorszámozott, és az adatkapcsolati réteg garantálja, hogy a keretek valóban meg is érkezzenek, továbbá, hogy minden keret pontosan egyszer és a megfelelő sorrendben érkezzen meg. Az összeköttetés-alapú szolgáltatás így megbízható bitfolyamot biztosít a hálózati réteg folyamatai számára. Ez a fajta szolgáltatás kifejezetten előnyös olyan megbízhatatlan csatornákon, mint a műholdas összeköttetések vagy nagy távolságú telefonvezetékek. Ilyen esetekben, ha nyugtázott összeköttetés nélküli szolgáltatást használnánk, azzal járna, hogy az elveszett nyugták miatt a kereteket többször újra kellene küldeni és venni, ami jelentős sávszélesség-veszteséget okozna.

Amikor összeköttetés-alapú szolgáltatást alkalmazunk, az átvitel három jól elkülöníthető fázisra bontható. Az első fázisban az összeköttetés felépül; mindkét oldalon inicializálódnak azok a változók és számlálók, melyek ahhoz szükségesek, hogy számon tarthassuk, hogy mely keretek érkeztek meg és melyek nem. A második fázisban egy vagy több keret tényleges továbbítása történik. A harmadik – egyben utolsó – fázisban az összeköttetést lebontjuk, felszabadítva a változókat, puffereket és egyéb erőforrásokat, melyeket a kapcsolat karbantartásához használtunk.

1.2. Keretezés

Ahhoz, hogy az adatkapcsolati réteg szolgáltatást nyújthasson a hálózati rétegnek, a fizikai réteg szolgáltatását kell igénybe vennie. A fizikai réteg nem tesz mást, mint a kapott bitsorozatot megpróbálja továbbítani a célhoz.

Ha a csatorna zajos – ahogy a legtöbb vezeték nélküli és néhány vezetékes adatkapcsolat is ilyen – a fizikai réteg, hogy a hibák számát csökkentse, redundanciát ad a kimenő jelekhez, de az érkező bitsorozat hibamentességét a fizikai réteg nem garantálja. A vett bitek száma lehet kevesebb, azonos vagy több, mint az elküldötteké, és a bitek értéke is különbözhet az eredetitől. Az adatkapcsolati réteg feladata, hogy jelezze, illetve – ha szükséges – kijavítsa a hibákat.

A szokásos megoldás az, hogy az adatkapcsolati réteg különálló keretekre tördeli a bitfolyamot, és a keretekhez ún. ellenőrző összeget számít. (Az ellenőrzőösszeg-képző algoritmusokat a fejezet későbbi részében tárgyaljuk.) Amikor a keret megérkezik a célhoz, az ellenőrző összeget újra kiszámolja az adatkapcsolati réteg.

Ha ez különbözik attól, amit a keret tartalmaz, a réteg tudja, hogy hiba történt, és lépéseket tesz ennek kezelésére (például eldobja a rossz keretet és hibajelzést küld vissza).

A bitfolyam keretekre tördelése sokkal bonyolultabb feladat, mint amilyennek első ránézésre tűnik. Egy jó megoldásnak lehetővé kell tenni a keretek kezdetének könnyű felismerését elenyésző csatorna-sávszélesség használata mellett. Ebben a szakaszban négy módszert vizsgálunk meg: bájtszámmezőt használ. Amikor a címzett állomás adatkapcsolati rétege megkapja a keretben levő bájtok számát, tudni fogja, hogy mennyi bájtnak kell érkeznie, és így azt is, hogy hol van a keret vége. Ennek a technikának az alkalmazása a 3.3.(a) ábrán látható négy keretre, melyek mérete 5, 5, 8 és 8 bájt.

3.3. ábra - Egy bájtfolyam (a) hiba nélkül (b) egy hibával

Ezzel az algoritmussal az a baj, hogy egy átviteli hiba elronthatja a bájtszámmezőt. Például, ha egy 5-ös bájtszám a 3.3.(b) ábra második keretében 7-té válik egyetlen bithiba eredményeképpen, a célállomás kiesik a szinkronból, és képtelen lesz megtalálni a következő keret elejét. Még ha az ellenőrző összeg hibás is, és a címzett tudja, hogy a keret rossz, akkor sincs mód arra, hogy megmondjuk, hol kezdődik a következő keret.

Szintén nem segít a keret újraküldésének kérése, hiszen a címzett nem tudja, hogy hány bájtot kell átlépnie ahhoz, hogy az újraküldött keret elejéhez érjen. Az előzőek miatt a bájtszámlálásos módszert ma már ritkán használják.

A második keretezési eljárás úgy kerüli meg a hibák utáni újraszinkronizálás problémáját, hogy minden keret elejét és végét egy-egy különleges bájttal jelzi. Régebben a keretek elejét és végét különböző bájtok jelezték, de az elmúlt években a legtöbb protokoll már ugyanazt a bájtot használja erre a célra. Ezt jelzőbájtnak (flag byte)nevezték el, a 3.4.(a) ábrán FLAG-ként tüntettük fel. Két egymást követő jelzőbájt közül az egyik a keret végét, a másik a következő keret elejét jelzi. Ha a vevő bármikor kiesik a szinkronból, akkor csak a jelzőbájtot kell megkeresnie ahhoz, hogy megtalálja az éppen futó keret végét.

3.4. ábra - (a) Egy jelzőbájtokkal határolt keret. (b) Négy bájtsorozat bájtbeszúrás előtt és után

Ennél a módszernél komoly gond jelentkezik, amikor bináris adatokat, például képeket vagy zenét kell átvinnünk. Könnyen előfordulhat, hogy a jelzőbájt bitmintája megjelenik az adatok között is, ez pedig általában belezavar a keretezésbe. A gond orvoslásának egyik módja az, hogy a küldő fél adatkapcsolati rétege egy különleges kivételbájtot (escape byte, ESC) helyez minden olyan jelzőbájt elé, amely „véletlenül” került az adatmezőbe, így minden jelzőbájt megkülönböztethető az adatokban előforduló azonos értékű bájtoktól az előtte álló kivételbájt (ESC) megléte, vagy hiánya alapján. A vevő oldal adatkapcsolati rétege eltávolítja ezt a kivétel

bájtot, mielőtt az adatokat a hálózati rétegnek továbbítaná. Ezt a módszert bájtbeszúrásnak (byte stuffing) nevezik.

A következő kérdés természetesen az, hogy mi történik abban az esetben, amikor a felhasználó adatai egy kivételbájtot tartalmaznak. A válasz az, hogy ezt is megjelölik egy kivételbájttal. Így minden egyedüli kivételbájt egy kivételbájt-sorozat (escape sequence) része, ahol minden kettős karakter azt jelenti, hogy egy kivételbájt volt a felhasználói adatok között. A 3.4.(b) ábra ezt az eljárást mutatja be néhány bájtsorozaton. A beszúrt bájtok eltávolítása után leszállított bájtsorozat minden esetben pontosan megegyezik az eredeti bájtsorozattal. A kerethatárok a kivételbájtok eltávolítása nélkül továbbra is megtalálhatók két, egymás melletti jelzőbájt keresésével.

A 3.4. ábrán feltüntetett bájtbeszúrási módszer egy enyhén leegyszerűsített változata annak, amelyet a PPP-protokoll (Point-to-Point Protocol – kétpontos PPP-protokoll) használ. A PPP az a PPP-protokoll, amelyet a legtöbb otthoni számítógép az internetszolgáltatójával való kommunikációhoz használ, és később még lesz róla szó ebben a fejezetben.

A harmadik módszer túllép a bájtbeszúrás azon hátrányán, hogy az tipikusan 8 bites bájtokat használ. Ez az új módszer lehetővé teszi, hogy tetszőleges számú bit legyen egy keretben, és az alkalmazott karakterkódok is tetszőleges számú bitet tartalmazzanak. A módszert az egykor nagyon népszerű HDLC (Highlevel Data Link Control – magas szintű adatkapcsolati vezérlés) protokollhoz fejlesztették ki. A módszer az alábbiak szerint működik: minden keret egy speciális, jelző- (flag) bájtnak nevezett bitmintával kezdődik. Ez a 01111110 (hexadecimálisan 0x7E). Amikor az adó adatkapcsolati rétege öt egymást követő 1-es bitet talál az adatok között, automatikusan beszúr egy 0-t a kimenő bitfolyamba. Ez a bitbeszúrás (bit stuffing) analóg a bájtbeszúrással, amelyben egy ESC-t szúrtunk be a kimenő bájtfolyamba az adatok között levő jelzőbájt elé.

Mivel a módszer a legkevesebb átmenettel jár, ezért a fizikai réteg könnyebben szinkronban marad. Éppen ezért alkalmazzák e módszert az USB- (Universal Serial Bus – univerzális soros sin) szabványban.

Amikor a vevő öt egymást követő 1-es bitet talál, melyet egy 0-s követ, automatikusan törli a 0-s bitet. Ahogyan a karakterbeszúrás teljesen átlátszó a hálózati réteg számára mindkét számítógépben, a bitbeszúrás is az. Ha a felhasználói adat tartalmazza a jelzőbájt bitmintáját (01111110), ez 011111010-ként továbbítódik, de a vevő memóriájában már 01111110 jelenik meg. A 3.5. ábra egy példát mutat a bitbeszúrásra.

3.5. ábra - Bitbeszúrás. (a) Az eredeti adat. (b) Az átviteli vonalon megjelenő adat. (c) A vevő memóriájában megjelenő, a beszúrt bitek törlése utáni adat

A bitbeszúrásos módszer segítségével egyértelműen felismerhetők a kerethatárok: ha a vevő szem elől téveszti a határokat, semmi mást nem kell tennie, mint a bemeneti bitfolyamban a jelző mintát keresnie, hiszen a minta csak kerethatárokon fordulhat elő, az adatok között sohasem.

Mind a bájtbeszúrásnál, mind a bitbeszúrásnál megjelenik az a mellékhatás, hogy a keret hossza a szállított adatok tartalmától függ. Például ha az adatmező nem tartalmaz jelzőbájtot, 100 bájtnyi adat nagyjából egy 100 bájtos keretben átvihető, míg egy kizárólag jelzőbájtokból álló adatmező a kivételbájtokkal körülbelül 200 bájtos keretben továbbítható. Ebből a szempontból a bitbeszúrás kedvezőbb, mert a keretméret növekedése nagyjából 12,5%, hiszen minden bájthoz egy bitet adtunk hozzá.

Az utolsó keretezési eljárás a fizikai réteg kódolásainak tulajdonságán alapszik. A 2. fejezetben láttuk, hogy a bitek fizikai jelekké kódolása gyakran redundanciát tartalmaz, amely azt jelenti, hogy bizonyos jelek nem fordulhatnak elő hagyományos adat kódolása esetén. Például a 4B/5B séma 4 adatbitet kódol 5 jellel a megfelelő mennyiségű jelátmenet előállítása érdekében. Ez azt jelenti, hogy a lehetséges 32 jelből 16-ot nem használnak, így ezek közül néhány fenntartott jel felhasználható a keret elejének és végének jelzésére. Gyakorlatilag tehát

„kódsértést” használtunk keretezésre. A módszer szépsége, hogy mivel ezek a jelek nem használatosak kódolás esetén, könnyű őket megtalálni, és nincs szükség az adatmező módosítására, bájtok vagy bitek beszúrására.

Végül megjegyezzük, hogy sok adatkapcsolati protokoll a nagyobb biztonság érdekében a fenti módszerek valamely kombinációját alkalmazza. Egy gyakori megoldásra láthatunk példát az Ethernet és a 802.11 protokollokban, ahol a keret egy jól definiált előtaggal (preamble) kezdődik. Az előtag megfelelően hosszú is lehet (802.11 esetén 72 bit), hogy segítse a vevőt felkészülni az adatok fogadására. Az előtagot egy hosszkód- (azaz bájtszám-) mező követi a fejlécben, melyet a keret végének meghatározására használnak.

1.3. Hibakezelés

Miután megoldottuk a keretek kezdetének és végének jelzését, szembekerülünk a következő problémával:

hogyan bizonyosodjunk meg arról, hogy minden keret ténylegesen megérkezik-e a címzett állomás hálózati rétegéhez, és hogy helyes sorrendben érkezik-e meg. Egyelőre tételezzük fel, hogy a vevő meg tudja állapítani, hogy a beérkezett keret helyes vagy hibás adatokat tartalmaz (a 3.2. fejezetben majd áttekintjük a hiba detektálására és javítására használatos kódolásokat). Nyugtázatlan összeköttetés nélküli szolgáltatáshoz megfelelő lehet, ha a küldő folyamatosan küldi a kereteket, függetlenül attól, hogy azok helyesen érkeztek-e meg, viszont megbízható, összeköttetés-alapú szolgáltatásoknál ez már nem elég.

A biztonságos átvitel megvalósításának általános módja az, hogy az adónak valamilyen visszacsatolást biztosítunk arról, hogy mi történik a vonal másik végén. Tipikusan az adó megköveteli a vevőtől, hogy speciális vezérlőkereteket küldjön vissza, melyek pozitív vagy negatív nyugtát hordoznak a bejövő keretekről. Ha a küldő pozitív nyugtát kap egy keretről, tudja, hogy a keret rendben megérkezett. A negatív nyugta ellenben azt jelenti, hogy valami nincs rendben, és a keretet újra kell adni.

További komplikáció származik abból, hogy hardverhibák (például zaj) egy keret teljes eltűnését okozhatják.

Ebben az esetben az adó egyáltalán nem reagál, mivel nincs is mire reagálnia. Hasonlóan, ha a nyugtázó keret veszik el, a küldő nem tudja folytatni tevékenységét. Tisztán látszik, hogy az a protokoll, amelyben a küldő a keret elküldése után vár a pozitív vagy negatív nyugtára, örökre felfüggesztődne, ha egy keret egyszer teljesen elveszne a hibásan működő hardver miatt.

Ezt a lehetőséget az adatkapcsolati rétegben időzítők bevezetésével küszöbölik ki. Amikor az adó továbbít egy keretet, általában egy időzítőt is elindít. Az időzítő úgy van beállítva, hogy lejártáig legyen elég idő arra, hogy a keret elérje a célt, ott feldolgozásra kerüljön, és a nyugta visszatérjen az adóhoz. Normális esetben a keret helyesen megérkezik, és a nyugta visszaér, mielőtt az időzítő lejárna. Ekkor az időzítő törlődik.

Ha viszont a keret vagy a nyugta elvész, az időzítő lejár, és jelzi az adónak, hogy valószínűleg hiba történt. A nyilvánvaló megoldás: egyszerűen újra elküldeni a keretet. Ha azonban a kereteket többször továbbítjuk, fennáll a veszélye annak, hogy a vevő többször veszi ugyanazt a keretet, és többször adja át a hálózati rétegnek. Hogy ezt megakadályozzuk, általában a kimenő kereteknek sorszámot adunk, hogy a vevő meg tudja különböztetni az újraadott kereteket az eredetiektől.

Egy másik fontos tervezési kérdés, amely megjelenik az adatkapcsolati rétegben (és a felsőbb rétegekben is) az, hogy mit tegyünk azzal az állomással, amelyik rendszeresen gyorsabban akarja adni a kereteket, mint ahogy a vevő azokat fogadni tudná. Ez a szituáció könnyen előállhat akkor, ha az adó egy gyors (vagy kevéssé terhelt) számítógép, a vevő pedig egy lassú (vagy erősen leterhelt) gép. Gyakori helyzet például, hogy egy okostelefon weboldalt kér le egy gyors szervertől, amely teljes sebességgel kiszolgálja a kérést, és a szerencsétlen telefont teljesen elárasztja adatokkal. Még ha az átvitel hibamentes is, a vevő egy bizonyos ponttól kezdve nem lesz képes kezelni a folyton érkező kereteket, és néhányat el fog veszíteni.

Világos, hogy valamit tenni kell, hogy megakadályozzuk ennek kialakulását. A gyakorlatban két megközelítés terjedt el. Az első a visszacsatolás-alapú forgalomszabályozás (feedback-based flow control). Ebben a megoldásban a vevő információt küld vissza a feladónak, amelyben engedélyt ad neki további adatok küldésére, vagy legalábbis tájékoztatja saját pillanatnyi állapotáról. A második a sebességalapú forgalomszabályozás (rate-based flow control). Itt a protokollba be van építve egy sebességkorlát, amelyet minden küldőnek minden adattovábbítás során tiszteletben kell tartania. Ez a megoldás a fogadó részéről semmilyen visszacsatolást nem igényel.