Subsections
2 Podział oprogramowania sieciowego na warstwy
Złożone systemy przesyłania danych nie korzystają z pojedynczego protokołu
do obsługi wszystkich zadań związanych z transmisją, lecz wymagają istnienia
zestawu współpracujących protokołów. Comer [Comer 97a] wyszczególnia
najważniejsze problemy, z którymi muszą sobie radzić protokoły sieciowe.
- Zawodność sprzętu. Należy wykrywać awarie sieci, ruterów
lub innych elementów sprzętowych i radzić sobie z nimi, jeżeli to możliwe.
- Przeciążenie sieci. Sieci mają skończoną przepustowość, której
nie można przekroczyć. Oprogramowanie protokołów musi zapewnić sposoby
na to, aby przeciążony komputer mógł zlikwidować nadmierny ruch.
- Gubienie pakietów i przychodzenie pakietów z opóźnieniem.
Oprogramowanie sieciowe musi dowiadywać się o zagubionych pakietach
i dostosowywać się do dużych opóźnień w ich dostarczaniu.
- Uszkodzenie danych. Elektryczne i magnetyczne zakłócenia oraz
błędy interfejsów sprzętowych mogą spowodować błędy w transmisji powodujące
uszkodzenie przesyłanych danych. Protokoły powinny
wykrywać takie błędy i obsługiwać je w jakiś sposób.
- Powielanie danych i błędy w kolejności napływania danych.
Sieci, w których dane mogą wędrować wieloma różnymi trasami, mogą dostarczać
dane nie w kolejności, a także powodować powielanie pakietów.
Protokoły muszą porządkować pakiety i pozbywać się dodatkowych kopii.
Trudno jest napisać jeden protokół, który poradzi sobie z tymi wszystkimi
problemami. Dlatego zadanie komunikacji sieciowej jest dzielone na
podzadania, rozwiązywane przez osobne moduły oprogramowania. Moduły
te można traktować tak, jakby były ułożone na stosie składającym się z warstw.
Każda warstwa jest odpowiedzialna za obsługę części problemu.
Wysłanie komunikatu od programu użytkowego na jednej maszynie do programu
użytkowego na drugiej oznacza przesłanie tego komunikatu w dół przez kolejne
warstwy oprogramowania sieciowego maszyny nadawcy, transmisję komunikatu
przez sieć oraz przesłanie komunikatu w górę przez kolejne warstwy
oprogramowania protokołów na maszynie odbiorcy.
W każdej warstwie może być zaimplementowanych wiele protokołów, pozwalających
wykonać na różne sposoby takie samo zadanie. Przykładem może być tu komputer
wyposażony w kilka interfejsów sieciowych różnego typu i w oprogramowanie,
które implementuje protokoły komunikacji z każdym z tych interfejsów.
Istnieje wiele schematów podziału oprogramowania sieciowego na warstwy.
Niezależnie od wybranego schematu i od zadań poszczególnych warstw,
działanie podzielonych na warstwy protokołów jest oparte na jednej
podstawowej idei, zwanej zasadą podziału na warstwy:
podział na warstwy jest tak zaprojektowany, aby warstwa n
u odbiorcy otrzymywała dokładnie te same obiekty, które wysłała
warstwa n u nadawcy. Dzięki tej idei projektant protokołu
może skupić uwagę tylko na jednej warstwie, nie martwiąc się o to,
jak działają warstwy położone niżej i wyżej.
Wadą podziału na warstwy może być mała wydajność protokołów. Ścisłe
przestrzeganie podziału na warstwy często uniemożliwia optymalizację
przesyłania, co ma znaczenie przy konstrukcji systemów pracujących
z sieciami o dużej przepustowości. Z tego powodu w praktycznych
implementacjach zazwyczaj nie stawia się wymagania ścisłej hermetyzacji
warstw, np. pozwala się, aby implementacja protokołu TCP wykorzystywała
informację o maksymalnej jednostce przesyłu (MTU -- ang. Maximum
Transmission Unit) w sieci dla unikania fragmentacji pakietów przez
oprogramowanie IP.
Wzorcowym sposobem podziału oprogramowania sieciowego na warstwy jest
model ISO OSI -- Model Wzorcowy Otwartych Systemów Połączeń
Międzysieciowych (ang. Reference Model of Open System Interconnection),
opracowany przez organizację ISO (Międzynarodowa Organizacja Standaryzacyjna,
ang. International Organization for Standarization). Model ten
wyszczególnia 7 warstw, przy czym warstwy o wyższych numerach są ułożone wyżej
na stosie ([Comer 97a]).
- Warstwa fizyczna (połączenie za pomocą fizycznego sprzętu).
- Warstwa łącza danych (interfejs sprzętowy).
- Warstwa sieci.
- Warstwa transportowa.
- Warstwa sesji.
- Warstwa reprezentacji danych.
- Warstwa programów użytkowych.
Oprogramowanie TCP/IP jest zorganizowane w cztery koncepcyjne warstwy, które
stanowią nadbudowę nad warstwą sprzętu. W większości implementacji
trzy najniższe warstwy należą do systemu operacyjnego. W systemach badanych
w niniejszej pracy wszystkie one są implementowane w jądrze. Oto kolejne
warstwy (za [Comer 97a]).
- Warstwa interfejsu sieciowego. Odpowiada za przyjmowanie
datagramów IP i przesyłanie ich przez daną sieć. Może składać się ze
sterownika urządzenia lub ze skomplikowanego podsystemu, który wykorzystuje
własny protokół łącza. Odpowiada warstwie łącza danych z modelu ISO
OSI6.
- Warstwa intersieci. Zajmuje się kapsułkowaniem pakietów TCP i UDP
w datagramach IP, wyznaczaniem tras pakietów, sprawdzaniem poprawności przychodzących
datagramów, obsługą protokołu ICMP. Odpowiada warstwie sieciowej z modelu ISO
OSI.
- Warstwa transportowa. Zapewnia komunikację między jednym
programem użytkownika a drugim. Może regulować przepływ informacji, zapewniać
bezbłędność i właściwą kolejność przesyłanych danych. Określa, który
program użytkowy powinien otrzymać przychodzące dane. Jej odpowiednik
w modelu ISO OSI nosi tę samą nazwę.
- Warstwa programów użytkowych. Odpowiada wszystkim warstwom
powyżej transportowej z modelu ISO OSI.
Warstwy transportu i intersieci bywają łączone w jedną, gdyż obie operują
adresami IP, w odróżnieniu od warstwy interfejsu, która używa adresów
niskopoziomowych (fizycznych).
Oprogramowanie Net/3 stosuje następujący podział na warstwy
(zob. [Stevens 98b]).
- Warstwa interfejsu. Zawiera programy obsługi urządzeń,
zazwyczaj komunikujące się z urządzeniami sieciowymi -- np. Ethernet,
SLIP, pętla zwrotna. Odpowiada warstwie łącza danych z modelu ISO
OSI7.
- Warstwa protokołu. Zawiera implementację czterech rodzin
protokołów: TCP/IP, XNS, OSI i domena uniksowa. Każdy zestaw protokołów
może mieć własną strukturę wewnętrzną, np. w zestawie protokołów
internetowych najniższą warstwą jest IP, powyżej znajdują się dwa
protokoły transportowe (TCP i UDP). Odpowiada warstwom sieciowej i
transportowej z modelu ISO OSI.
- Warstwa gniazd. Stanowi interfejs do położonej
niżej warstwy zależnej od protokołu. Wszystkie wywołania systemowe
rozpoczynają się w niezależnej od protokołu warstwie gniazd. Kod
umieszczony w tej warstwie sprawdza poprawność argumentów wywołania
systemowego i uruchamia zależny od protokołu kod w niższej warstwie.
W omówionych poprzednio modelach warstwa gniazd nie występuje,
gdyż jest ona interfejsem pomiędzy programami
użytkownika i jądrem, a nie implementacją protokołu sieciowego.
Warstwa fizyczna z modelu ISO OSI jest implementowana przez sprzęt,
natomiast warstwy sesji, prezentacji i aplikacji są obsługiwane przez
procesy użytkowe.
Podobnego podziału dokonano w jądrze Linuksa (zob. [Beck 99]).
Tak jak w kodzie Net/3, występują tutaj warstwy gniazd i interfejsu,
natomiast warstwie protokołu dla TCP/IP odpowiadają 3 warstwy.
- Warstwa protokołu sieciowego. Implementuje protokół IP.
- Warstwa protokołu transportowego. Implementuje protokoły
TCP i UDP, dla gniazd surowych nie występuje.
- Warstwa gniazd INET. Podobna do warstwy gniazd, ponieważ pełni
rolę administracyjną. Różnica polega na tym, że warstwa gniazd INET operuje
na danych związanych z protokołami TCP/IP, zgromadzonych w strukturze
sock i jej podstrukturach. Leżąca powyżej warstwa gniazd jest niezależna
od protokołu.
Podział na warstwy protokołu sieciowego i transportowego nie jest ścisły:
implementacja TCP różni się w zależności od tego, czy ma działać
z protokołem IP w wersji 4, czy w wersji 6. Z drugiej strony w kodzie
systemów BSD można dostrzec podział jednolitej warstwy protokołu na warstwy
sieciową i transportową (zob. rozdział 3).
Warto zauważyć, że takie wywołania systemowe jak read() i write()
mogą odnosić się nie tylko do plików, lecz również do gniazd. W wyniku takiego
wywołania sterowanie nie trafia od razu do warstwy gniazd, lecz przechodzi
najpierw przez kod, który może być traktowany jak wyższa warstwa w stosie
protokołów. Jego zadaniem jest rozpoznanie, że odwołanie dotyczy gniazda
i wywołanie odpowiedniej funkcji z warstwy gniazd. Kod ten może też
zajmować się innymi czynnościami, np. badać poprawność argumentów wywołania
i dostępność odpowiednich obszarów przestrzeni adresowej. W Linuksie tymi
zadaniami zajmuje się warstwa VFS (ang. Virtual Filesystem Switch
-- Przełącznik Wirtualnego Systemu Plików). W systemach BSD nie używa się
tej terminologii, ale Net/3 również zawiera kod operacji plikowych, który
w razie potrzeby przekierowuje wywołania systemowe do warstwy gniazd.
W niniejszej pracy przyjmujemy, że ten kod, podobnie jak w Linuksie, należy do
warstwy VFS.
Warstwy administracyjne kodu sieciowego: VFS, gniazd i gniazd INET mogą
być pomijane w rozważaniach
dotyczących działania protokołów sieciowych. Nie można jednak o nich zapominać
przy badaniu przebiegu sterowania w jądrze i analizie wydajności kodu
sieciowego.
W tabeli 2.1 podsumowano odpowiedniość różnych warstw
w przedstawionych modelach.
Dla ścisłości należy wspomnieć, że na poziomie jądra mogą być zaimplementowane
takie usługi, jak serwer HTTP czy klient NFS8. Obejmują one swoim zakresem protokoły
z wyższych warstw: sesji, reprezentacji danych, a nawet aplikacji. Przypadki
te nie będą rozważane w niniejszej pracy.
Tabela 2.1:
Modele podziału kodu sieciowego na warstwy
|
Footnotes
- ...
OSI6
- Niektóre zadania należące do warstwy łącza danych mogą być
wykonywane przez sprzęt. I tak np. karty Ethernet liczą sumy kontrolne
wysyłanych i otrzymywanych pakietów; czynność ta niewątpliwie nie należy
do zadań warstwy fizycznej.
- ...
OSI7
- Z zastrzeżeniem takim, jak w poprzednim przypisie.
- ... NFS8
- Nie da się tego uniknąć,
jeśli chcemy, aby system plików NFS był widziany przez warstwę VFS w ten sam
sposób, jak inne systemy plików.