Vývojový
tým: general project manager Soňa
NEHYBOVÁ,
programmers Martin KOŠTUŘÍK, Martin
SCHOVÁNEK
Úkol: Implementujte ovladač protokolu IPX pro operační systém TUOX.
Zdrojove kody
Komunikační
protokol IPX (Internetwork Packet Exchange) je nespojově
orientovaným (datagramovým) protokolem, který zaručuje
předávání nezávislých paketů v intersíti. Pohybujeme se
tedy na úrovni síťové vrstvy OSI modelu. Každý paket se
sítí šíří samostatně bez vazby na ostatní pakety a bez
garance, že vůbec bude doručen.
IPX driver je implementován jako integrální součást File Systému. Tj. využívá stejné task number, tj.přijímá zprávy z hlavní smyčky File Systému.
Jeho úkolem je:
zaregistrovat se u driveru síťové karty jako ovladač protokolu IPX. Od této chvíle, kdykoli driver síťové karty obdrží rámec obsahující IPX packet, zasílá na IPX driver zprávu C_NOTIFY. IPX, driver si packet přebírá zasíláním zprávy C_READ na driver síťové karty (DSK).
převzaté packety rozbalit a data předat aplikaci, uložit do cache nebo zahodit, podle toho, je-li daný socket otevřen a čeká-li aplikace na data
předat aplikacím data uložená v cache
přebírat od aplikací data, balit je do packetů a odesílat je na driver síťové karty (DSK)
otevírat a zavírat sockety
Skládá se z
níže uvedených částí.
Aplikační rozhraní IPX:
Socket (local_port, remote_port, remote_node, remote_net, protocol, dev_num).
Učel:
Vytváří soket. Tj. najde a vyplní volný záznam v tabulce TOS.Parametry:
local_port - číslo otvíraného soketu
remote_port - číslo soketu na vzdáleném stroji
remote_node - adresa uzlu v rámci remoute_net
remote_net - adresa vzdálené sítě
protocol - číslo protokolu
device_num - číslo síťové kartyVrací:
Deskriptor vytvořeného soketu, nebo ERR (záporná hodnota).Formát vstupní zprávy:
m_type = C_SOCKET
m4_l1 = ipx_sc_lport_prot = local_port(16b) + protocol(16b)
m4_l2 = ipx_sc_rport_rnodeh = r_port(16b) + r_node_h(16b)
m4_l3 = ipx_sc_rnodel = r_node_l(32b)
m4_l4 = ipx_sc_rnet = r_net(32b)
m4_l5 = ipx_sc_devnum = null(16b) + dev_num(16b)Formát výstupní zprávy:
m1_i1 = ipx_rp_fdRelizováno funkcí:
int ipx_do_socket()Popis algoritmu:
- zjisti zda již není socket otevřen
- najdi volný záznam v TOS
- vygeneruj descriptor soketu
Read (file_descriptor, dest_segment, dest_offset, nbytes).
Účel:
Na požadovaée místo v adr. prostoru aplikace uloží data z otevřeného soketu, max. však lenght bytů a max 1 paket.
- pokud není co číst nastaví se blokovací flag v TOS (wait_proc bude obsahovat číslo čekajícího procesu) a do TOS se uloží položky potřebné pro pozdější odeslání dat aplikaci jako délka požadovaných dat, cílový segment a offset dat. Aplikaci neodpovíme zprávou, čímž ji zablokujeme, protože ta čeká na odpověď. Když data příjdou (IPX driver dostane zprávu notify, zkontroluje se TOS a je-li nastaven blokovací flag, tj. existuje požadavek na čtení, data z paketu se zkopírují do adr. prostoru aplikace), a aplikace se odblokuje tím, že ji konečně pošleme odpověď.
- Pakety jsou odesílány aplikaci v tom pořadí v jakém byly přijaty.
- aplikace požaduje méně dat něž je délka aktuálniho paketu -> aplikaci je předáno požadované množství dat a zbylá část paketu je zahozena.
- aplikace požaduje více dat něž je délka aktuálniho paketu -> aplikaci je předán celý paket. Požadavek na zbylá data je ignorován.
- k přenosu dat do adresního prostoru aplikace se použije systémové volání SYS_COPY.
Parametry:
file_descriptor - descriptor soketu
dest_segment - cílový segment dat
dest_offset - cílový offset dat
nbytes - délka požadovaných datVrací:
Vrací počet skutečně přenesených dat, ERR (záporná hodnota) nebo NIC.Formát vstupní zprávy:
m_type = C_READ
m1_i1 = ipx_rw_ fd = file_descriptor
m1_i2 = ipx_rw_segment = dest_segment
m1_i3 = ipx_rw_nbytes = nbytes
m1_p1 = ipx_rw_offset = dest_offsetFormát výstupní zprávy:
m1_i1 = ipx_rp_nbytesRelizováno funkcí:
int ipx_do_read()Popis algoritmu:
- jestliže daný soket neobsahuje data uspi volající proces (dont_replay = 0) a skonči
- jinak, pošli data uživateli
- uvolni datový buffer
Write (file_descriptor, dest_segment, dest_offset, nbytes).
Účel:
Odešle data z uživatelské oblasti na otevřený socket, maximálně však jeden packet.Parametry:
file_descriptor - descriptor soketu
dest_segment - zdrojový segment dat
dest_offset - zdrojový offset dat
nbytes - délka odesílaných datVrací:
Vrací počet skutečně přenesených dat nebo ERR (záporná hodnota).Formát vstupní zprávy:
m_type = C_WRITE
m1_i1 = ipx_rw_ fd = file_descriptor
m1_i2 = ipx_rw_segment = dest_segment
m1_i3 = ipx_rw_nbytes = nbytes
m1_p1 = ipx_rw_offset = dest_offset
Formát výstupní zprávy:
m1_i1 = ipx_rp_nbytesRelizováno funkcí:
int ipx_do_write()Popis algoritmu:
- zkontroluj jestli je daný soket otevřený
- vytvoř paket a zkopíruj do něj data z uživatelské oblasti
- odešli paket driveru siťové karty
Close (file_descriptor)
Učel:
Uzavře otevřený socket, a uvolní jim obsazené buffery.Parametry:
file_descriptor - descriptor soketuVrací:
OK nebo ERR (záporná hodnota).Formát vstupní zprávy:
m_type = C_CLOSE
m1_i1 = ipx_rw_ fd = file_descriptorFormát výstupní zprávy:
m1_i1 = ipx_rp_errRelizováno funkcí:
int ipx_do_close()Popis algoritmu:
- zkontroluj jestli je daný soket otevřený
- uvolni buffery obsazené soketem
- zneplatni patřičný záznam v tabulce TOS
SetLocalNet (local_net)
Učel:
Nastaví adresu lokální sítě.Parametry:
local_net - adresa lokální sítě.Vrací:
Nic.Formát vstupní zprávy:
m_type = C_SETLNET
m2_l1 = ipx_sn_lnet = local_netRelizováno funkcí:
int ipx_set_lnet()Popis algoritmu:
- přiřaď proměnné "local_net" hodnotu local_net
SetLocalNode (local_node)
Účel:
Nastaví adresu uzlu lokální sítě.Parametry:
local_node - adresa uzlu lokální sítě (48b).Vrací:
Nic.Formát vstupní zprávy:
m_type = C_SETLNODE
m2_i1 = ipx_sn_lnodeh = local_node (horních 16b)
m2_l1 = ipx_sn_lnodel = local_node (dolních 32b)Relizováno funkcí:
int ipx_set_lnode()Popis algoritmu:
- přiřaď proměnné "local_node" hodnotu local_node
SetGateway (gateway)
Účel:
Nastaví adresu brány.Parametry:
gateway - adresa brány (48b).Vrací:
Nic.Formát vstupní zprávy:
m_type = C_SETGATEWAY
m2_i1 = ipx_s_lneth = local_net (horních 16b)
m2_l1 = ipx_s_lnetl = local_net (dolních 32b)Relizováno funkcí:
int ipx_set_gateway()Popis algoritmu:
- přiřaď proměnné "gateway" hodnotu gateway
Rozhraní IPX driveru a driveru síťové karty (DSK)
Rozhraní obsahuje čtyři funkce (služby).
Notify( )
Účel:
- Převezme paket od DSK, pokud soket (číslo soketu) uvedený v těle paketu není otevřený, paket je zahozen. Jinak jsou data paketu uložena do bufferu nebo přímo zaslána aplikaci pokud na ně apliiace již čeká. V případě že všechny buffery vyhrazené soketu jsou obsazeny, paket je zahozen.
- Volání provádí driver siťové karty (DSK) vždy, když přijde nějaký rámec s IPX paketem.Parametry:
Bez parametrů.Vrací:
Nic.Relizováno funkcí:
int ipx_do_notify()Popis algoritmu:
- pošli zprávu READ na síťovou kartu (převzatí paketu)
- vytáhni z packetu číslo soketu (portu)
- pokud daný soket není otevřený, tak paket zahoď, Konec
- jestli aplikace čeká na data, tak ji je pošli, Konec
- jinak, najdi volný datový buffer a zkopiruj do něj data z paketu
- index datové bufferu přidej do kruhového bufferu soketu
- pokud volný datový buffer není paket zahoď
Read (user_task, nbytes, dest_segment, dest_offset).
Účel:
Na místo určené "dest_segment:dest_offset" v mém adr. prostoru uloží data z doručeného paketu max. však "nbytes" bytů a max. 1 paket. Funkce DSK.
Parametry:
user_task - číslo uživatelského procesu
nbytes - max. délka paketu, kterou jsme ochotni převzít
dest_segment - cílový segment dat
dest_offset - cílový offset datVrací:
Funkce vrací skutečně načtený počet bytů nebo ERR.
Write (user_task, nbytes, source_segment, source_offset).
Účel:
Odešle paket o délce nbytes, který je umístěn v adr. prostoru "source_segment:source_offset", na DSK. Funkce DSK.
Parametry:
user_task - číslo uživatelského procesu
nbytes - délka paketu, který odesíláme
source_segment - zdrojový segment dat
source_offset - zdrojový offset datVrací:
Vrací počet skutečně přenesených bytů nebo ERR (záporná hodnota).
Register(user_task, protocol).
Účel:
Zaregistruje IPX driver u DSK.Funkce DSK.
Parametry:
user_task - číslo registrovaného procesu
protocol - ID protokolu, který daný proces obsluhujeVrací:
Funkce vrací OK nebo ERR.
Odbočka v hlavní smyčce File Systému
Odchytává zprávy určené pro IPX. Smyčka je aktivní, pokud globální proměnná "ipx_ready" = TRUE (nastavuje funkce ipx_init(), pokud inicializace IPX driveru proběhla úspěšně).
Což jsou:
a) veškeré zprávy C_SOCKET, C_NOTIFY, C_SETLNET, C_SETLNODE, C_SETGATEWAY
b) C_READ, C_WRITE, C_CLOSE, které mají file descriptor větší než IPX_SOCK_PREF
Datová cache
Obsahuje:
Data z doručených a aplikací dosud nepřečtených paketů.
Je tvořena:
- Polem struktur "IPX_BUF buffers[]". Struktura obsahuje datový buffer "char buf[]", proměnnou "len" - délka platných dat a proměnnou "next" - ukazuje na následující neobsazenou strukturu IPX_BUF nebo obsahuje -1 v případě, že je poslední.
- "Kruhovým bufferem" indexů do pole "buffers[]" v každé zaznamu TOS_ELEMENT pole TOS. Ke každému "kruhovému bufferu" existují dvě proměnné, "buf_start" - ukazuje na začátek "kruhového bufferu" a "buff_len" - udavá počet záznamů v "kruhovému bufferu".
- Globální proměnnou "first_buf" - ukazuje na první neobsazenou strukturu IPX_BUF nebo obsahuje -1 v případě, že všechny struktury jsou obsazeny.
Použití:
Uložení dat do cache:
1) pokud "first_buf" neobsahuje -1 použij strukturu na kterou "first_buf" ukazuje
2) do první neobsazené položky "kruhového bufferu" přiřaď hodnotu "first_buf"
3) inkrementuj odpovídající "buff_len"
4) nakopíruj do struktury data + vyplň proměnnou "len"
5) nastav "first_buf" na následující volnou strukturuUvolnění cache:
1) zpracuj data uložená v sruktuře IPX_BUF na niž ukazuje patřičný "buf_start"
2) nastav "first_buf" na uvolněnou strukturu
3) nastav proměnnou "next" uvolněné struktury na původní hodnotu "first_buf"
4) posuň "buf_start" na následující položku "kruhového bufferu"
5) dekrementuj "buff_len"
Tabulka otevřených soketů -TOS
Je reprezentována polem struktur TOS_ELEMENT. Záznam tabulky představuje jeden momentálně otevřený soket.
Struktura obsahuje:
local_port - číslo otevřeného soketu
remote_port - číslo soketu na vzdáleném stroji
remote_node - adresa uzlu v rámci remoute_net
remote_net - adresa vzdálené sítě
device_num - číslo síťové karty
in_use_flag - indikuje platná data
wait_proc - číslo čekajícího procesu
wait_data_len - požadovaná délka dat čekajícího procesu
wait_segment - cílový segment dat čekajícího procesu
wait_offset - cílový offset dat čekajícího procesu
buffers[] - kruhový buffer indexů do pole "buffers[]"
buf_start - ukazuje na začátek kruhového bufferu
buf_len - udavá počet záznamů v kruhovému bufferu
IPX Packet
Jedná se o strukturu sloužící k sestavování packetu a k vybalování dat z doručených packetů.
Struktura obsahuje:
checksum - kontrolní součet packetu (počítá driver síťové karty)
length - délka datové části packetu
transport_control - pole používané směrovači pro likvidaci bloudivých paketů
packet_type - typ paketu, blíže definuje určení údajů v datové části paketu
destination_network - adresa cílové síťě
destination_node - adresa cílového uzlu
destination_socket - číslo cílového socketu
source_network - zdrojová adresa síťě
source_node - adresa zdrojového uzlu
source_socket - číslo zdrojového socketu
data - datová část packetu
NODE_ADR
Struktura určená pro ukladání 48b adresy uzlu.
Struktura obsahuje:
node_h16 - horních 16b adresy uzlu
node_l32 - dolních 32b adresy uzlu
Globální proměnné:
Poslední změna : 27. 7. 1999